mirror of
https://github.com/dborth/snes9xgx.git
synced 2024-11-30 14:34:22 +01:00
6a045e6441
audio buffer
170 lines
3.8 KiB
C++
170 lines
3.8 KiB
C++
/****************************************************************************
|
|
* Snes9x Nintendo Wii/Gamecube Port
|
|
*
|
|
* softdev July 2006
|
|
* Tantric 2008-2010
|
|
*
|
|
* audio.cpp
|
|
*
|
|
* Audio driver
|
|
* Audio is fixed to 32Khz/16bit/Stereo
|
|
***************************************************************************/
|
|
|
|
#include <gccore.h>
|
|
#include <ogcsys.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <asndlib.h>
|
|
|
|
#include "video.h"
|
|
|
|
#include "snes9x/snes9x.h"
|
|
#include "snes9x/memmap.h"
|
|
#include "snes9x/cpuexec.h"
|
|
#include "snes9x/ppu.h"
|
|
#include "snes9x/apu/apu.h"
|
|
#include "snes9x/display.h"
|
|
#include "snes9x/gfx.h"
|
|
#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
|
|
#define BUFFERCOUNT 16
|
|
static u8 soundbuffer[BUFFERCOUNT][AUDIOBUFFER] __attribute__ ((__aligned__ (32)));
|
|
static int playab = 0;
|
|
static int nextab = 0;
|
|
static int unplayed = 0;
|
|
|
|
static inline void updateUnplayed(int diff) {
|
|
unplayed += diff;
|
|
|
|
if(unplayed < 0) {
|
|
unplayed = 0;
|
|
}
|
|
else if(unplayed > BUFFERCOUNT-1) {
|
|
unplayed = BUFFERCOUNT-1;
|
|
}
|
|
}
|
|
|
|
static void DMACallback () {
|
|
if (!ScreenshotRequested && !ConfigRequested) {
|
|
updateUnplayed(-1);
|
|
AUDIO_InitDMA ((u32) soundbuffer[playab], AUDIOBUFFER);
|
|
playab = (playab + 1) % BUFFERCOUNT;
|
|
}
|
|
}
|
|
|
|
static void S9xAudioCallback (void *data) {
|
|
double rate = 1.0;
|
|
|
|
if(unplayed > 8) {
|
|
rate = 1.005;
|
|
}
|
|
else if(unplayed < 4) {
|
|
rate = 0.995;
|
|
}
|
|
|
|
S9xUpdateDynamicRate(rate);
|
|
S9xFinalizeSamples();
|
|
|
|
if (ScreenshotRequested || ConfigRequested) {
|
|
AUDIO_StopDMA();
|
|
}
|
|
else if(S9xGetSampleCount() >= SAMPLES_TO_PROCESS) {
|
|
S9xMixSamples (soundbuffer[nextab], SAMPLES_TO_PROCESS);
|
|
DCFlushRange (soundbuffer[nextab], AUDIOBUFFER);
|
|
updateUnplayed(1);
|
|
nextab = (nextab + 1) % BUFFERCOUNT;
|
|
|
|
if(!Settings.TurboMode && ((nextab + 1) % BUFFERCOUNT) == playab) {
|
|
// quick and dirty attempt to prevent reading and writing from/to the same buffer
|
|
nextab = (nextab + BUFFERCOUNT/2) % BUFFERCOUNT;
|
|
}
|
|
|
|
if(playab == -1) {
|
|
if(unplayed > 2) {
|
|
playab = 0;
|
|
AUDIO_StartDMA();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/****************************************************************************
|
|
* InitAudio
|
|
***************************************************************************/
|
|
void
|
|
InitAudio ()
|
|
{
|
|
#ifdef NO_SOUND
|
|
AUDIO_Init (NULL);
|
|
AUDIO_SetDSPSampleRate(AI_SAMPLERATE_48KHZ);
|
|
AUDIO_RegisterDMACallback(DMACallback);
|
|
#else
|
|
ASND_Init();
|
|
#endif
|
|
}
|
|
|
|
/****************************************************************************
|
|
* SwitchAudioMode
|
|
*
|
|
* Switches between menu sound and emulator sound
|
|
***************************************************************************/
|
|
void
|
|
SwitchAudioMode(int mode)
|
|
{
|
|
if(mode == 0) // emulator
|
|
{
|
|
#ifndef NO_SOUND
|
|
ASND_Pause(1);
|
|
ASND_End();
|
|
AUDIO_StopDMA();
|
|
AUDIO_RegisterDMACallback(NULL);
|
|
DSP_Halt();
|
|
AUDIO_RegisterDMACallback(DMACallback);
|
|
#endif
|
|
S9xSetSamplesAvailableCallback(S9xAudioCallback, NULL);
|
|
}
|
|
else // menu
|
|
{
|
|
S9xSetSamplesAvailableCallback(NULL, NULL);
|
|
#ifndef NO_SOUND
|
|
DSP_Unhalt();
|
|
ASND_Init();
|
|
ASND_Pause(0);
|
|
#else
|
|
AUDIO_StopDMA();
|
|
#endif
|
|
}
|
|
}
|
|
|
|
/****************************************************************************
|
|
* ShutdownAudio
|
|
*
|
|
* Shuts down audio subsystem. Useful to avoid unpleasant sounds if a
|
|
* crash occurs during shutdown.
|
|
***************************************************************************/
|
|
void ShutdownAudio()
|
|
{
|
|
AUDIO_StopDMA();
|
|
}
|
|
|
|
/****************************************************************************
|
|
* AudioStart
|
|
*
|
|
* Called to kick off the Audio Queue
|
|
***************************************************************************/
|
|
void
|
|
AudioStart ()
|
|
{
|
|
unplayed = 0;
|
|
nextab = 0;
|
|
playab = -1;
|
|
}
|