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:
parent
eddafd450e
commit
06218e9ebb
|
@ -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);
|
||||
|
|
|
@ -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!");
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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."));
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue