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; }
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; }