mirror of
https://github.com/dborth/snes9xgx.git
synced 2025-01-23 16:41:12 +01:00
rewritten audio code. a work-in-progress.
This commit is contained in:
parent
e67a58812b
commit
babf402d01
108
source/audio.cpp
108
source/audio.cpp
@ -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;
|
||||
}
|
||||
|
@ -485,6 +485,7 @@ DefaultSettings ()
|
||||
Settings.SoundPlaybackRate = 48000;
|
||||
Settings.SoundInputRate = 31950;
|
||||
Settings.DynamicRateControl = true;
|
||||
Settings.DynamicRateLimit = 1;
|
||||
|
||||
// Graphics
|
||||
Settings.Transparency = true;
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
||||
|
@ -388,6 +388,7 @@ struct SSettings
|
||||
bool8 ReverseStereo;
|
||||
bool8 Mute;
|
||||
bool8 DynamicRateControl;
|
||||
int32 DynamicRateLimit; /* Multiplied by 1000 */
|
||||
|
||||
bool8 SupportHiRes;
|
||||
bool8 Transparency;
|
||||
|
Loading…
x
Reference in New Issue
Block a user