Exemplo n.º 1
0
/**
 * Custom audio player.
 * @param udata User data to send to the player.
 * @param stream Raw audio to output.
 * @param len Length of audio to output.
 */
void AdlibMusic::player(void *udata, Uint8 *stream, int len)
{
#ifndef __NO_MUSIC
	if (Options::musicVolume == 0)
		return;
	if (Options::musicAlwaysLoop && !func_is_music_playing())
	{
		AdlibMusic *music = (AdlibMusic*)udata;
		music->play();
		return;
	}
	while (len != 0)
	{
		if (!opl[0] || !opl[1])
			return;
		int i = std::min(delay, len);
		if (i)
		{
			float volume = Game::volumeExponent(Options::musicVolume);
			YM3812UpdateOne(opl[0], (INT16*)stream, i / 2, 2, volume);
			YM3812UpdateOne(opl[1], ((INT16*)stream) + 1, i / 2, 2, volume);
			stream += i;
			delay -= i;
			len -= i;
		}
		if (!len)
			return;
		func_play_tick();

		delay = delayRates[rate]; 
	}
#endif
}
Exemplo n.º 2
0
void CEmuopl::update(short *buf, int samples)
{
	int i;

	if(use16bit) {
		YM3812UpdateOne(0,buf,samples);

		if(stereo)
			for(i=samples-1;i>=0;i--) {
				buf[i*2] = buf[i];
				buf[i*2+1] = buf[i];
			}
	} else {
		short *tempbuf = new short[stereo ? samples*2 : samples];
		int i;

		YM3812UpdateOne(0,tempbuf,samples);

		if(stereo)
			for(i=samples-1;i>=0;i--) {
				tempbuf[i*2] = tempbuf[i];
				tempbuf[i*2+1] = tempbuf[i];
			}

		for(i=0;i<(stereo ? samples*2 : samples);i++)
			((char *)buf)[i] = (tempbuf[i] >> 8) ^ 0x80;

		delete [] tempbuf;
	}
}
Exemplo n.º 3
0
// Drop-in replacement for id_sd.c:alOut
void BE_ST_ALOut(uint8_t reg,uint8_t val)
{
	BE_ST_LockAudioRecursively(); // RECURSIVE lock

	// FIXME: The original code for alOut adds 6 reads of the
	// register port after writing to it (3.3 microseconds), and
	// then 35 more reads of register port after writing to the
	// data port (23 microseconds).
	//
	// It is apparently important for a portion of the fuse
	// breakage sound at the least. For now a hack is implied.
	YM3812Write(&oplChip, reg, val);
	// Hack comes with a "magic number"
	// that appears to make it work better
	unsigned int length = OPL_SAMPLE_RATE / 10000;

	if (length > OPL_NUM_OF_SAMPLES - g_sdlALOutSamplesEnd)
	{
		BE_Cross_LogMessage(BE_LOG_MSG_WARNING, "BE_ST_ALOut overflow, want %u, have %u\n", length, OPL_NUM_OF_SAMPLES - g_sdlALOutSamplesEnd); // FIXME - Other thread
		length = OPL_NUM_OF_SAMPLES - g_sdlALOutSamplesEnd;
	}
	if (length)
	{
		YM3812UpdateOne(&oplChip, &g_sdlALOutSamples[g_sdlALOutSamplesEnd], length);
		g_sdlALOutSamplesEnd += length;
	}

	BE_ST_UnlockAudioRecursively(); // RECURSIVE unlock
}
Exemplo n.º 4
0
int AdLibMusic::readBuffer(int16 *data, const int numSamples) {
	if (_musicData == NULL) {
		// no music loaded
		memset(data, 0, numSamples * sizeof(int16));
	} else if ((_currentMusic == 0) || (_numberOfChannels == 0)) {
		// music loaded but not played as of yet
		memset(data, 0, numSamples * sizeof(int16));
		// poll anyways as pollMusic() can activate the music
		pollMusic();
		_nextMusicPoll = _sampleRate / 50;
	} else {
		uint32 render;
		uint remaining = numSamples;
		while (remaining) {
			render = (remaining > _nextMusicPoll) ? _nextMusicPoll : remaining;
			remaining -= render;
			_nextMusicPoll -= render;
			YM3812UpdateOne(_opl, data, render);
			data += render;
			if (_nextMusicPoll == 0) {
				pollMusic();
				_nextMusicPoll = _sampleRate / 50;
			}
		}
	}
	return numSamples;
}
Exemplo n.º 5
0
static void YM3812Render(int nSegmentLength)
{
	if (nYM3812Position >= nSegmentLength) {
		return;
	}

//	bprintf(PRINT_NORMAL, _T("    YM3812 render %6i -> %6i\n", nYM3812Position, nSegmentLength));

	nSegmentLength -= nYM3812Position;

	YM3812UpdateOne(0, pBuffer + 0 * 4096 + 4 + nYM3812Position, nSegmentLength);

	nYM3812Position += nSegmentLength;
}
Exemplo n.º 6
0
static void YM3812Render(INT32 nSegmentLength)
{
#if defined FBA_DEBUG
	if (!DebugSnd_YM3812Initted) bprintf(PRINT_ERROR, _T("YM3812Render called without init\n"));
#endif

	if (nYM3812Position >= nSegmentLength) {
		return;
	}

//	bprintf(PRINT_NORMAL, _T("    YM3812 render %6i -> %6i\n", nYM3812Position, nSegmentLength));

	nSegmentLength -= nYM3812Position;

	YM3812UpdateOne(0, pBuffer + 0 * 4096 + 4 + nYM3812Position, nSegmentLength);

	nYM3812Position += nSegmentLength;
}
Exemplo n.º 7
0
static void ym3812_stream_update(void *param, stream_sample_t **inputs, stream_sample_t **buffer, int length)
{
	struct ym3812_info *info = param;
	YM3812UpdateOne(info->chip, buffer[0], length);
}
Exemplo n.º 8
0
void opl_update( OPLSAMPLE *buf, int samples )
{
	YM3812UpdateOne(opl, buf, samples);
}
Exemplo n.º 9
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:
		}
	}
Exemplo n.º 10
0
void SDL_IMFMusicPlayer(void *udata, Uint8 *stream, int len)
{
    int stereolen = len>>1;
    int sampleslen = stereolen>>1;
    Sint16 *stream16 = (Sint16 *) (void *) stream;    // expect correct alignment

    while(1)
    {
        if(numreadysamples)
        {
            if(numreadysamples<sampleslen)
            {
                if(MusicMode == smm_AdLib || SoundMode == sdm_AdLib)
                    YM3812UpdateOne(oplChip, stream16, numreadysamples);

                // Mix the emulated PC sounds into the AdLib buffer:
                SDL_PCEmulateAndMix(stream16, numreadysamples);

                stream16 += numreadysamples*2;
                sampleslen -= numreadysamples;
            }
            else
            {
                if(MusicMode == smm_AdLib || SoundMode == sdm_AdLib)
                    YM3812UpdateOne(oplChip, stream16, sampleslen);

                // Mix the emulated PC sounds into the AdLib buffer:
                SDL_PCEmulateAndMix(stream16, sampleslen);

                numreadysamples -= sampleslen;
                return;
            }
        }

        SDL_LockMutex(audioMutex);

        soundTimeCounter--;
        if(!soundTimeCounter)
        {
            // Sound effects are played at 140 Hz (every 5 cycles of the 700 Hz music service)
            soundTimeCounter = SOUND_TICKS;

            SDL_PCService();

            // THIS is the way the original Wolfenstein 3-D code handled it!
            if(alSound)
            {
                if(*alSound)
                {
                    alOut(alFreqL, *alSound);
                    alOut(alFreqH, alBlock);
                } else alOut(alFreqH, 0);
                alSound++;
                if (!(--alLengthLeft))
                {
                    alSound = 0;
                    SoundPriority=0;
                    alOut(alFreqH, 0);
                }
            }
        }
        if(sqActive)
        {
            do
            {
                if(sqHackTime > alTimeCount) break;
                sqHackTime = alTimeCount + LittleShort(*(sqHackPtr+1));
                alOutMusic(*(byte *) sqHackPtr, *(((byte *) sqHackPtr)+1));
                sqHackPtr += 2;
                sqHackLen -= 4;
            }
            while(sqHackLen>0);
            alTimeCount++;
            if(!sqHackLen)
            {
                sqHackPtr = sqHack;
                sqHackLen = sqHackSeqLen;
                sqHackTime = 0;
                alTimeCount = 0;
            }
        }
        numreadysamples = samplesPerMusicTick;

        SDL_UnlockMutex(audioMutex);
    }
}
Exemplo n.º 11
0
void AdLibMidiDriver::generateSamples(int16 *data, int len) {
	memset(data, 0, sizeof(int16) * len);
	YM3812UpdateOne(_opl, data, len);
}
Exemplo n.º 12
0
static void SD_IMFMusicPlayer(void *udata, Uint8 *stream, int len)
{
   int stereolen = len>>1;
   int sampleslen = stereolen>>1;
   INT16 *stream16 = (INT16 *) (void *) stream;    /* expect correct alignment */

   while(1)
   {
      if(numreadysamples)
      {
         if(numreadysamples < sampleslen)
         {
            YM3812UpdateOne(0, stream16, numreadysamples);
            stream16 += numreadysamples*2;
            sampleslen -= numreadysamples;
         }
         else
         {
            YM3812UpdateOne(0, stream16, sampleslen);
            numreadysamples -= sampleslen;
            return;
         }
      }
      soundTimeCounter--;
      if(!soundTimeCounter)
      {
         soundTimeCounter = 5;
         if(curAlSound != alSound)
         {
            curAlSound = curAlSoundPtr = alSound;
            curAlLengthLeft = alLengthLeft;
         }
         if(curAlSound)
         {
            if(*curAlSoundPtr)
            {
               YM3812Write(0, alFreqL, *curAlSoundPtr);
               YM3812Write(0, alFreqH, alBlock);
            }
            else YM3812Write(0, alFreqH, 0);
            curAlSoundPtr++;
            curAlLengthLeft--;
            if(!curAlLengthLeft)
            {
               curAlSound = alSound = 0;
               SoundNumber = (soundnames) 0;
               SoundPriority = 0;
               YM3812Write(0, alFreqH, 0);
            }
         }
      }
      if(sqActive)
      {
         do
         {
            if(sqHackTime > alTimeCount) break;
            sqHackTime = alTimeCount + (word)Retro_SwapLES16(*(sqHackPtr+1));
            YM3812Write(0, *(byte *) sqHackPtr, *(((byte *) sqHackPtr)+1));
            sqHackPtr += 2;
            sqHackLen -= 4;
         }
         while(sqHackLen>0);
         alTimeCount++;
         if(!sqHackLen)
         {
            sqHackPtr = sqHack;
            sqHackLen = sqHackSeqLen;
            sqHackTime = 0;
            alTimeCount = 0;
         }
      }
      numreadysamples = samplesPerMusicTick;
   }
}
Exemplo n.º 13
0
void CEmuopl::update(short *buf, int samples)
{
  int i;

  //ensure that our mix buffers are adequately sized
  if(unlikely (mixbufSamples < samples)) {

      if (mixbuf0) {
          delete[] mixbuf0;
          mixbuf0 = 0;
      }
      if (mixbuf1) {
          delete[] mixbuf1;
          mixbuf1 = 0;
      }
    //*2 = make room for stereo, if we need it
    mixbuf0 = new short[samples*2]; 
    mixbuf1 = new short[samples*2];
  }

  mixbufSamples = samples;
  //data should be rendered to outbuf
  //tempbuf should be used as a temporary buffer
  //if we are supposed to generate 16bit output,
  //then outbuf may point directly to the actual waveform output "buf"
  //if we are supposed to generate 8bit output,
  //then outbuf cannot point to "buf" (because there will not be enough room)
  //and so it must point to a mixbuf instead--
  //it will be reduced to 8bit and put in "buf" later
  short *outbuf;
  if (likely (use16bit)) {
      outbuf = buf;
  }
  else {
      outbuf = mixbuf1;
  }
  //...there is a potentially confusing situation where mixbuf1 can be aliased.
  //beware. it is a little loony.

  //all of the following rendering code produces 16bit output

  switch(currType) {
  case TYPE_OPL2:
    //for opl2 mode:
    //render chip0 to the output buffer
    YM3812UpdateOne(opl[0],outbuf,samples);

    //if we are supposed to output stereo,
    //then we need to dup the mono channel
    if(unlikely (stereo)) {
        for(i=samples-1;i>=0;i--) {
            outbuf[i*2] = outbuf[i];
            outbuf[i*2+1] = outbuf[i];
        }
    }
    break;

  case TYPE_OPL3:	// unsupported
    break;

  case TYPE_DUAL_OPL2:
    //for dual opl2 mode:
    //render each chip to a different tempbuffer
    YM3812UpdateOne(opl[0],mixbuf1,samples);
    YM3812UpdateOne(opl[1],mixbuf0,samples);

    //output stereo:
    //then we need to interleave the two buffers
    if(unlikely (stereo)){
        //first, spread tempbuf's samples across left channel
        for(i=0;i<samples;i++)
            outbuf[i*2] = mixbuf1[i];
        //next, insert the samples from tempbuf2 into right channel
        for(i=0;i<samples;i++)
            outbuf[i*2+1] = mixbuf0[i];
    } else {
        //output mono:
        //then we need to mix the two buffers into buf
        for(i=0;i<samples;i++) {
            int sample = (int)mixbuf0[i] + (int)mixbuf1[i];
            if (unlikely (sample > 32767)) {
                sample = 32767;
            }
            else if (unlikely (sample < -32768)) {
                sample = -32768;
            }
            outbuf[i] = (short)sample;
        }
    }
    break;
  }

  //now reduce to 8bit if we need to
  if(unlikely (!use16bit)) {
      int smp = stereo ? samples*2 : samples;
      for(i=0;i<smp;i++) {
          ((char *)buf)[i] = (outbuf[i] >> 8) ^ 0x80;
      }
  }