update audio core to match VBA-M (BUG: static added to GBA sound!)

This commit is contained in:
dborth 2009-01-10 08:03:58 +00:00
parent ad6f2134fc
commit 5dcdb7e86a
11 changed files with 159 additions and 140 deletions

View File

@ -13,6 +13,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "audio.h"
extern int ConfigRequested; extern int ConfigRequested;
/** Locals **/ /** Locals **/
@ -55,61 +57,17 @@ static int MIXER_GetSamples( u8 *dstbuffer, int maxlen )
static void AudioPlayer() static void AudioPlayer()
{ {
if ( !ConfigRequested ) if (IsPlaying)
{ {
int len = MIXER_GetSamples(soundbuffer[whichab], 3200); int len = MIXER_GetSamples(soundbuffer[whichab], 3200);
DCFlushRange(soundbuffer[whichab],len);
AUDIO_InitDMA((u32)soundbuffer[whichab],len); AUDIO_InitDMA((u32)soundbuffer[whichab],len);
AUDIO_StartDMA(); DCFlushRange(soundbuffer[whichab],len);
whichab ^= 1; whichab ^= 1;
IsPlaying = 1;
}
else
IsPlaying = 0;
}
/****************************************************************************
* MIXER_AddSamples
*
* Upsample from 11025 to 48000
* 11025 == 15052
* 22050 == 30106
* 44100 == 60211
*
* Audio officianados should look away now !
****************************************************************************/
void MIXER_AddSamples( u8 *sampledata, int len )
{
u32 *src = (u32 *)sampledata;
u32 *dst = (u32 *)mixerdata;
u32 intlen = (3200 >> 2);
u32 fixofs = 0;
u32 fixinc;
if ( !len )
fixinc = 30106;
else
fixinc = 60211;
do
{
// Do simple linear interpolate, and swap channels from L-R to R-L
dst[head++] = SWAP(src[fixofs >> 16]);
head &= MIXERMASK;
fixofs += fixinc;
}
while( --intlen );
// Restart Sound Processing if stopped
if (IsPlaying == 0)
{
ConfigRequested = 0;
AudioPlayer();
} }
} }
/**************************************************************************** /****************************************************************************
* MIXER_GetSamples * InitialiseSound
***************************************************************************/ ***************************************************************************/
void InitialiseSound() void InitialiseSound()
@ -122,21 +80,72 @@ void InitialiseSound()
} }
/**************************************************************************** /****************************************************************************
* MIXER_GetSamples * SoundDriver
***************************************************************************/ ***************************************************************************/
void ResetAudio() SoundWii::SoundWii()
{ {
memset(soundbuffer, 0, 3840*2); memset(soundbuffer, 0, 3840*2);
memset(mixerdata, 0, MIXBUFFSIZE); memset(mixerdata, 0, MIXBUFFSIZE);
AudioPlayer();
AUDIO_StartDMA();
} }
/**************************************************************************** /****************************************************************************
* MIXER_GetSamples * SoundWii::write
***************************************************************************/ *
* Upsample from 11025 to 48000
* 11025 == 15052
* 22050 == 30106
* 44100 == 60211
*
* Audio officianados should look away now !
****************************************************************************/
void StopAudio() void SoundWii::write(u16 * finalWave, int length)
{
u32 *src = (u32 *)finalWave;
u32 *dst = (u32 *)mixerdata;
u32 intlen = (3200 >> 2);
u32 fixofs = 0;
u32 fixinc;
if (length < 2940) // length = 1468 - GBA
fixinc = 30106;
else // length = 2940 - GB
fixinc = 60211;
do
{
// Do simple linear interpolate, and swap channels from L-R to R-L
dst[head++] = SWAP(src[fixofs >> 16]);
head &= MIXERMASK;
fixofs += fixinc;
}
while( --intlen );
}
bool SoundWii::init(long sampleRate)
{
return true;
}
SoundWii::~SoundWii()
{
}
void SoundWii::pause()
{ {
AUDIO_StopDMA(); AUDIO_StopDMA();
IsPlaying = 0; IsPlaying = 0;
} }
void SoundWii::resume()
{
AUDIO_StartDMA();
IsPlaying = 1;
}
void SoundWii::reset()
{
}

View File

@ -11,9 +11,21 @@
#ifndef __AUDIOMIXER__ #ifndef __AUDIOMIXER__
#define __AUDIOMIXER__ #define __AUDIOMIXER__
void MIXER_AddSamples( u8 *sampledata, int len ); #include "common/SoundDriver.h"
void StopAudio();
void ResetAudio();
void InitialiseSound(); void InitialiseSound();
class SoundWii: public SoundDriver
{
public:
SoundWii();
virtual ~SoundWii();
virtual bool init(long sampleRate);
virtual void pause();
virtual void reset();
virtual void resume();
virtual void write(u16 * finalWave, int length);
};
#endif #endif

View File

@ -13,7 +13,6 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <math.h> #include <math.h>
#include <ogcsys.h> #include <ogcsys.h>
#include <unistd.h> #include <unistd.h>
#include <wiiuse/wpad.h> #include <wiiuse/wpad.h>
@ -331,7 +330,6 @@ u32 GetJoy(int pad)
#endif #endif
) )
{ {
StopAudio();
ConfigRequested = 1; ConfigRequested = 1;
return 0; return 0;
} }

View File

@ -22,6 +22,8 @@ extern "C" {
} }
#endif #endif
#include "gba/Sound.h"
#include "vba.h" #include "vba.h"
#include "vbasupport.h" #include "vbasupport.h"
#include "preferences.h" #include "preferences.h"
@ -246,6 +248,7 @@ int main(int argc, char *argv[])
LWP_SuspendThread (devicethread); LWP_SuspendThread (devicethread);
ResetVideo_Emu(); ResetVideo_Emu();
soundResume();
while (emulating) // emulation loop while (emulating) // emulation loop
{ {
@ -259,6 +262,7 @@ int main(int argc, char *argv[])
if(ConfigRequested) if(ConfigRequested)
{ {
soundPause();
ResetVideo_Menu (); // change to menu video mode ResetVideo_Menu (); // change to menu video mode
if (GCSettings.AutoSave == 1) if (GCSettings.AutoSave == 1)
@ -277,7 +281,6 @@ int main(int argc, char *argv[])
// save zoom level // save zoom level
SavePrefs(SILENT); SavePrefs(SILENT);
ConfigRequested = 0; ConfigRequested = 0;
break; break;
} }

View File

@ -444,15 +444,10 @@ bool SaveBatteryOrState(int method, int action, bool silent)
* Sound * Sound
****************************************************************************/ ****************************************************************************/
void systemWriteDataToSoundBuffer() SoundDriver * systemSoundInit()
{ {
MIXER_AddSamples((u8 *)soundFinalWave, (cartridgeType == 1)); soundShutdown();
} return new SoundWii();
bool systemSoundInit()
{
ResetAudio();
return true;
} }
bool systemCanChangeSoundQuality() bool systemCanChangeSoundQuality()
@ -460,10 +455,13 @@ bool systemCanChangeSoundQuality()
return true; return true;
} }
void systemSoundPause() {} void systemOnWriteDataToSoundBuffer(const u16 * finalWave, int length)
void systemSoundResume() {} {
void systemSoundReset() {} }
void systemSoundShutdown() {}
void systemOnSoundShutdown()
{
}
/**************************************************************************** /****************************************************************************
* systemReadJoypads * systemReadJoypads
@ -773,8 +771,7 @@ bool LoadVBAROM(int method)
hAspect = 70; hAspect = 70;
vAspect = 46; vAspect = 46;
srcPitch = 484; srcPitch = 484;
soundQuality = 2; soundSetSampleRate(44100 / 2);
soundBufferLen = 736 * 2;
cpuSaveType = 0; cpuSaveType = 0;
break; break;
@ -807,8 +804,7 @@ bool LoadVBAROM(int method)
hAspect = 60; hAspect = 60;
vAspect = 46; vAspect = 46;
srcPitch = 324; srcPitch = 324;
soundQuality = 1; soundSetSampleRate(44100);
soundBufferLen = 1470 * 2;
break; break;
} }
@ -833,7 +829,6 @@ bool LoadVBAROM(int method)
LoadPatch(method); LoadPatch(method);
gbSoundReset(); gbSoundReset();
gbSoundSetQuality(soundQuality);
gbSoundSetDeclicking(true); gbSoundSetDeclicking(true);
gbReset(); gbReset();
} }
@ -851,7 +846,6 @@ bool LoadVBAROM(int method)
doMirroring(mirroringEnable); doMirroring(mirroringEnable);
soundReset(); soundReset();
soundSetQuality(soundQuality);
CPUInit("BIOS.GBA", 1); CPUInit("BIOS.GBA", 1);
LoadPatch(method); LoadPatch(method);
CPUReset(); CPUReset();

View File

@ -51,12 +51,9 @@ extern u32 systemReadJoypad(int);
extern u32 systemGetClock(); extern u32 systemGetClock();
extern void systemMessage(int, const char *, ...); extern void systemMessage(int, const char *, ...);
extern void systemSetTitle(const char *); extern void systemSetTitle(const char *);
extern void systemWriteDataToSoundBuffer(); extern SoundDriver * systemSoundInit();
extern void systemSoundShutdown(); extern void systemOnWriteDataToSoundBuffer(const u16 * finalWave, int length);
extern void systemSoundPause(); extern void systemOnSoundShutdown();
extern void systemSoundResume();
extern void systemSoundReset();
extern bool systemSoundInit();
extern void systemScreenMessage(const char *); extern void systemScreenMessage(const char *);
extern void systemUpdateMotionSensor(); extern void systemUpdateMotionSensor();
extern int systemGetSensorX(); extern int systemGetSensorX();

View File

@ -9,6 +9,7 @@
#include "../apu/Effects_Buffer.h" #include "../apu/Effects_Buffer.h"
extern int gbHardware; extern int gbHardware;
extern long soundSampleRate; // current sound quality
gb_effects_config_t gb_effects_config = { false, 0.20f, 0.15f, false }; gb_effects_config_t gb_effects_config = { false, 0.20f, 0.15f, false };
@ -50,22 +51,6 @@ static void end_frame( blip_time_t time )
stereo_buffer->end_frame( time ); stereo_buffer->end_frame( time );
} }
static void flush_samples()
{
// number of samples in output buffer
int const out_buf_size = soundBufferLen / sizeof *soundFinalWave;
// Keep filling and writing soundFinalWave until it can't be fully filled
while ( stereo_buffer->samples_avail() >= out_buf_size )
{
stereo_buffer->read_samples( (blip_sample_t*) soundFinalWave, out_buf_size );
if(soundPaused)
soundResume();
systemWriteDataToSoundBuffer();
}
}
static void apply_effects() static void apply_effects()
{ {
prevSoundEnable = soundGetEnable(); prevSoundEnable = soundGetEnable();
@ -106,7 +91,7 @@ void gbSoundTick()
// Run sound hardware to present // Run sound hardware to present
end_frame( SOUND_CLOCK_TICKS * ticks_to_time ); end_frame( SOUND_CLOCK_TICKS * ticks_to_time );
flush_samples(); flush_samples(stereo_buffer);
// Update effects config if it was changed // Update effects config if it was changed
if ( memcmp( &gb_effects_config_current, &gb_effects_config, if ( memcmp( &gb_effects_config_current, &gb_effects_config,
@ -141,7 +126,7 @@ static void remake_stereo_buffer()
stereo_buffer = 0; stereo_buffer = 0;
stereo_buffer = new Simple_Effects_Buffer; // TODO: handle out of memory stereo_buffer = new Simple_Effects_Buffer; // TODO: handle out of memory
if ( stereo_buffer->set_sample_rate( 44100 / soundQuality ) ) { } // TODO: handle out of memory if ( stereo_buffer->set_sample_rate( soundSampleRate ) ) { } // TODO: handle out of memory
stereo_buffer->clock_rate( gb_apu->clock_rate ); stereo_buffer->clock_rate( gb_apu->clock_rate );
// APU // APU
@ -231,19 +216,19 @@ void gbSoundReset()
} }
} }
void gbSoundSetQuality(int quality) void gbSoundSetSampleRate( long sampleRate )
{ {
if ( soundQuality != quality ) if ( soundSampleRate != sampleRate )
{ {
if ( systemCanChangeSoundQuality() ) if ( systemCanChangeSoundQuality() )
{ {
soundShutdown(); soundShutdown();
soundQuality = quality; soundSampleRate = sampleRate;
soundInit(); soundInit();
} }
else else
{ {
soundQuality = quality; soundSampleRate = sampleRate;
} }
remake_stereo_buffer(); remake_stereo_buffer();
@ -380,7 +365,7 @@ static void gbSoundReadGameOld(int version,gzFile gzFile)
if ( version >= 7 ) if ( version >= 7 )
quality = utilReadInt( gzFile ); quality = utilReadInt( gzFile );
gbSoundSetQuality( quality ); gbSoundSetSampleRate( 44100 / quality );
// Convert to format Gb_Apu uses // Convert to format Gb_Apu uses
gb_apu_state_t& s = state.apu; gb_apu_state_t& s = state.apu;

View File

@ -7,9 +7,7 @@
//// GB sound options //// GB sound options
// Sets sample rate to 44100 / quality void gbSoundSetSampleRate( long sampleRate );
void gbSoundSetQuality( int quality );
extern int soundQuality; // current sound quality
// Manages declicking mode. When enabled, clicks are reduced. Note that clicks // Manages declicking mode. When enabled, clicks are reduced. Note that clicks
// are normal for GB and GBC sound hardware. // are normal for GB and GBC sound hardware.

View File

@ -1951,9 +1951,9 @@ void CPUSoftwareInterrupt(int comment)
} }
#endif #endif
if(reg[0].I) if(reg[0].I)
systemSoundPause(); soundPause();
else else
systemSoundResume(); soundResume();
break; break;
case 0x1F: case 0x1F:
BIOS_MidiKey2Freq(); BIOS_MidiKey2Freq();

View File

@ -10,6 +10,8 @@
#include "../apu/Gb_Apu.h" #include "../apu/Gb_Apu.h"
#include "../apu/Multi_Buffer.h" #include "../apu/Multi_Buffer.h"
#include "../common/SoundDriver.h"
#define NR10 0x60 #define NR10 0x60
#define NR11 0x62 #define NR11 0x62
#define NR12 0x63 #define NR12 0x63
@ -32,21 +34,21 @@
#define NR51 0x81 #define NR51 0x81
#define NR52 0x84 #define NR52 0x84
SoundDriver * soundDriver = 0;
extern bool stopState; // TODO: silence sound when true extern bool stopState; // TODO: silence sound when true
int const SOUND_CLOCK_TICKS_ = 167772; // 1/100 second int const SOUND_CLOCK_TICKS_ = 167772; // 1/100 second
u16 soundFinalWave [1470]; static u16 soundFinalWave [1600];
int soundBufferLen = sizeof soundFinalWave; long soundSampleRate = 44100;
int soundQuality = 1;
bool soundInterpolation = true; bool soundInterpolation = true;
bool soundPaused = true; bool soundPaused = true;
float soundFiltering = 0.5f; float soundFiltering = 0.5f;
float soundVolume = 1.0f;
bool soundEcho = false;
int SOUND_CLOCK_TICKS = SOUND_CLOCK_TICKS_; int SOUND_CLOCK_TICKS = SOUND_CLOCK_TICKS_;
int soundTicks = SOUND_CLOCK_TICKS_; int soundTicks = SOUND_CLOCK_TICKS_;
static float soundVolume = 1.0f;
static int soundEnableFlag = 0x3ff; // emulator channels enabled static int soundEnableFlag = 0x3ff; // emulator channels enabled
static float soundFiltering_ = -1; static float soundFiltering_ = -1;
static float soundVolume_ = -1; static float soundVolume_ = -1;
@ -344,8 +346,14 @@ static void end_frame( blip_time_t time )
stereo_buffer->end_frame( time ); stereo_buffer->end_frame( time );
} }
static void flush_samples() void flush_samples(Multi_Buffer * buffer)
{ {
// We want to write the data frame by frame to support legacy audio drivers
// that don't use the length parameter of the write method.
// TODO: Update the Win32 audio drivers (DS, OAL, XA2), and flush all the
// samples at once to help reducing the audio delay on all platforms.
int soundBufferLen = ( soundSampleRate / 60 ) * 4;
// soundBufferLen should have a whole number of sample pairs // soundBufferLen should have a whole number of sample pairs
assert( soundBufferLen % (2 * sizeof *soundFinalWave) == 0 ); assert( soundBufferLen % (2 * sizeof *soundFinalWave) == 0 );
@ -353,13 +361,14 @@ static void flush_samples()
int const out_buf_size = soundBufferLen / sizeof *soundFinalWave; int const out_buf_size = soundBufferLen / sizeof *soundFinalWave;
// Keep filling and writing soundFinalWave until it can't be fully filled // Keep filling and writing soundFinalWave until it can't be fully filled
while ( stereo_buffer->samples_avail() >= out_buf_size ) while ( buffer->samples_avail() >= out_buf_size )
{ {
stereo_buffer->read_samples( (blip_sample_t*) soundFinalWave, out_buf_size ); buffer->read_samples( (blip_sample_t*) soundFinalWave, out_buf_size );
if(soundPaused) if(soundPaused)
soundResume(); soundResume();
systemWriteDataToSoundBuffer(); soundDriver->write(soundFinalWave, soundBufferLen);
systemOnWriteDataToSoundBuffer(soundFinalWave, soundBufferLen);
} }
} }
@ -386,7 +395,7 @@ void psoundTickfn()
// Run sound hardware to present // Run sound hardware to present
end_frame( SOUND_CLOCK_TICKS ); end_frame( SOUND_CLOCK_TICKS );
flush_samples(); flush_samples(stereo_buffer);
if ( soundFiltering_ != soundFiltering ) if ( soundFiltering_ != soundFiltering )
apply_filtering(); apply_filtering();
@ -442,8 +451,7 @@ static void remake_stereo_buffer()
stereo_buffer = 0; stereo_buffer = 0;
stereo_buffer = new Stereo_Buffer; // TODO: handle out of memory stereo_buffer = new Stereo_Buffer; // TODO: handle out of memory
long const sample_rate = 44100 / soundQuality; stereo_buffer->set_sample_rate( soundSampleRate ); // TODO: handle out of memory
stereo_buffer->set_sample_rate( sample_rate ); // TODO: handle out of memory
stereo_buffer->clock_rate( gb_apu->clock_rate ); stereo_buffer->clock_rate( gb_apu->clock_rate );
// PCM // PCM
@ -464,19 +472,27 @@ static void remake_stereo_buffer()
void soundShutdown() void soundShutdown()
{ {
systemSoundShutdown(); if (soundDriver)
{
delete soundDriver;
soundDriver = 0;
}
systemOnSoundShutdown();
} }
void soundPause() void soundPause()
{ {
soundPaused = true; soundPaused = true;
systemSoundPause(); if (soundDriver)
soundDriver->pause();
} }
void soundResume() void soundResume()
{ {
soundPaused = false; soundPaused = false;
systemSoundResume(); if (soundDriver)
soundDriver->resume();
} }
void soundSetVolume( float volume ) void soundSetVolume( float volume )
@ -502,7 +518,7 @@ int soundGetEnable()
void soundReset() void soundReset()
{ {
systemSoundReset(); soundDriver->reset();
remake_stereo_buffer(); remake_stereo_buffer();
reset_apu(); reset_apu();
@ -516,26 +532,35 @@ void soundReset()
bool soundInit() bool soundInit()
{ {
if ( !systemSoundInit() ) soundDriver = systemSoundInit();
if ( !soundDriver )
return false;
if (!soundDriver->init(soundSampleRate))
return false; return false;
soundPaused = true; soundPaused = true;
return true; return true;
} }
void soundSetQuality(int quality) long soundGetSampleRate()
{ {
if ( soundQuality != quality ) return soundSampleRate;
}
void soundSetSampleRate(long sampleRate)
{
if ( soundSampleRate != sampleRate )
{ {
if ( systemCanChangeSoundQuality() ) if ( systemCanChangeSoundQuality() )
{ {
soundShutdown(); soundShutdown();
soundQuality = quality; soundSampleRate = sampleRate;
soundInit(); soundInit();
} }
else else
{ {
soundQuality = quality; soundSampleRate = sampleRate;
} }
remake_stereo_buffer(); remake_stereo_buffer();

View File

@ -33,16 +33,10 @@ extern bool soundPaused; // current paused state
// Cleans up sound. Afterwards, soundInit() can be called again. // Cleans up sound. Afterwards, soundInit() can be called again.
void soundShutdown(); void soundShutdown();
// Sound buffering
extern int soundBufferLen; // size of sound buffer in BYTES
extern u16 soundFinalWave[1470];// 16-bit SIGNED stereo sample buffer
//// GBA sound options //// GBA sound options
// Sets sample rate to 44100 / quality long soundGetSampleRate();
void soundSetQuality( int quality ); void soundSetSampleRate(long sampleRate);
extern int soundQuality; // current sound quality
// Sound settings // Sound settings
extern bool soundInterpolation; // 1 if PCM should have low-pass filtering extern bool soundInterpolation; // 1 if PCM should have low-pass filtering
@ -80,4 +74,8 @@ extern int soundTicks; // Number of 16.8 MHz clocks until soundTick() w
void soundSaveGame( gzFile ); void soundSaveGame( gzFile );
void soundReadGame( gzFile, int version ); void soundReadGame( gzFile, int version );
class Multi_Buffer;
void flush_samples(Multi_Buffer * buffer);
#endif // SOUND_H #endif // SOUND_H