rewritten audio code. a work-in-progress.

This commit is contained in:
Daryl Borth 2018-08-22 15:19:11 -06:00
parent e67a58812b
commit babf402d01
5 changed files with 58 additions and 91 deletions

View File

@ -29,65 +29,58 @@
#include "snes9x/spc7110.h"
#include "snes9x/controls.h"
extern int ScreenshotRequested;
extern int ConfigRequested;
/*** Double buffered audio ***/
#define SAMPLES_TO_PROCESS 1024
#define AUDIOBUFFER 2048
static unsigned char soundbuffer[2][AUDIOBUFFER] __attribute__ ((__aligned__ (32)));
static int whichab = 0; /*** Audio buffer flip switch ***/
#define BUFFERCOUNT 16
static u8 soundbuffer[BUFFERCOUNT][AUDIOBUFFER] __attribute__ ((__aligned__ (32)));
static int playab = 0;
static int nextab = 0;
int available = 0;
#define AUDIOSTACK 16384
static lwpq_t audioqueue;
static lwp_t athread;
static uint8 astack[AUDIOSTACK];
static mutex_t audiomutex = LWP_MUTEX_NULL;
static inline void updateAvailable(int diff) {
available += diff;
/****************************************************************************
* Audio Threading
***************************************************************************/
static void *
AudioThread (void *arg)
{
LWP_InitQueue (&audioqueue);
while (1)
{
if (ConfigRequested)
memset (soundbuffer[whichab], 0, AUDIOBUFFER);
else
{
LWP_MutexLock(audiomutex);
S9xMixSamples (soundbuffer[whichab], AUDIOBUFFER >> 1);
LWP_MutexUnlock(audiomutex);
if(available < 0) {
available = 0;
}
DCFlushRange (soundbuffer[whichab], AUDIOBUFFER);
LWP_ThreadSleep (audioqueue);
}
return NULL;
}
/****************************************************************************
* MixSamples
* This continually calls S9xMixSamples On each DMA Completion
***************************************************************************/
static void
GCMixSamples ()
{
if (!ConfigRequested)
{
whichab ^= 1;
AUDIO_InitDMA ((u32) soundbuffer[whichab], AUDIOBUFFER);
LWP_ThreadSignal (audioqueue);
else if(available > BUFFERCOUNT-1) {
available = BUFFERCOUNT-1;
}
}
static void FinalizeSamplesCallback (void *data)
{
LWP_MutexLock(audiomutex);
UpdatePlaybackRateWithDynamicRate();
static void DMACallback () {
if (!ScreenshotRequested && !ConfigRequested) {
AUDIO_InitDMA ((u32) soundbuffer[playab], AUDIOBUFFER);
updateAvailable(-1);
playab = (playab + 1) % BUFFERCOUNT;
}
}
static void S9xAudioCallback (void *data) {
//S9xUpdateDynamicRate(); // TODO: what arguments should be passed here?
S9xFinalizeSamples();
LWP_MutexUnlock(audiomutex);
int availableSamples = S9xGetSampleCount();
if (ScreenshotRequested || ConfigRequested) {
AUDIO_StopDMA();
}
else if(availableSamples >= SAMPLES_TO_PROCESS) {
nextab = (nextab + 1) % BUFFERCOUNT;
updateAvailable(1);
S9xMixSamples (soundbuffer[nextab], SAMPLES_TO_PROCESS);
DCFlushRange (soundbuffer[nextab], AUDIOBUFFER);
if(playab == -1) {
if(available > 2) {
playab = 0;
AUDIO_StartDMA();
}
}
}
}
/****************************************************************************
@ -99,12 +92,10 @@ InitAudio ()
#ifdef NO_SOUND
AUDIO_Init (NULL);
AUDIO_SetDSPSampleRate(AI_SAMPLERATE_48KHZ);
AUDIO_RegisterDMACallback(GCMixSamples);
AUDIO_RegisterDMACallback(DMACallback);
#else
ASND_Init();
#endif
LWP_MutexInit(&audiomutex, false);
LWP_CreateThread (&athread, AudioThread, NULL, astack, AUDIOSTACK, 70);
}
/****************************************************************************
@ -123,16 +114,9 @@ SwitchAudioMode(int mode)
AUDIO_StopDMA();
AUDIO_RegisterDMACallback(NULL);
DSP_Halt();
AUDIO_RegisterDMACallback(GCMixSamples);
AUDIO_RegisterDMACallback(DMACallback);
#endif
memset(soundbuffer[0],0,AUDIOBUFFER);
memset(soundbuffer[1],0,AUDIOBUFFER);
DCFlushRange(soundbuffer[0],AUDIOBUFFER);
DCFlushRange(soundbuffer[1],AUDIOBUFFER);
AUDIO_InitDMA((u32)soundbuffer[whichab],AUDIOBUFFER);
AUDIO_StartDMA();
S9xSetSamplesAvailableCallback(FinalizeSamplesCallback, NULL);
S9xSetSamplesAvailableCallback(S9xAudioCallback, NULL);
}
else // menu
{
@ -166,5 +150,7 @@ void ShutdownAudio()
void
AudioStart ()
{
GCMixSamples ();
available = 0;
nextab = 0;
playab = -1;
}

View File

@ -485,6 +485,7 @@ DefaultSettings ()
Settings.SoundPlaybackRate = 48000;
Settings.SoundInputRate = 31950;
Settings.DynamicRateControl = true;
Settings.DynamicRateLimit = 1;
// Graphics
Settings.Transparency = true;

View File

@ -387,27 +387,6 @@ int S9xGetSampleCount (void)
return (spc::resampler->avail() >> (Settings.Stereo ? 0 : 1));
}
#ifdef GEKKO
static double new_dynamic_rate_multiplier = 1.0;
void UpdatePlaybackRateWithDynamicRate() {
if(spc::dynamic_rate_multiplier != new_dynamic_rate_multiplier) {
spc::dynamic_rate_multiplier = new_dynamic_rate_multiplier;
UpdatePlaybackRate();
}
}
static inline void IncreaseDynamicRateMultiplier ()
{
new_dynamic_rate_multiplier = 1.01;
}
static inline void ResetDynamicRateMultiplier ()
{
new_dynamic_rate_multiplier = 1.0;
}
#endif
void S9xFinalizeSamples (void)
{
bool drop_current_msu1_samples = TRUE;
@ -420,7 +399,6 @@ void S9xFinalizeSamples (void)
{
/* We weren't able to process the entire buffer. Potential overrun. */
spc::sound_in_sync = FALSE;
S9xClearSamples();
if (Settings.SoundSync && !Settings.TurboMode)
return;
@ -452,13 +430,6 @@ void S9xFinalizeSamples (void)
else
spc::sound_in_sync = FALSE;
if(spc::sound_in_sync) {
ResetDynamicRateMultiplier ();
}
else {
IncreaseDynamicRateMultiplier ();
}
spc_core->set_output((SNES_SPC::sample_t *) spc::landing_buffer, spc::buffer_size >> 1);
}
@ -494,6 +465,14 @@ void S9xSetSamplesAvailableCallback (apu_callback callback, void *data)
spc::extra_data = data;
}
void S9xUpdateDynamicRate (int avail, int buffer_size)
{
spc::dynamic_rate_multiplier = 1.0 + (Settings.DynamicRateLimit * (buffer_size - 2 * avail)) /
(double)(1000 * buffer_size);
UpdatePlaybackRate();
}
void UpdatePlaybackRate (void)
{
if (Settings.SoundInputRate == 0)

View File

@ -211,10 +211,10 @@ void S9xSetSoundControl (uint8);
void S9xSetSoundMute (bool8);
void S9xLandSamples (void);
void S9xFinalizeSamples (void);
void UpdatePlaybackRateWithDynamicRate();
void S9xClearSamples (void);
bool8 S9xMixSamples (uint8 *, int);
void S9xSetSamplesAvailableCallback (apu_callback, void *);
void S9xUpdateDynamicRate (int, int);
extern SNES_SPC *spc_core;

View File

@ -388,6 +388,7 @@ struct SSettings
bool8 ReverseStereo;
bool8 Mute;
bool8 DynamicRateControl;
int32 DynamicRateLimit; /* Multiplied by 1000 */
bool8 SupportHiRes;
bool8 Transparency;