コード例 #1
0
ファイル: player.cpp プロジェクト: Noplace/DSP
DWORD Player::InstancePlayThread() {
  Timer timer;

  uint64_t current_cycles=0,prev_cycles=0;
  double span_accumulator = 0;
  double update_time = 1000.0;
  double timer_res = timer.resolution();
  uint32_t samples_to_render = uint32_t(update_time * 0.001 * audio_interface_->wave_format().nSamplesPerSec);
  uint32_t buffer_size = samples_to_render * audio_interface_->wave_format().nBlockAlign;

  thread_time_span = 0;
  while (1) {
    EnterCriticalSection(&cs);
    if (thread_msg == WM_SP_QUIT) {
        thread_msg = 0;
        break;
    } else if (thread_msg == WM_SP_PLAY) {
      if (state_ != kStatePlaying) {
        prev_cycles = timer.GetCurrentCycles();
        state_ = kStatePlaying;
        span_accumulator = update_time;
        audio_interface_->Play();
      }
    } else if (thread_msg == WM_SP_PAUSE) {
      if (state_ != kStatePaused) {
        ResetEvent(player_event);
        state_ = kStatePaused;
        
        memset(output_buffer,0,output_buffer_samples_*sizeof(short));
        audio_interface_->Write(output_buffer,output_buffer_samples_*sizeof(short));
      }
    } else if (thread_msg == WM_SP_STOP) {
      if (state_ != kStateStopped) {
        ResetEvent(player_event);
        state_ = kStateStopped;
        synth_->Reset();
        song_counter_ms = 0;
        audio_interface_->Stop();
        thread_time_span = 0;
      }
    } 
    thread_msg = 0;
    LeaveCriticalSection(&cs);

    if (state_ == kStatePlaying) {
      current_cycles = timer.GetCurrentCycles();
      double time_span =  (current_cycles - prev_cycles) * timer_res;
      if (time_span >= output_buffer_length_ms_) //should be at max, output buffer length in ms
        time_span = output_buffer_length_ms_;
 
      while (span_accumulator >= update_time) {
        //memset(mix_buffer,0,output_buffer_samples_*sizeof(real_t));
        synth_->RenderSamplesStereo(samples_to_render,mix_buffer);
        song_counter_ms += update_time;
        if (TryEnterCriticalSection(&vis_cs) != 0) {
          if (visual_addon_ != nullptr && samples_to_render >= 256)
            visual_addon_->AddPCMData256(mix_buffer,2,update_time);
          LeaveCriticalSection(&vis_cs);
        }
        clamp(output_buffer,mix_buffer,samples_to_render<<1);

        audio_interface_->Write(output_buffer,buffer_size);
        span_accumulator -= update_time;
      }
      span_accumulator += time_span;
      thread_time_span += time_span;
      prev_cycles = current_cycles;
    } else {
      //wait for pause/stop events with timer
      WaitForSingleObject(player_event,2000);
    }
  }

  return S_OK;
}