void writeSound(void) { int ret = soundBufferLen; //int i; while (mod.outMod->CanWrite() < ((ret*sndNumChannels*(sndBitsPerSample/8))<<(mod.dsp_isactive()?1:0))) Sleep(50); mod.SAAddPCMData((char *)soundFinalWave,sndNumChannels,sndBitsPerSample,decode_pos_ms); mod.VSAAddPCMData((char *)soundFinalWave,sndNumChannels,sndBitsPerSample,decode_pos_ms); decode_pos_ms += (ret/(2*sndNumChannels) * 1000) / (float)sndSamplesPerSec; if (mod.dsp_isactive()) ret=mod.dsp_dosamples((short *)soundFinalWave,ret/sndNumChannels/(sndBitsPerSample/8),sndBitsPerSample,sndNumChannels,sndSamplesPerSec)*(sndNumChannels*(sndBitsPerSample/8)); //if(soundFinalWave[0]==0&&soundFinalWave[1]==0&&soundFinalWave[2]==0&&soundFinalWave[3]==0) // DisplayError("%.2X%.2X%.2X%.2X - %d", soundFinalWave[0],soundFinalWave[1],soundFinalWave[2],soundFinalWave[3],ret); mod.outMod->Write((char *)&soundFinalWave,ret); if (seek_needed != -1) //if a seek is initiated { mod.outMod->Flush((long)decode_pos_ms); if (seek_needed < decode_pos_ms) //if we are asked to seek backwards. we have to start from the beginning { GSFClose(); GSFRun(lastfn); decode_pos_ms = 0; } } }
DWORD WINAPI __stdcall DecodeThread(void *b) { int done=0; while (! *((int *)b) ) { if (seek_needed != -1) { //DisplayError("seek to %d",seek_needed); if (decode_pos_ms>seek_needed) { if (!InitADPFILE(NULL, &cubefile) || !InitADXFILE(NULL, &cubefile) || !InitDSPFILE(NULL, &cubefile)); decode_pos_ms=-1; // -1 ms, force it to work even if we want to seek to 0 } while (decode_pos_ms<seek_needed && ! *((int *)b)) { get_576_samples((short*)sample_buffer); mod.outMod->Flush((int)decode_pos_ms); decode_pos_ms+=(576.0*1000.0)/(double)cubefile.ch[0].sample_rate; } seek_needed=-1; } if (done) { mod.outMod->CanWrite(); if (!mod.outMod->IsPlaying()) { PostMessage(mod.hMainWindow,WM_WA_MPEG_EOF,0,0); return 0; } Sleep(10); } else if (mod.outMod->CanWrite() >= ((576*cubefile.NCH*(BPS/8))<<(mod.dsp_isactive()?1:0))) { int l=576*cubefile.NCH*(BPS/8); l=get_576_samples((short*)sample_buffer); if (!l) { done=1; } else { if (l==576*cubefile.NCH*(BPS/8)) { mod.SAAddPCMData((char *)sample_buffer,cubefile.NCH,BPS,mod.outMod->GetWrittenTime()); mod.VSAAddPCMData((char *)sample_buffer,cubefile.NCH,BPS,mod.outMod->GetWrittenTime()); } decode_pos_ms+=(576.0*1000.0)/(double)cubefile.ch[0].sample_rate; if (mod.dsp_isactive()) l=mod.dsp_dosamples((short *)sample_buffer,l/cubefile.NCH/(BPS/8),BPS,cubefile.NCH,cubefile.ch[0].sample_rate)*(cubefile.NCH*(BPS/8)); mod.outMod->Write(sample_buffer,l); } } else Sleep(20); } return 0; }
static DWORD WINAPI DecodeThread(void *unused) { const unsigned channels = stream_data_.channels; const unsigned bits_per_sample = stream_data_.bits_per_sample; const unsigned target_bps = stream_data_.output_bits_per_sample; const unsigned sample_rate = stream_data_.sample_rate; const unsigned fact = channels * (target_bps/8); while (stream_data_.is_playing) { /* seek needed */ if (stream_data_.seek_to != -1) { const int pos = FLAC_plugin__seek(decoder_, &stream_data_); if (pos != -1) mod_.outMod->Flush(pos); } /* stream ended */ else if (stream_data_.eof) { if (!mod_.outMod->IsPlaying()) { PostMessage(mod_.hMainWindow, WM_WA_MPEG_EOF, 0, 0); return 0; } Sleep(10); } /* decode */ else { /* decode samples */ int bytes = FLAC_plugin__decode(decoder_, &stream_data_, sample_buffer_); const int n = bytes / fact; /* visualization */ do_vis(sample_buffer_, channels, target_bps, mod_.outMod->GetWrittenTime(), n); /* dsp */ if (mod_.dsp_isactive()) bytes = mod_.dsp_dosamples((short*)sample_buffer_, n, target_bps, channels, sample_rate) * fact; /* output */ while (mod_.outMod->CanWrite()<bytes && stream_data_.is_playing && stream_data_.seek_to==-1) Sleep(20); if (stream_data_.is_playing && stream_data_.seek_to==-1) mod_.outMod->Write(sample_buffer_, bytes); /* show bitrate */ if (flac_cfg.display.show_bps) { const int rate = FLAC_plugin__get_rate(mod_.outMod->GetWrittenTime(), mod_.outMod->GetOutputTime(), &stream_data_); if (rate) mod_.SetInfo(rate/1000, stream_data_.sample_rate/1000, stream_data_.channels, 1); } } } return 0; }
static DWORD WINAPI playThread(LPVOID dummy) { while (thread_run) { static #if BITS_PER_SAMPLE == 8 byte #else short #endif buffer[BUFFERED_BLOCKS * 2 #if SUPPORT_EQUALIZER * 2 #endif ]; int buffered_bytes = BUFFERED_BLOCKS * channels * (BITS_PER_SAMPLE / 8); if (seek_needed >= 0) { mod.outMod->Flush(seek_needed); ASAP_Seek(&asap, seek_needed); seek_needed = -1; } if (mod.outMod->CanWrite() >= buffered_bytes #if SUPPORT_EQUALIZER << mod.dsp_isactive() #endif ) { int t; buffered_bytes = ASAP_Generate(&asap, buffer, buffered_bytes, BITS_PER_SAMPLE); if (buffered_bytes <= 0) { mod.outMod->CanWrite(); if (!mod.outMod->IsPlaying()) { PostMessage(mod.hMainWindow, WM_WA_MPEG_EOF, 0, 0); return 0; } Sleep(10); continue; } t = mod.outMod->GetWrittenTime(); mod.SAAddPCMData(buffer, channels, BITS_PER_SAMPLE, t); mod.VSAAddPCMData(buffer, channels, BITS_PER_SAMPLE, t); #if SUPPORT_EQUALIZER t = buffered_bytes / (channels * (BITS_PER_SAMPLE / 8)); t = mod.dsp_dosamples((short *) buffer, t, BITS_PER_SAMPLE, channels, ASAP_SAMPLE_RATE); t *= channels * (BITS_PER_SAMPLE / 8); mod.outMod->Write((char *) buffer, t); #else mod.outMod->Write((char *) buffer, buffered_bytes); #endif } else Sleep(20); } return 0; }
DWORD WINAPI PlayThread(void *b) { int done=0; int l; int decoded_frames=0; int br_calc_frames=0; int br_bytes_consumed=0; unsigned long bytesconsumed; PlayThreadAlive = 1; last_frame = 0; while (! *((int *)b) ) { if (seek_needed != -1) { int seconds; // Round off to a second seconds = seek_needed - (seek_needed%1000); mod.outMod->Flush(decode_pos_ms); aac_seek(seconds, seek_table); decode_pos_ms = seconds; seek_needed = -1; decoded_frames = 0; br_calc_frames = 0; br_bytes_consumed = 0; } if (done) { mod.outMod->CanWrite(); if (!mod.outMod->IsPlaying()) { PostMessage(mod.hMainWindow,WM_WA_AAC_EOF,0,0); PlayThreadAlive = 0; return 0; } Sleep(10); } //assume that max channels is 2. else if (mod.outMod->CanWrite() >= ((1024*file_info.channels*sizeof(short))<<(mod.dsp_isactive()?1:0))) { if(last_frame) { done=1; } else { if (current_file_mode) bytesconsumed = PlayThread_memmap(); else bytesconsumed = PlayThread_file(); decoded_frames++; br_calc_frames++; br_bytes_consumed += bytesconsumed; /* Update the variable bitrate about every second */ if(m_variable_bitrate_display && br_calc_frames == 43) { int br; br = (int)((br_bytes_consumed * 8) / (decoded_frames / 43.07)); mod.SetInfo(br/1000, file_info.sampling_rate/1000, file_info.channels, 1); br_calc_frames = 0; } if (!killPlayThread && (frameInfo.samples > 0)) { mod.SAAddPCMData(sample_buffer,file_info.channels, 16, decode_pos_ms); mod.VSAAddPCMData(sample_buffer,file_info.channels, 16, decode_pos_ms); decode_pos_ms+=(1024*1000)/file_info.sampling_rate; if (mod.dsp_isactive()) l=mod.dsp_dosamples((short *)sample_buffer,frameInfo.samples*sizeof(short)/file_info.channels/(16/8),16,file_info.channels,file_info.sampling_rate)*(file_info.channels*(16/8)); else l = frameInfo.samples*sizeof(short); mod.outMod->Write(sample_buffer, l); } } } else { Sleep(10); } } if(seek_table) { free(seek_table); seek_table = NULL; seek_table_length = 0; } PlayThreadAlive = 0; return 0; }
DWORD WINAPI DecodeThread(LPVOID b) { int done=0; // set to TRUE if decoding has finished while (!killDecodeThread) { if (seek_needed != -1) // seek is needed. { int offs; decode_pos_ms = seek_needed; seek_needed=-1; done=0; mod.outMod->Flush(decode_pos_ms); // flush output device and set // output position to the seek position offs = MulDiv(decode_pos_ms,SAMPLERATE,1000); // decode_pos_ms*SAMPLERATE/1000 SetFilePointer(input_file,offs*NCH*(BPS/8),NULL,FILE_BEGIN); // seek! } if (done) // done was set to TRUE during decoding, signaling eof { mod.outMod->CanWrite(); // some output drivers need CanWrite // to be called on a regular basis. if (!mod.outMod->IsPlaying()) { // we're done playing, so tell Winamp and quit the thread. PostMessage(mod.hMainWindow,WM_WA_MPEG_EOF,0,0); return 0; // quit thread } Sleep(10); // give a little CPU time back to the system. } else if (mod.outMod->CanWrite() >= ((576*NCH*(BPS/8))*(mod.dsp_isactive()?2:1))) // CanWrite() returns the number of bytes you can write, so we check that // to the block size. the reason we multiply the block size by two if // mod.dsp_isactive() is that DSP plug-ins can change it by up to a // factor of two (for tempo adjustment). { int l=576*NCH*(BPS/8); // block length in bytes static char sample_buffer[576*NCH*(BPS/8)*2]; // sample buffer. twice as // big as the blocksize l=get_576_samples(sample_buffer); // retrieve samples if (!l) // no samples means we're at eof { done=1; } else // we got samples! { // give the samples to the vis subsystems mod.SAAddPCMData((char *)sample_buffer,NCH,BPS,decode_pos_ms); mod.VSAAddPCMData((char *)sample_buffer,NCH,BPS,decode_pos_ms); // adjust decode position variable decode_pos_ms+=(576*1000)/SAMPLERATE; // if we have a DSP plug-in, then call it on our samples if (mod.dsp_isactive()) l=mod.dsp_dosamples( (short *)sample_buffer,l/NCH/(BPS/8),BPS,NCH,SAMPLERATE ) // dsp_dosamples *(NCH*(BPS/8)); // write the pcm data to the output system mod.outMod->Write(sample_buffer,l); } } else Sleep(20); // if we can't write data, wait a little bit. Otherwise, continue // through the loop writing more data (without sleeping) } return 0; }
DWORD WINAPI __stdcall DecodeThread(void *b) { int done = 0; while(! *((int *)b) ) { const unsigned channels = file_info_.channels; const unsigned bits_per_sample = file_info_.bits_per_sample; #ifdef FLAC__DO_DITHER const unsigned target_bps = min(bits_per_sample, 16); #else const unsigned target_bps = bits_per_sample; #endif const unsigned sample_rate = file_info_.sample_rate; if(seek_needed_ != -1) { const double distance = (double)seek_needed_ / (double)getlength(); const unsigned target_sample = (unsigned)(distance * (double)file_info_.total_samples); if(FLAC__file_decoder_seek_absolute(decoder_, (FLAC__uint64)target_sample)) { decode_pos_ms_ = (int)(distance * (double)getlength()); seek_needed_ = -1; done = 0; mod_.outMod->Flush(decode_pos_ms_); } } if(done) { if(!mod_.outMod->IsPlaying()) { PostMessage(mod_.hMainWindow, WM_WA_MPEG_EOF, 0, 0); return 0; } Sleep(10); } else if(mod_.outMod->CanWrite() >= ((int)(SAMPLES_PER_WRITE*channels*((target_bps+7)/8)) << (mod_.dsp_isactive()?1:0))) { while(wide_samples_in_reservoir_ < SAMPLES_PER_WRITE) { if(FLAC__file_decoder_get_state(decoder_) == FLAC__FILE_DECODER_END_OF_FILE) { done = 1; break; } else if(!FLAC__file_decoder_process_single(decoder_)) { MessageBox(mod_.hMainWindow, FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(decoder_)], "READ ERROR processing frame", 0); done = 1; break; } } if(wide_samples_in_reservoir_ == 0) { done = 1; } else { const unsigned n = min(wide_samples_in_reservoir_, SAMPLES_PER_WRITE); const unsigned delta = n * channels; int bytes = (int)FLAC__plugin_common__pack_pcm_signed_little_endian(sample_buffer_, reservoir_, n, channels, bits_per_sample, target_bps); unsigned i; for(i = delta; i < wide_samples_in_reservoir_ * channels; i++) reservoir_[i-delta] = reservoir_[i]; wide_samples_in_reservoir_ -= n; do_vis((char *)sample_buffer_, channels, target_bps, decode_pos_ms_, n); decode_pos_ms_ += (n*1000 + sample_rate/2)/sample_rate; if(mod_.dsp_isactive()) bytes = mod_.dsp_dosamples((short *)sample_buffer_, n, target_bps, channels, sample_rate) * (channels*target_bps/8); mod_.outMod->Write(sample_buffer_, bytes); } } else Sleep(20); } return 0; }
static DWORD WINAPI DecodeThread( LPVOID ) { MSG msg; PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ); bool eof = false; while ( true ) { bool quit = false; while ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ) { if ( msg.message == WM_QUIT ) { quit = true; } else if ( msg.message == WM_OPENMPT_SEEK ) { double pos_seconds = self->mod->set_position_seconds( msg.lParam * 0.001 ); self->decode_position_frames = (std::int64_t)( pos_seconds * (double)self->samplerate); eof = false; inmod.outMod->Flush( (int)( pos_seconds * 1000.0 ) ); } } if ( quit ) { break; } if ( eof ) { inmod.outMod->CanWrite(); // update output plugin state if ( !inmod.outMod->IsPlaying() ) { PostMessage( inmod.hMainWindow, WM_WA_MPEG_EOF, 0, 0 ); return 0; } Sleep( 10 ); } else { bool dsp_active = inmod.dsp_isactive() ? true : false; if ( inmod.outMod->CanWrite() >= (int)( WINAMP_BUFFER_SIZE_FRAMES * self->channels * sizeof( signed short ) ) * ( dsp_active ? WINAMP_DSP_HEADROOM_FACTOR : 1 ) ) { int frames = 0; switch ( self->channels ) { case 1: frames = self->mod->read( self->samplerate, WINAMP_BUFFER_SIZE_FRAMES, (&(self->buffer[0]))+0*WINAMP_BUFFER_SIZE_FRAMES ); for ( int frame = 0; frame < frames; frame++ ) { self->interleaved_buffer[frame*1+0] = self->buffer[0*WINAMP_BUFFER_SIZE_FRAMES+frame]; } break; case 2: frames = self->mod->read( self->samplerate, WINAMP_BUFFER_SIZE_FRAMES, (&(self->buffer[0]))+0*WINAMP_BUFFER_SIZE_FRAMES, (&(self->buffer[0]))+1*WINAMP_BUFFER_SIZE_FRAMES ); for ( int frame = 0; frame < frames; frame++ ) { self->interleaved_buffer[frame*2+0] = self->buffer[0*WINAMP_BUFFER_SIZE_FRAMES+frame]; self->interleaved_buffer[frame*2+1] = self->buffer[1*WINAMP_BUFFER_SIZE_FRAMES+frame]; } break; case 4: frames = self->mod->read( self->samplerate, WINAMP_BUFFER_SIZE_FRAMES, (&(self->buffer[0]))+0*WINAMP_BUFFER_SIZE_FRAMES, (&(self->buffer[0]))+1*WINAMP_BUFFER_SIZE_FRAMES, (&(self->buffer[0]))+2*WINAMP_BUFFER_SIZE_FRAMES, (&(self->buffer[0]))+3*WINAMP_BUFFER_SIZE_FRAMES ); for ( int frame = 0; frame < frames; frame++ ) { self->interleaved_buffer[frame*4+0] = self->buffer[0*WINAMP_BUFFER_SIZE_FRAMES+frame]; self->interleaved_buffer[frame*4+1] = self->buffer[1*WINAMP_BUFFER_SIZE_FRAMES+frame]; self->interleaved_buffer[frame*4+2] = self->buffer[2*WINAMP_BUFFER_SIZE_FRAMES+frame]; self->interleaved_buffer[frame*4+3] = self->buffer[3*WINAMP_BUFFER_SIZE_FRAMES+frame]; } break; } if ( frames == 0 ) { eof = true; } else { self->decode_position_frames += frames; std::int64_t decode_pos_ms = (self->decode_position_frames * 1000 / self->samplerate ); inmod.SAAddPCMData( &( self->interleaved_buffer[0] ), self->channels, BPS, (int)decode_pos_ms ); inmod.VSAAddPCMData( &( self->interleaved_buffer[0] ), self->channels, BPS, (int)decode_pos_ms ); if ( dsp_active ) { frames = inmod.dsp_dosamples( &( self->interleaved_buffer[0] ), frames, BPS, self->channels, self->samplerate ); } int bytes = frames * self->channels * sizeof( signed short ); inmod.outMod->Write( (char*)&( self->interleaved_buffer[0] ), bytes ); } } else { Sleep( 10 ); } } } return 0; }