summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorskidau <skidau@gmail.com>2013-01-09 22:57:32 +1100
committerskidau <skidau@gmail.com>2013-01-09 22:57:32 +1100
commit63b38be97c12e6b6f0ec39008f6b0dd06dbcf3f0 (patch)
treed7fae9dfd060af3d1736b0156368e300efd6b32b /Source/Core
parentc8c78e0aa9c7ec1ef738ca064daad5903a9e7b48 (diff)
Added audio time stretching by using the SoundTouch library.
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/AudioCommon/AudioCommon.vcxproj24
-rw-r--r--Source/Core/AudioCommon/Src/Mixer.h5
-rw-r--r--Source/Core/AudioCommon/Src/OpenALStream.cpp79
-rw-r--r--Source/Core/AudioCommon/Src/OpenALStream.h12
-rw-r--r--Source/Core/Core/Src/Core.cpp9
5 files changed, 91 insertions, 38 deletions
diff --git a/Source/Core/AudioCommon/AudioCommon.vcxproj b/Source/Core/AudioCommon/AudioCommon.vcxproj
index 4bcee7559b..85608330dd 100644
--- a/Source/Core/AudioCommon/AudioCommon.vcxproj
+++ b/Source/Core/AudioCommon/AudioCommon.vcxproj
@@ -115,8 +115,8 @@
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
<Lib>
- <AdditionalDependencies>OpenAL32.lib;dsound.lib;dxerr.lib</AdditionalDependencies>
- <AdditionalLibraryDirectories>..\..\..\Externals\OpenAL\Win32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>SoundTouchD.lib;OpenAL32.lib;dsound.lib;dxerr.lib</AdditionalDependencies>
+ <AdditionalLibraryDirectories>..\..\..\Externals\OpenAL\Win32;..\..\..\Externals\SoundTouch\Win32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@@ -127,8 +127,8 @@
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
<Lib>
- <AdditionalDependencies>OpenAL32.lib;dsound.lib;dxerr.lib</AdditionalDependencies>
- <AdditionalLibraryDirectories>..\..\..\Externals\OpenAL\Win64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>SoundTouchD.lib;OpenAL32.lib;dsound.lib;dxerr.lib</AdditionalDependencies>
+ <AdditionalLibraryDirectories>..\..\..\Externals\OpenAL\Win64;..\..\..\Externals\SoundTouch\Win64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@@ -141,8 +141,8 @@
<OptimizeReferences>true</OptimizeReferences>
</Link>
<Lib>
- <AdditionalDependencies>OpenAL32.lib;dsound.lib;dxerr.lib</AdditionalDependencies>
- <AdditionalLibraryDirectories>..\..\..\Externals\OpenAL\Win32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>SoundTouch.lib;OpenAL32.lib;dsound.lib;dxerr.lib</AdditionalDependencies>
+ <AdditionalLibraryDirectories>..\..\..\Externals\OpenAL\Win32;..\..\..\Externals\SoundTouch\Win32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|Win32'">
@@ -155,8 +155,8 @@
<OptimizeReferences>true</OptimizeReferences>
</Link>
<Lib>
- <AdditionalDependencies>OpenAL32.lib;dsound.lib;dxerr.lib</AdditionalDependencies>
- <AdditionalLibraryDirectories>..\..\..\Externals\OpenAL\Win32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>SoundTouch.lib;OpenAL32.lib;dsound.lib;dxerr.lib</AdditionalDependencies>
+ <AdditionalLibraryDirectories>..\..\..\Externals\OpenAL\Win32;..\..\..\Externals\SoundTouch\Win32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@@ -169,8 +169,8 @@
<OptimizeReferences>true</OptimizeReferences>
</Link>
<Lib>
- <AdditionalDependencies>OpenAL32.lib;dsound.lib;dxerr.lib</AdditionalDependencies>
- <AdditionalLibraryDirectories>..\..\..\Externals\OpenAL\Win64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>SoundTouch.lib;OpenAL32.lib;dsound.lib;dxerr.lib</AdditionalDependencies>
+ <AdditionalLibraryDirectories>..\..\..\Externals\OpenAL\Win64;..\..\..\Externals\SoundTouch\Win64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|x64'">
@@ -183,8 +183,8 @@
<OptimizeReferences>true</OptimizeReferences>
</Link>
<Lib>
- <AdditionalDependencies>OpenAL32.lib;dsound.lib;dxerr.lib</AdditionalDependencies>
- <AdditionalLibraryDirectories>..\..\..\Externals\OpenAL\Win64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>SoundTouch.lib;OpenAL32.lib;dsound.lib;dxerr.lib</AdditionalDependencies>
+ <AdditionalLibraryDirectories>..\..\..\Externals\OpenAL\Win64;..\..\..\Externals\SoundTouch\Win64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Lib>
</ItemDefinitionGroup>
<ItemGroup>
diff --git a/Source/Core/AudioCommon/Src/Mixer.h b/Source/Core/AudioCommon/Src/Mixer.h
index da456d5bf7..c1a387cf49 100644
--- a/Source/Core/AudioCommon/Src/Mixer.h
+++ b/Source/Core/AudioCommon/Src/Mixer.h
@@ -92,6 +92,9 @@ public:
std::mutex& MixerCritical() { return m_csMixing; }
+ volatile float GetCurrentSpeed() const { return m_speed; }
+ void UpdateSpeed(volatile float val) { m_speed = val; }
+
protected:
unsigned int m_sampleRate;
unsigned int m_aiSampleRate;
@@ -113,6 +116,8 @@ protected:
bool m_AIplaying;
std::mutex m_csMixing;
+
+ volatile float m_speed; // Current rate of the emulation (1.0 = 100% speed)
private:
};
diff --git a/Source/Core/AudioCommon/Src/OpenALStream.cpp b/Source/Core/AudioCommon/Src/OpenALStream.cpp
index 4cc64a17de..6f429db495 100644
--- a/Source/Core/AudioCommon/Src/OpenALStream.cpp
+++ b/Source/Core/AudioCommon/Src/OpenALStream.cpp
@@ -19,11 +19,12 @@
#include "aldlist.h"
#include "OpenALStream.h"
-#include "../../Core/Src/HW/SystemTimers.h"
-#include "../../Core/Src/HW/AudioInterface.h"
#if defined HAVE_OPENAL && HAVE_OPENAL
+using namespace soundtouch;
+SoundTouch soundTouch;
+
//
// AyuanX: Spec says OpenAL1.1 is thread safe already
//
@@ -67,6 +68,7 @@ bool OpenALStream::Start()
PanicAlertT("OpenAL: can't find sound devices");
}
+ soundTouch.clear();
return bReturn;
}
@@ -76,6 +78,8 @@ void OpenALStream::Stop()
// kick the thread if it's waiting
soundSyncEvent.Set();
+ soundTouch.clear();
+
thread.join();
alSourceStop(uiSource);
@@ -105,6 +109,7 @@ void OpenALStream::SetVolume(int volume)
void OpenALStream::Update()
{
soundSyncEvent.Set();
+ mainSyncEvent.Wait();
}
void OpenALStream::Clear(bool mute)
@@ -113,6 +118,7 @@ void OpenALStream::Clear(bool mute)
if(m_muted)
{
+ soundTouch.clear();
alSourceStop(uiSource);
}
else
@@ -136,9 +142,10 @@ void OpenALStream::SoundLoop()
alGenSources(1, &uiSource);
// Short Silence
+ memset(sampleBuffer, 0, OAL_MAX_SAMPLES * 4 * OAL_NUM_BUFFERS);
memset(realtimeBuffer, 0, OAL_MAX_SAMPLES * 4);
for (int i = 0; i < OAL_NUM_BUFFERS; i++)
- alBufferData(uiBuffers[i], AL_FORMAT_STEREO16, realtimeBuffer, OAL_MAX_SAMPLES, ulFrequency);
+ alBufferData(uiBuffers[i], AL_FORMAT_STEREO16, realtimeBuffer, OAL_MAX_SAMPLES * 4, ulFrequency);
alSourceQueueBuffers(uiSource, OAL_NUM_BUFFERS, uiBuffers);
alSourcePlay(uiSource);
@@ -152,42 +159,68 @@ void OpenALStream::SoundLoop()
ALint iBuffersProcessed = 0;
ALuint uiBufferTemp[OAL_NUM_BUFFERS] = {0};
+ soundTouch.setChannels(2);
+ soundTouch.setSampleRate(ulFrequency);
+ soundTouch.setSetting(SETTING_USE_QUICKSEEK, 0);
+ soundTouch.setSetting(SETTING_USE_AA_FILTER, 0);
+ soundTouch.setSetting(SETTING_SEQUENCE_MS, 1);
+ soundTouch.setSetting(SETTING_SEEKWINDOW_MS, 28);
+ soundTouch.setSetting(SETTING_OVERLAP_MS, 12);
+
while (!threadData)
{
- if (iBuffersProcessed == iBuffersFilled)
- {
- alGetSourcei(uiSource, AL_BUFFERS_PROCESSED, &iBuffersProcessed);
- iBuffersFilled = 0;
- }
-
// num_samples_to_render in this update - depends on SystemTimers::AUDIO_DMA_PERIOD.
const u32 stereo_16_bit_size = 4;
const u32 dma_length = 32;
- const u64 audio_dma_period = SystemTimers::GetTicksPerSecond() / (AudioInterface::GetAIDSampleRate() * stereo_16_bit_size / dma_length);
const u64 ais_samples_per_second = 48000 * stereo_16_bit_size;
- const u64 num_samples_to_render = (audio_dma_period * ais_samples_per_second) / SystemTimers::GetTicksPerSecond();
+ u64 audio_dma_period = SystemTimers::GetTicksPerSecond() / (AudioInterface::GetAIDSampleRate() * stereo_16_bit_size / dma_length);
+ u64 num_samples_to_render = (audio_dma_period * ais_samples_per_second) / SystemTimers::GetTicksPerSecond();
unsigned int numSamples = (unsigned int)num_samples_to_render;
+ numSamples = (numSamples > OAL_MAX_SAMPLES) ? OAL_MAX_SAMPLES : numSamples;
+ numSamples = m_mixer->Mix(realtimeBuffer, numSamples);
+ soundTouch.putSamples(realtimeBuffer, numSamples);
+
+ if (iBuffersProcessed == iBuffersFilled)
+ {
+ alGetSourcei(uiSource, AL_BUFFERS_PROCESSED, &iBuffersProcessed);
+ iBuffersFilled = 0;
+ }
+
if (iBuffersProcessed)
{
- numSamples = (numSamples > OAL_MAX_SAMPLES) ? OAL_MAX_SAMPLES : numSamples;
- // Remove the Buffer from the Queue. (uiBuffer contains the Buffer ID for the unqueued Buffer)
- if (iBuffersFilled == 0)
- alSourceUnqueueBuffers(uiSource, iBuffersProcessed, uiBufferTemp);
-
- m_mixer->Mix(realtimeBuffer, numSamples);
- alBufferData(uiBufferTemp[iBuffersFilled], AL_FORMAT_STEREO16, realtimeBuffer, numSamples * 4, ulFrequency);
- alSourceQueueBuffers(uiSource, 1, &uiBufferTemp[iBuffersFilled]);
- iBuffersFilled++;
-
- if (iBuffersFilled == OAL_NUM_BUFFERS)
- alSourcePlay(uiSource);
+ float rate = m_mixer->GetCurrentSpeed();
+ if (rate <= 0)
+ {
+ Core::RequestRefreshInfo();
+ rate = m_mixer->GetCurrentSpeed();
+ }
+ if (rate > 0)
+ {
+ // Adjust SETTING_SEQUENCE_MS to balance between lag vs hollow audio
+ soundTouch.setSetting(SETTING_SEQUENCE_MS, (int)pow(1 / rate, 2));
+ soundTouch.setTempo(rate);
+ }
+ unsigned int nSamples = soundTouch.receiveSamples(sampleBuffer, OAL_MAX_SAMPLES * 2 * OAL_NUM_BUFFERS);
+ if (nSamples > 0)
+ {
+ // Remove the Buffer from the Queue. (uiBuffer contains the Buffer ID for the unqueued Buffer)
+ if (iBuffersFilled == 0)
+ alSourceUnqueueBuffers(uiSource, iBuffersProcessed, uiBufferTemp);
+ alBufferData(uiBufferTemp[iBuffersFilled], AL_FORMAT_STEREO16, sampleBuffer, nSamples * 4, ulFrequency);
+ alSourceQueueBuffers(uiSource, 1, &uiBufferTemp[iBuffersFilled]);
+ iBuffersFilled++;
+
+ if (iBuffersFilled == OAL_NUM_BUFFERS)
+ alSourcePlay(uiSource);
+ }
}
else
{
soundSyncEvent.Wait();
}
+ mainSyncEvent.Set();
}
}
diff --git a/Source/Core/AudioCommon/Src/OpenALStream.h b/Source/Core/AudioCommon/Src/OpenALStream.h
index a9c1f51399..c6dfe519ae 100644
--- a/Source/Core/AudioCommon/Src/OpenALStream.h
+++ b/Source/Core/AudioCommon/Src/OpenALStream.h
@@ -34,10 +34,16 @@
#include <AL/alc.h>
#endif
+#include "../../Core/Src/Core.h"
+#include "../../Core/Src/HW/SystemTimers.h"
+#include "../../Core/Src/HW/AudioInterface.h"
+#include "../../../../Externals/SoundTouch/STTypes.h"
+#include "../../../../Externals/SoundTouch/SoundTouch.h"
+
// 16 bit Stereo
#define SFX_MAX_SOURCE 1
#define OAL_NUM_BUFFERS 16
-#define OAL_MAX_SAMPLES 512 // AyuanX: Don't make it too large, as larger buffer means longer delay
+#define OAL_MAX_SAMPLES 512
#endif
class OpenALStream: public SoundStream
@@ -63,8 +69,10 @@ public:
private:
std::thread thread;
Common::Event soundSyncEvent;
-
+ Common::Event mainSyncEvent;
+
short realtimeBuffer[OAL_MAX_SAMPLES * 2];
+ soundtouch::SAMPLETYPE sampleBuffer[OAL_MAX_SAMPLES * 2 * OAL_NUM_BUFFERS];
ALuint uiBuffers[OAL_NUM_BUFFERS];
ALuint uiSource;
ALfloat fVolume;
diff --git a/Source/Core/Core/Src/Core.cpp b/Source/Core/Core/Src/Core.cpp
index e92b9088bc..c06755a90b 100644
--- a/Source/Core/Core/Src/Core.cpp
+++ b/Source/Core/Core/Src/Core.cpp
@@ -683,7 +683,14 @@ void VideoThrottle()
SMessage;
// Show message
- g_video_backend->UpdateFPSDisplay(SMessage.c_str());
+ g_video_backend->UpdateFPSDisplay(SMessage.c_str());
+
+ // Update the audio timestretcher with the current speed
+ if (soundStream)
+ {
+ CMixer* pMixer = soundStream->GetMixer();
+ pMixer->UpdateSpeed((float)Speed / 100);
+ }
if (_CoreParameter.bRenderToMain &&
SConfig::GetInstance().m_InterfaceStatusbar) {