fceugx/source/gcaudio.cpp

179 lines
4.3 KiB
C++
Raw Normal View History

2008-09-02 03:57:21 +02:00
/****************************************************************************
2009-07-22 04:05:49 +02:00
* FCE Ultra
2008-09-02 03:57:21 +02:00
* Nintendo Wii/Gamecube Port
*
2009-03-28 18:23:08 +01:00
* Tantric 2008-2009
* eke-eke October 2008
2008-09-02 03:57:21 +02:00
*
2009-03-28 18:23:08 +01:00
* gcaudio.cpp
2008-09-02 03:57:21 +02:00
*
* Audio driver
****************************************************************************/
#include <gccore.h>
#include <string.h>
2009-03-28 18:23:08 +01:00
#include <asndlib.h>
2008-09-02 03:57:21 +02:00
#define SAMPLERATE 48000
static u8 ConfigRequested = 0;
static u8 soundbuffer[2][3840] ATTRIBUTE_ALIGN(32);
static u8 mixbuffer[16000];
static int mixhead = 0;
static int mixtail = 0;
static int whichab = 0;
static int IsPlaying = 0;
/****************************************************************************
* MixerCollect
*
* Collects sound samples from mixbuffer and puts them into outbuffer
* Makes sure to align them to 32 bytes for AUDIO_InitDMA
***************************************************************************/
static int MixerCollect( u8 *outbuffer, int len )
{
u32 *dst = (u32 *)outbuffer;
u32 *src = (u32 *)mixbuffer;
int done = 0;
// Always clear output buffer
memset(outbuffer, 0, len);
while ( ( mixtail != mixhead ) && ( done < len ) )
{
*dst++ = src[mixtail++];
if (mixtail == 4000) mixtail = 0;
done += 4;
}
// Realign to 32 bytes for DMA
mixtail -= ((done&0x1f) >> 2);
if (mixtail < 0)
mixtail += 4000;
done &= ~0x1f;
if (!done)
return len >> 1;
return done;
}
2008-09-02 03:57:21 +02:00
/****************************************************************************
* AudioSwitchBuffers
*
* Manages which buffer is played next
***************************************************************************/
static void AudioSwitchBuffers()
2008-09-02 03:57:21 +02:00
{
if ( !ConfigRequested )
{
2010-04-14 01:33:52 +02:00
whichab ^= 1;
int len = MixerCollect( soundbuffer[whichab], 3840 );
DCFlushRange(soundbuffer[whichab], len);
AUDIO_InitDMA((u32)soundbuffer[whichab], len);
IsPlaying = 1;
}
else IsPlaying = 0;
2008-09-02 03:57:21 +02:00
}
/****************************************************************************
* InitialiseAudio
*
* Initializes sound system on first load of emulator
***************************************************************************/
void InitialiseAudio()
2008-09-02 03:57:21 +02:00
{
#ifdef NO_SOUND
AUDIO_Init (NULL);
2010-05-27 23:08:02 +02:00
AUDIO_SetDSPSampleRate(AI_SAMPLERATE_48KHZ);
2009-07-01 19:39:55 +02:00
AUDIO_RegisterDMACallback(AudioSwitchBuffers);
#else
ASND_Init();
#endif
memset(soundbuffer, 0, 3840*2);
memset(mixbuffer, 0, 16000);
2008-09-02 03:57:21 +02:00
}
/****************************************************************************
* ResetAudio
*
* Reset audio output when loading a new game
***************************************************************************/
void ResetAudio()
{
memset(soundbuffer, 0, 3840*2);
memset(mixbuffer, 0, 16000);
mixhead = mixtail = 0;
}
2009-03-28 18:23:08 +01:00
/****************************************************************************
* SwitchAudioMode
*
* Switches between menu sound and emulator sound
***************************************************************************/
void
SwitchAudioMode(int mode)
{
if(mode == 0) // emulator
{
#ifndef NO_SOUND
ASND_Pause(1);
AUDIO_StopDMA();
2009-03-28 18:23:08 +01:00
AUDIO_RegisterDMACallback(AudioSwitchBuffers);
2010-05-21 03:36:10 +02:00
#endif
2010-04-14 01:33:52 +02:00
memset(soundbuffer[0],0,3840);
memset(soundbuffer[1],0,3840);
DCFlushRange(soundbuffer[0],3840);
DCFlushRange(soundbuffer[1],3840);
AUDIO_InitDMA((u32)soundbuffer[whichab],3200);
AUDIO_StartDMA();
2009-03-28 18:23:08 +01:00
}
else // menu
{
2009-03-28 19:26:47 +01:00
IsPlaying = 0;
2009-03-28 18:23:08 +01:00
#ifndef NO_SOUND
2009-06-13 19:43:24 +02:00
ASND_Init();
2009-03-28 18:23:08 +01:00
ASND_Pause(0);
2009-06-13 19:43:24 +02:00
#else
AUDIO_StopDMA();
2009-03-28 18:23:08 +01:00
#endif
}
}
/****************************************************************************
* ShutdownAudio
*
* Shuts down audio subsystem. Useful to avoid unpleasant sounds if a
* crash occurs during shutdown.
***************************************************************************/
void ShutdownAudio()
{
AUDIO_StopDMA();
}
/****************************************************************************
* PlaySound
2008-09-02 03:57:21 +02:00
*
* Puts incoming mono samples into mixbuffer
* Splits mono samples into two channels (stereo)
2008-09-02 03:57:21 +02:00
****************************************************************************/
void PlaySound( int *Buffer, int count )
2008-09-02 03:57:21 +02:00
{
int i;
u16 sample;
u32 *dst = (u32 *)mixbuffer;
for( i = 0; i < count; i++ )
{
sample = Buffer[i] & 0xffff;
dst[mixhead++] = sample | ( sample << 16);
if (mixhead == 4000)
mixhead = 0;
}
// Restart Sound Processing if stopped
if (IsPlaying == 0)
{
AudioSwitchBuffers ();
}
2008-09-02 03:57:21 +02:00
}