Sound System Rework: Phase 2 (cont'ed)

. Fixed super fast refresh rate issue

. Recovered <TAB> shortcut key for ThrottleSkipping

. Removed redundant "soundstream->Update()" in DSPLLE
  (Thanks to LordMark)


git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@4728 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
ayuanx 2009-12-25 11:59:04 +00:00
parent eddafd450e
commit 06218e9ebb
20 changed files with 96 additions and 139 deletions

View File

@ -111,7 +111,7 @@ void DSound::SoundLoop()
int numBytesToRender = FIX128(ModBufferSize(currentPos - lastPos));
if (numBytesToRender >= 256)
{
if (numBytesToRender > sizeof(realtimeBuffer) * sizeof(short))
if (numBytesToRender > sizeof(realtimeBuffer))
PanicAlert("soundThread: too big render call");
m_mixer->Mix(realtimeBuffer, numBytesToRender / 4);
WriteDataToBuffer(lastPos, (char*)realtimeBuffer, numBytesToRender);

View File

@ -17,7 +17,6 @@
#include "Atomic.h"
#include "Mixer.h"
#include "AudioCommon.h"
@ -41,37 +40,13 @@ unsigned int CMixer::Mix(short* samples, unsigned int numSamples)
numLeft = (numLeft > numSamples) ? numSamples : numLeft;
// Do re-sampling if needed
if (m_sampleRate == m_dspSampleRate)
if (m_sampleRate == 32000)
{
for (unsigned int i = 0; i < numLeft * 2; i++)
samples[i] = Common::swap16(m_buffer[(m_indexR + i) & INDEX_MASK]);
m_indexR += numLeft * 2;
}
else if (m_sampleRate < m_dspSampleRate) // If down-sampling needed
{
_dbg_assert_msg_(DSPHLE, !(numSamples % 2), "Number of Samples: %i must be even!", numSamples);
short *pDest = samples;
int last_l, last_r, cur_l, cur_r;
for (unsigned int i = 0; i < numLeft * 3 / 2; i++)
{
cur_l = Common::swap16(m_buffer[(m_indexR + i * 2) & INDEX_MASK]);
cur_r = Common::swap16(m_buffer[(m_indexR + i * 2 + 1) & INDEX_MASK]);
if (i % 3)
{
*pDest++ = (last_l + cur_r) / 2;
*pDest++ = (last_r + cur_r) / 2;
}
last_l = cur_l;
last_r = cur_r;
}
m_indexR += numLeft * 2 * 3 / 2;
}
else if (m_sampleRate > m_dspSampleRate)
else
{
// AyuanX: Up-sampling is not implemented yet
PanicAlert("Mixer: Up-sampling is not implemented yet!");
@ -143,16 +118,8 @@ unsigned int CMixer::Mix(short* samples, unsigned int numSamples)
if (numSamples > numLeft)
memset(&samples[numLeft * 2], 0, (numSamples - numLeft) * 4);
// Add the HLE sound
if (m_sampleRate < m_dspSampleRate)
{
PanicAlert("Mixer: DSPHLE down-sampling is not implemented yet!\n"
"Usually no game should require this, please report!");
}
else
{
Premix(samples, numSamples, m_sampleRate);
}
// Add the DSPHLE sound, re-sampling is done inside
Premix(samples, numSamples);
// Add the DTK Music
if (m_EnableDTKMusic)
@ -161,19 +128,17 @@ unsigned int CMixer::Mix(short* samples, unsigned int numSamples)
g_dspInitialize.pGetAudioStreaming(samples, numSamples, m_sampleRate);
}
Common::AtomicAdd(m_numSamples, -(int)numLeft);
Common::AtomicAdd(m_numSamples, -(s32)numLeft);
return numSamples;
}
void CMixer::PushSamples(short *samples, unsigned int num_samples, unsigned int sample_rate)
void CMixer::PushSamples(short *samples, unsigned int num_samples)
{
// The auto throttle function. This loop will put a ceiling on the CPU MHz.
if (m_throttle)
{
// AyuanX: Remember to reserve "num_samples * 1.5" free sample space at least!
// Becuse we may do re-sampling later
while (Common::AtomicLoad(m_numSamples) >= MAX_SAMPLES - RESERVED_SAMPLES)
{
if (g_dspInitialize.pEmulatorState)
@ -181,8 +146,12 @@ void CMixer::PushSamples(short *samples, unsigned int num_samples, unsigned int
if (*g_dspInitialize.pEmulatorState != 0)
break;
}
soundStream->Update();
// Shortcut key for Throttle Skipping
#ifdef _WIN32
if (GetAsyncKeyState(VK_TAB)) break;;
#endif
SLEEP(1);
soundStream->Update();
}
}
@ -191,7 +160,7 @@ void CMixer::PushSamples(short *samples, unsigned int num_samples, unsigned int
return;
// AyuanX: Actual re-sampling work has been moved to sound thread
// to alleviates the workload on main thread
// to alleviate the workload on main thread
// and we simply store raw data here to make fast mem copy
int over_bytes = num_samples * 4 - (MAX_SAMPLES * 2 - (m_indexW & INDEX_MASK)) * sizeof(short);
if (over_bytes > 0)
@ -206,12 +175,7 @@ void CMixer::PushSamples(short *samples, unsigned int num_samples, unsigned int
m_indexW += num_samples * 2;
if (m_sampleRate < m_dspSampleRate)
{
// This is kind of tricky :P
num_samples = num_samples * 2 / 3;
}
else if (m_sampleRate > m_dspSampleRate)
if (m_sampleRate != 32000)
{
PanicAlert("Mixer: Up-sampling is not implemented yet!");
}

View File

@ -19,16 +19,16 @@
#define _MIXER_H_
// 16 bit Stereo
#define MAX_SAMPLES (1024 * 4)
#define MAX_SAMPLES (1024 * 8)
#define INDEX_MASK (MAX_SAMPLES * 2 - 1)
#define RESERVED_SAMPLES (MAX_SAMPLES / 8)
#define RESERVED_SAMPLES (256)
class CMixer {
public:
CMixer(unsigned int AISampleRate = 48000, unsigned int DSPSampleRate = 48000)
CMixer(unsigned int AISampleRate = 48000, unsigned int DACSampleRate = 48000)
: m_aiSampleRate(AISampleRate)
, m_dspSampleRate(DSPSampleRate)
, m_dacSampleRate(DACSampleRate)
, m_bits(16)
, m_channels(2)
, m_HLEready(false)
@ -36,19 +36,21 @@ public:
, m_indexW(0)
, m_indexR(0)
{
// AyuanX: When sample rate differs, we have to do re-sampling
// AyuanX: The internal (Core & DSP) sample rate is fixed at 32KHz
// So when AI/DAC sample rate differs than 32KHz, we have to do re-sampling
// I perfer speed so let's do down-sampling instead of up-sampling
// If you like better sound than speed, feel free to implement the up-sampling code
m_sampleRate = (m_aiSampleRate < m_dspSampleRate) ? m_aiSampleRate : m_dspSampleRate;
m_sampleRate = 32000;
NOTICE_LOG(AUDIO_INTERFACE, "Mixer is initialized (AISampleRate:%i, DACSampleRate:%i)", AISampleRate, DACSampleRate);
}
// Called from audio threads
virtual unsigned int Mix(short* samples, unsigned int numSamples);
virtual void Premix(short *samples, unsigned int numSamples, unsigned int sampleRate) {}
virtual void Premix(short *samples, unsigned int numSamples) {}
unsigned int GetNumSamples();
// Called from main thread
virtual void PushSamples(short* samples, unsigned int num_samples, unsigned int sample_rate);
virtual void PushSamples(short* samples, unsigned int num_samples);
unsigned int GetSampleRate() {return m_sampleRate;}
void SetThrottle(bool use) { m_throttle = use;}
@ -62,7 +64,7 @@ public:
protected:
unsigned int m_sampleRate;
unsigned int m_aiSampleRate;
unsigned int m_dspSampleRate;
unsigned int m_dacSampleRate;
int m_bits;
int m_channels;

View File

@ -25,7 +25,7 @@ class NullMixer : public CMixer {
public:
virtual unsigned int Mix(short *samples, unsigned int numSamples) { return 0; }
virtual void PushSamples(short* samples, unsigned int num_samples, unsigned int sample_rate) {}
virtual void PushSamples(short* samples, unsigned int num_samples) {}
};
class NullSound : public SoundStream

View File

@ -35,9 +35,9 @@
#endif // WIN32
// 16 bit Stereo
#define SFX_MAX_SOURCE 1
#define OAL_NUM_BUFFERS 8
#define OAL_NUM_BUFFERS 16
#define OAL_MAX_SAMPLES 512 // AyuanX: Don't make it too large, as larger buffer means longer delay
#define OAL_THRESHOLD 128
#define OAL_THRESHOLD 128 // Some games are quite sensitive to delay
#endif
class OpenALStream: public SoundStream

View File

@ -27,7 +27,7 @@ typedef void (__cdecl* TDSP_WriteMailBox)(bool _CPUMailbox, unsigned short);
typedef unsigned short (__cdecl* TDSP_ReadMailBox)(bool _CPUMailbox);
typedef unsigned short (__cdecl* TDSP_ReadControlRegister)();
typedef unsigned short (__cdecl* TDSP_WriteControlRegister)(unsigned short);
typedef void (__cdecl *TDSP_SendAIBuffer)(unsigned int address, unsigned int num_samples, unsigned int sample_rate);
typedef void (__cdecl *TDSP_SendAIBuffer)(unsigned int address, unsigned int num_samples);
typedef void (__cdecl *TDSP_Update)(int cycles);
typedef void (__cdecl *TDSP_StopSoundStream)();
typedef void (__cdecl *TDSP_ClearAudioBuffer)();

View File

@ -700,7 +700,7 @@ void Callback_VideoCopiedToXFB(bool video_update)
while (Timer.GetTimeDifference() < wait_frametime * frames)
{
if (no_framelimit==0)
if (no_framelimit == 0)
Common::SleepCurrentThread(1);
}
}

View File

@ -54,13 +54,13 @@ union AICR
struct
{
unsigned PSTAT : 1; // sample counter/playback enable
unsigned AFR : 1; // AI Frequency (0=32khz 1=48khz)
unsigned AIFR : 1; // AI Frequency (0=32khz 1=48khz)
unsigned AIINTMSK : 1; // 0=interrupt masked 1=interrupt enabled
unsigned AIINT : 1; // audio interrupt status
unsigned AIINTVLD : 1; // This bit controls whether AIINT is affected by the AIIT register
// matching AISLRCNT. Once set, AIINT will hold
unsigned SCRESET : 1; // write to reset counter
unsigned DSPFR : 1; // DSP Frequency (0=48khz 1=32khz)
unsigned DACFR : 1; // DAC Frequency (0=48khz 1=32khz)
unsigned :25;
};
u32 hex;
@ -90,16 +90,16 @@ struct SAudioRegister
// STATE_TO_SAVE
static SAudioRegister g_AudioRegister;
static u64 g_LastCPUTime = 0;
static unsigned int g_SampleRate = 32000;
static unsigned int g_DSPSampleRate = 32000;
static unsigned int g_AISampleRate = 32000;
static unsigned int g_DACSampleRate = 32000;
static u64 g_CPUCyclesPerSample = 0xFFFFFFFFFFFULL;
void DoState(PointerWrap &p)
{
p.Do(g_AudioRegister);
p.Do(g_LastCPUTime);
p.Do(g_SampleRate);
p.Do(g_DSPSampleRate);
p.Do(g_AISampleRate);
p.Do(g_DACSampleRate);
p.Do(g_CPUCyclesPerSample);
}
@ -111,7 +111,7 @@ void ReadStreamBlock(short* _pPCM);
void Init()
{
g_AudioRegister.m_SampleCounter = 0;
g_AudioRegister.m_Control.AFR = 1;
g_AudioRegister.m_Control.AIFR = 1;
}
void Shutdown()
@ -169,22 +169,22 @@ void Write32(const u32 _Value, const u32 _Address)
g_AudioRegister.m_Control.AIINTVLD = tmpAICtrl.AIINTVLD;
// Set frequency
if (tmpAICtrl.AFR != g_AudioRegister.m_Control.AFR)
if (tmpAICtrl.AIFR != g_AudioRegister.m_Control.AIFR)
{
INFO_LOG(AUDIO_INTERFACE, "Change Freq to %s", tmpAICtrl.AFR ? "48khz":"32khz");
g_AudioRegister.m_Control.AFR = tmpAICtrl.AFR;
INFO_LOG(AUDIO_INTERFACE, "Change Freq to %s", tmpAICtrl.AIFR ? "48khz":"32khz");
g_AudioRegister.m_Control.AIFR = tmpAICtrl.AIFR;
}
// Set DSP frequency
if (tmpAICtrl.DSPFR != g_AudioRegister.m_Control.DSPFR)
if (tmpAICtrl.DACFR != g_AudioRegister.m_Control.DACFR)
{
INFO_LOG(AUDIO_INTERFACE, "AI_CONTROL_REGISTER: Change DSPFR Freq to %s", tmpAICtrl.DSPFR ? "48khz":"32khz");
g_AudioRegister.m_Control.DSPFR = tmpAICtrl.DSPFR;
INFO_LOG(AUDIO_INTERFACE, "AI_CONTROL_REGISTER: Change DSPFR Freq to %s", tmpAICtrl.DACFR ? "48khz":"32khz");
g_AudioRegister.m_Control.DACFR = tmpAICtrl.DACFR;
}
g_SampleRate = tmpAICtrl.AFR ? 48000 : 32000;
g_DSPSampleRate = tmpAICtrl.DSPFR ? 32000 : 48000;
g_AISampleRate = tmpAICtrl.AIFR ? 48000 : 32000;
g_DACSampleRate = tmpAICtrl.DACFR ? 32000 : 48000;
g_CPUCyclesPerSample = SystemTimers::GetTicksPerSecond() / g_SampleRate;
g_CPUCyclesPerSample = SystemTimers::GetTicksPerSecond() / g_AISampleRate;
// Streaming counter
if (tmpAICtrl.PSTAT != g_AudioRegister.m_Control.PSTAT)
@ -264,10 +264,10 @@ void GenerateAudioInterrupt()
UpdateInterrupts();
}
void Callback_GetSampleRate(unsigned int &_AISampleRate, unsigned int &_DSPSampleRate)
void Callback_GetSampleRate(unsigned int &_AISampleRate, unsigned int &_DACSampleRate)
{
_AISampleRate = g_SampleRate;
_DSPSampleRate = g_DSPSampleRate;
_AISampleRate = g_AISampleRate;
_DACSampleRate = g_DACSampleRate;
}
// Callback for the disc streaming
@ -282,12 +282,12 @@ unsigned int Callback_GetStreaming(short* _pDestBuffer, unsigned int _numSamples
const int rvolume = g_AudioRegister.m_Volume.rightVolume;
if (g_SampleRate == 48000 && _sampleRate == 32000)
if (g_AISampleRate == 48000 && _sampleRate == 32000)
{
_dbg_assert_msg_(AUDIO_INTERFACE, !(_numSamples % 2), "Number of Samples: %i must be even!", _numSamples);
_numSamples = _numSamples * 3 / 2;
}
else if (g_SampleRate == 32000 && _sampleRate == 48000)
else if (g_AISampleRate == 32000 && _sampleRate == 48000)
{
// AyuanX: Up-sampling is not implemented yet
PanicAlert("AUDIO_INTERFACE: Up-sampling is not implemented yet!");
@ -299,7 +299,7 @@ unsigned int Callback_GetStreaming(short* _pDestBuffer, unsigned int _numSamples
if (pos == 0)
ReadStreamBlock(pcm);
if (g_SampleRate == 48000 && _sampleRate == 32000)
if (g_AISampleRate == 48000 && _sampleRate == 32000)
{
if (i % 3)
{
@ -393,16 +393,6 @@ void IncreaseSampleCount(const u32 _iAmount)
}
}
unsigned int GetAISampleRate()
{
return g_SampleRate;
}
unsigned int GetDSPSampleRate()
{
return g_DSPSampleRate;
}
void Update()
{
// update timer

View File

@ -34,16 +34,12 @@ void DoState(PointerWrap &p);
void Update();
// Called by DSP plugin
void Callback_GetSampleRate(unsigned int &_AISampleRate, unsigned int &_DSPSampleRate);
void Callback_GetSampleRate(unsigned int &_AISampleRate, unsigned int &_DACSampleRate);
unsigned int Callback_GetStreaming(short* _pDestBuffer, unsigned int _numSamples, unsigned int _sampleRate = 48000);
void Read32(u32& _uReturnValue, const u32 _iAddress);
void Write32(const u32 _iValue, const u32 _iAddress);
// Get the audio rates (48000 or 32000 only)
unsigned int GetAISampleRate();
unsigned int GetDSPSampleRate();
} // namespace
#endif

View File

@ -484,17 +484,17 @@ void UpdateAudioDMA()
// AyuanX: let's do it in a bundle to speed up
if (g_audioDMA.BlocksLeft == g_audioDMA.AudioDMAControl.NumBlocks)
dsp_plugin->DSP_SendAIBuffer(g_audioDMA.SourceAddress, g_audioDMA.AudioDMAControl.NumBlocks * 8, AudioInterface::GetDSPSampleRate());
dsp_plugin->DSP_SendAIBuffer(g_audioDMA.SourceAddress, g_audioDMA.AudioDMAControl.NumBlocks * 8);
// g_audioDMA.ReadAddress += 32;
g_audioDMA.BlocksLeft--;
if (g_audioDMA.BlocksLeft == 0)
{
GenerateDSPInterrupt(DSP::INT_AID);
// g_audioDMA.ReadAddress = g_audioDMA.SourceAddress;
g_audioDMA.BlocksLeft = g_audioDMA.AudioDMAControl.NumBlocks;
// DEBUG_LOG(DSPLLE, "ADMA read addresses: %08x", g_audioDMA.ReadAddress);
GenerateDSPInterrupt(DSP::INT_AID);
}
}
else

View File

@ -112,7 +112,7 @@ int et_Dec;
int et_VI;
int et_SI;
int et_AI;
int et_AudioFifo;
int et_AudioDMA;
int et_DSP;
int et_IPC_HLE;
int et_FakeGPWD; // DC watchdog hack
@ -127,6 +127,9 @@ int
// These shouldn't be period controlled either, most likely.
DSP_PERIOD,
// This is a fixed value, don't change it
AUDIO_DMA_PERIOD,
// This is completely arbitrary. If we find that we need lower latency, we can just
// increase this number.
IPC_HLE_PERIOD,
@ -165,12 +168,10 @@ void DSPCallback(u64 userdata, int cyclesLate)
CoreTiming::ScheduleEvent(DSP_PERIOD - cyclesLate, et_DSP);
}
void AudioFifoCallback(u64 userdata, int cyclesLate)
void AudioDMACallback(u64 userdata, int cyclesLate)
{
int period = CPU_CORE_CLOCK / (AudioInterface::GetDSPSampleRate() * 4 / 32);
DSP::UpdateAudioDMA(); // Push audio to speakers.
CoreTiming::ScheduleEvent(period - cyclesLate, et_AudioFifo);
CoreTiming::ScheduleEvent(AUDIO_DMA_PERIOD - cyclesLate, et_AudioDMA);
}
void IPC_HLE_UpdateCallback(u64 userdata, int cyclesLate)
@ -275,6 +276,9 @@ void Init()
// This is the biggest question mark.
AI_PERIOD = GetTicksPerSecond() / 80;
// System internal sample rate is fixed at 32KHz
AUDIO_DMA_PERIOD = CPU_CORE_CLOCK / (32000 * 4 / 32);
Common::Timer::IncreaseResolution();
// store and convert localtime at boot to timebase ticks
startTimeBaseTicks = (u64)(CPU_CORE_CLOCK / TIMER_RATIO) * (u64)CEXIIPL::GetGCTime();
@ -284,7 +288,7 @@ void Init()
et_VI = CoreTiming::RegisterEvent("VICallback", VICallback);
et_SI = CoreTiming::RegisterEvent("SICallback", SICallback);
et_DSP = CoreTiming::RegisterEvent("DSPCallback", DSPCallback);
et_AudioFifo = CoreTiming::RegisterEvent("AudioFifoCallback", AudioFifoCallback);
et_AudioDMA = CoreTiming::RegisterEvent("AudioDMACallback", AudioDMACallback);
et_IPC_HLE = CoreTiming::RegisterEvent("IPC_HLE_UpdateCallback", IPC_HLE_UpdateCallback);
// Always register this. Increases chances of DC/SC save state compatibility.
et_FakeGPWD = CoreTiming::RegisterEvent("FakeGPWatchdogCallback", FakeGPWatchdogCallback);
@ -294,7 +298,7 @@ void Init()
CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerLine(), et_VI);
CoreTiming::ScheduleEvent(DSP_PERIOD, et_DSP);
CoreTiming::ScheduleEvent(GetTicksPerSecond() / 60, et_SI);
CoreTiming::ScheduleEvent(CPU_CORE_CLOCK / (32000 * 4 / 32), et_AudioFifo);
CoreTiming::ScheduleEvent(AUDIO_DMA_PERIOD, et_AudioDMA);
// For DC watchdog hack
if (Core::GetStartupParameter().bCPUThread)

View File

@ -141,6 +141,7 @@
// cr (Not g_dsp.r[CR]) bits
// See HW/DSP.cpp.
#define CR_HALT 0x0004
#define CR_INIT 0x0400
#define CR_EXTERNAL_INT 0x0002

View File

@ -286,7 +286,7 @@ void CConfigMain::CreateGUIControls()
wxT("\nIt can be convenient in a Wii game that already has a cursor."));
WiimoteStatusLEDs->SetToolTip(wxT("Show which wiimotes are connected in the statusbar."));
WiimoteStatusSpeakers->SetToolTip(wxT("Show wiimote speaker status in the statusbar."));
DSPThread->SetToolTip(wxT("This should be on when using HLE and off when using LLE."));
DSPThread->SetToolTip(wxT("Run DSPLLE on a dedicate thread, this has no affect on DSPHLE."));
CPUThread->SetToolTip(wxT("This splits the Video and CPU threads, so they can be run on separate cores.")
wxT("\nCauses major speed improvements on PCs with more than one core,")
wxT("\nbut can also cause occasional crashes/glitches."));

View File

@ -17,7 +17,7 @@ typedef const char* (*TName)(void);
typedef void (*TDebuggerBreak)(void);
typedef void (*TGenerateDSPInt)(void);
typedef unsigned int (*TAudioGetStreaming)(short* _pDestBuffer, unsigned int _numSamples, unsigned int _sampleRate);
typedef void (*TGetSampleRate)(unsigned int &AISampleRate, unsigned int &DSPSampleRate);
typedef void (*TGetSampleRate)(unsigned int &AISampleRate, unsigned int &DACSampleRate);
typedef struct
{
@ -98,9 +98,8 @@ EXPORT void CALL DSP_Update(int cycles);
// Purpose: This function sends the current AI Buffer to the DSP plugin
// input: _Address : Memory-Address
// input: _Number : Number of the Samples
// input: _Rate : Sample Rate 32000/48000
//
EXPORT void CALL DSP_SendAIBuffer(unsigned int address, unsigned int num_samples, unsigned int sample_rate);
EXPORT void CALL DSP_SendAIBuffer(unsigned int address, unsigned int num_samples);
// __________________________________________________________________________________________________
// Function: DSP_StopSoundStream

View File

@ -58,10 +58,9 @@ DSPConfigDialogHLE::DSPConfigDialogHLE(wxWindow *parent, wxWindowID id, const wx
m_buttonEnableDTKMusic->SetToolTip(wxT("This is used to play music tracks, like BGM."));
m_buttonEnableThrottle->SetToolTip(wxT("This is used to control game speed by sound throttle.\n")
wxT("Disabling this could cause abnormal game speed, such as too fast.\n")
wxT("But sometimes enabling this causes constant noise."));
wxT("But sometimes enabling this could cause constant noise.\n")
wxT("\nKeyboard Shortcut <TAB>: Hold down to instantly disable Throttle."));
m_buttonEnableRE0Fix->SetToolTip(wxT("This fixes audio in Resident Evil Zero and maybe some other games."));
m_BackendSelection->SetToolTip(wxT("Changing this will have no effect while the emulator is running!"));
// Create sizer and add items to dialog

View File

@ -20,7 +20,7 @@
#include "DSPHandler.h"
#include "HLEMixer.h"
void HLEMixer::Premix(short *samples, unsigned int numSamples, unsigned int sampleRate)
void HLEMixer::Premix(short *samples, unsigned int numSamples)
{
// if this was called directly from the HLE
if (g_Config.m_EnableHLEAudio && IsHLEReady())

View File

@ -6,10 +6,10 @@
class HLEMixer : public CMixer
{
public:
HLEMixer(unsigned int AISampleRate = 48000, unsigned int DSPSampleRate = 48000)
: CMixer(AISampleRate, DSPSampleRate) {};
HLEMixer(unsigned int AISampleRate = 48000, unsigned int DACSampleRate = 48000)
: CMixer(AISampleRate, DACSampleRate) {};
virtual void Premix(short *samples, unsigned int numSamples, unsigned int sampleRate);
virtual void Premix(short *samples, unsigned int numSamples);
};
#endif // HLEMIXER_H

View File

@ -307,9 +307,9 @@ unsigned short DSP_WriteControlRegister(unsigned short _Value)
{
if (!Temp.DSPHalt && Temp.DSPInit)
{
unsigned int AISampleRate, DSPSampleRate;
g_dspInitialize.pGetSampleRate(AISampleRate, DSPSampleRate);
soundStream = AudioCommon::InitSoundStream(new HLEMixer(AISampleRate, DSPSampleRate));
unsigned int AISampleRate, DACSampleRate;
g_dspInitialize.pGetSampleRate(AISampleRate, DACSampleRate);
soundStream = AudioCommon::InitSoundStream(new HLEMixer(AISampleRate, DACSampleRate));
if(!soundStream) PanicAlert("Error starting up sound stream");
// Mixer is initialized
g_InitMixer = true;
@ -334,7 +334,7 @@ void DSP_Update(int cycles)
inside Mixer_PushSamples(), the reason that we don't disable this entire
function when Other Audio is disabled is that then we can't turn it back on
again once the game has started. */
void DSP_SendAIBuffer(unsigned int address, unsigned int num_samples, unsigned int sample_rate)
void DSP_SendAIBuffer(unsigned int address, unsigned int num_samples)
{
if (!soundStream)
return;
@ -344,9 +344,8 @@ void DSP_SendAIBuffer(unsigned int address, unsigned int num_samples, unsigned i
if (pMixer && address)
{
short* samples = (short*)Memory_Get_Pointer(address);
// sample_rate could be 32khz/48khz here,
// see Core/DSP/DSP.cpp for better information
pMixer->PushSamples(samples, num_samples, sample_rate);
// Internal sample rate is always 32khz
pMixer->PushSamples(samples, num_samples);
// FIXME: Write the audio to a file
//if (log_ai)

View File

@ -39,7 +39,7 @@ DSPConfigDialogLLE::DSPConfigDialogLLE(wxWindow *parent, wxWindowID id, const wx
// Create items
m_buttonEnableDTKMusic = new wxCheckBox(this, ID_ENABLE_DTK_MUSIC, wxT("Enable DTK Music"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
m_buttonEnableThrottle = new wxCheckBox(this, ID_ENABLE_THROTTLE, wxT("Enable Other Audio (Throttle)"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
m_buttonEnableThrottle = new wxCheckBox(this, ID_ENABLE_THROTTLE, wxT("Enable Audio Throttle"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
wxStaticText *BackendText = new wxStaticText(this, wxID_ANY, wxT("Audio Backend"), wxDefaultPosition, wxDefaultSize, 0);
m_BackendSelection = new wxComboBox(this, ID_BACKEND, wxEmptyString, wxDefaultPosition, wxSize(90, 20), wxArrayBackends, wxCB_READONLY, wxDefaultValidator);
@ -51,10 +51,11 @@ DSPConfigDialogLLE::DSPConfigDialogLLE(wxWindow *parent, wxWindowID id, const wx
m_buttonEnableThrottle->SetValue(ac_Config.m_EnableThrottle ? true : false);
// Add tooltips
m_buttonEnableDTKMusic->SetToolTip(wxT("This is sometimes used to play music tracks from the disc"));
m_buttonEnableThrottle->SetToolTip(wxT("This is sometimes used together with pre-rendered movies.\n")
wxT("Disabling this also disables the speed throttle which this causes,\n")
wxT("meaning that there will be no upper limit on your FPS."));
m_buttonEnableDTKMusic->SetToolTip(wxT("This is used to play music tracks, like BGM."));
m_buttonEnableThrottle->SetToolTip(wxT("This is used to control game speed by sound throttle.\n")
wxT("Disabling this could cause abnormal game speed, such as too fast.\n")
wxT("But sometimes enabling this could cause constant noise.\n")
wxT("\nKeyboard Shortcut <TAB>: Hold down to instantly disable Throttle."));
m_BackendSelection->SetToolTip(wxT("Changing this will have no effect while the emulator is running!"));
// Create sizer and add items to dialog

View File

@ -263,9 +263,9 @@ u16 DSP_WriteControlRegister(u16 _uFlag)
{
if (!Temp.DSPHalt && Temp.DSPInit)
{
unsigned int AISampleRate, DSPSampleRate;
g_dspInitialize.pGetSampleRate(AISampleRate, DSPSampleRate);
soundStream = AudioCommon::InitSoundStream(new CMixer(AISampleRate, DSPSampleRate));
unsigned int AISampleRate, DACSampleRate;
g_dspInitialize.pGetSampleRate(AISampleRate, DACSampleRate);
soundStream = AudioCommon::InitSoundStream(new CMixer(AISampleRate, DACSampleRate));
if(!soundStream) PanicAlert("Error starting up sound stream");
// Mixer is initialized
g_InitMixer = true;
@ -334,6 +334,8 @@ void DSP_WriteMailboxLow(bool _CPUMailbox, u16 _uLowMail)
void DSP_Update(int cycles)
{
// Sound stream update job has been handled by AudioDMA routine, which is more efficient
/*
// This gets called VERY OFTEN. The soundstream update might be expensive so only do it 200 times per second or something.
int cycles_between_ss_update;
@ -350,7 +352,7 @@ void DSP_Update(int cycles)
cycle_count -= cycles_between_ss_update;
soundStream->Update();
}
*/
// If we're not on a thread, run cycles here.
if (!g_dspInitialize.bOnThread)
{
@ -358,7 +360,7 @@ void DSP_Update(int cycles)
}
}
void DSP_SendAIBuffer(unsigned int address, unsigned int num_samples, unsigned int sample_rate)
void DSP_SendAIBuffer(unsigned int address, unsigned int num_samples)
{
if (!soundStream)
return;
@ -369,7 +371,7 @@ void DSP_SendAIBuffer(unsigned int address, unsigned int num_samples, unsigned i
{
short* samples = (short*)Memory_Get_Pointer(address);
pMixer->PushSamples(samples, num_samples, sample_rate);
pMixer->PushSamples(samples, num_samples);
}
soundStream->Update();