From 49534ca5868e15c90bf053041f4de6744ffe646b Mon Sep 17 00:00:00 2001 From: hrydgard Date: Wed, 8 Oct 2008 18:57:33 +0000 Subject: [PATCH] Added AI FIFO wave logging to HLE plugin. Same for LLE plugin is coming soon. Plus some extra critical section locks in LLE plugin. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@797 8ced0084-cf51-0410-be5f-012b33b47a6e --- Source/Core/Common/Src/WaveFile.cpp | 121 ++++++++++++++++++ Source/Core/Common/Src/WaveFile.h | 54 ++++++++ .../Plugin_DSP_HLE/Src/Logging/Logging.cpp | 2 +- Source/Plugins/Plugin_DSP_HLE/Src/main.cpp | 21 ++- .../Plugins/Plugin_DSP_LLE/Src/gdsp_aram.cpp | 29 ++--- Source/Plugins/Plugin_DSP_LLE/Src/gdsp_aram.h | 6 +- .../Plugin_DSP_LLE/Src/gdsp_interface.cpp | 29 +++-- 7 files changed, 227 insertions(+), 35 deletions(-) create mode 100644 Source/Core/Common/Src/WaveFile.cpp create mode 100644 Source/Core/Common/Src/WaveFile.h diff --git a/Source/Core/Common/Src/WaveFile.cpp b/Source/Core/Common/Src/WaveFile.cpp new file mode 100644 index 0000000000..89c260fc3d --- /dev/null +++ b/Source/Core/Common/Src/WaveFile.cpp @@ -0,0 +1,121 @@ +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "Common.h" +#include "WaveFile.h" + +enum {BUF_SIZE = 32*1024}; + +WaveFileWriter::WaveFileWriter() +{ + conv_buffer = 0; + skip_silence = false; +} + +WaveFileWriter::~WaveFileWriter() +{ + delete [] conv_buffer; + Stop(); +} + +bool WaveFileWriter::Start(const char *filename) +{ + if (!conv_buffer) + conv_buffer = new short[BUF_SIZE]; + + if (file) + return false; + file = fopen(filename, "wb"); + if (!file) + return false; + + Write4("RIFF"); + Write(100 * 1000 * 1000); // write big value in case the file gets truncated + Write4("WAVE"); + Write4("fmt "); + Write(16); // size of fmt block + Write(0x00020001); //two channels, uncompressed + const u32 sample_rate = 32000; + Write(sample_rate); + Write(sample_rate * 2 * 2); //two channels, 16bit + Write(0x00100004); + Write4("data"); + Write(100 * 1000 * 1000 - 32); + // We are now at offset 44 + if (ftell(file) != 44) + PanicAlert("wrong offset: %i", ftell(file)); +} + +void WaveFileWriter::Stop() +{ + if (!file) + return; + u32 file_size = (u32)ftell(file); + fseek(file, 4, SEEK_SET); + Write(audio_size + 36); + fseek(file, 40, SEEK_SET); + Write(audio_size); + fclose(file); + file = 0; +} + +void WaveFileWriter::Write(u32 value) +{ + fwrite(&value, 4, 1, file); +} + +void WaveFileWriter::Write4(const char *ptr) +{ + fwrite(ptr, 4, 1, file); +} + +void WaveFileWriter::AddStereoSamples(const short *sample_data, int count) +{ + if (!file) + PanicAlert("WaveFileWriter - file not open."); + if (skip_silence) { + bool all_zero = true; + for (int i = 0; i < count * 2; i++) + if (sample_data[i]) + all_zero = false; + if (all_zero) + return; + } + fwrite(sample_data, count * 4, 1, file); + audio_size += count * 4; +} + +void WaveFileWriter::AddStereoSamplesBE(const short *sample_data, int count) +{ + if (!file) + PanicAlert("WaveFileWriter - file not open."); + if (count > BUF_SIZE * 2) + PanicAlert("WaveFileWriter - buffer too small (count = %i).", count); + if (skip_silence) { + bool all_zero = true; + for (int i = 0; i < count * 2; i++) + if (sample_data[i]) + all_zero = false; + if (all_zero) + return; + } + for (int i = 0; i < count * 2; i++) { + conv_buffer[i] = Common::swap16((u16)sample_data[i]); + } + fwrite(conv_buffer, count * 4, 1, file); + audio_size += count * 4; +} \ No newline at end of file diff --git a/Source/Core/Common/Src/WaveFile.h b/Source/Core/Common/Src/WaveFile.h new file mode 100644 index 0000000000..9293da9f32 --- /dev/null +++ b/Source/Core/Common/Src/WaveFile.h @@ -0,0 +1,54 @@ +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +// WaveFileWriter + +// Simple utility class to make it easy to write long 16-bit stereo +// audio streams to disk. +// Use Start() to start recording to a file, and AddStereoSamples to add wave data. +// The float variant will convert from -1.0-1.0 range and clamp. +// Alternatively, AddSamplesBE for big endian wave data. +// If Stop is not called when it destructs, the destructor will call Stop(). + +#ifndef _WAVEFILE_H +#define _WAVEFILE_H + +#include + +class WaveFileWriter +{ + FILE *file; + bool skip_silence; + u32 audio_size; + short *conv_buffer; + void Write(u32 value); + void Write4(const char *ptr); + +public: + WaveFileWriter(); + ~WaveFileWriter(); + + bool Start(const char *filename); + void Stop(); + + void SetSkipSilence(bool skip) { skip_silence = skip; } + + void AddStereoSamples(const short *sample_data, int count); + void AddStereoSamplesBE(const short *sample_data, int count); // big endian +}; + +#endif // _WAVEFILE_H diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/Logging/Logging.cpp b/Source/Plugins/Plugin_DSP_HLE/Src/Logging/Logging.cpp index 1d99c8965b..df8277547e 100644 --- a/Source/Plugins/Plugin_DSP_HLE/Src/Logging/Logging.cpp +++ b/Source/Plugins/Plugin_DSP_HLE/Src/Logging/Logging.cpp @@ -163,7 +163,7 @@ void CUCode_AX::Logging(short* _pBuffer, int _iSize, int a) for (int i = 0; i < numberOfPBs; i++) { - vector1.at(i).at(vectorLength-1) = PBs[i].running; + vector1.at(i).at(vectorLength-1) = PBs[i].running ? true : false; } // ============== diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/main.cpp b/Source/Plugins/Plugin_DSP_HLE/Src/main.cpp index aee34d0519..b0f4adab29 100644 --- a/Source/Plugins/Plugin_DSP_HLE/Src/main.cpp +++ b/Source/Plugins/Plugin_DSP_HLE/Src/main.cpp @@ -15,9 +15,9 @@ // Official SVN repository and contact information can be found at // http://code.google.com/p/dolphin-emu/ - #include "Debugger/Debugger.h" // for the CDebugger class #include "ChunkFile.h" +#include "WaveFile.h" #include "resource.h" #ifdef _WIN32 @@ -34,15 +34,14 @@ #include "Config.h" #include "Logging/Console.h" // for startConsoleWin, wprintf, GetConsoleHwnd -// =================== - -// ======================================================================================= -// DSP struct -// ------------------- DSPInitialize g_dspInitialize; u8* g_pMemory; +// Set this if you want to log audio. search for log_ai in this file to see the filename. +static bool log_ai = false; +static WaveFileWriter g_wave_writer; + struct DSPState { u32 CPUMailbox; @@ -168,7 +167,7 @@ void GetDllInfo(PLUGIN_INFO* _PluginInfo) #ifndef _DEBUG sprintf(_PluginInfo->Name, "Dolphin DSP-HLE Plugin "); #else - sprintf(_PluginInfo->Name, "Dolphin DSP-HLE Plugin (Debug) "); + sprintf(_PluginInfo ->Name, "Dolphin DSP-HLE Plugin (Debug) "); #endif #endif } @@ -211,10 +210,16 @@ void DSP_Initialize(DSPInitialize _dspInitialize) #else AOSound::AOSound_StartSound(48000, Mixer); #endif + if (log_ai) { + g_wave_writer.Start("D:\\ai_log.wav"); + g_wave_writer.SetSkipSilence(false); + } } void DSP_Shutdown() { + if (log_ai) + g_wave_writer.Stop(); // delete the UCodes #ifdef _WIN32 DSound::DSound_StopSound(); @@ -315,6 +320,8 @@ void DSP_SendAIBuffer(unsigned int address, int sample_rate) for (int i = 0; i < 16; i++) { samples[i] = Memory_Read_U16(address + i * 2); } + if (log_ai) + g_wave_writer.AddStereoSamples(samples, 8); } Mixer_PushSamples(samples, 32 / 4, sample_rate); diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_aram.cpp b/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_aram.cpp index 6b106490ad..6034898129 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_aram.cpp +++ b/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_aram.cpp @@ -14,13 +14,13 @@ // Official SVN repository and contact information can be found at // http://code.google.com/p/dolphin-emu/ + #include "Globals.h" #include "gdsp_interface.h" extern uint16 dsp_swap16(uint16 x); - -// the hardware adpcm decoder :) +// The hardware adpcm decoder :) sint16 ADPCM_Step(uint32& _rSamplePos, uint32 _BaseAddress) { sint16* pCoefTable = (sint16*)&gdsp_ifx_regs[DSP_COEF_A1_0]; @@ -42,30 +42,25 @@ sint16 ADPCM_Step(uint32& _rSamplePos, uint32 _BaseAddress) (g_dspInitialize.pARAM_Read_U8(_rSamplePos >> 1) >> 4); if (temp >= 8) - { - temp -= 16; //temp += 0xFFFFFFF0; - } + temp -= 16; - //0x400 = 0.5 in 11-bit fixed point + // 0x400 = 0.5 in 11-bit fixed point int val = (scale * temp) + ((0x400 + coef1 * (sint16)gdsp_ifx_regs[DSP_YN1] + coef2 * (sint16)gdsp_ifx_regs[DSP_YN2]) >> 11); + // Clamp values. if (val > 0x7FFF) - { val = 0x7FFF; - } else if (val < -0x7FFF) - { val = -0x7FFF; - } gdsp_ifx_regs[DSP_YN2] = gdsp_ifx_regs[DSP_YN1]; gdsp_ifx_regs[DSP_YN1] = val; _rSamplePos++; - return(val); - - // I think the interpolation (linear, polyphase,...) is done by the UCode + // The advanced interpolation (linear, polyphase,...) is done by the UCode, so we don't + // need to bother with it here. + return val; } @@ -104,8 +99,12 @@ uint16 dsp_read_aram() if (Address > EndAddress) { Address = (gdsp_ifx_regs[DSP_ACSAH] << 16) | gdsp_ifx_regs[DSP_ACSAL]; - //ErrorLog("Should we generate a lvl5 exception !??!"); - //gdsp_exception(5); + // ErrorLog("Should we generate a lvl5 exception !??!"); + // gdsp_exception(5); + + // Somehow, YN1 and YN2 must be initialized with their "loop" values, so yeah, + // it seems likely that we should raise an exception to let the DSP program do that, + // at least if DSP_FORMAT == 0x0A. } gdsp_ifx_regs[DSP_ACCAH] = Address >> 16; diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_aram.h b/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_aram.h index ef37193c19..46547f3b23 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_aram.h +++ b/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_aram.h @@ -14,6 +14,10 @@ // Official SVN repository and contact information can be found at // http://code.google.com/p/dolphin-emu/ -#pragma once + +#ifndef _GDSP_ARAM_H +#define _GDSP_ARAM_H uint16 dsp_read_aram(); + +#endif diff --git a/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_interface.cpp b/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_interface.cpp index dbb6fca636..739af272a2 100644 --- a/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_interface.cpp +++ b/Source/Plugins/Plugin_DSP_LLE/Src/gdsp_interface.cpp @@ -25,6 +25,7 @@ #include #include "Globals.h" +#include "Thread.h" #include "gdsp_aram.h" #include "gdsp_interpreter.h" @@ -66,9 +67,8 @@ const char* reg_names[] = void gdsp_dma(); - -#ifdef _WIN32 -extern CRITICAL_SECTION g_CriticalSection; +#ifdef WITH_DSP_ON_THREAD +Common::CriticalSection g_CriticalSection; #endif static volatile uint16 gdsp_mbox[2][2]; @@ -93,20 +93,27 @@ void gdsp_ifx_init() uint32 gdsp_mbox_peek(uint8 mbx) { - return((gdsp_mbox[mbx][0] << 16) | gdsp_mbox[mbx][1]); +#if WITH_DSP_ON_THREAD + g_CriticalSection.Enter(); +#endif + uint32 value = ((gdsp_mbox[mbx][0] << 16) | gdsp_mbox[mbx][1]); +#if WITH_DSP_ON_THREAD + g_CriticalSection.Leave(); +#endif + return value; } void gdsp_mbox_write_h(uint8 mbx, uint16 val) { #if WITH_DSP_ON_THREAD - EnterCriticalSection(&g_CriticalSection); + g_CriticalSection.Enter(); #endif gdsp_mbox[mbx][0] = val & 0x7fff; #if WITH_DSP_ON_THREAD - LeaveCriticalSection(&g_CriticalSection); + g_CriticalSection.Leave(); #endif } @@ -114,14 +121,14 @@ void gdsp_mbox_write_h(uint8 mbx, uint16 val) void gdsp_mbox_write_l(uint8 mbx, uint16 val) { #if WITH_DSP_ON_THREAD - EnterCriticalSection(&g_CriticalSection); + g_CriticalSection.Enter(); #endif gdsp_mbox[mbx][1] = val; gdsp_mbox[mbx][0] |= 0x8000; #if WITH_DSP_ON_THREAD - LeaveCriticalSection(&g_CriticalSection); + g_CriticalSection.Leave(); #endif if (mbx == GDSP_MBOX_DSP) @@ -133,7 +140,7 @@ void gdsp_mbox_write_l(uint8 mbx, uint16 val) uint16 gdsp_mbox_read_h(uint8 mbx) { - return(gdsp_mbox[mbx][0]); + return (gdsp_mbox[mbx][0]); } @@ -141,14 +148,14 @@ uint16 gdsp_mbox_read_l(uint8 mbx) { uint16 val; #if WITH_DSP_ON_THREAD - EnterCriticalSection(&g_CriticalSection); + g_CriticalSection.Enter(); #endif val = gdsp_mbox[mbx][1]; gdsp_mbox[mbx][0] &= ~0x8000; #if WITH_DSP_ON_THREAD - LeaveCriticalSection(&g_CriticalSection); + g_CriticalSection.Leave(); #endif return(val); }