void OPLmusicFile::Dump()
{
	int time;

	time = PlayTick();
	while (time != 0)
	{
		io->WriteDelay(time);
		time = PlayTick();
	}
}
int OPLDumperMIDIDevice::Resume()
{
	int time;

	time = PlayTick();
	while (time != 0)
	{
		io->WriteDelay(time);
		time = PlayTick();
	}
	return 0;
}
bool OPLmusicBlock::ServiceStream (void *buff, int numbytes)
{
	float *samples1 = (float *)buff;
	int stereoshift = (int)(FullPan | io->IsOPL3);
	int numsamples = numbytes / (sizeof(float) << stereoshift);
	bool prevEnded = false;
	bool res = true;

	memset(buff, 0, numbytes);

	ChipAccess.Enter();
	while (numsamples > 0)
	{
		double ticky = NextTickIn;
		int tick_in = int(NextTickIn);
		int samplesleft = MIN(numsamples, tick_in);
		size_t i;

		if (samplesleft > 0)
		{
			for (i = 0; i < io->NumChips; ++i)
			{
				io->chips[i]->Update(samples1, samplesleft);
			}
			OffsetSamples(samples1, samplesleft << stereoshift);
			assert(NextTickIn == ticky);
			NextTickIn -= samplesleft;
			assert (NextTickIn >= 0);
			numsamples -= samplesleft;
			samples1 += samplesleft << stereoshift;
		}
		
		if (NextTickIn < 1)
		{
			int next = PlayTick();
			assert(next >= 0);
			if (next == 0)
			{ // end of song
				if (!Looping || prevEnded)
				{
					if (numsamples > 0)
					{
						for (i = 0; i < io->NumChips; ++i)
						{
							io->chips[i]->Update(samples1, numsamples);
						}
						OffsetSamples(samples1, numsamples << stereoshift);
					}
					res = false;
					break;
				}
				else
				{
					// Avoid infinite loops from songs that do nothing but end
					prevEnded = true;
					Restart ();
				}
			}
			else
			{
				prevEnded = false;
				io->WriteDelay(next);
				NextTickIn += SamplesPerTick * next;
				assert (NextTickIn >= 0);
				MLtime += next;
			}
		}
	}
	ChipAccess.Leave();
	return res;
}
Beispiel #4
0
bool OPLmusicBlock::ServiceStream (void *buff, int numbytes)
{
	short *samples = (short *)buff;
	int *samples1 = SampleBuff;
	int numsamples = numbytes / 2;
	bool prevEnded = false;
	bool res = true;

	memset (SampleBuff, 0, numsamples * 4);

#ifdef _WIN32
	EnterCriticalSection (&ChipAccess);
#else
	if (SDL_mutexP (ChipAccess) != 0)
		return true;
#endif
	while (numsamples > 0)
	{
		int samplesleft = MIN (numsamples, NextTickIn);

		if (samplesleft > 0)
		{
			YM3812UpdateOne (0, samples1, samplesleft);
			if (TwoChips)
			{
				YM3812UpdateOne (1, samples1, samplesleft);
			}
			NextTickIn -= samplesleft;
			assert (NextTickIn >= 0);
			numsamples -= samplesleft;
			samples1 += samplesleft;
		}
		
		if (NextTickIn == 0)
		{
			int next = PlayTick ();
			if (next == 0)
			{ // end of song
				if (!Looping || prevEnded)
				{
					if (numsamples > 0)
					{
						YM3812UpdateOne (0, samples1, numsamples);
						if (TwoChips)
						{
							YM3812UpdateOne (1, samples1, numsamples);
						}
					}
					res = false;
					break;
				}
				else
				{
					// Avoid infinite loops from songs that do nothing but end
					prevEnded = true;
					Restart ();
				}
			}
			else
			{
				prevEnded = false;
				NextTickIn = SamplesPerTick * next;
				assert (NextTickIn >= 0);
				MLtime += next;
			}
		}
	}
#ifdef _WIN32
	LeaveCriticalSection (&ChipAccess);
#else
	SDL_mutexV (ChipAccess);
#endif
	numsamples = numbytes / 2;
	samples1 = SampleBuff;

#if defined(_MSC_VER) && defined(USEASM)
	if (CPU.bCMOV && numsamples > 1)
	{
		__asm
		{
			mov ecx, numsamples
			mov esi, samples1
			mov edi, samples
			shr ecx, 1
			lea esi, [esi+ecx*8]
			lea edi, [edi+ecx*4]
			neg ecx
			mov edx, 0x00007fff
looper:		mov eax, [esi+ecx*8]
			mov ebx, [esi+ecx*8+4]

			// Shift the samples down to reduce the chance of clipping at the high end.
			// Since most of the waveforms we produce only use the upper half of the
			// sine wave, this is a good thing. Although it does leave less room at
			// the bottom of the sine before clipping, almost none of the songs I tested
			// went below -9000.
			sub eax, 18000
			sub ebx, 18000

			// Clamp high
			cmp eax, edx
			cmovg eax, edx
			cmp ebx, edx
			cmovg ebx, edx

			// Clamp low
			not edx
			cmp eax, edx
			cmovl eax, edx
			cmp ebx, edx
			cmovl ebx, edx

			not edx
			mov [edi+ecx*4], ax
			mov [edi+ecx*4+2], bx

			inc ecx
			jnz looper

			test numsamples, 1
			jz done

			mov eax, [esi+ecx*8]
			sub eax, 18000
			cmp eax, edx
			cmovg eax, edx
			not edx
			cmp eax, edx
			cmovl eax, edx
			mov [edi+ecx*2], ax
done:
		}
	}