示例#1
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;
}
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;
}