diff --git a/Source/Core/AudioCommon/Src/AudioCommon.cpp b/Source/Core/AudioCommon/Src/AudioCommon.cpp index 1bea5458ff..4a52615134 100644 --- a/Source/Core/AudioCommon/Src/AudioCommon.cpp +++ b/Source/Core/AudioCommon/Src/AudioCommon.cpp @@ -34,19 +34,19 @@ namespace AudioCommon mixer = new CMixer(); std::string backend = ac_Config.sBackend; - if (backend == BACKEND_COREAUDIO && CoreAudioSound::isValid()) - soundStream = new CoreAudioSound(mixer); - if (backend == BACKEND_DIRECTSOUND && DSound::isValid()) - soundStream = new DSound(mixer, g_dspInitialize.hWnd); - if (backend == BACKEND_AOSOUND && AOSound::isValid()) - soundStream = new AOSound(mixer); - if (backend == BACKEND_OPENAL && OpenALStream::isValid()) + if (backend == BACKEND_OPENAL && OpenALStream::isValid()) soundStream = new OpenALStream(mixer); - if (backend == BACKEND_ALSA && AlsaSound::isValid()) + else if (backend == BACKEND_DIRECTSOUND && DSound::isValid()) + soundStream = new DSound(mixer, g_dspInitialize.hWnd); + else if (backend == BACKEND_AOSOUND && AOSound::isValid()) + soundStream = new AOSound(mixer); + else if (backend == BACKEND_ALSA && AlsaSound::isValid()) soundStream = new AlsaSound(mixer); - if (backend == BACKEND_PULSEAUDIO && PulseAudio::isValid()) + else if (backend == BACKEND_COREAUDIO && CoreAudioSound::isValid()) + soundStream = new CoreAudioSound(mixer); + else if (backend == BACKEND_PULSEAUDIO && PulseAudio::isValid()) soundStream = new PulseAudio(mixer); - if (backend == BACKEND_NULL && NullSound::isValid()) + else if (backend == BACKEND_NULL && NullSound::isValid()) soundStream = new NullSound(mixer); if (soundStream != NULL) @@ -60,12 +60,10 @@ namespace AudioCommon soundStream->StartLogAudio(FULL_DUMP_DIR g_Config.recordFile); } */ - return soundStream; } PanicAlert("Could not initialize backend %s, falling back to NULL", backend.c_str()); } - PanicAlert("Sound backend %s is not valid, falling back to NULL", backend.c_str()); delete soundStream; @@ -77,7 +75,7 @@ namespace AudioCommon void ShutdownSoundStream() { - NOTICE_LOG(DSPHLE, "Shutting down sound stream"); + INFO_LOG(DSPHLE, "Shutting down sound stream"); if (soundStream) { @@ -94,16 +92,16 @@ namespace AudioCommon { std::vector backends; - if (CoreAudioSound::isValid()) - backends.push_back(BACKEND_COREAUDIO); if (DSound::isValid()) backends.push_back(BACKEND_DIRECTSOUND); - if (AOSound::isValid()) - backends.push_back(BACKEND_AOSOUND); if (OpenALStream::isValid()) backends.push_back(BACKEND_OPENAL); + if (AOSound::isValid()) + backends.push_back(BACKEND_AOSOUND); if (AlsaSound::isValid()) backends.push_back(BACKEND_ALSA); + if (CoreAudioSound::isValid()) + backends.push_back(BACKEND_COREAUDIO); if (PulseAudio::isValid()) backends.push_back(BACKEND_PULSEAUDIO); if (NullSound::isValid()) diff --git a/Source/Core/AudioCommon/Src/Mixer.cpp b/Source/Core/AudioCommon/Src/Mixer.cpp index d120159e2c..63bc8c7088 100644 --- a/Source/Core/AudioCommon/Src/Mixer.cpp +++ b/Source/Core/AudioCommon/Src/Mixer.cpp @@ -81,9 +81,6 @@ void CMixer::PushSamples(short *samples, int num_stereo_samples, int core_sample sample_queue.push((s16)0); } push_sync.Leave(); - static int PV1l=0,PV2l=0,PV3l=0,PV4l=0; - static int PV1r=0,PV2r=0,PV3r=0,PV4r=0; - static int acc=0; #ifdef _WIN32 if (GetAsyncKeyState(VK_TAB)) @@ -113,6 +110,23 @@ void CMixer::PushSamples(short *samples, int num_stereo_samples, int core_sample // ----------------------------------------------------------------------- push_sync.Enter(); + while (num_stereo_samples) + { + sample_queue.push(Common::swap16(*samples)); + samples++; + sample_queue.push(Common::swap16(*samples)); + samples++; + m_queueSize += 2; + num_stereo_samples--; + } + push_sync.Leave(); + return; + +/* + static int PV1l=0,PV2l=0,PV3l=0,PV4l=0; + static int PV1r=0,PV2r=0,PV3r=0,PV4r=0; + static int acc=0; + while (num_stereo_samples) { acc += core_sample_rate; while (num_stereo_samples && (acc >= 48000)) { @@ -170,6 +184,8 @@ void CMixer::PushSamples(short *samples, int num_stereo_samples, int core_sample m_queueSize += 2; } push_sync.Leave(); +*/ + } int CMixer::GetNumSamples() diff --git a/Source/Core/AudioCommon/Src/Mixer.h b/Source/Core/AudioCommon/Src/Mixer.h index 3c4d66cc76..4fcf1c7d16 100644 --- a/Source/Core/AudioCommon/Src/Mixer.h +++ b/Source/Core/AudioCommon/Src/Mixer.h @@ -29,7 +29,17 @@ class CMixer { public: - CMixer() : m_sampleRate(48000),m_bits(16),m_channels(2), m_mode(2), m_HLEready(false),m_queueSize(0) {} + // AyuanX: Mixer sample rate is fixed to 32khz for now + // if any game sets DSP sample rate to 48khz, we are doomed + // TODO: Fix this somehow! + CMixer(unsigned int SampleRate = 32000) + : m_sampleRate(SampleRate) + , m_bits(16) + , m_channels(2) + , m_mode(2) + , m_HLEready(false) + , m_queueSize(0) + {} // Called from audio threads virtual int Mix(short *sample, int numSamples); diff --git a/Source/Core/Core/Src/HW/AudioInterface.cpp b/Source/Core/Core/Src/HW/AudioInterface.cpp index fd8ba2363f..94366ef6a0 100644 --- a/Source/Core/Core/Src/HW/AudioInterface.cpp +++ b/Source/Core/Core/Src/HW/AudioInterface.cpp @@ -60,7 +60,7 @@ union AICR 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=32khz 1=48khz) + unsigned DSPFR : 1; // DSP Frequency (0=48khz 1=32khz) WTF, who designed this? unsigned :25; }; u32 hex; @@ -181,9 +181,8 @@ void Write32(const u32 _Value, const u32 _Address) g_AudioRegister.m_Control.DSPFR = tmpAICtrl.DSPFR; } - g_SampleRate = tmpAICtrl.AFR ? 32000 : 48000; + g_SampleRate = tmpAICtrl.AFR ? 48000 : 32000; g_DSPSampleRate = tmpAICtrl.DSPFR ? 32000 : 48000; -// PanicAlert("Sample rate %i %i", g_Aui, g_SampleRate); g_CPUCyclesPerSample = SystemTimers::GetTicksPerSecond() / g_SampleRate; @@ -276,29 +275,49 @@ u32 Callback_GetStreaming(short* _pDestBuffer, u32 _numSamples) const int lvolume = g_AudioRegister.m_Volume.leftVolume; const int rvolume = g_AudioRegister.m_Volume.rightVolume; + // AyuanX: I hate this, but for now we have to do down-sampling to support 48khz + if (g_SampleRate == 48000) + { + _dbg_assert_msg_(AUDIO_INTERFACE, !(_numSamples % 2), "Number of Samples: %i must be even!", _numSamples); + _numSamples = _numSamples * 3 / 2; + } + + short pcm_l = 0; + short pcm_r = 0; for (unsigned int i = 0; i < _numSamples; i++) { if (pos == 0) - { ReadStreamBlock(pcm); - } - *_pDestBuffer++ = (pcm[pos*2] * lvolume) >> 8; - *_pDestBuffer++ = (pcm[pos*2+1] * rvolume) >> 8; - - pos++; - if (pos == 28) + if (g_SampleRate == 48000) { - pos = 0; + if (i % 3) + { + *_pDestBuffer++ = ((pcm_l / 2 + pcm[pos*2] / 2) * lvolume) >> 8; + *_pDestBuffer++ = ((pcm_r / 2 + pcm[pos*2+1] / 2) * rvolume) >> 8; + } + pcm_l = pcm[pos*2]; + pcm_r = pcm[pos*2+1]; } + else + { + *_pDestBuffer++ = (pcm[pos*2] * lvolume) >> 8; + *_pDestBuffer++ = (pcm[pos*2+1] * rvolume) >> 8; + } + + if (++pos == 28) + pos = 0; } } else { + // AyuanX: We have already preset those bytes, no need to do this again + /* for (unsigned int i = 0; i < _numSamples * 2; i++) { _pDestBuffer[i] = 0; //silence! } + */ } return _numSamples; diff --git a/Source/Core/Core/Src/HW/DSP.cpp b/Source/Core/Core/Src/HW/DSP.cpp index d94f26ac97..aa864aeb17 100644 --- a/Source/Core/Core/Src/HW/DSP.cpp +++ b/Source/Core/Core/Src/HW/DSP.cpp @@ -63,16 +63,17 @@ enum AR_SIZE = 0x5012, // These names are a good guess at best AR_MODE = 0x5016, // AR_REFRESH = 0x501a, // - AUDIO_DMA_START_HI = 0x5030, - AUDIO_DMA_START_LO = 0x5032, - AUDIO_DMA_CONTROL_LEN = 0x5036, - AUDIO_DMA_BLOCKS_LEFT = 0x503A, AR_DMA_MMADDR_H = 0x5020, AR_DMA_MMADDR_L = 0x5022, AR_DMA_ARADDR_H = 0x5024, AR_DMA_ARADDR_L = 0x5026, AR_DMA_CNT_H = 0x5028, - AR_DMA_CNT_L = 0x502A + AR_DMA_CNT_L = 0x502A, + AUDIO_DMA_START_HI = 0x5030, + AUDIO_DMA_START_LO = 0x5032, + AUDIO_DMA_BLOCKS_LENGTH = 0x5034, // Ever used? + AUDIO_DMA_CONTROL_LEN = 0x5036, + AUDIO_DMA_BLOCKS_LEFT = 0x503A, }; // UARAMCount @@ -128,7 +129,7 @@ union UAudioDMAControl struct { unsigned NumBlocks : 15; - unsigned Reload : 1; + unsigned Enable : 1; }; UAudioDMAControl(u16 _Hex = 0) : Hex(_Hex) @@ -378,6 +379,27 @@ void Write16(const u16 _Value, const u32 _Address) g_dspState.DSPControl.DSPHalt = tmpControl.DSPHalt; g_dspState.DSPControl.DSPInit = tmpControl.DSPInit; + // AyuanX: WTF, sample rate between AI & DSP can be different? + // This is a big problem especially when our mixer is fixed to 32000 + // TODO: Try to support these! + // More info: AudioCommon/Mixer.h, HW/AudioInterface.cpp + static bool FirstTimeWarning = false; + if (!FirstTimeWarning) + { + if (!g_dspState.DSPControl.DSPHalt && g_dspState.DSPControl.DSPInit) + { + // It's time to check now, and we do this only once + FirstTimeWarning = true; + if (AudioInterface::GetAISampleRate() != 32000 || AudioInterface::GetDSPSampleRate() != 32000) + { + WARN_LOG(DSPINTERFACE, "Unsupported Sample Rate, AI:%i, DSP:%i", AudioInterface::GetAISampleRate(), AudioInterface::GetDSPSampleRate()); + if (AudioInterface::GetDSPSampleRate() != 32000) + PanicAlert("DSPINTERFACE: Unsupported Sample Rate, AI:%i, DSP:%i\n" + "You may get incorrect sound output, please report!", AudioInterface::GetAISampleRate(), AudioInterface::GetDSPSampleRate()); + } + } + } + // Interrupt (mask) g_dspState.DSPControl.AID_mask = tmpControl.AID_mask; g_dspState.DSPControl.ARAM_mask = tmpControl.ARAM_mask; @@ -457,8 +479,8 @@ void Write16(const u16 _Value, const u32 _Address) case AUDIO_DMA_CONTROL_LEN: // called by AIStartDMA() g_audioDMA.AudioDMAControl.Hex = _Value; - g_audioDMA.BlocksLeft = g_audioDMA.AudioDMAControl.NumBlocks; g_audioDMA.ReadAddress = g_audioDMA.SourceAddress; + g_audioDMA.BlocksLeft = g_audioDMA.AudioDMAControl.NumBlocks; INFO_LOG(DSPINTERFACE, "AID DMA started - source address %08x, length %i blocks", g_audioDMA.SourceAddress, g_audioDMA.AudioDMAControl.NumBlocks); break; @@ -475,7 +497,7 @@ void Write16(const u16 _Value, const u32 _Address) // This happens at 4 khz, since 32 bytes at 4khz = 4 bytes at 32 khz (16bit stereo pcm) void UpdateAudioDMA() { - if (g_audioDMA.BlocksLeft) + if (g_audioDMA.AudioDMAControl.Enable && g_audioDMA.BlocksLeft) { // Read audio at g_audioDMA.ReadAddress in RAM and push onto an // external audio fifo in the emulator, to be mixed with the disc @@ -486,11 +508,8 @@ void UpdateAudioDMA() g_audioDMA.BlocksLeft--; if (g_audioDMA.BlocksLeft == 0) { - if (g_audioDMA.AudioDMAControl.Reload) - { - g_audioDMA.BlocksLeft = g_audioDMA.AudioDMAControl.NumBlocks; - g_audioDMA.ReadAddress = g_audioDMA.SourceAddress; - } + 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); } diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/Globals.cpp b/Source/Plugins/Plugin_DSP_HLE/Src/Globals.cpp index 3376192ec2..3ba1e10bed 100644 --- a/Source/Plugins/Plugin_DSP_HLE/Src/Globals.cpp +++ b/Source/Plugins/Plugin_DSP_HLE/Src/Globals.cpp @@ -58,3 +58,9 @@ float Memory_Read_Float(u32 _uAddress) u32 uTemp = Memory_Read_U32(_uAddress); return *(float*)&uTemp; } + +void* Memory_Get_Pointer(u32 _uAddress) +{ + _uAddress &= RAM_MASK; + return &g_pMemory[_uAddress]; +} \ No newline at end of file diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/Globals.h b/Source/Plugins/Plugin_DSP_HLE/Src/Globals.h index bcd99a6140..af33439421 100644 --- a/Source/Plugins/Plugin_DSP_HLE/Src/Globals.h +++ b/Source/Plugins/Plugin_DSP_HLE/Src/Globals.h @@ -43,6 +43,7 @@ u8 Memory_Read_U8(u32 _uAddress); u16 Memory_Read_U16(u32 _uAddress); u32 Memory_Read_U32(u32 _uAddress); float Memory_Read_Float(u32 _uAddress); +void* Memory_Get_Pointer(u32 _uAddress); extern PLUGIN_GLOBALS* globals; diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/main.cpp b/Source/Plugins/Plugin_DSP_HLE/Src/main.cpp index 9821a58601..77e2f24958 100644 --- a/Source/Plugins/Plugin_DSP_HLE/Src/main.cpp +++ b/Source/Plugins/Plugin_DSP_HLE/Src/main.cpp @@ -332,8 +332,10 @@ void DSP_SendAIBuffer(unsigned int address, int sample_rate) } CMixer* pMixer = soundStream->GetMixer(); - if (pMixer) + if (pMixer && address) { + short* samples = (short*)Memory_Get_Pointer(address); +/* short samples[16] = {0}; // interleaved stereo if (address) { @@ -346,7 +348,7 @@ void DSP_SendAIBuffer(unsigned int address, int sample_rate) //if (log_ai) // g_wave_writer.AddStereoSamples(samples, 8); } - +*/ // sample_rate is usually 32k here, // see Core/DSP/DSP.cpp for better information pMixer->PushSamples(samples, 32 / 4, sample_rate); diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/DSPConfigDlgLLE.cpp b/Source/Plugins/Plugin_DSP_LLE/Src/DSPConfigDlgLLE.cpp index 709c601b9c..8e6499e0e1 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/DSPConfigDlgLLE.cpp +++ b/Source/Plugins/Plugin_DSP_LLE/Src/DSPConfigDlgLLE.cpp @@ -105,6 +105,11 @@ void DSPConfigDialogLLE::AddBackend(const char* backend) #endif } +void DSPConfigDialogLLE::ClearBackends() +{ + m_BackendSelection->Clear(); +} + DSPConfigDialogLLE::~DSPConfigDialogLLE() { } diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/DSPConfigDlgLLE.h b/Source/Plugins/Plugin_DSP_LLE/Src/DSPConfigDlgLLE.h index 84370bde64..a3ab732042 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/DSPConfigDlgLLE.h +++ b/Source/Plugins/Plugin_DSP_LLE/Src/DSPConfigDlgLLE.h @@ -35,6 +35,7 @@ public: long style = wxDEFAULT_DIALOG_STYLE); virtual ~DSPConfigDialogLLE(); void AddBackend(const char *backend); + void ClearBackends(); private: DECLARE_EVENT_TABLE(); diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/main.cpp b/Source/Plugins/Plugin_DSP_LLE/Src/main.cpp index 42f6c74162..07b908ae4f 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/main.cpp +++ b/Source/Plugins/Plugin_DSP_LLE/Src/main.cpp @@ -145,6 +145,7 @@ void DllConfig(HWND _hParent) else if (!m_ConfigFrame->GetParent()->IsShown()) m_ConfigFrame->Close(true); + m_ConfigFrame->ClearBackends(); // add backends std::vector backends = AudioCommon::GetSoundBackends();