diff --git a/Core/PCE/CdRom/PceAdpcm.cpp b/Core/PCE/CdRom/PceAdpcm.cpp index 08f6e1bc3..09a8ba6ff 100644 --- a/Core/PCE/CdRom/PceAdpcm.cpp +++ b/Core/PCE/CdRom/PceAdpcm.cpp @@ -324,7 +324,7 @@ void PceAdpcm::PlaySample() int8_t sign = data & 0x08 ? -1 : 1; int16_t adjustment = _stepSize[(_magnitude << 3) | value] * sign; - _currentOutput = std::clamp(_currentOutput + adjustment, 0, 4095); + _currentOutput += adjustment; _magnitude = std::clamp(_magnitude + _stepFactor[value], 0, 48); @@ -333,7 +333,7 @@ void PceAdpcm::PlaySample() SetEndReached(true); } - int16_t out = (_currentOutput - 2048) * 10; + int16_t out = (std::clamp(_currentOutput, 0, 4095) - 2048) * 10; _samplesToPlay.push_back(out); _samplesToPlay.push_back(out); } @@ -344,7 +344,7 @@ void PceAdpcm::MixAudio(int16_t* out, uint32_t sampleCount, uint32_t sampleRate) double volume = _cdrom->GetAudioFader().GetVolume(PceAudioFaderTarget::Adpcm); _resampler.SetVolume(_emu->GetSettings()->GetPcEngineConfig().AdpcmVolume / 100.0 * volume); _resampler.SetSampleRates(freq, sampleRate); - _resampler.Resample(_samplesToPlay.data(), (uint32_t)_samplesToPlay.size() / 2, out, sampleCount); + _resampler.Resample(_samplesToPlay.data(), (uint32_t)_samplesToPlay.size() / 2, out, sampleCount, _state.Playing); _samplesToPlay.clear(); } diff --git a/Core/PCE/CdRom/PceCdAudioPlayer.cpp b/Core/PCE/CdRom/PceCdAudioPlayer.cpp index 5e2b23941..75720db0c 100644 --- a/Core/PCE/CdRom/PceCdAudioPlayer.cpp +++ b/Core/PCE/CdRom/PceCdAudioPlayer.cpp @@ -94,7 +94,7 @@ void PceCdAudioPlayer::MixAudio(int16_t* out, uint32_t sampleCount, uint32_t sam double volume = _cdrom->GetAudioFader().GetVolume(PceAudioFaderTarget::CdAudio); _resampler.SetVolume(_emu->GetSettings()->GetPcEngineConfig().CdAudioVolume / 100.0 * volume); _resampler.SetSampleRates(44100, sampleRate); - _resampler.Resample(_samplesToPlay.data(), (uint32_t)_samplesToPlay.size() / 2, out, sampleCount); + _resampler.Resample(_samplesToPlay.data(), (uint32_t)_samplesToPlay.size() / 2, out, sampleCount, _state.Status == CdAudioStatus::Playing); _samplesToPlay.clear(); } diff --git a/Core/SMS/SmsFmAudio.cpp b/Core/SMS/SmsFmAudio.cpp index f5cee1e87..e08264d05 100644 --- a/Core/SMS/SmsFmAudio.cpp +++ b/Core/SMS/SmsFmAudio.cpp @@ -77,12 +77,13 @@ void SmsFmAudio::MixAudio(int16_t* out, uint32_t sampleCount, uint32_t sampleRat if(_audioControl == 0 || _audioControl == 2) { //FM audio is muted when 0 or 2 + _samplesToPlay.clear(); return; } _resampler.SetSampleRates(_console->GetMasterClockRate() / 72.0, sampleRate); _resampler.SetVolume(_emu->GetSettings()->GetSmsConfig().FmAudioVolume * 1.5 / 100.0); - _resampler.Resample(_samplesToPlay.data(), (uint32_t)_samplesToPlay.size() / 2, out, sampleCount); + _resampler.Resample(_samplesToPlay.data(), (uint32_t)_samplesToPlay.size() / 2, out, sampleCount, true); _samplesToPlay.clear(); } diff --git a/Core/SNES/Coprocessors/SGB/SuperGameboy.cpp b/Core/SNES/Coprocessors/SGB/SuperGameboy.cpp index d9ea7b8fb..3bc1d0695 100644 --- a/Core/SNES/Coprocessors/SGB/SuperGameboy.cpp +++ b/Core/SNES/Coprocessors/SGB/SuperGameboy.cpp @@ -275,7 +275,7 @@ void SuperGameboy::MixAudio(int16_t* out, uint32_t sampleCount, uint32_t sampleR if(!_spc->IsMuted()) { _resampler.SetSampleRates(GbApu::SampleRate * _effectiveClockRate / _gameboy->GetMasterClockRate(), sampleRate); - _resampler.Resample(gbSamples, gbSampleCount, out, sampleCount); + _resampler.Resample(gbSamples, gbSampleCount, out, sampleCount, true); } } diff --git a/Utilities/Audio/HermiteResampler.cpp b/Utilities/Audio/HermiteResampler.cpp index 2cec3e31d..1a22aec9c 100644 --- a/Utilities/Audio/HermiteResampler.cpp +++ b/Utilities/Audio/HermiteResampler.cpp @@ -66,7 +66,7 @@ void HermiteResampler::WriteSample(int16_t* out, uint32_t pos, int16_t left, int } template -uint32_t HermiteResampler::Resample(int16_t* in, uint32_t inSampleCount, int16_t* out, size_t maxOutSampleCount) +uint32_t HermiteResampler::Resample(int16_t* in, uint32_t inSampleCount, int16_t* out, size_t maxOutSampleCount, bool fillToMax) { maxOutSampleCount *= 2; if(_pendingSamples.size() >= maxOutSampleCount) { @@ -86,31 +86,42 @@ uint32_t HermiteResampler::Resample(int16_t* in, uint32_t inSampleCount, int16_t _pendingSamples.push_back(in[i]); _pendingSamples.push_back(in[i + 1]); } - return (count + outPos) / 2; - } - - for(uint32_t i = 0; i < inSampleCount * 2; i += 2) { - while(_fraction <= 1.0) { - //Generate interpolated samples until we have enough samples for the current source sample - if(outPos <= maxOutSampleCount - 2) { - WriteSample(out, outPos, HermiteInterpolate(_prevLeft, _fraction), HermiteInterpolate(_prevRight, _fraction)); - outPos += 2; - } else { - _pendingSamples.push_back(HermiteInterpolate(_prevLeft, _fraction)); - _pendingSamples.push_back(HermiteInterpolate(_prevRight, _fraction)); + _left = in[inSampleCount * 2 - 2]; + _right = in[inSampleCount * 2 - 1]; + outPos += count; + } else { + for(uint32_t i = 0; i < inSampleCount * 2; i += 2) { + while(_fraction <= 1.0) { + //Generate interpolated samples until we have enough samples for the current source sample + _left = HermiteInterpolate(_prevLeft, _fraction); + _right = HermiteInterpolate(_prevRight, _fraction); + if(outPos <= maxOutSampleCount - 2) { + WriteSample(out, outPos, _left, _right); + outPos += 2; + } else { + _pendingSamples.push_back(_left); + _pendingSamples.push_back(_right); + } + + _fraction += _rateRatio; } - _fraction += _rateRatio; + //Move to the next source sample + PushSample(_prevLeft, in[i]); + PushSample(_prevRight, in[i + 1]); + _fraction -= 1.0; } + } - //Move to the next source sample - PushSample(_prevLeft, in[i]); - PushSample(_prevRight, in[i + 1]); - _fraction -= 1.0; + if(fillToMax) { + while(outPos < maxOutSampleCount) { + WriteSample(out, outPos, _left, _right); + outPos += 2; + } } return outPos / 2; } -template uint32_t HermiteResampler::Resample(int16_t* in, uint32_t inSampleCount, int16_t* out, size_t maxOutSampleCount); -template uint32_t HermiteResampler::Resample(int16_t* in, uint32_t inSampleCount, int16_t* out, size_t maxOutSampleCount); \ No newline at end of file +template uint32_t HermiteResampler::Resample(int16_t* in, uint32_t inSampleCount, int16_t* out, size_t maxOutSampleCount, bool fillToMax); +template uint32_t HermiteResampler::Resample(int16_t* in, uint32_t inSampleCount, int16_t* out, size_t maxOutSampleCount, bool fillToMax); \ No newline at end of file diff --git a/Utilities/Audio/HermiteResampler.h b/Utilities/Audio/HermiteResampler.h index a029d860b..e4e7108ba 100644 --- a/Utilities/Audio/HermiteResampler.h +++ b/Utilities/Audio/HermiteResampler.h @@ -10,6 +10,9 @@ class HermiteResampler double _rateRatio = 1.0; double _fraction = 0.0; + int16_t _left = 0; + int16_t _right = 0; + vector _pendingSamples; __forceinline int16_t HermiteInterpolate(double values[4], double mu); @@ -26,5 +29,5 @@ class HermiteResampler uint32_t GetPendingCount(); template - uint32_t Resample(int16_t* in, uint32_t inSampleCount, int16_t* out, size_t maxOutSampleCount); + uint32_t Resample(int16_t* in, uint32_t inSampleCount, int16_t* out, size_t maxOutSampleCount, bool fillToMax = false); };