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
This commit is contained in:
hrydgard 2008-10-08 18:57:33 +00:00
parent 8dc32f5dee
commit 49534ca586
7 changed files with 227 additions and 35 deletions

View File

@ -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;
}

View File

@ -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 <stdio.h>
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

View File

@ -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;
}
// ==============

View File

@ -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;
@ -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);

View File

@ -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
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;
}
@ -106,6 +101,10 @@ uint16 dsp_read_aram()
Address = (gdsp_ifx_regs[DSP_ACSAH] << 16) | gdsp_ifx_regs[DSP_ACSAL];
// 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;

View File

@ -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

View File

@ -25,6 +25,7 @@
#include <stdlib.h>
#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)
@ -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);
}