| 
						
						
							
								
							
						
						
					 | 
				
			
			 | 
			 | 
			
				@ -9,23 +9,6 @@
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				#include <imgui.h>
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				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;
 | 
			
		
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
			
			 | 
			 | 
			
				@ -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];
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  if (!voice.IsOn())
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    return std::make_tuple<s16, s16>(0, 0);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    return {};
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  if (!voice.has_samples)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  {
 | 
			
		
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
			
			 | 
			 | 
			
				@ -806,24 +789,14 @@ std::tuple<SPU::SampleFormat, SPU::SampleFormat> SPU::SampleVoice(u32 voice_inde
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  // TODO: Volume
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  const float adsr_volume = S16ToFloat(voice.regs.adsr_volume);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  // interpolate/sample and apply ADSR volume
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  const s32 sample = ApplyVolumeUnsaturated(voice.Interpolate(), voice.regs.adsr_volume);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  voice.TickADSR();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  const s32 sample = voice.Interpolate();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  // s32 sample = voice.SampleBlock(voice.counter.sample_index);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  const s16 sample16 = Clamp16(sample);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  const float samplef = S16ToFloat(sample16) * adsr_volume;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  // 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);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  // apply per-channel volume
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  const s16 left = ApplyVolumeUnsaturated(sample, voice.regs.volume_left.GetVolume());
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  const s16 right = ApplyVolumeUnsaturated(sample, voice.regs.volume_right.GetVolume());
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  return std::make_tuple(left, right);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				void SPU::EnsureCDAudioSpace(u32 num_samples)
 | 
			
		
		
	
	
		
			
				
					| 
						
							
								
							
						
						
						
					 | 
				
			
			 | 
			 | 
			
				
 
 |