OpenALStream: Remove audio stretching
This commit is contained in:
parent
29344cb5ff
commit
6a4945090c
|
@ -20,8 +20,6 @@
|
||||||
#pragma comment(lib, "openal32.lib")
|
#pragma comment(lib, "openal32.lib")
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static soundtouch::SoundTouch soundTouch;
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// AyuanX: Spec says OpenAL1.1 is thread safe already
|
// AyuanX: Spec says OpenAL1.1 is thread safe already
|
||||||
//
|
//
|
||||||
|
@ -71,7 +69,6 @@ bool OpenALStream::Start()
|
||||||
// Initialize DPL2 parameters
|
// Initialize DPL2 parameters
|
||||||
DPL2Reset();
|
DPL2Reset();
|
||||||
|
|
||||||
soundTouch.clear();
|
|
||||||
return bReturn;
|
return bReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,8 +78,6 @@ void OpenALStream::Stop()
|
||||||
// kick the thread if it's waiting
|
// kick the thread if it's waiting
|
||||||
soundSyncEvent.Set();
|
soundSyncEvent.Set();
|
||||||
|
|
||||||
soundTouch.clear();
|
|
||||||
|
|
||||||
thread.join();
|
thread.join();
|
||||||
|
|
||||||
alSourceStop(uiSource);
|
alSourceStop(uiSource);
|
||||||
|
@ -120,7 +115,6 @@ void OpenALStream::Clear(bool mute)
|
||||||
|
|
||||||
if (m_muted)
|
if (m_muted)
|
||||||
{
|
{
|
||||||
soundTouch.clear();
|
|
||||||
alSourceStop(uiSource);
|
alSourceStop(uiSource);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -213,15 +207,6 @@ void OpenALStream::SoundLoop()
|
||||||
unsigned int numBuffersQueued = 0;
|
unsigned int numBuffersQueued = 0;
|
||||||
ALint iState = 0;
|
ALint iState = 0;
|
||||||
|
|
||||||
soundTouch.setChannels(2);
|
|
||||||
soundTouch.setSampleRate(ulFrequency);
|
|
||||||
soundTouch.setTempo(1.0);
|
|
||||||
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 (m_run_thread.IsSet())
|
while (m_run_thread.IsSet())
|
||||||
{
|
{
|
||||||
// Block until we have a free buffer
|
// Block until we have a free buffer
|
||||||
|
@ -243,62 +228,29 @@ void OpenALStream::SoundLoop()
|
||||||
numBuffersQueued -= numBuffersProcessed;
|
numBuffersQueued -= numBuffersProcessed;
|
||||||
}
|
}
|
||||||
|
|
||||||
// num_samples_to_render in this update - depends on SystemTimers::AUDIO_DMA_PERIOD.
|
// DPL2 accepts 240 samples minimum (FWRDURATION)
|
||||||
const u32 stereo_16_bit_size = 4;
|
unsigned int minSamples = surround_capable ? 240 : 0;
|
||||||
const u32 dma_length = 32;
|
|
||||||
const u64 ais_samples_per_second = 48000 * stereo_16_bit_size;
|
|
||||||
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;
|
unsigned int numSamples = OAL_MAX_SAMPLES;
|
||||||
unsigned int minSamples =
|
numSamples = m_mixer->Mix(realtimeBuffer, numSamples);
|
||||||
surround_capable ? 240 : 0; // DPL2 accepts 240 samples minimum (FWRDURATION)
|
|
||||||
|
|
||||||
numSamples = (numSamples > OAL_MAX_SAMPLES) ? OAL_MAX_SAMPLES : numSamples;
|
|
||||||
numSamples = m_mixer->Mix(realtimeBuffer, numSamples, false);
|
|
||||||
|
|
||||||
// Convert the samples from short to float
|
// Convert the samples from short to float
|
||||||
float dest[OAL_MAX_SAMPLES * STEREO_CHANNELS];
|
|
||||||
for (u32 i = 0; i < numSamples * STEREO_CHANNELS; ++i)
|
for (u32 i = 0; i < numSamples * STEREO_CHANNELS; ++i)
|
||||||
dest[i] = (float)realtimeBuffer[i] / (1 << 15);
|
sampleBuffer[i] = static_cast<float>(realtimeBuffer[i]) / (1 << 15);
|
||||||
|
|
||||||
soundTouch.putSamples(dest, numSamples);
|
if (numSamples <= minSamples)
|
||||||
|
|
||||||
double rate = (double)m_mixer->GetCurrentSpeed();
|
|
||||||
if (rate <= 0)
|
|
||||||
{
|
|
||||||
Core::RequestRefreshInfo();
|
|
||||||
rate = (double)m_mixer->GetCurrentSpeed();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Place a lower limit of 10% speed. When a game boots up, there will be
|
|
||||||
// many silence samples. These do not need to be timestretched.
|
|
||||||
if (rate > 0.10)
|
|
||||||
{
|
|
||||||
soundTouch.setTempo(rate);
|
|
||||||
if (rate > 10)
|
|
||||||
{
|
|
||||||
soundTouch.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int nSamples = soundTouch.receiveSamples(sampleBuffer, OAL_MAX_SAMPLES * numBuffers);
|
|
||||||
|
|
||||||
if (nSamples <= minSamples)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (surround_capable)
|
if (surround_capable)
|
||||||
{
|
{
|
||||||
float dpl2[OAL_MAX_SAMPLES * OAL_MAX_BUFFERS * SURROUND_CHANNELS];
|
float dpl2[OAL_MAX_SAMPLES * OAL_MAX_BUFFERS * SURROUND_CHANNELS];
|
||||||
DPL2Decode(sampleBuffer, nSamples, dpl2);
|
DPL2Decode(sampleBuffer, numSamples, dpl2);
|
||||||
|
|
||||||
// zero-out the subwoofer channel - DPL2Decode generates a pretty
|
// zero-out the subwoofer channel - DPL2Decode generates a pretty
|
||||||
// good 5.0 but not a good 5.1 output. Sadly there is not a 5.0
|
// good 5.0 but not a good 5.1 output. Sadly there is not a 5.0
|
||||||
// AL_FORMAT_50CHN32 to make this super-explicit.
|
// AL_FORMAT_50CHN32 to make this super-explicit.
|
||||||
// DPL2Decode output: LEFTFRONT, RIGHTFRONT, CENTREFRONT, (sub), LEFTREAR, RIGHTREAR
|
// DPL2Decode output: LEFTFRONT, RIGHTFRONT, CENTREFRONT, (sub), LEFTREAR, RIGHTREAR
|
||||||
for (u32 i = 0; i < nSamples; ++i)
|
for (u32 i = 0; i < numSamples; ++i)
|
||||||
{
|
{
|
||||||
dpl2[i * SURROUND_CHANNELS + 3 /*sub/lfe*/] = 0.0f;
|
dpl2[i * SURROUND_CHANNELS + 3 /*sub/lfe*/] = 0.0f;
|
||||||
}
|
}
|
||||||
|
@ -306,13 +258,13 @@ void OpenALStream::SoundLoop()
|
||||||
if (float32_capable)
|
if (float32_capable)
|
||||||
{
|
{
|
||||||
alBufferData(uiBuffers[nextBuffer], AL_FORMAT_51CHN32, dpl2,
|
alBufferData(uiBuffers[nextBuffer], AL_FORMAT_51CHN32, dpl2,
|
||||||
nSamples * FRAME_SURROUND_FLOAT, ulFrequency);
|
numSamples * FRAME_SURROUND_FLOAT, ulFrequency);
|
||||||
}
|
}
|
||||||
else if (fixed32_capable)
|
else if (fixed32_capable)
|
||||||
{
|
{
|
||||||
int surround_int32[OAL_MAX_SAMPLES * SURROUND_CHANNELS * OAL_MAX_BUFFERS];
|
int surround_int32[OAL_MAX_SAMPLES * SURROUND_CHANNELS * OAL_MAX_BUFFERS];
|
||||||
|
|
||||||
for (u32 i = 0; i < nSamples * SURROUND_CHANNELS; ++i)
|
for (u32 i = 0; i < numSamples * SURROUND_CHANNELS; ++i)
|
||||||
{
|
{
|
||||||
// For some reason the ffdshow's DPL2 decoder outputs samples bigger than 1.
|
// For some reason the ffdshow's DPL2 decoder outputs samples bigger than 1.
|
||||||
// Most are close to 2.5 and some go up to 8. Hard clamping here, we need to
|
// Most are close to 2.5 and some go up to 8. Hard clamping here, we need to
|
||||||
|
@ -327,13 +279,13 @@ void OpenALStream::SoundLoop()
|
||||||
}
|
}
|
||||||
|
|
||||||
alBufferData(uiBuffers[nextBuffer], AL_FORMAT_51CHN32, surround_int32,
|
alBufferData(uiBuffers[nextBuffer], AL_FORMAT_51CHN32, surround_int32,
|
||||||
nSamples * FRAME_SURROUND_INT32, ulFrequency);
|
numSamples * FRAME_SURROUND_INT32, ulFrequency);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
short surround_short[OAL_MAX_SAMPLES * SURROUND_CHANNELS * OAL_MAX_BUFFERS];
|
short surround_short[OAL_MAX_SAMPLES * SURROUND_CHANNELS * OAL_MAX_BUFFERS];
|
||||||
|
|
||||||
for (u32 i = 0; i < nSamples * SURROUND_CHANNELS; ++i)
|
for (u32 i = 0; i < numSamples * SURROUND_CHANNELS; ++i)
|
||||||
{
|
{
|
||||||
dpl2[i] = dpl2[i] * (1 << 15);
|
dpl2[i] = dpl2[i] * (1 << 15);
|
||||||
if (dpl2[i] > SHRT_MAX)
|
if (dpl2[i] > SHRT_MAX)
|
||||||
|
@ -345,7 +297,7 @@ void OpenALStream::SoundLoop()
|
||||||
}
|
}
|
||||||
|
|
||||||
alBufferData(uiBuffers[nextBuffer], AL_FORMAT_51CHN16, surround_short,
|
alBufferData(uiBuffers[nextBuffer], AL_FORMAT_51CHN16, surround_short,
|
||||||
nSamples * FRAME_SURROUND_SHORT, ulFrequency);
|
numSamples * FRAME_SURROUND_SHORT, ulFrequency);
|
||||||
}
|
}
|
||||||
|
|
||||||
err = CheckALError("buffering data");
|
err = CheckALError("buffering data");
|
||||||
|
@ -362,7 +314,7 @@ void OpenALStream::SoundLoop()
|
||||||
if (float32_capable)
|
if (float32_capable)
|
||||||
{
|
{
|
||||||
alBufferData(uiBuffers[nextBuffer], AL_FORMAT_STEREO_FLOAT32, sampleBuffer,
|
alBufferData(uiBuffers[nextBuffer], AL_FORMAT_STEREO_FLOAT32, sampleBuffer,
|
||||||
nSamples * FRAME_STEREO_FLOAT, ulFrequency);
|
numSamples * FRAME_STEREO_FLOAT, ulFrequency);
|
||||||
|
|
||||||
err = CheckALError("buffering float32 data");
|
err = CheckALError("buffering float32 data");
|
||||||
if (err == AL_INVALID_ENUM)
|
if (err == AL_INVALID_ENUM)
|
||||||
|
@ -374,21 +326,21 @@ void OpenALStream::SoundLoop()
|
||||||
{
|
{
|
||||||
// Clamping is not necessary here, samples are always between (-1,1)
|
// Clamping is not necessary here, samples are always between (-1,1)
|
||||||
int stereo_int32[OAL_MAX_SAMPLES * STEREO_CHANNELS * OAL_MAX_BUFFERS];
|
int stereo_int32[OAL_MAX_SAMPLES * STEREO_CHANNELS * OAL_MAX_BUFFERS];
|
||||||
for (u32 i = 0; i < nSamples * STEREO_CHANNELS; ++i)
|
for (u32 i = 0; i < numSamples * STEREO_CHANNELS; ++i)
|
||||||
stereo_int32[i] = (int)((float)sampleBuffer[i] * (INT64_C(1) << 31));
|
stereo_int32[i] = (int)((float)sampleBuffer[i] * (INT64_C(1) << 31));
|
||||||
|
|
||||||
alBufferData(uiBuffers[nextBuffer], AL_FORMAT_STEREO32, stereo_int32,
|
alBufferData(uiBuffers[nextBuffer], AL_FORMAT_STEREO32, stereo_int32,
|
||||||
nSamples * FRAME_STEREO_INT32, ulFrequency);
|
numSamples * FRAME_STEREO_INT32, ulFrequency);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Convert the samples from float to short
|
// Convert the samples from float to short
|
||||||
short stereo[OAL_MAX_SAMPLES * STEREO_CHANNELS * OAL_MAX_BUFFERS];
|
short stereo[OAL_MAX_SAMPLES * STEREO_CHANNELS * OAL_MAX_BUFFERS];
|
||||||
for (u32 i = 0; i < nSamples * STEREO_CHANNELS; ++i)
|
for (u32 i = 0; i < numSamples * STEREO_CHANNELS; ++i)
|
||||||
stereo[i] = (short)((float)sampleBuffer[i] * (1 << 15));
|
stereo[i] = (short)((float)sampleBuffer[i] * (1 << 15));
|
||||||
|
|
||||||
alBufferData(uiBuffers[nextBuffer], AL_FORMAT_STEREO16, stereo,
|
alBufferData(uiBuffers[nextBuffer], AL_FORMAT_STEREO16, stereo,
|
||||||
nSamples * FRAME_STEREO_SHORT, ulFrequency);
|
numSamples * FRAME_STEREO_SHORT, ulFrequency);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,18 +26,6 @@
|
||||||
#include <AL/alext.h>
|
#include <AL/alext.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __APPLE__
|
|
||||||
// Avoid conflict with objc.h (on Windows, ST uses the system BOOL type, so this doesn't work)
|
|
||||||
#define BOOL SoundTouch_BOOL
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <soundtouch/STTypes.h>
|
|
||||||
#include <soundtouch/SoundTouch.h>
|
|
||||||
|
|
||||||
#ifdef __APPLE__
|
|
||||||
#undef BOOL
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define SFX_MAX_SOURCE 1
|
#define SFX_MAX_SOURCE 1
|
||||||
#define OAL_MAX_BUFFERS 32
|
#define OAL_MAX_BUFFERS 32
|
||||||
#define OAL_MAX_SAMPLES 256
|
#define OAL_MAX_SAMPLES 256
|
||||||
|
@ -89,7 +77,7 @@ private:
|
||||||
Common::Event soundSyncEvent;
|
Common::Event soundSyncEvent;
|
||||||
|
|
||||||
short realtimeBuffer[OAL_MAX_SAMPLES * STEREO_CHANNELS];
|
short realtimeBuffer[OAL_MAX_SAMPLES * STEREO_CHANNELS];
|
||||||
soundtouch::SAMPLETYPE sampleBuffer[OAL_MAX_SAMPLES * SURROUND_CHANNELS * OAL_MAX_BUFFERS];
|
float sampleBuffer[OAL_MAX_SAMPLES * SURROUND_CHANNELS * OAL_MAX_BUFFERS];
|
||||||
ALuint uiBuffers[OAL_MAX_BUFFERS];
|
ALuint uiBuffers[OAL_MAX_BUFFERS];
|
||||||
ALuint uiSource;
|
ALuint uiSource;
|
||||||
ALfloat fVolume;
|
ALfloat fVolume;
|
||||||
|
|
Loading…
Reference in New Issue