SPU: Float-less volume application

This commit is contained in:
Connor McLaughlin 2019-10-20 16:27:30 +10:00
parent 03e4c71b4c
commit f3cd100b16
2 changed files with 20 additions and 39 deletions

View File

@ -9,23 +9,6 @@
#include <imgui.h> #include <imgui.h>
Log_SetChannel(SPU); Log_SetChannel(SPU);
static s16 Clamp16(s32 value)
{
return static_cast<s16>(std::clamp<s32>(value, -32768, 32767));
}
static constexpr float S16ToFloat(s16 value)
{
return (value >= 0) ? (static_cast<float>(value) / static_cast<float>(std::numeric_limits<s16>::max())) :
(static_cast<float>(value) / -static_cast<float>(std::numeric_limits<s16>::min()));
}
static constexpr s16 FloatToS16(float value)
{
return (value >= 0.0f) ? (static_cast<s16>(value * static_cast<float>(std::numeric_limits<s16>::max()))) :
(static_cast<s16>(value * -static_cast<float>(std::numeric_limits<s16>::min())));
}
SPU::SPU() = default; SPU::SPU() = default;
SPU::~SPU() = default; SPU::~SPU() = default;
@ -754,11 +737,11 @@ void SPU::ReadADPCMBlock(u16 address, ADPCMBlock* block)
} }
} }
std::tuple<SPU::SampleFormat, SPU::SampleFormat> SPU::SampleVoice(u32 voice_index) std::tuple<s32, s32> SPU::SampleVoice(u32 voice_index)
{ {
Voice& voice = m_voices[voice_index]; Voice& voice = m_voices[voice_index];
if (!voice.IsOn()) if (!voice.IsOn())
return std::make_tuple<s16, s16>(0, 0); return {};
if (!voice.has_samples) if (!voice.has_samples)
{ {
@ -806,24 +789,14 @@ std::tuple<SPU::SampleFormat, SPU::SampleFormat> SPU::SampleVoice(u32 voice_inde
} }
} }
// TODO: Volume // interpolate/sample and apply ADSR volume
const float adsr_volume = S16ToFloat(voice.regs.adsr_volume); const s32 sample = ApplyVolumeUnsaturated(voice.Interpolate(), voice.regs.adsr_volume);
voice.TickADSR(); voice.TickADSR();
const s32 sample = voice.Interpolate(); // apply per-channel volume
// s32 sample = voice.SampleBlock(voice.counter.sample_index); const s16 left = ApplyVolumeUnsaturated(sample, voice.regs.volume_left.GetVolume());
const s16 sample16 = Clamp16(sample); const s16 right = ApplyVolumeUnsaturated(sample, voice.regs.volume_right.GetVolume());
const float samplef = S16ToFloat(sample16) * adsr_volume; return std::make_tuple(left, right);
// apply volume
const float volume_left = S16ToFloat(voice.regs.volume_left.GetVolume());
const float volume_right = S16ToFloat(voice.regs.volume_right.GetVolume());
const float final_left = volume_left * samplef;
const float final_right = volume_right * samplef;
return std::make_tuple(FloatToS16(final_left), FloatToS16(final_right));
// return std::make_tuple(FloatToS16(samplef), FloatToS16(samplef));
// return std::make_tuple(sample16, sample16);
} }
void SPU::EnsureCDAudioSpace(u32 num_samples) void SPU::EnsureCDAudioSpace(u32 num_samples)

View File

@ -251,6 +251,14 @@ private:
void TickADSR(); void TickADSR();
}; };
static constexpr s16 Clamp16(s32 value)
{
return (value < -0x8000) ? -0x8000 : (value > 0x7FFF) ? 0x7FFF : static_cast<s16>(value);
}
static constexpr s16 ApplyVolume(s16 sample, s16 volume) { return Clamp16((s32(sample) * s32(volume)) >> 15); }
static constexpr s32 ApplyVolumeUnsaturated(s32 sample, s16 volume) { return (sample * s32(volume)) >> 15; }
static ADSRPhase GetNextADSRPhase(ADSRPhase phase); static ADSRPhase GetNextADSRPhase(ADSRPhase phase);
u16 ReadVoiceRegister(u32 offset); u16 ReadVoiceRegister(u32 offset);
@ -261,7 +269,7 @@ private:
void RAMTransferWrite(u16 value); void RAMTransferWrite(u16 value);
void ReadADPCMBlock(u16 address, ADPCMBlock* block); void ReadADPCMBlock(u16 address, ADPCMBlock* block);
std::tuple<SampleFormat, SampleFormat> SampleVoice(u32 voice_index); std::tuple<s32, s32> SampleVoice(u32 voice_index);
void GenerateSample(); void GenerateSample();
System* m_system = nullptr; System* m_system = nullptr;