diff options
| author | nakeee <nakeee@gmail.com> | 2009-03-23 17:56:37 +0000 |
|---|---|---|
| committer | nakeee <nakeee@gmail.com> | 2009-03-23 17:56:37 +0000 |
| commit | 07381b9962ba93780482b2cd9b66ff64c30bd49e (patch) | |
| tree | 26523ce55e9ded1c3965296e024ee34ddedc0789 /Source/Core/AudioCommon | |
| parent | 788cc7386728658db90fb551620d697218708baa (diff) | |
Starting audio common
Going to slowly make LLE-testing and HLE use it
(This commit is missing some proj files for windows)
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@2741 8ced0084-cf51-0410-be5f-012b33b47a6e
Diffstat (limited to 'Source/Core/AudioCommon')
| -rw-r--r-- | Source/Core/AudioCommon/Src/AOSoundStream.cpp | 96 | ||||
| -rw-r--r-- | Source/Core/AudioCommon/Src/AOSoundStream.h | 77 | ||||
| -rw-r--r-- | Source/Core/AudioCommon/Src/DSoundStream.cpp | 171 | ||||
| -rw-r--r-- | Source/Core/AudioCommon/Src/DSoundStream.h | 89 | ||||
| -rw-r--r-- | Source/Core/AudioCommon/Src/NullSoundStream.h | 42 | ||||
| -rw-r--r-- | Source/Core/AudioCommon/Src/SoundStream.h | 50 |
6 files changed, 525 insertions, 0 deletions
diff --git a/Source/Core/AudioCommon/Src/AOSoundStream.cpp b/Source/Core/AudioCommon/Src/AOSoundStream.cpp new file mode 100644 index 0000000000..e6402a5186 --- /dev/null +++ b/Source/Core/AudioCommon/Src/AOSoundStream.cpp @@ -0,0 +1,96 @@ +// Copyright (C) 2003-2009 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 <string.h> + +#include "AOSoundStream.h" + +#if defined(HAVE_AO) && HAVE_AO + +void AOSound::SoundLoop() +{ + ao_initialize(); + default_driver = ao_default_driver_id(); + format.bits = 16; + format.channels = 2; + format.rate = sampleRate; + format.byte_format = AO_FMT_LITTLE; + + device = ao_open_live(default_driver, &format, NULL /* no options */); + if (!device) + { + PanicAlert("DSP_HLE: Error opening AO device.\n"); + ao_shutdown(); + Stop(); + return; + } + + buf_size = format.bits/8 * format.channels * format.rate; + + while (!threadData) + { + soundCriticalSection->Enter(); + + uint_32 numBytesToRender = 256; + (*callback)(realtimeBuffer, numBytesToRender >> 2, 16, sampleRate, 2); + ao_play(device, (char*)realtimeBuffer, numBytesToRender); + soundCriticalSection->Leave(); + soundSyncEvent->Wait(); + } +} + +void *soundThread(void *args) +{ + ((AOSound *)args)->SoundLoop(); + return NULL; +} + +bool AOSound::Start() +{ + memset(realtimeBuffer, 0, sizeof(realtimeBuffer)); + + soundSyncEvent = new Common::Event(); + soundSyncEvent->Init(); + + soundCriticalSection = new Common::CriticalSection(1); + + thread = new Common::Thread(soundThread, (void *)this); + return true; +} + +void AOSound::Update() +{ + soundSyncEvent->Set(); +} + +void AOSound::Stop() +{ + soundCriticalSection->Enter(); + threadData = 1; + soundSyncEvent->Set(); + soundCriticalSection->Leave(); + soundSyncEvent->Shutdown(); + delete soundCriticalSection; + delete thread; + delete soundSyncEvent; + + ao_close(device); + device = NULL; + ao_shutdown(); +} + +#endif diff --git a/Source/Core/AudioCommon/Src/AOSoundStream.h b/Source/Core/AudioCommon/Src/AOSoundStream.h new file mode 100644 index 0000000000..2456e6c8fb --- /dev/null +++ b/Source/Core/AudioCommon/Src/AOSoundStream.h @@ -0,0 +1,77 @@ +// Copyright (C) 2003-2009 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 __AOSOUNDSTREAM_H__ +#define __AOSOUNDSTREAM_H__ + +#include "SoundStream.h" + +#if defined(HAVE_AO) && HAVE_AO +#include <ao/ao.h> +#endif + +#include "Thread.h" + +class AOSound : public SoundStream +{ +#if defined(HAVE_AO) && HAVE_AO + Common::Thread *thread; + Common::CriticalSection *soundCriticalSection; + Common::Event *soundSyncEvent; + + int buf_size; + + ao_device *device; + ao_sample_format format; + int default_driver; + + short realtimeBuffer[1024 * 1024]; + +public: + AOSound(int _sampleRate, StreamCallback _callback) : + SoundStream(_sampleRate, _callback) {} + + virtual ~AOSound() {} + + virtual bool Start(); + + virtual void SoundLoop(); + + virtual void Stop(); + + static bool isValid() { + return true; + } + + virtual bool usesMixer() const { + return true; + } + + virtual void Update(); + + virtual int GetSampleRate() { + return sampleRate; + } + +#else +public: + AOSound(int _sampleRate, StreamCallback _callback) : + SoundStream(_sampleRate, _callback) {} +#endif +}; + +#endif //__AOSOUNDSTREAM_H__ diff --git a/Source/Core/AudioCommon/Src/DSoundStream.cpp b/Source/Core/AudioCommon/Src/DSoundStream.cpp new file mode 100644 index 0000000000..ff47d8c73f --- /dev/null +++ b/Source/Core/AudioCommon/Src/DSoundStream.cpp @@ -0,0 +1,171 @@ +// Copyright (C) 2003-2009 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 <dxerr.h> +#include "DSoundStream.h" + +extern bool log_ai; + +bool DSound::CreateBuffer() +{ + PCMWAVEFORMAT pcmwf; + DSBUFFERDESC dsbdesc; + + memset(&pcmwf, 0, sizeof(PCMWAVEFORMAT)); + memset(&dsbdesc, 0, sizeof(DSBUFFERDESC)); + + pcmwf.wf.wFormatTag = WAVE_FORMAT_PCM; + pcmwf.wf.nChannels = 2; + pcmwf.wf.nSamplesPerSec = sampleRate; + pcmwf.wf.nBlockAlign = 4; + pcmwf.wf.nAvgBytesPerSec = pcmwf.wf.nSamplesPerSec * pcmwf.wf.nBlockAlign; + pcmwf.wBitsPerSample = 16; + + // Fill out DSound buffer description. + dsbdesc.dwSize = sizeof(DSBUFFERDESC); + dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_STICKYFOCUS; + dsbdesc.dwBufferBytes = bufferSize = BUFSIZE; + dsbdesc.lpwfxFormat = (WAVEFORMATEX *)&pcmwf; + + HRESULT res = ds->CreateSoundBuffer(&dsbdesc, &dsBuffer, NULL); + if (SUCCEEDED(res)) + { + dsBuffer->SetCurrentPosition(0); + return true; + } + else + { + // Failed. + PanicAlert("Sound buffer creation failed: %s", DXGetErrorString(res)); + dsBuffer = NULL; + return false; + } +} + +bool DSound::WriteDataToBuffer(DWORD dwOffset, // Our own write cursor. + char* soundData, // Start of our data. + DWORD dwSoundBytes) // Size of block to copy. +{ + // I want to record the regular audio to, how do I do that? + // Well, it's gonna be a bit tricky. For future work :) + //std::string Data = ArrayToString((const u8*)soundData, dwSoundBytes); + //Console::Print("Data: %s\n\n", Data.c_str()); + //if (log_ai) g_wave_writer.AddStereoSamples((const short*)soundData, dwSoundBytes); + + void *ptr1, *ptr2; + DWORD numBytes1, numBytes2; + // Obtain memory address of write block. This will be in two parts if the block wraps around. + HRESULT hr = dsBuffer->Lock(dwOffset, dwSoundBytes, &ptr1, &numBytes1, &ptr2, &numBytes2, 0); + + // If the buffer was lost, restore and retry lock. + if (DSERR_BUFFERLOST == hr) + { + dsBuffer->Restore(); + hr = dsBuffer->Lock(dwOffset, dwSoundBytes, &ptr1, &numBytes1, &ptr2, &numBytes2, 0); + } + if (SUCCEEDED(hr)) + { + memcpy(ptr1, soundData, numBytes1); + if (ptr2 != 0) + memcpy(ptr2, soundData + numBytes1, numBytes2); + + // Release the data back to DirectSound. + dsBuffer->Unlock(ptr1, numBytes1, ptr2, numBytes2); + return true; + } + + return false; +} + +// The audio thread. +DWORD WINAPI soundThread(void* args) +{ + (reinterpret_cast<DSound *>(args))->SoundLoop(); + return 0; +} + +void DSound::SoundLoop() +{ + currentPos = 0; + lastPos = 0; + dsBuffer->Play(0, 0, DSBPLAY_LOOPING); + while (!threadData) + { + // No blocking inside the csection + soundCriticalSection.Enter(); + dsBuffer->GetCurrentPosition((DWORD*)¤tPos, 0); + int numBytesToRender = FIX128(ModBufferSize(currentPos - lastPos)); + if (numBytesToRender >= 256) + { + if (numBytesToRender > sizeof(realtimeBuffer)) + PanicAlert("soundThread: too big render call"); + (*callback)(realtimeBuffer, numBytesToRender >> 2, 16, sampleRate, 2); + WriteDataToBuffer(lastPos, (char*)realtimeBuffer, numBytesToRender); + currentPos = ModBufferSize(lastPos + numBytesToRender); + totalRenderedBytes += numBytesToRender; + lastPos = currentPos; + } + + soundCriticalSection.Leave(); + if (threadData) + break; + soundSyncEvent.Wait(); + } + + dsBuffer->Stop(); +} + +bool DSound::Start() +{ + soundSyncEvent.Init(); + if (FAILED(DirectSoundCreate8(0, &ds, 0))) + return false; + if (hWnd) + ds->SetCooperativeLevel((HWND)hWnd, DSSCL_NORMAL); + if (!CreateBuffer()) + return false; + + DWORD num1; + short* p1; + dsBuffer->Lock(0, bufferSize, (void* *)&p1, &num1, 0, 0, 0); + memset(p1, 0, num1); + dsBuffer->Unlock(p1, num1, 0, 0); + totalRenderedBytes = -bufferSize; + thread = new Common::Thread(soundThread, (void *)this); + return true; +} + +void DSound::Update() +{ + soundSyncEvent.Set(); +} + +void DSound::Stop() +{ + soundCriticalSection.Enter(); + threadData = 1; + // kick the thread if it's waiting + soundSyncEvent.Set(); + soundCriticalSection.Leave(); + delete thread; + + dsBuffer->Release(); + ds->Release(); + + soundSyncEvent.Shutdown(); + thread = NULL; +} diff --git a/Source/Core/AudioCommon/Src/DSoundStream.h b/Source/Core/AudioCommon/Src/DSoundStream.h new file mode 100644 index 0000000000..e81fc8e233 --- /dev/null +++ b/Source/Core/AudioCommon/Src/DSoundStream.h @@ -0,0 +1,89 @@ +// Copyright (C) 2003-2009 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 __DSOUNDSTREAM_H__ +#define __DSOUNDSTREAM_H__ +#include "SoundStream.h" + +#include "Thread.h" + +#ifdef _WIN32 +#include "stdafx.h" + +#include <mmsystem.h> +#include <dsound.h> + +#define BUFSIZE 32768 +#define MAXWAIT 70 //ms + +#endif + +class DSound : public SoundStream +{ +#ifdef _WIN32 + Common::Thread *thread; + Common::CriticalSection soundCriticalSection; + Common::Event soundSyncEvent; + void *hWnd; + + IDirectSound8* ds; + IDirectSoundBuffer* dsBuffer; + + int bufferSize; //i bytes + int totalRenderedBytes; + + // playback position + int currentPos; + int lastPos; + short realtimeBuffer[1024 * 1024]; + + inline int FIX128(int x) { + return x & (~127); + } + + inline int ModBufferSize(int x) { + return (x + bufferSize) % bufferSize; + } + + bool CreateBuffer(); + bool WriteDataToBuffer(DWORD dwOffset, char* soundData, + DWORD dwSoundBytes); + +public: + DSound(int _sampleRate, StreamCallback _callback) : + SoundStream(_sampleRate, _callback) {} + + DSound(int _sampleRate, StreamCallback _callback, void *_hWnd) : + SoundStream(_sampleRate, _callback), hWnd(_hWnd) {} + + virtual ~DSound() {} + + virtual bool Start(); + virtual void SoundLoop(); + virtual void Stop(); + static bool isValid() { return true; } + virtual bool usesMixer() const { return true; } + virtual void Update(); + +#else +public: + DSound(int _sampleRate, StreamCallback _callback, void *hWnd = NULL) : + SoundStream(_sampleRate, _callback) {} +#endif +}; + +#endif //__DSOUNDSTREAM_H__ diff --git a/Source/Core/AudioCommon/Src/NullSoundStream.h b/Source/Core/AudioCommon/Src/NullSoundStream.h new file mode 100644 index 0000000000..bd6728b1ae --- /dev/null +++ b/Source/Core/AudioCommon/Src/NullSoundStream.h @@ -0,0 +1,42 @@ +// Copyright (C) 2003-2009 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 __NULLSOUNDSTREAM_H__ +#define __NULLSOUNDSTREAM_H__ + +#include "SoundStream.h" + +class NullSound : public SoundStream +{ +public: + NullSound(int _sampleRate, StreamCallback _callback) : + SoundStream(_sampleRate, _callback) {} + + virtual ~NullSound() {} + + static bool isValid() { + return true; + } + + virtual bool Start() { return true; } + + virtual void Update() { + (*callback)(NULL, 256 >> 2, 16, sampleRate, 2); + } +}; + +#endif //__NULLSOUNDSTREAM_H__ diff --git a/Source/Core/AudioCommon/Src/SoundStream.h b/Source/Core/AudioCommon/Src/SoundStream.h new file mode 100644 index 0000000000..44ffdd43b8 --- /dev/null +++ b/Source/Core/AudioCommon/Src/SoundStream.h @@ -0,0 +1,50 @@ +// Copyright (C) 2003-2009 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 __SOUNDSTREAM_H__ +#define __SOUNDSTREAM_H__ + +#include "Common.h" + +typedef void (*StreamCallback)(short* buffer, int numSamples, int bits, int rate, int channels); + +class SoundStream +{ +protected: + int sampleRate; + StreamCallback callback; + + // We set this to shut down the sound thread. + // 0=keep playing, 1=stop playing NOW. + volatile int threadData; + +public: + SoundStream(int _sampleRate, StreamCallback _callback) : + sampleRate(_sampleRate), callback(_callback), threadData(0) {} + virtual ~SoundStream() {} + + static bool isValid() { return false; } + virtual bool usesMixer() const { return false; } + virtual bool Start() { return false; } + virtual void SoundLoop() {} + virtual void Stop() {} + virtual void Update() {} + + virtual int GetSampleRate() const { return sampleRate; } +}; + +#endif |
