From d20dbbc92fe78bd5e5005bb6512c688beb3df681 Mon Sep 17 00:00:00 2001 From: degasus Date: Thu, 6 Feb 2014 06:55:45 +0100 Subject: [PATCH] audiocommon: sync mixer by fifo instead of estimate values --- Source/Core/AudioCommon/Mixer.cpp | 115 +++++++++--------------------- Source/Core/AudioCommon/Mixer.h | 3 - 2 files changed, 34 insertions(+), 84 deletions(-) diff --git a/Source/Core/AudioCommon/Mixer.cpp b/Source/Core/AudioCommon/Mixer.cpp index a015f25f7f..dd1e7ed386 100644 --- a/Source/Core/AudioCommon/Mixer.cpp +++ b/Source/Core/AudioCommon/Mixer.cpp @@ -32,16 +32,7 @@ unsigned int CMixer::Mix(short* samples, unsigned int numSamples) return numSamples; } - unsigned int numLeft = GetNumSamples(); - if (m_AIplaying) { - if (numLeft < numSamples)//cannot do much about this - m_AIplaying = false; - if (numLeft < MAX_SAMPLES/4)//low watermark - m_AIplaying = false; - } else { - if (numLeft > MAX_SAMPLES/2)//high watermark - m_AIplaying = true; - } + unsigned int currentSample = 0; // Cache access in non-volatile variable // This is the only function changing the read value, so it's safe to @@ -53,72 +44,55 @@ unsigned int CMixer::Mix(short* samples, unsigned int numSamples) u32 indexR = Common::AtomicLoad(m_indexR); u32 indexW = Common::AtomicLoad(m_indexW); - if (m_AIplaying) { - numLeft = (numLeft > numSamples) ? numSamples : numLeft; + //render numleft sample pairs to samples[] + //advance indexR with sample position + //remember fractional offset - //render numleft sample pairs to samples[] - //advance indexR with sample position - //remember fractional offset + static u32 frac = 0; + const u32 ratio = (u32)( 65536.0f * (float)AudioInterface::GetAIDSampleRate() / (float)m_sampleRate ); - static u32 frac = 0; - const u32 ratio = (u32)( 65536.0f * (float)AudioInterface::GetAIDSampleRate() / (float)m_sampleRate ); + if(ratio > 0x10000) + ERROR_LOG(AUDIO, "ratio out of range"); - for (u32 i = 0; i < numLeft * 2; i+=2) { - u32 indexR2 = indexR + 2; //next sample - if ((indexR2 & INDEX_MASK) == (indexW & INDEX_MASK)) //..if it exists - indexR2 = indexR; + for (; currentSample < numSamples*2 && ((indexW-indexR) & INDEX_MASK) > 2; currentSample+=2) { + u32 indexR2 = indexR + 2; //next sample - s16 l1 = Common::swap16(m_buffer[indexR & INDEX_MASK]); //current - s16 l2 = Common::swap16(m_buffer[indexR2 & INDEX_MASK]); //next - int sampleL = ((l1 << 16) + (l2 - l1) * (u16)frac) >> 16; - samples[i+1] = sampleL; + s16 l1 = Common::swap16(m_buffer[indexR & INDEX_MASK]); //current + s16 l2 = Common::swap16(m_buffer[indexR2 & INDEX_MASK]); //next + int sampleL = ((l1 << 16) + (l2 - l1) * (u16)frac) >> 16; + samples[currentSample+1] = sampleL; - s16 r1 = Common::swap16(m_buffer[(indexR + 1) & INDEX_MASK]); //current - s16 r2 = Common::swap16(m_buffer[(indexR2 + 1) & INDEX_MASK]); //next - int sampleR = ((r1 << 16) + (r2 - r1) * (u16)frac) >> 16; - samples[i] = sampleR; + s16 r1 = Common::swap16(m_buffer[(indexR + 1) & INDEX_MASK]); //current + s16 r2 = Common::swap16(m_buffer[(indexR2 + 1) & INDEX_MASK]); //next + int sampleR = ((r1 << 16) + (r2 - r1) * (u16)frac) >> 16; + samples[currentSample] = sampleR; - frac += ratio; - indexR += 2 * (u16)(frac >> 16); - frac &= 0xffff; - } - - } else { - numLeft = 0; + frac += ratio; + indexR += 2 * (u16)(frac >> 16); + frac &= 0xffff; } // Padding - if (numSamples > numLeft) + unsigned short s[2]; + s[0] = Common::swap16(m_buffer[(indexR - 1) & INDEX_MASK]); + s[1] = Common::swap16(m_buffer[(indexR - 2) & INDEX_MASK]); + for (; currentSample < numSamples*2; currentSample+=2) { - unsigned short s[2]; - s[0] = Common::swap16(m_buffer[(indexR - 1) & INDEX_MASK]); - s[1] = Common::swap16(m_buffer[(indexR - 2) & INDEX_MASK]); - for (unsigned int i = numLeft*2; i < numSamples*2; i+=2) - *(u32*)(samples+i) = *(u32*)(s); -// memset(&samples[numLeft * 2], 0, (numSamples - numLeft) * 4); + samples[currentSample] = s[0]; + samples[currentSample+1] = s[1]; } // Flush cached variable Common::AtomicStore(m_indexR, indexR); - //when logging, also throttle HLE audio - if (m_logAudio) { - if (m_AIplaying) { - Premix(samples, numLeft); + // Add the DSPHLE sound, re-sampling is done inside + Premix(samples, numSamples); - AudioInterface::Callback_GetStreaming(samples, numLeft, m_sampleRate); - - g_wave_writer.AddStereoSamples(samples, numLeft); - } - } - else { //or mix as usual - // Add the DSPHLE sound, re-sampling is done inside - Premix(samples, numSamples); - - // Add the DTK Music - // Re-sampling is done inside - AudioInterface::Callback_GetStreaming(samples, numSamples, m_sampleRate); - } + // Add the DTK Music + // Re-sampling is done inside + AudioInterface::Callback_GetStreaming(samples, numSamples, m_sampleRate); + if (m_logAudio) + g_wave_writer.AddStereoSamples(samples, numSamples); return numSamples; } @@ -170,24 +144,3 @@ void CMixer::PushSamples(const short *samples, unsigned int num_samples) return; } -unsigned int CMixer::GetNumSamples() -{ - // Guess how many samples would be available after interpolation. - // As interpolation needs at least on sample from the future to - // linear interpolate between them, one sample less is available. - // We also can't say the current interpolation state (specially - // the frac), so to be sure, subtract one again to be sure not - // to underflow the fifo. - - u32 numSamples = ((Common::AtomicLoad(m_indexW) - Common::AtomicLoad(m_indexR)) & INDEX_MASK) / 2; - - if (AudioInterface::GetAIDSampleRate() == m_sampleRate) - ; //numSamples = numSamples; // 1:1 - else if (m_sampleRate == 48000 && AudioInterface::GetAIDSampleRate() == 32000) - numSamples = numSamples * 3 / 2 - 2; // most common case - else - numSamples = numSamples * m_sampleRate / AudioInterface::GetAIDSampleRate() - 2; - - return numSamples; -} - diff --git a/Source/Core/AudioCommon/Mixer.h b/Source/Core/AudioCommon/Mixer.h index 6b2c4b95f3..e38a64b067 100644 --- a/Source/Core/AudioCommon/Mixer.h +++ b/Source/Core/AudioCommon/Mixer.h @@ -24,7 +24,6 @@ public: , m_logAudio(0) , m_indexW(0) , m_indexR(0) - , m_AIplaying(true) { // AyuanX: The internal (Core & DSP) sample rate is fixed at 32KHz // So when AI/DAC sample rate differs than 32KHz, we have to do re-sampling @@ -40,7 +39,6 @@ public: // Called from audio threads virtual unsigned int Mix(short* samples, unsigned int numSamples); virtual void Premix(short * /*samples*/, unsigned int /*numSamples*/) {} - unsigned int GetNumSamples(); // Called from main thread virtual void PushSamples(const short* samples, unsigned int num_samples); @@ -98,7 +96,6 @@ protected: volatile u32 m_indexW; volatile u32 m_indexR; - bool m_AIplaying; std::mutex m_csMixing; volatile float m_speed; // Current rate of the emulation (1.0 = 100% speed)