Attempt to move mixer to audio common, it's a bit more complicated than I expected

so please check I didn't break anything in hle



git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@2756 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
nakeee 2009-03-26 09:29:14 +00:00
parent d7038fea17
commit fff663e8c7
35 changed files with 386 additions and 619 deletions

View File

@ -433,6 +433,14 @@
RelativePath=".\Src\SoundStream.h" RelativePath=".\Src\SoundStream.h"
> >
</File> </File>
<File
RelativePath=".\Src\Mixer.h"
>
</File>
<File
RelativePath=".\Src\Mixer.cpp"
>
</File>
<File <File
RelativePath=".\Src\WaveFile.cpp" RelativePath=".\Src\WaveFile.cpp"
> >

View File

@ -18,16 +18,18 @@
#include <string.h> #include <string.h>
#include "AOSoundStream.h" #include "AOSoundStream.h"
#include "Mixer.h"
#if defined(HAVE_AO) && HAVE_AO #if defined(HAVE_AO) && HAVE_AO
void AOSound::SoundLoop() void AOSound::SoundLoop()
{ {
uint_32 numBytesToRender = 256;
ao_initialize(); ao_initialize();
default_driver = ao_default_driver_id(); default_driver = ao_default_driver_id();
format.bits = 16; format.bits = 16;
format.channels = 2; format.channels = 2;
format.rate = sampleRate; format.rate = m_mixer->GetSampleRate();
format.byte_format = AO_FMT_LITTLE; format.byte_format = AO_FMT_LITTLE;
device = ao_open_live(default_driver, &format, NULL /* no options */); device = ao_open_live(default_driver, &format, NULL /* no options */);
@ -43,14 +45,21 @@ void AOSound::SoundLoop()
while (!threadData) while (!threadData)
{ {
soundCriticalSection->Enter(); soundCriticalSection.Enter();
uint_32 numBytesToRender = 256; m_mixer->Mix(realtimeBuffer, numBytesToRender >> 2);
(*callback)(realtimeBuffer, numBytesToRender >> 2, 16, sampleRate, 2);
ao_play(device, (char*)realtimeBuffer, numBytesToRender); ao_play(device, (char*)realtimeBuffer, numBytesToRender);
soundCriticalSection->Leave();
soundSyncEvent->Wait(); soundCriticalSection.Leave();
if (! threadData)
soundSyncEvent.Wait();
} }
ao_close(device);
device = NULL;
ao_shutdown();
} }
void *soundThread(void *args) void *soundThread(void *args)
@ -63,34 +72,28 @@ bool AOSound::Start()
{ {
memset(realtimeBuffer, 0, sizeof(realtimeBuffer)); memset(realtimeBuffer, 0, sizeof(realtimeBuffer));
soundSyncEvent = new Common::Event(); soundSyncEvent.Init();
soundSyncEvent->Init();
soundCriticalSection = new Common::CriticalSection(1);
thread = new Common::Thread(soundThread, (void *)this); thread = new Common::Thread(soundThread, (void *)this);
return true; return true;
} }
void AOSound::Update() void AOSound::Update()
{ {
soundSyncEvent->Set(); soundSyncEvent.Set();
} }
void AOSound::Stop() void AOSound::Stop()
{ {
soundCriticalSection->Enter(); soundCriticalSection.Enter();
threadData = 1; threadData = 1;
soundSyncEvent->Set(); soundSyncEvent.Set();
soundCriticalSection->Leave(); soundCriticalSection.Leave();
soundSyncEvent->Shutdown();
delete soundCriticalSection; delete thread;
delete thread; thread = NULL;
delete soundSyncEvent; soundSyncEvent.Shutdown();
ao_close(device);
device = NULL;
ao_shutdown();
} }
#endif #endif

View File

@ -30,8 +30,8 @@ class AOSound : public SoundStream
{ {
#if defined(HAVE_AO) && HAVE_AO #if defined(HAVE_AO) && HAVE_AO
Common::Thread *thread; Common::Thread *thread;
Common::CriticalSection *soundCriticalSection; Common::CriticalSection soundCriticalSection;
Common::Event *soundSyncEvent; Common::Event soundSyncEvent;
int buf_size; int buf_size;
@ -42,9 +42,8 @@ class AOSound : public SoundStream
short realtimeBuffer[1024 * 1024]; short realtimeBuffer[1024 * 1024];
public: public:
AOSound(int _sampleRate, StreamCallback _callback) : AOSound(CMixer *mixer) : SoundStream(mixer) {}
SoundStream(_sampleRate, _callback) {}
virtual ~AOSound() {} virtual ~AOSound() {}
virtual bool Start(); virtual bool Start();
@ -63,14 +62,10 @@ public:
virtual void Update(); virtual void Update();
virtual int GetSampleRate() {
return sampleRate;
}
#else #else
public: public:
AOSound(int _sampleRate, StreamCallback _callback) : AOSound(CMixer *mixer) :
SoundStream(_sampleRate, _callback) {} SoundStream(mixer) {}
#endif #endif
}; };

View File

@ -0,0 +1,51 @@
#include "AudioCommon.h"
#include "Mixer.h"
#include "AOSoundStream.h"
#include "DSoundStream.h"
#include "NullSoundStream.h"
namespace AudioCommon {
SoundStream *InitSoundStream(std::string backend, CMixer *mixer) {
if (!mixer) {
mixer = new CMixer();
}
if (backend == "DSound") {
if (DSound::isValid())
soundStream = new DSound(mixer, g_dspInitialize.hWnd);
}
else if (backend == "AOSound") {
if (AOSound::isValid())
soundStream = new AOSound(mixer);
}
else if (backend == "NullSound") {
soundStream = new NullSound(mixer);
}
else {
PanicAlert("Cannot recognize backend %s", backend.c_str());
return NULL;
}
if (soundStream) {
if (!soundStream->Start()) {
PanicAlert("Could not initialize backend %s, falling back to NULL",
backend.c_str());
delete soundStream;
soundStream = new NullSound(mixer);
soundStream->Start();
}
}
else {
PanicAlert("Sound backend %s is not valid, falling back to NULL",
backend.c_str());
delete soundStream;
soundStream = new NullSound(mixer);
soundStream->Start();
}
return soundStream;
}
} // Namespace

View File

@ -0,0 +1,18 @@
#ifndef _AUDIO_COMMON_H
#define _AUDIO_COMMON_H
#include "Common.h"
#include "pluginspecs_dsp.h"
#include "SoundStream.h"
class CMixer;
extern DSPInitialize g_dspInitialize;
extern SoundStream *soundStream;
namespace AudioCommon {
SoundStream *InitSoundStream(std::string backend, CMixer *mixer = NULL);
} // Namespace
#endif // AUDIO_COMMON

View File

@ -19,7 +19,7 @@
#include <dxerr.h> #include <dxerr.h>
#include "DSoundStream.h" #include "DSoundStream.h"
extern bool log_ai; //extern bool log_ai;
bool DSound::CreateBuffer() bool DSound::CreateBuffer()
{ {
@ -114,7 +114,7 @@ void DSound::SoundLoop()
{ {
if (numBytesToRender > sizeof(realtimeBuffer)) if (numBytesToRender > sizeof(realtimeBuffer))
PanicAlert("soundThread: too big render call"); PanicAlert("soundThread: too big render call");
(*callback)(realtimeBuffer, numBytesToRender >> 2, 16, sampleRate, 2); m_mixer->Mix(realtimeBuffer, numBytesToRender >> 2);
WriteDataToBuffer(lastPos, (char*)realtimeBuffer, numBytesToRender); WriteDataToBuffer(lastPos, (char*)realtimeBuffer, numBytesToRender);
currentPos = ModBufferSize(lastPos + numBytesToRender); currentPos = ModBufferSize(lastPos + numBytesToRender);
totalRenderedBytes += numBytesToRender; totalRenderedBytes += numBytesToRender;

View File

@ -64,12 +64,10 @@ class DSound : public SoundStream
DWORD dwSoundBytes); DWORD dwSoundBytes);
public: public:
DSound(int _sampleRate, StreamCallback _callback) : DSound(CMixer *mixer, void *hWnd = NULL) : SoundStream(mixer) {}
SoundStream(_sampleRate, _callback) {}
DSound(CMixer *mixer) : SoundStream(mixer) {}
DSound(int _sampleRate, StreamCallback _callback, void *_hWnd) :
SoundStream(_sampleRate, _callback), hWnd(_hWnd) {}
virtual ~DSound() {} virtual ~DSound() {}
virtual bool Start(); virtual bool Start();
@ -81,8 +79,8 @@ public:
#else #else
public: public:
DSound(int _sampleRate, StreamCallback _callback, void *hWnd = NULL) : DSound(CMixer *mixer, void *hWnd = NULL) :
SoundStream(_sampleRate, _callback) {} SoundStream(mixer) {}
#endif #endif
}; };

View File

@ -21,87 +21,51 @@
#include "Thread.h" // Common #include "Thread.h" // Common
#include "../Config.h" // Local
#include "../Globals.h"
#include "../DSPHandler.h"
#include "../Debugger/File.h"
#include "../main.h"
#include "Mixer.h" #include "Mixer.h"
#include "FixedSizeQueue.h" #include "FixedSizeQueue.h"
#include "AudioCommon.h"
namespace { void CMixer::Mix(short *samples, int numSamples)
Common::CriticalSection push_sync;
// On real hardware, this fifo is much, much smaller. But timing is also tighter than under Windows, so...
const int queue_minlength = 1024 * 4;
const int queue_maxlength = 1024 * 28;
FixedSizeQueue<s16, queue_maxlength> sample_queue;
} // namespace
volatile bool mixer_HLEready = false;
volatile int queue_size = 0;
void Mixer(short *buffer, int numSamples, int bits, int rate, int channels)
{ {
// silence // silence
memset(buffer, 0, numSamples * 2 * sizeof(short)); memset(samples, 0, numSamples * 2 * sizeof(short));
if (g_dspInitialize.pEmulatorState) { if (g_dspInitialize.pEmulatorState) {
if (*g_dspInitialize.pEmulatorState != 0) if (*g_dspInitialize.pEmulatorState != 0)
return; return;
} }
// first get the DTK Music Premix(samples, numSamples);
if (g_Config.m_EnableDTKMusic)
{
g_dspInitialize.pGetAudioStreaming(buffer, numSamples);
}
Mixer_MixUCode(buffer, numSamples, bits, rate, channels);
push_sync.Enter(); push_sync.Enter();
int count = 0; int count = 0;
while (queue_size > queue_minlength && count < numSamples * 2) { while (m_queueSize > queue_minlength && count < numSamples * 2) {
int x = buffer[count]; int x = samples[count];
x += sample_queue.front(); x += sample_queue.front();
if (x > 32767) x = 32767; if (x > 32767) x = 32767;
if (x < -32767) x = -32767; if (x < -32767) x = -32767;
buffer[count++] = x; samples[count++] = x;
sample_queue.pop(); sample_queue.pop();
x = buffer[count]; x = samples[count];
x += sample_queue.front(); x += sample_queue.front();
if (x > 32767) x = 32767; if (x > 32767) x = 32767;
if (x < -32767) x = -32767; if (x < -32767) x = -32767;
buffer[count++] = x; samples[count++] = x;
sample_queue.pop(); sample_queue.pop();
queue_size-=2; m_queueSize-=2;
} }
push_sync.Leave(); push_sync.Leave();
} }
void Mixer_MixUCode(short *buffer, int numSamples, int bits, int rate,
int channels) {
//if this was called directly from the HLE, and not by timeout
if (g_Config.m_EnableHLEAudio && mixer_HLEready)
{
IUCode* pUCode = CDSPHandler::GetInstance().GetUCode();
if (pUCode != NULL)
pUCode->MixAdd(buffer, numSamples);
}
}
void Mixer_PushSamples(short *buffer, int num_stereo_samples, int sample_rate) void CMixer::PushSamples(short *samples, int num_stereo_samples)
{ {
if (!soundStream) if (!soundStream)
return; return;
if (queue_size == 0) if (m_queueSize == 0)
{ {
queue_size = queue_minlength; m_queueSize = queue_minlength;
for (int i = 0; i < queue_minlength; i++) for (int i = 0; i < queue_minlength; i++)
sample_queue.push((s16)0); sample_queue.push((s16)0);
} }
@ -116,12 +80,11 @@ void Mixer_PushSamples(short *buffer, int num_stereo_samples, int sample_rate)
#endif #endif
// Write Other Audio // Write Other Audio
if (g_Config.m_EnableThrottle) if (m_throttle) {
{
/* This is only needed for non-AX sound, currently directly /* This is only needed for non-AX sound, currently directly
streamed and DTK sound. For AX we call SoundStream::Update in streamed and DTK sound. For AX we call SoundStream::Update in
AXTask() for example. */ AXTask() for example. */
while (queue_size > queue_maxlength / 2) { while (m_queueSize > queue_maxlength / 2) {
// Urgh. // Urgh.
if (g_dspInitialize.pEmulatorState) { if (g_dspInitialize.pEmulatorState) {
if (*g_dspInitialize.pEmulatorState != 0) if (*g_dspInitialize.pEmulatorState != 0)
@ -129,25 +92,22 @@ void Mixer_PushSamples(short *buffer, int num_stereo_samples, int sample_rate)
} }
soundStream->Update(); soundStream->Update();
Common::SleepCurrentThread(0); Common::SleepCurrentThread(0);
} }
//convert into config option?
const int mode = 2;
push_sync.Enter(); push_sync.Enter();
while (num_stereo_samples) while (num_stereo_samples)
{ {
acc += sample_rate; acc += m_sampleRate;
while (num_stereo_samples && (acc >= 48000)) while (num_stereo_samples && (acc >= 48000))
{ {
PV4l=PV3l; PV4l=PV3l;
PV3l=PV2l; PV3l=PV2l;
PV2l=PV1l; PV2l=PV1l;
PV1l=*(buffer++); //32bit processing PV1l=*(samples++); //32bit processing
PV4r=PV3r; PV4r=PV3r;
PV3r=PV2r; PV3r=PV2r;
PV2r=PV1r; PV2r=PV1r;
PV1r=*(buffer++); //32bit processing PV1r=*(samples++); //32bit processing
num_stereo_samples--; num_stereo_samples--;
acc-=48000; acc-=48000;
} }
@ -156,12 +116,12 @@ void Mixer_PushSamples(short *buffer, int num_stereo_samples, int sample_rate)
s32 DataL = PV1l; s32 DataL = PV1l;
s32 DataR = PV1r; s32 DataR = PV1r;
if (mode == 1) //linear if (m_mode == 1) //linear
{ {
DataL = PV1l + ((PV2l - PV1l)*acc)/48000; DataL = PV1l + ((PV2l - PV1l)*acc)/48000;
DataR = PV1r + ((PV2r - PV1r)*acc)/48000; DataR = PV1r + ((PV2r - PV1r)*acc)/48000;
} }
else if (mode == 2) //cubic else if (m_mode == 2) //cubic
{ {
s32 a0l = PV1l - PV2l - PV4l + PV3l; s32 a0l = PV1l - PV2l - PV4l + PV3l;
s32 a0r = PV1r - PV2r - PV4r + PV3r; s32 a0r = PV1r - PV2r - PV4r + PV3r;
@ -192,7 +152,7 @@ void Mixer_PushSamples(short *buffer, int num_stereo_samples, int sample_rate)
if (r > 32767) r = 32767; if (r > 32767) r = 32767;
sample_queue.push(l); sample_queue.push(l);
sample_queue.push(r); sample_queue.push(r);
queue_size += 2; m_queueSize += 2;
} }
push_sync.Leave(); push_sync.Leave();
} }

View File

@ -0,0 +1,67 @@
// 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/
#ifndef _MIXER_H
#define _MIXER_H
#include "FixedSizeQueue.h"
// On real hardware, this fifo is much, much smaller. But timing is also
// tighter than under Windows, so...
#define queue_minlength 1024 * 4
#define queue_maxlength 1024 * 28
class CMixer {
public:
CMixer() : m_sampleRate(48000),m_bits(16),m_channels(2), m_mode(2), m_HLEready(false) {}
// Called from audio threads
void Mix(short *sample, int numSamples);
// Called from main thread
void PushSamples(short* samples, int num_stereo_samples);
virtual void Premix(short *samples, int numSamples) {}
int GetSampleRate() {return m_sampleRate;}
void SetThrottle(bool use) { m_throttle = use;}
// FIXME do we need this
bool IsHLEReady() { return m_HLEready;}
void SetHLEReady(bool ready) { m_HLEready = ready;}
//////
protected:
int m_sampleRate;
int m_bits;
int m_channels;
int m_mode;
bool m_HLEready;
int m_queueSize;
bool m_throttle;
private:
Common::CriticalSection push_sync;
FixedSizeQueue<s16, queue_maxlength> sample_queue;
};
#endif

View File

@ -23,8 +23,7 @@
class NullSound : public SoundStream class NullSound : public SoundStream
{ {
public: public:
NullSound(int _sampleRate, StreamCallback _callback) : NullSound(CMixer *mixer) : SoundStream(mixer) {}
SoundStream(_sampleRate, _callback) {}
virtual ~NullSound() {} virtual ~NullSound() {}
@ -35,7 +34,8 @@ public:
virtual bool Start() { return true; } virtual bool Start() { return true; }
virtual void Update() { virtual void Update() {
(*callback)(NULL, 256 >> 2, 16, sampleRate, 2); m_mixer->Mix(NULL, 256 >> 2);
//(*callback)(NULL, 256 >> 2, 16, sampleRate, 2);
} }
}; };

View File

@ -5,6 +5,8 @@ Import('env')
files = [ files = [
'AOSoundStream.cpp', 'AOSoundStream.cpp',
'WaveFile.cpp', 'WaveFile.cpp',
'Mixer.cpp',
'AudioCommon.cpp',
] ]
env_audiocommon = env.Clone() env_audiocommon = env.Clone()

View File

@ -19,32 +19,27 @@
#define __SOUNDSTREAM_H__ #define __SOUNDSTREAM_H__
#include "Common.h" #include "Common.h"
#include "Mixer.h"
typedef void (*StreamCallback)(short* buffer, int numSamples, int bits, int rate, int channels);
class SoundStream class SoundStream
{ {
protected: protected:
int sampleRate;
StreamCallback callback;
CMixer *m_mixer;
// We set this to shut down the sound thread. // We set this to shut down the sound thread.
// 0=keep playing, 1=stop playing NOW. // 0=keep playing, 1=stop playing NOW.
volatile int threadData; volatile int threadData;
public: public:
SoundStream(int _sampleRate, StreamCallback _callback) : SoundStream(CMixer *mixer) : m_mixer(mixer), threadData(0) {}
sampleRate(_sampleRate), callback(_callback), threadData(0) {} virtual ~SoundStream() { delete m_mixer;}
virtual ~SoundStream() {}
static bool isValid() { return false; } static bool isValid() { return false; }
virtual bool usesMixer() const { return false; } virtual CMixer *GetMixer() const { return m_mixer; }
virtual bool Start() { return false; } virtual bool Start() { return false; }
virtual void SoundLoop() {} virtual void SoundLoop() {}
virtual void Stop() {} virtual void Stop() {}
virtual void Update() {} virtual void Update() {}
virtual int GetSampleRate() const { return sampleRate; }
}; };
#endif #endif

View File

@ -548,18 +548,6 @@
<References> <References>
</References> </References>
<Files> <Files>
<Filter
Name="PCHW"
>
<File
RelativePath=".\Src\Pchw\Mixer.cpp"
>
</File>
<File
RelativePath=".\Src\Pchw\Mixer.h"
>
</File>
</Filter>
<Filter <Filter
Name="UCodes" Name="UCodes"
> >
@ -748,6 +736,14 @@
RelativePath=".\Src\DSPHandler.h" RelativePath=".\Src\DSPHandler.h"
> >
</File> </File>
<File
RelativePath=".\Src\HLEMixer.cpp"
>
</File>
<File
RelativePath=".\Src\HLEMixer.h"
>
</File>
<File <File
RelativePath=".\Src\Globals.cpp" RelativePath=".\Src\Globals.cpp"
> >

View File

@ -0,0 +1,25 @@
#include "Config.h" // Local
#include "Globals.h"
#include "DSPHandler.h"
#include "HLEMixer.h"
void HLEMixer::MixUCode(short *samples, int numSamples) {
//if this was called directly from the HLE, and not by timeout
if (g_Config.m_EnableHLEAudio && IsHLEReady()) {
IUCode* pUCode = CDSPHandler::GetInstance().GetUCode();
if (pUCode != NULL)
pUCode->MixAdd(samples, numSamples);
}
}
void HLEMixer::Premix(short *samples, int numSamples) {
// first get the DTK Music
if (g_Config.m_EnableDTKMusic) {
g_dspInitialize.pGetAudioStreaming(samples, numSamples);
}
MixUCode(samples, numSamples);
}

View File

@ -0,0 +1,16 @@
#ifndef HLEMIXER_H
#define HLEMIXER_H
#include "AudioCommon.h"
#include "Mixer.h"
class HLEMixer : public CMixer
{
public:
void MixUCode(short *samples, int numSamples);
virtual void Premix(short *samples, int numSamples);
};
#endif // HLEMIXER_H

View File

@ -1,32 +0,0 @@
// 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/
#ifndef _MIXER_H
#define _MIXER_H
extern volatile bool mixer_HLEready;
// Called from audio threads
void Mixer(short* buffer, int numSamples, int bits, int rate, int channels);
void Mixer_MixUCode(short *buffer, int numSamples, int bits, int rate, int channels);
// Called from main thread
void Mixer_PushSamples(short *buffer, int num_stereo_samples, int sample_rate);
#endif

View File

@ -8,11 +8,10 @@ name = "Plugin_DSP_HLE"
files = [ files = [
'DSPHandler.cpp', 'DSPHandler.cpp',
'MailHandler.cpp', 'MailHandler.cpp',
'HLEMixer.cpp',
'main.cpp', 'main.cpp',
'Config.cpp', 'Config.cpp',
'Globals.cpp', 'Globals.cpp',
# 'PCHW/AOSoundStream.cpp',
'PCHW/Mixer.cpp',
'Debugger/File.cpp', 'Debugger/File.cpp',
'UCodes/UCode_AX.cpp', 'UCodes/UCode_AX.cpp',
'UCodes/UCode_AXWii.cpp', 'UCodes/UCode_AXWii.cpp',

View File

@ -25,7 +25,7 @@ extern CDebugger* m_frame;
#include <sstream> #include <sstream>
#include "../Globals.h" #include "../Globals.h"
#include "../PCHW/Mixer.h" #include "Mixer.h"
#include "../MailHandler.h" #include "../MailHandler.h"
#include "UCodes.h" #include "UCodes.h"
@ -513,7 +513,7 @@ bool CUCode_AX::AXTask(u32& _uMail)
m_addressPBs = Memory_Read_U32(uAddress); m_addressPBs = Memory_Read_U32(uAddress);
uAddress += 4; uAddress += 4;
mixer_HLEready = true; soundStream->GetMixer()->SetHLEReady(true);
SaveLog("%08x : AXLIST PB address: %08x", uAddress, m_addressPBs); SaveLog("%08x : AXLIST PB address: %08x", uAddress, m_addressPBs);
SaveLog("Update the SoundThread to be in sync"); SaveLog("Update the SoundThread to be in sync");

View File

@ -23,8 +23,8 @@
extern CDebugger * m_frame; extern CDebugger * m_frame;
#endif #endif
#include "../PCHW/Mixer.h"
#include "../MailHandler.h" #include "../MailHandler.h"
#include "Mixer.h"
#include "UCodes.h" #include "UCodes.h"
#include "UCode_AXStructs.h" #include "UCode_AXStructs.h"
@ -324,7 +324,7 @@ bool CUCode_AXWii::AXTask(u32& _uMail)
case 0x0004: // PBs are here now case 0x0004: // PBs are here now
m_addressPBs = Memory_Read_U32(uAddress); m_addressPBs = Memory_Read_U32(uAddress);
lCUCode_AX->m_addressPBs = m_addressPBs; // for the sake of logging lCUCode_AX->m_addressPBs = m_addressPBs; // for the sake of logging
mixer_HLEready = true; soundStream->GetMixer()->SetHLEReady(true);
SaveLog("%08x : AXLIST PB address: %08x", uAddress, m_addressPBs); SaveLog("%08x : AXLIST PB address: %08x", uAddress, m_addressPBs);
soundStream->Update(); soundStream->Update();
uAddress += 4; uAddress += 4;

View File

@ -21,7 +21,7 @@
#include "UCode_AX_ADPCM.h" #include "UCode_AX_ADPCM.h"
#include "UCode_AX.h" #include "UCode_AX.h"
#include "../main.h" #include "../main.h"
#include "Mixer.h"
// ---------------------------------------------------- // ----------------------------------------------------
// Externals // Externals
@ -107,7 +107,7 @@ inline void WriteBackPBsWii(u32 pbs_address, ParamBlockType& _pPBs, int _num)
template<class ParamBlockType> template<class ParamBlockType>
inline void MixAddVoice(ParamBlockType &pb, int *templbuffer, int *temprbuffer, int _iSize, bool Wii) inline void MixAddVoice(ParamBlockType &pb, int *templbuffer, int *temprbuffer, int _iSize, bool Wii)
{ {
ratioFactor = 32000.0f / (float)soundStream->GetSampleRate(); ratioFactor = 32000.0f / (float)soundStream->GetMixer()->GetSampleRate();
DoVoiceHacks(pb, Wii); DoVoiceHacks(pb, Wii);
@ -115,7 +115,6 @@ inline void MixAddVoice(ParamBlockType &pb, int *templbuffer, int *temprbuffer,
if (pb.running) if (pb.running)
{ {
// =======================================================================================
// Read initial parameters // Read initial parameters
// ------------ // ------------
//constants //constants

View File

@ -24,7 +24,7 @@
#include "../MailHandler.h" #include "../MailHandler.h"
#include "../main.h" #include "../main.h"
#include "../PCHW/Mixer.h" #include "Mixer.h"
CUCode_Zelda::CUCode_Zelda(CMailHandler& _rMailHandler) CUCode_Zelda::CUCode_Zelda(CMailHandler& _rMailHandler)
@ -157,8 +157,7 @@ void CUCode_Zelda::ExecuteList()
tmp[2] = Read32(); tmp[2] = Read32();
// We're ready to mix // We're ready to mix
mixer_HLEready = true; soundStream->GetMixer()->SetHLEReady(true);
DEBUG_LOG(DSPHLE, "Update the SoundThread to be in sync"); DEBUG_LOG(DSPHLE, "Update the SoundThread to be in sync");
soundStream->Update(); //do it in this thread to avoid sync problems soundStream->Update(); //do it in this thread to avoid sync problems

View File

@ -28,16 +28,17 @@ CDebugger* m_frame = NULL;
#include "ChunkFile.h" #include "ChunkFile.h"
#include "WaveFile.h" #include "WaveFile.h"
#include "PCHW/Mixer.h" #include "HLEMixer.h"
#include "DSPHandler.h" #include "DSPHandler.h"
#include "Config.h" #include "Config.h"
#include "Setup.h" #include "Setup.h"
#include "StringUtil.h" #include "StringUtil.h"
#include "AudioCommon.h"
#include "AOSoundStream.h" #include "AOSoundStream.h"
#include "DSoundStream.h" #include "DSoundStream.h"
#include "NullSoundStream.h" #include "NullSoundStream.h"
// Declarations and definitions // Declarations and definitions
PLUGIN_GLOBALS* globals = NULL; PLUGIN_GLOBALS* globals = NULL;
DSPInitialize g_dspInitialize; DSPInitialize g_dspInitialize;
@ -192,6 +193,7 @@ void DllConfig(HWND _hParent)
#endif #endif
} }
void Initialize(void *init) void Initialize(void *init)
{ {
g_dspInitialize = *(DSPInitialize*)init; g_dspInitialize = *(DSPInitialize*)init;
@ -201,45 +203,9 @@ void Initialize(void *init)
CDSPHandler::CreateInstance(); CDSPHandler::CreateInstance();
if (g_Config.sBackend == "DSound") soundStream = AudioCommon::InitSoundStream(g_Config.sBackend,
{ new HLEMixer());
if (DSound::isValid()) soundStream->GetMixer()->SetThrottle(g_Config.m_EnableThrottle);
soundStream = new DSound(48000, Mixer, g_dspInitialize.hWnd);
}
else if (g_Config.sBackend == "AOSound")
{
if (AOSound::isValid())
soundStream = new AOSound(48000, Mixer);
}
else if (g_Config.sBackend == "NullSound")
{
soundStream = new NullSound(48000, Mixer_MixUCode);
}
else
{
PanicAlert("Cannot recognize backend %s", g_Config.sBackend.c_str());
return;
}
if (soundStream)
{
if (!soundStream->Start())
{
PanicAlert("Could not initialize backend %s, falling back to NULL",
g_Config.sBackend.c_str());
delete soundStream;
soundStream = new NullSound(48000, Mixer);
soundStream->Start();
}
}
else
{
PanicAlert("Sound backend %s is not valid, falling back to NULL",
g_Config.sBackend.c_str());
delete soundStream;
soundStream = new NullSound(48000, Mixer);
soundStream->Start();
}
// Start the sound recording // Start the sound recording
if (log_ai) if (log_ai)
@ -251,15 +217,20 @@ void Initialize(void *init)
void DSP_StopSoundStream() void DSP_StopSoundStream()
{ {
// fprintf(stderr, "in dsp stop\n");
if (!soundStream) if (!soundStream)
PanicAlert("Can't stop non running SoundStream!"); PanicAlert("Can't stop non running SoundStream!");
soundStream->Stop(); soundStream->Stop();
delete soundStream; delete soundStream;
soundStream = NULL; soundStream = NULL;
// fprintf(stderr, "in dsp stop end\n");
} }
void Shutdown() void Shutdown()
{ {
// FIXME: called before stop is finished????
// fprintf(stderr, "in dsp shutdown\n");
// Check that soundstream already is stopped. // Check that soundstream already is stopped.
if (soundStream) if (soundStream)
PanicAlert("SoundStream alive in DSP::Shutdown!"); PanicAlert("SoundStream alive in DSP::Shutdown!");
@ -384,7 +355,7 @@ void DSP_SendAIBuffer(unsigned int address, int sample_rate)
return; return;
} }
if (soundStream->usesMixer()) if (soundStream->GetMixer())
{ {
short samples[16] = {0}; // interleaved stereo short samples[16] = {0}; // interleaved stereo
if (address) if (address)
@ -398,7 +369,7 @@ void DSP_SendAIBuffer(unsigned int address, int sample_rate)
if (log_ai) if (log_ai)
g_wave_writer.AddStereoSamples(samples, 8); g_wave_writer.AddStereoSamples(samples, 8);
} }
Mixer_PushSamples(samples, 32 / 4, sample_rate); soundStream->GetMixer()->PushSamples(samples, 32 / 4);
} }
// SoundStream is updated only when necessary (there is no 70 ms limit // SoundStream is updated only when necessary (there is no 70 ms limit

View File

@ -33,8 +33,7 @@ void CConfig::Load()
IniFile file; IniFile file;
file.Load(FULL_CONFIG_DIR "DSP.ini"); file.Load(FULL_CONFIG_DIR "DSP.ini");
file.Get("Config", "EnableHLEAudio", &m_EnableHLEAudio, true); // Sound Settings file.Get("Config", "EnableHLEAudio", &m_EnableHLEAudio, false);
file.Get("Config", "EnableDTKMusic", &m_EnableDTKMusic, true);
file.Get("Config", "EnableThrottle", &m_EnableThrottle, true); file.Get("Config", "EnableThrottle", &m_EnableThrottle, true);
#ifdef _WIN32 #ifdef _WIN32
file.Get("Config", "Backend", &sBackend, "DSound"); file.Get("Config", "Backend", &sBackend, "DSound");
@ -48,7 +47,6 @@ void CConfig::Save()
IniFile file; IniFile file;
file.Load(FULL_CONFIG_DIR "DSP.ini"); file.Load(FULL_CONFIG_DIR "DSP.ini");
file.Set("Config", "EnableHLEAudio", m_EnableHLEAudio); // Sound Settings file.Set("Config", "EnableHLEAudio", m_EnableHLEAudio); // Sound Settings
file.Set("Config", "EnableDTKMusic", m_EnableDTKMusic);
file.Set("Config", "EnableThrottle", m_EnableThrottle); file.Set("Config", "EnableThrottle", m_EnableThrottle);
file.Set("Config", "Backend", sBackend.c_str()); file.Set("Config", "Backend", sBackend.c_str());

View File

@ -39,19 +39,16 @@ ConfigDialog::ConfigDialog(wxWindow *parent, wxWindowID id, const wxString &titl
// Create items // Create items
m_buttonEnableHLEAudio = new wxCheckBox(this, ID_ENABLE_HLE_AUDIO, wxT("Enable HLE Audio"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); m_buttonEnableHLEAudio = new wxCheckBox(this, ID_ENABLE_HLE_AUDIO, wxT("Enable HLE Audio"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
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 Other Audio (Throttle)"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
wxStaticText *BackendText = new wxStaticText(this, wxID_ANY, wxT("Audio Backend"), wxDefaultPosition, wxDefaultSize, 0); wxStaticText *BackendText = new wxStaticText(this, wxID_ANY, wxT("Audio Backend"), wxDefaultPosition, wxDefaultSize, 0);
m_BackendSelection = new wxComboBox(this, ID_BACKEND, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxArrayBackends, wxCB_READONLY, wxDefaultValidator); m_BackendSelection = new wxComboBox(this, ID_BACKEND, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxArrayBackends, wxCB_READONLY, wxDefaultValidator);
// Update values // Update values
m_buttonEnableHLEAudio->SetValue(g_Config.m_EnableHLEAudio ? true : false); m_buttonEnableHLEAudio->SetValue(g_Config.m_EnableHLEAudio ? true : false);
m_buttonEnableDTKMusic->SetValue(g_Config.m_EnableDTKMusic ? true : false);
m_buttonEnableThrottle->SetValue(g_Config.m_EnableThrottle ? true : false); m_buttonEnableThrottle->SetValue(g_Config.m_EnableThrottle ? true : false);
// Add tooltips // Add tooltips
m_buttonEnableHLEAudio->SetToolTip(wxT("This is the most common sound type")); m_buttonEnableHLEAudio->SetToolTip(wxT("This is the most common sound type"));
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" m_buttonEnableThrottle->SetToolTip(wxT("This is sometimes used together with pre-rendered movies.\n"
"Disabling this also disables the speed throttle which this causes,\n" "Disabling this also disables the speed throttle which this causes,\n"
"meaning that there will be no upper limit on your FPS.")); "meaning that there will be no upper limit on your FPS."));
@ -61,7 +58,6 @@ ConfigDialog::ConfigDialog(wxWindow *parent, wxWindowID id, const wxString &titl
wxBoxSizer *sMain = new wxBoxSizer(wxVERTICAL); wxBoxSizer *sMain = new wxBoxSizer(wxVERTICAL);
wxStaticBoxSizer *sbSettings = new wxStaticBoxSizer(wxVERTICAL, this, wxT("Sound Settings")); wxStaticBoxSizer *sbSettings = new wxStaticBoxSizer(wxVERTICAL, this, wxT("Sound Settings"));
sbSettings->Add(m_buttonEnableHLEAudio, 0, wxALL, 5); sbSettings->Add(m_buttonEnableHLEAudio, 0, wxALL, 5);
sbSettings->Add(m_buttonEnableDTKMusic, 0, wxALL, 5);
sbSettings->Add(m_buttonEnableThrottle, 0, wxALL, 5); sbSettings->Add(m_buttonEnableThrottle, 0, wxALL, 5);
wxBoxSizer *sBackend = new wxBoxSizer(wxHORIZONTAL); wxBoxSizer *sBackend = new wxBoxSizer(wxHORIZONTAL);
sBackend->Add(BackendText, 0, wxALIGN_CENTRE_VERTICAL|wxALL, 5); sBackend->Add(BackendText, 0, wxALIGN_CENTRE_VERTICAL|wxALL, 5);
@ -91,7 +87,6 @@ ConfigDialog::~ConfigDialog()
void ConfigDialog::SettingsChanged(wxCommandEvent& event) void ConfigDialog::SettingsChanged(wxCommandEvent& event)
{ {
g_Config.m_EnableHLEAudio = m_buttonEnableHLEAudio->GetValue(); g_Config.m_EnableHLEAudio = m_buttonEnableHLEAudio->GetValue();
g_Config.m_EnableDTKMusic = m_buttonEnableDTKMusic->GetValue();
g_Config.m_EnableThrottle = m_buttonEnableThrottle->GetValue(); g_Config.m_EnableThrottle = m_buttonEnableThrottle->GetValue();
g_Config.sBackend = m_BackendSelection->GetValue().mb_str(); g_Config.sBackend = m_BackendSelection->GetValue().mb_str();
g_Config.Save(); g_Config.Save();

View File

@ -18,15 +18,14 @@
#ifndef _GLOBALS_H #ifndef _GLOBALS_H
#define _GLOBALS_H #define _GLOBALS_H
#include "pluginspecs_dsp.h" #include "AudioCommon.h"
#include "Common.h"
#include <stdio.h> #include <stdio.h>
#define WITH_DSP_ON_THREAD 1 #define WITH_DSP_ON_THREAD 1
#define DUMP_DSP_IMEM 0 #define DUMP_DSP_IMEM 0
#define PROFILE 1 #define PROFILE 1
extern DSPInitialize g_dspInitialize;
void DSP_DebugBreak(); void DSP_DebugBreak();

View File

@ -23,10 +23,9 @@
extern u32 m_addressPBs; extern u32 m_addressPBs;
// ======================================================================================= // Get the parameter block location - Example SSBM: We get the addr 8049cf00,
// Get the parameter block location - Example SSBM: We get the addr 8049cf00, first we // first we always get 0 and go to AXLIST_STUDIOADDR, then we end up at
// always get 0 and go to AXLIST_STUDIOADDR, then we end up at AXLIST_PBADDR. // AXLIST_PBADDR.
// --------------
bool AXTask(u32& _uMail) bool AXTask(u32& _uMail)
{ {
u32 uAddress = _uMail; u32 uAddress = _uMail;
@ -37,15 +36,12 @@ bool AXTask(u32& _uMail)
while (bExecuteList) while (bExecuteList)
{ {
// ---------------------------------------------------------------------------------------
// SSBM: We get the addr 8049cf00, first we always get 0 // SSBM: We get the addr 8049cf00, first we always get 0
u16 iCommand = Memory_Read_U16(uAddress); u16 iCommand = Memory_Read_U16(uAddress);
uAddress += 2; uAddress += 2;
// ---------------------------------------------------------------------------------------
switch (iCommand) switch (iCommand)
{ {
// ---------------------------------------------------------------------------------------
// ? // ?
case 0: // AXLIST_STUDIOADDR: //00 case 0: // AXLIST_STUDIOADDR: //00
{ {
@ -53,10 +49,8 @@ bool AXTask(u32& _uMail)
DEBUG_LOG(DSPHLE, "AXLIST AXLIST_SBUFFER: %08x", uAddress); DEBUG_LOG(DSPHLE, "AXLIST AXLIST_SBUFFER: %08x", uAddress);
} }
break; break;
// ---------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------
case 2: // AXLIST_PBADDR: // 02 case 2: // AXLIST_PBADDR: // 02
{ {
m_addressPBs = Memory_Read_U32(uAddress); m_addressPBs = Memory_Read_U32(uAddress);
@ -66,7 +60,6 @@ bool AXTask(u32& _uMail)
} }
break; break;
// ---------------------------------------------------------------------------------------
case 7: // AXLIST_SBUFFER: // 7 case 7: // AXLIST_SBUFFER: // 7
{ {
// Hopefully this is where in main ram to write. // Hopefully this is where in main ram to write.
@ -79,11 +72,9 @@ bool AXTask(u32& _uMail)
default: default:
{ {
// ---------------------------------------------------------------------------------------
// Stop the execution of this TaskList // Stop the execution of this TaskList
DEBUG_LOG(DSPHLE, "AXLIST default: %08x", uAddress); DEBUG_LOG(DSPHLE, "AXLIST default: %08x", uAddress);
bExecuteList = false; bExecuteList = false;
// ---------------------------------------------------------------------------------------
} }
break; break;
} // end of switch } // end of switch
@ -95,6 +86,6 @@ bool AXTask(u32& _uMail)
// now resume // now resume
return true; return true;
} }
// =======================================================================================

View File

@ -16,82 +16,65 @@
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#ifdef _WIN32
// =======================================================================================
// Includes
// --------------
#include <iostream> #include <iostream>
#include <vector> #include <vector>
#include <string> // So that we can test if std::string == abc #include <string> // So that we can test if std::string == abc
#include <windows.h>
#include "Common.h" #include "Common.h"
#include "UCode_AXStructs.h" // they are only in a virtual dir called UCodes AX #include "UCode_AXStructs.h" // they are only in a virtual dir called UCodes AX
// =====================
// =======================================================================================
// Declarations and definitions
// --------------
// ----------------------------------
// Settings // Settings
// --------------
#define NUMBER_OF_PBS 64 // Todo: move this to a logging class #define NUMBER_OF_PBS 64 // Todo: move this to a logging class
// -----------------------------------
// Externals // Externals
// --------------
extern u32 m_addressPBs; extern u32 m_addressPBs;
float ratioFactor; float ratioFactor;
int globaliSize; int globaliSize;
short globalpBuffer; short globalpBuffer;
u32 gLastBlock; u32 gLastBlock;
// --------------
// -----------------------------------
// Vectors and other things // Vectors and other things
// --------------
std::vector<u32> gloopPos(64); std::vector<u32> gloopPos(64);
std::vector<u32> gsampleEnd(64); std::vector<u32> gsampleEnd(64);
std::vector<u32> gsamplePos(64); std::vector<u32> gsamplePos(64);
std::vector<u32> gratio(64); std::vector<u32> gratio(64);
std::vector<u32> gratiohi(64); std::vector<u32> gratiohi(64);
std::vector<u32> gratiolo(64); std::vector<u32> gratiolo(64);
std::vector<u32> gfrac(64); std::vector<u32> gfrac(64);
std::vector<u32> gcoef(64); std::vector<u32> gcoef(64);
// PBSampleRateConverter mixer // PBSampleRateConverter mixer
std::vector<u16> gvolume_left(64); std::vector<u16> gvolume_left(64);
std::vector<u16> gvolume_right(64); std::vector<u16> gvolume_right(64);
std::vector<u16> gmixer_control(64); std::vector<u16> gmixer_control(64);
std::vector<u16> gcur_volume(64); std::vector<u16> gcur_volume(64);
std::vector<u16> gcur_volume_delta(64); std::vector<u16> gcur_volume_delta(64);
std::vector<u16> gaudioFormat(64); std::vector<u16> gaudioFormat(64);
std::vector<u16> glooping(64); std::vector<u16> glooping(64);
std::vector<u16> gsrc_type(64); std::vector<u16> gsrc_type(64);
std::vector<u16> gis_stream(64); std::vector<u16> gis_stream(64);
// loop // loop
std::vector<u16> gloop1(64); std::vector<u16> gloop1(64);
std::vector<u16> gloop2(64); std::vector<u16> gloop2(64);
std::vector<u16> gloop3(64); std::vector<u16> gloop3(64);
std::vector<u16> gadloop1(64); std::vector<u16> gadloop1(64);
std::vector<u16> gadloop2(64); std::vector<u16> gadloop2(64);
std::vector<u16> gadloop3(64); std::vector<u16> gadloop3(64);
// updates // updates
std::vector<u16> gupdates1(64); std::vector<u16> gupdates1(64);
std::vector<u16> gupdates2(64); std::vector<u16> gupdates2(64);
std::vector<u16> gupdates3(64); std::vector<u16> gupdates3(64);
std::vector<u16> gupdates4(64); std::vector<u16> gupdates4(64);
std::vector<u16> gupdates5(64); std::vector<u16> gupdates5(64);
std::vector<u32> gupdates_addr(64); std::vector<u32> gupdates_addr(64);
// Other things // Other things
std::vector<u16> Jump(64); // this is 1 or 0 std::vector<u16> Jump(64); // this is 1 or 0
@ -101,7 +84,7 @@ std::vector<int> numberRunning(64);
int j = 0; int j = 0;
int k = 0; int k = 0;
__int64 l = 0; s64 l = 0;
int iupd = 0; int iupd = 0;
bool iupdonce = false; bool iupdonce = false;
std::vector<u16> viupd(15); // the length of the update frequency bar std::vector<u16> viupd(15); // the length of the update frequency bar
@ -112,18 +95,11 @@ std::vector<u16> vector62(vectorLength);
std::vector<u16> vector63(vectorLength); std::vector<u16> vector63(vectorLength);
int ReadOutPBs(AXParamBlock * _pPBs, int _num); int ReadOutPBs(AXParamBlock * _pPBs, int _num);
// =====================
// =======================================================================================
// Main logging function // Main logging function
// --------------
void Logging() void Logging()
{ {
// ---------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------
// Control how often the screen is updated // Control how often the screen is updated
j++; j++;
l++; l++;
@ -151,16 +127,13 @@ void Logging()
} }
// ================= // =================
// ---------------------------------------------------------------------------------------
// Enter the latest value // Enter the latest value
for (int i = 0; i < numberOfPBs; i++) 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;
} }
// -----------------
// ---------------------------------------------------------------------------------------
// Count how many blocks we have running now // Count how many blocks we have running now
int jj = 0; int jj = 0;
for (int i = 0; i < 64; i++) for (int i = 0; i < 64; i++)
@ -174,27 +147,22 @@ void Logging()
numberRunning.at(i) = jj; numberRunning.at(i) = jj;
} }
} }
// --------------
// ---------------------------------------------------------------------------------------
// Write the first row // Write the first row
char buffer [1000] = ""; char buffer [1000] = "";
std::string sbuff; std::string sbuff;
//sbuff = sbuff + " Nr | | frac ratio | old new \n"; // 5 //sbuff = sbuff + " Nr | | frac ratio | old new \n"; // 5
sbuff = sbuff + " Nr pos / end lpos | voll volr curv vold mix | isl[pre yn1 yn2] iss | frac ratio[hi lo] | 1 2 3 4 5\n"; sbuff = sbuff + " Nr pos / end lpos | voll volr curv vold mix | isl[pre yn1 yn2] iss | frac ratio[hi lo] | 1 2 3 4 5\n";
// --------------
// ---------------------------------------------------------------------------------------
// Read out values for all blocks // Read out values for all blocks
for (int i = 0; i < numberOfPBs; i++) for (int i = 0; i < numberOfPBs; i++)
{ {
if (numberRunning.at(i) > 0) if (numberRunning.at(i) > 0)
{ {
// =======================================================================================
// Write the playback bar // Write the playback bar
// -------------
for (int j = 0; j < vectorLength; j++) for (int j = 0; j < vectorLength; j++)
{ {
if(vector1.at(i).at(j) == 0) if(vector1.at(i).at(j) == 0)
@ -207,16 +175,13 @@ void Logging()
sbuff = sbuff + buffer; strcpy(buffer, ""); sbuff = sbuff + buffer; strcpy(buffer, "");
} }
} }
// ==============
// ================================================================================================
int sampleJump; int sampleJump;
int loopJump; int loopJump;
//if (PBs[i].running && PBs[i].adpcm_loop_info.yn1 && PBs[i].mixer.volume_left) //if (PBs[i].running && PBs[i].adpcm_loop_info.yn1 && PBs[i].mixer.volume_left)
if (true) if (true)
{ {
// ---------------------------------------------------------------------------------------
// AXPB base // AXPB base
//int running = pb.running; //int running = pb.running;
gcoef[i] = PBs[i].unknown1; gcoef[i] = PBs[i].unknown1;
@ -271,13 +236,11 @@ void Logging()
musicLength[i] = gsampleEnd[i] - gloopPos[i]; musicLength[i] = gsampleEnd[i] - gloopPos[i];
} }
// ================================================================================================
// =======================================================================================
// PRESETS // PRESETS
// ---------------------------------------------------------------------------------------
/* /*
/" Nr pos / end lpos | voll volr curv vold mix | isl[pre yn1 yn2] iss | frac ratio[hi lo] | 1 2 3 4 5\n"; /" Nr pos / end lpos | voll volr curv vold mix | isl[pre yn1 yn2] iss | frac ratio[hi lo] | 1 2 3 4 5\n";
"---------------|00 12341234/12341234 12341234 | 00000 00000 00000 0000 00000 | 0[000 00000 00000] 0 | 00000 00000[0 00000] | "---------------|00 12341234/12341234 12341234 | 00000 00000 00000 0000 00000 | 0[000 00000 00000] 0 | 00000 00000[0 00000] |
@ -289,7 +252,6 @@ void Logging()
gfrac[i], gratio[i], gratiohi[i], gratiolo[i], gfrac[i], gratio[i], gratiohi[i], gratiolo[i],
gupdates1[i], gupdates2[i], gupdates3[i], gupdates4[i], gupdates5[i] gupdates1[i], gupdates2[i], gupdates3[i], gupdates4[i], gupdates5[i]
); );
// =======================================================================================
// write a new line // write a new line
sbuff = sbuff + buffer; strcpy(buffer, ""); sbuff = sbuff + buffer; strcpy(buffer, "");
@ -301,16 +263,12 @@ void Logging()
} // end of big loop - for (int i = 0; i < numberOfPBs; i++) } // end of big loop - for (int i = 0; i < numberOfPBs; i++)
// =======================================================================================
// Write global values // Write global values
sprintf(buffer, "\nParameter blocks span from %08x | to %08x | distance %i %i\n", m_addressPBs, gLastBlock, (gLastBlock-m_addressPBs), (gLastBlock-m_addressPBs) / 192); sprintf(buffer, "\nParameter blocks span from %08x | to %08x | distance %i %i\n", m_addressPBs, gLastBlock, (gLastBlock-m_addressPBs), (gLastBlock-m_addressPBs) / 192);
sbuff = sbuff + buffer; strcpy(buffer, ""); sbuff = sbuff + buffer; strcpy(buffer, "");
// ==============
// =======================================================================================
// Show update frequency // Show update frequency
// ---------------
sbuff = sbuff + "\n"; sbuff = sbuff + "\n";
if(!iupdonce) if(!iupdonce)
{ {
@ -358,10 +316,8 @@ void Logging()
// ================ // ================
// =======================================================================================
// Print // Print
// ---------------
// Console::ClearScreen();
INFO_LOG(DSPHLE, "%s", sbuff.c_str()); INFO_LOG(DSPHLE, "%s", sbuff.c_str());
sbuff.clear(); strcpy(buffer, ""); sbuff.clear(); strcpy(buffer, "");
// --------------- // ---------------
@ -370,13 +326,9 @@ void Logging()
// --------------- // ---------------
} }
// ---------------------------------------------------------------------------------------
} }
// =======================================================================================
#endif

View File

@ -15,9 +15,9 @@
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#ifndef LOGGING_H
#ifdef _WIN32 #define LOGGING_H
void Logging(); void Logging();
#endif #endif

View File

@ -33,10 +33,6 @@
u32 m_addressPBs = 0; u32 m_addressPBs = 0;
extern u32 gLastBlock; extern u32 gLastBlock;
#ifdef _WIN32
int m = 0; int m = 0;
int n = 0; int n = 0;
#ifdef LOG2 #ifdef LOG2
@ -56,20 +52,18 @@ int ReadOutPBs(AXParamBlock * _pPBs, int _num)
//FIXME if (n > 20 && logall) {Console::ClearScreen();} //FIXME if (n > 20 && logall) {Console::ClearScreen();}
for (int i = 0; i < _num; i++) for (int i = 0; i < _num; i++)
{ {
// ---------------------------------------------------------------------------------------
// Check if there is something here. // Check if there is something here.
const short * pSrc = (const short *)g_dspInitialize.pGetMemoryPointer(blockAddr); const short * pSrc = (const short *)g_dspInitialize.pGetMemoryPointer(blockAddr);
// ------------- // -------------
if (pSrc != NULL) // only read non-blank blocks if (pSrc != NULL) // only read non-blank blocks
{ {
// ---------------------------------------------------------------------------------------
// Create a shortcut that let us update struct members // Create a shortcut that let us update struct members
short * pDest = (short *) & _pPBs[i]; short * pDest = (short *) & _pPBs[i];
if (n > 20 && logall) {DEBUG_LOG(DSPHLE, "%c%i:", 223, i);} // logging if (n > 20 && logall) {DEBUG_LOG(DSPHLE, "%c%i:", 223, i);} // logging
// --------------
// Here we update the PB. We do it by going through all 192 / 2 = 96 u16 values // Here we update the PB. We do it by going through all 192 / 2 = 96 u16 values
for (size_t p = 0; p < sizeof(AXParamBlock) / 2; p++) for (size_t p = 0; p < sizeof(AXParamBlock) / 2; p++)
{ {
@ -88,10 +82,8 @@ int ReadOutPBs(AXParamBlock * _pPBs, int _num)
} }
if(n > 20 && logall) {DEBUG_LOG(DSPHLE, "\n");} // logging if(n > 20 && logall) {DEBUG_LOG(DSPHLE, "\n");} // logging
// --------------
// Here we update the block address to the starting point of the next PB // Here we update the block address to the starting point of the next PB
blockAddr = (_pPBs[i].next_pb_hi << 16) | _pPBs[i].next_pb_lo; blockAddr = (_pPBs[i].next_pb_hi << 16) | _pPBs[i].next_pb_lo;
// --------------
// save some values // save some values
count++; count++;
gLastBlock = paraAddr; // blockAddr gLastBlock = paraAddr; // blockAddr
@ -109,6 +101,3 @@ int ReadOutPBs(AXParamBlock * _pPBs, int _num)
// return the number of readed PBs // return the number of readed PBs
return count; return count;
} }
// =======================================================================================
#endif

View File

@ -14,8 +14,6 @@
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#ifdef _WIN32
#ifndef UCODE_AX_STRUCTS #ifndef UCODE_AX_STRUCTS
#define UCODE_AX_STRUCTS #define UCODE_AX_STRUCTS
@ -142,5 +140,4 @@ enum {
#endif #endif
#endif // win32

View File

@ -1,164 +0,0 @@
// 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/
// This queue solution is temporary. I'll implement something more efficient later.
#include <queue>
#include "Thread.h"
#include "Mixer.h"
#include "FixedSizeQueue.h"
#ifdef _WIN32
#include "DSoundStream.h"
#else
#include <unistd.h>
#endif
namespace {
Common::CriticalSection push_sync;
// On real hardware, this fifo is much, much smaller. But timing is also tighter than under Windows, so...
const int queue_minlength = 1024 * 4;
const int queue_maxlength = 1024 * 28;
FixedSizeQueue<s16, queue_maxlength> sample_queue;
} // namespace
volatile bool mixer_HLEready = false;
volatile int queue_size = 0;
void Mixer(short *buffer, int numSamples, int bits, int rate, int channels)
{
// silence
memset(buffer, 0, numSamples * 2 * sizeof(short));
push_sync.Enter();
int count = 0;
while (queue_size > queue_minlength && count < numSamples * 2) {
int x = buffer[count];
x += sample_queue.front();
if (x > 32767) x = 32767;
if (x < -32767) x = -32767;
buffer[count++] = x;
sample_queue.pop();
x = buffer[count];
x += sample_queue.front();
if (x > 32767) x = 32767;
if (x < -32767) x = -32767;
buffer[count++] = x;
sample_queue.pop();
queue_size-=2;
}
push_sync.Leave();
}
void Mixer_PushSamples(short *buffer, int num_stereo_samples, int sample_rate) {
// static FILE *f;
// if (!f)
// f = fopen("d:\\hello.raw", "wb");
// fwrite(buffer, num_stereo_samples * 4, 1, f);
if (queue_size == 0)
{
queue_size = queue_minlength;
for (int i = 0; i < queue_minlength; i++)
sample_queue.push((s16)0);
}
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)) {
while (queue_size > queue_maxlength / 2) {
DSound::DSound_UpdateSound();
Sleep(0);
}
} else {
return;
}
#else
while (queue_size > queue_maxlength) {
sleep(0);
}
#endif
//convert into config option?
const int mode = 2;
push_sync.Enter();
while (num_stereo_samples)
{
acc += sample_rate;
while (num_stereo_samples && (acc >= 48000))
{
PV4l=PV3l;
PV3l=PV2l;
PV2l=PV1l;
PV1l=*(buffer++); //32bit processing
PV4r=PV3r;
PV3r=PV2r;
PV2r=PV1r;
PV1r=*(buffer++); //32bit processing
num_stereo_samples--;
acc-=48000;
}
// defaults to nearest
s32 DataL = PV1l;
s32 DataR = PV1r;
if (mode == 1) //linear
{
DataL = PV1l + ((PV2l - PV1l)*acc)/48000;
DataR = PV1r + ((PV2r - PV1r)*acc)/48000;
}
else if (mode == 2) //cubic
{
s32 a0l = PV1l - PV2l - PV4l + PV3l;
s32 a0r = PV1r - PV2r - PV4r + PV3r;
s32 a1l = PV4l - PV3l - a0l;
s32 a1r = PV4r - PV3r - a0r;
s32 a2l = PV1l - PV4l;
s32 a2r = PV1r - PV4r;
s32 a3l = PV2l;
s32 a3r = PV2r;
s32 t0l = ((a0l )*acc)/48000;
s32 t0r = ((a0r )*acc)/48000;
s32 t1l = ((t0l+a1l)*acc)/48000;
s32 t1r = ((t0r+a1r)*acc)/48000;
s32 t2l = ((t1l+a2l)*acc)/48000;
s32 t2r = ((t1r+a2r)*acc)/48000;
s32 t3l = ((t2l+a3l));
s32 t3r = ((t2r+a3r));
DataL = t3l;
DataR = t3r;
}
int l = DataL, r = DataR;
if (l < -32767) l = -32767;
if (r < -32767) r = -32767;
if (l > 32767) l = 32767;
if (r > 32767) r = 32767;
sample_queue.push(l);
sample_queue.push(r);
}
push_sync.Leave();
}

View File

@ -1,30 +0,0 @@
// 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/
#ifndef _MIXER_H
#define _MIXER_H
extern volatile bool mixer_HLEready;
// Called from audio threads
void Mixer(short* buffer, int numSamples, int bits, int rate, int channels);
// Called from main thread
void Mixer_PushSamples(short *buffer, int num_stereo_samples, int sample_rate);
#endif

View File

@ -25,7 +25,6 @@ files = [
"HLE_Functions.cpp", "HLE_Functions.cpp",
"HLE_Helper.cpp", "HLE_Helper.cpp",
"main.cpp", "main.cpp",
"Mixer.cpp",
"opcodes.cpp", "opcodes.cpp",
# "RegisterDlg.cpp", # "RegisterDlg.cpp",
# "RegSettings.cpp", # "RegSettings.cpp",

View File

@ -417,7 +417,7 @@ void Hacks()
} }
} */ } */
if (g_dsp.pc == 0x468) /* if (g_dsp.pc == 0x468)
{ {
int numSamples = g_dsp.r[25] / 2; int numSamples = g_dsp.r[25] / 2;
uint16 bufferAddr = g_dsp.r[27]; uint16 bufferAddr = g_dsp.r[27];
@ -429,7 +429,7 @@ void Hacks()
{ {
samples[i] = dsp_dmem_read(bufferAddr+i); samples[i] = dsp_dmem_read(bufferAddr+i);
} }
Mixer_PushSamples(samples, numSamples / 2, 32000); //sample_rate); PushSamples(samples, numSamples / 2, 32000); //sample_rate);
g_wave_writer.AddStereoSamples(samples, numSamples/2); // 2 channels g_wave_writer.AddStereoSamples(samples, numSamples/2); // 2 channels
@ -439,5 +439,5 @@ void Hacks()
g_wave_writer.Stop(); g_wave_writer.Stop();
exit(1); exit(1);
} }
} }*/
} }

View File

@ -31,27 +31,20 @@
#include "ConfigDlg.h" #include "ConfigDlg.h"
#endif #endif
#include "AudioCommon.h"
#include "AOSoundStream.h" #include "AOSoundStream.h"
#include "DSoundStream.h" #include "DSoundStream.h"
#include "NullSoundStream.h" #include "NullSoundStream.h"
#include "Logging/Logging.h" // For Logging
#ifdef _WIN32 #ifdef _WIN32
#include "DisAsmDlg.h" #include "DisAsmDlg.h"
#include "Logging/Logging.h" // For Logging
HINSTANCE g_hInstance = NULL; HINSTANCE g_hInstance = NULL;
CDisAsmDlg g_Dialog; CDisAsmDlg g_Dialog;
#else
#define WINAPI
#define LPVOID void*
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include "AOSoundStream.h"
#endif #endif
#include "Thread.h"
#include "ChunkFile.h" #include "ChunkFile.h"
PLUGIN_GLOBALS* globals = NULL; PLUGIN_GLOBALS* globals = NULL;
@ -159,7 +152,7 @@ void DllDebugger(HWND _hParent, bool Show)
} }
// Regular thread /*// Regular thread
#ifdef _WIN32 #ifdef _WIN32
DWORD WINAPI dsp_thread(LPVOID lpParameter) DWORD WINAPI dsp_thread(LPVOID lpParameter)
#else #else
@ -203,7 +196,7 @@ void* dsp_thread_debug(void* lpParameter)
return NULL; return NULL;
} }
*/
void DSP_DebugBreak() void DSP_DebugBreak()
{ {
#ifdef _WIN32 #ifdef _WIN32
@ -230,24 +223,22 @@ void Initialize(void *init)
g_dsp.irq_request = dspi_req_dsp_irq; g_dsp.irq_request = dspi_req_dsp_irq;
gdsp_reset(); gdsp_reset();
if (!gdsp_load_rom((char *)DSP_ROM_FILE)) if (!gdsp_load_rom((char *)DSP_ROM_FILE)) {
{
bCanWork = false; bCanWork = false;
PanicAlert("Cannot load DSP ROM"); PanicAlert("Cannot load DSP ROM");
} }
if (!gdsp_load_coef((char *)DSP_COEF_FILE)) if (!gdsp_load_coef((char *)DSP_COEF_FILE)) {
{
bCanWork = false; bCanWork = false;
PanicAlert("Cannot load DSP COEF"); PanicAlert("Cannot load DSP COEF");
} }
if(!bCanWork) if(!bCanWork)
return; // TODO: Don't let it work return; // TODO: Don't let it work
// First create DSP_UCode.bin by setting "#define DUMP_DSP_IMEM 1" in /*/ First create DSP_UCode.bin by setting "#define DUMP_DSP_IMEM 1" in
// Globals.h. Then make the disassembled file here. Dump UCode to file... // Globals.h. Then make the disassembled file here. Dump UCode to file...
FILE* t = fopen("C:\\_\\DSP_UC_09CD143F.txt", "wb"); FILE* t = fopen("C:\\_\\DSP_UC_09CD143F.txt", "wb");
if (t != NULL) if (t != NULL)
{ {
@ -255,49 +246,15 @@ void Initialize(void *init)
gd_dis_file(&gdg, (char *)"C:\\_\\DSP_UC_09CD143F.bin", t); gd_dis_file(&gdg, (char *)"C:\\_\\DSP_UC_09CD143F.bin", t);
fclose(t); fclose(t);
} }
*/
if (g_Config.sBackend == "DSound")
soundStream = AudioCommon::InitSoundStream(g_Config.sBackend);
soundStream->GetMixer()->SetThrottle(g_Config.m_EnableThrottle);
// Start the sound recording
if (log_ai)
{ {
if (DSound::isValid()) g_wave_writer.Start("ai_log.wav");
soundStream = new DSound(48000, Mixer, g_dspInitialize.hWnd);
}
else if (g_Config.sBackend == "AOSound")
{
if (AOSound::isValid())
soundStream = new AOSound(48000, Mixer);
}
else if (g_Config.sBackend == "NullSound")
{
soundStream = new NullSound(48000, Mixer);
}
else
{
PanicAlert("Cannot recognize backend %s", g_Config.sBackend.c_str());
return;
}
if (soundStream)
{
if (!soundStream->Start())
{
PanicAlert("Could not initialize backend %s, falling back to NULL",
g_Config.sBackend.c_str());
delete soundStream;
soundStream = new NullSound(48000, Mixer);
soundStream->Start();
}
}
else
{
PanicAlert("Sound backend %s is not valid, falling back to NULL",
g_Config.sBackend.c_str());
delete soundStream;
soundStream = new NullSound(48000, Mixer);
soundStream->Start();
}
if (log_ai) {
g_wave_writer.Start("C:\\_\\ai_log.wav");
g_wave_writer.SetSkipSilence(false); g_wave_writer.SetSkipSilence(false);
} }
} }
@ -418,25 +375,39 @@ void DSP_Update(int cycles)
} }
void DSP_SendAIBuffer(unsigned int address, int sample_rate) void DSP_SendAIBuffer(unsigned int address, int sample_rate)
{ {
short samples[16] = {0}; // interleaved stereo // TODO: This is not yet fully threadsafe.
if (address) { if (!soundStream) {
for (int i = 0; i < 16; i++) { return;
samples[i] = Memory_Read_U16(address + i * 2);
}
if (log_ai)
g_wave_writer.AddStereoSamples(samples, 8);
} }
Mixer_PushSamples(samples, 32 / 4, sample_rate);
if (soundStream->GetMixer())
{
short samples[16] = {0}; // interleaved stereo
if (address)
{
for (int i = 0; i < 16; i++)
{
samples[i] = Memory_Read_U16(address + i * 2);
}
// Write the audio to a file
if (log_ai)
g_wave_writer.AddStereoSamples(samples, 8);
}
soundStream->GetMixer()->PushSamples(samples, 32 / 4);
}
// SoundStream is updated only when necessary (there is no 70 ms limit
// so each sample now triggers the sound stream)
// TODO: think about this.
static int counter = 0; static int counter = 0;
counter++; counter++;
#ifdef _WIN32 if ((counter & 31) == 0 && soundStream)
if ((counter & 255) == 0) soundStream->Update();
DSound::DSound_UpdateSound();
#endif
} }