mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu-mainline.git
				synced 2025-03-21 01:53:15 +00:00 
			
		
		
		
	mix buffer depopping
This commit is contained in:
		
							parent
							
								
									1b8fe7073b
								
							
						
					
					
						commit
						0947f613b1
					
				| @ -46,6 +46,24 @@ void ApplyGainWithoutDelta(s32* output, const s32* input, s32 gain, s32 sample_c | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| s32 ApplyMixDepop(s32* output, s32 first_sample, s32 delta, s32 sample_count) { | ||||
|     const bool positive = first_sample > 0; | ||||
|     auto final_sample = std::abs(first_sample); | ||||
|     for (s32 i = 0; i < sample_count; i++) { | ||||
|         final_sample = static_cast<s32>((static_cast<s64>(final_sample) * delta) >> 15); | ||||
|         if (positive) { | ||||
|             output[i] += final_sample; | ||||
|         } else { | ||||
|             output[i] -= final_sample; | ||||
|         } | ||||
|     } | ||||
|     if (positive) { | ||||
|         return final_sample; | ||||
|     } else { | ||||
|         return -final_sample; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| } // namespace
 | ||||
| 
 | ||||
| CommandGenerator::CommandGenerator(AudioCommon::AudioRendererParameter& worker_params, | ||||
| @ -55,12 +73,15 @@ CommandGenerator::CommandGenerator(AudioCommon::AudioRendererParameter& worker_p | ||||
|       splitter_context(splitter_context), memory(memory), | ||||
|       mix_buffer((worker_params.mix_buffer_count + AudioCommon::MAX_CHANNEL_COUNT) * | ||||
|                  worker_params.sample_count), | ||||
|       sample_buffer(MIX_BUFFER_SIZE) {} | ||||
|       sample_buffer(MIX_BUFFER_SIZE), | ||||
|       depop_buffer((worker_params.mix_buffer_count + AudioCommon::MAX_CHANNEL_COUNT) * | ||||
|                    worker_params.sample_count) {} | ||||
| CommandGenerator::~CommandGenerator() = default; | ||||
| 
 | ||||
| void CommandGenerator::ClearMixBuffers() { | ||||
|     std::fill(mix_buffer.begin(), mix_buffer.end(), 0); | ||||
|     std::fill(sample_buffer.begin(), sample_buffer.end(), 0); | ||||
|     // std::fill(depop_buffer.begin(), depop_buffer.end(), 0);
 | ||||
| } | ||||
| 
 | ||||
| void CommandGenerator::GenerateVoiceCommands() { | ||||
| @ -195,32 +216,39 @@ void CommandGenerator::GenerateDataSourceCommand(ServerVoiceInfo& voice_info, Vo | ||||
|     auto& in_params = voice_info.GetInParams(); | ||||
|     const auto depop = in_params.should_depop; | ||||
| 
 | ||||
|     if (in_params.mix_id != AudioCommon::NO_MIX) { | ||||
|         [[maybe_unused]] auto& mix_info = mix_context.GetInfo(in_params.mix_id); | ||||
|         // mix_info.
 | ||||
|         // TODO(ogniK): Depop to destination mix
 | ||||
|     } else if (in_params.splitter_info_id != AudioCommon::NO_SPLITTER) { | ||||
|         // TODO(ogniK): Depop to splitter
 | ||||
|     } | ||||
| 
 | ||||
|     if (depop) { | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     switch (in_params.sample_format) { | ||||
|     case SampleFormat::Pcm16: | ||||
|         DecodeFromWaveBuffers(voice_info, GetChannelMixBuffer(channel), dsp_state, channel, | ||||
|                               worker_params.sample_rate, worker_params.sample_count, | ||||
|                               in_params.node_id); | ||||
|         break; | ||||
|     case SampleFormat::Adpcm: | ||||
|         ASSERT(channel == 0 && in_params.channel_count == 1); | ||||
|         DecodeFromWaveBuffers(voice_info, GetChannelMixBuffer(0), dsp_state, 0, | ||||
|                               worker_params.sample_rate, worker_params.sample_count, | ||||
|                               in_params.node_id); | ||||
|         break; | ||||
|     default: | ||||
|         UNREACHABLE_MSG("Unimplemented sample format={}", in_params.sample_format); | ||||
|         if (in_params.mix_id != AudioCommon::NO_MIX) { | ||||
|             auto& mix_info = mix_context.GetInfo(in_params.mix_id); | ||||
|             const auto& mix_in = mix_info.GetInParams(); | ||||
|             GenerateDepopPrepareCommand(dsp_state, mix_in.buffer_count, mix_in.buffer_offset); | ||||
|         } else if (in_params.splitter_info_id != AudioCommon::NO_SPLITTER) { | ||||
|             s32 index{}; | ||||
|             while (const auto* destination = | ||||
|                        GetDestinationData(in_params.splitter_info_id, index++)) { | ||||
|                 if (!destination->IsConfigured()) { | ||||
|                     continue; | ||||
|                 } | ||||
|                 auto& mix_info = mix_context.GetInfo(destination->GetMixId()); | ||||
|                 const auto& mix_in = mix_info.GetInParams(); | ||||
|                 GenerateDepopPrepareCommand(dsp_state, mix_in.buffer_count, mix_in.buffer_offset); | ||||
|             } | ||||
|         } | ||||
|     } else { | ||||
|         switch (in_params.sample_format) { | ||||
|         case SampleFormat::Pcm16: | ||||
|             DecodeFromWaveBuffers(voice_info, GetChannelMixBuffer(channel), dsp_state, channel, | ||||
|                                   worker_params.sample_rate, worker_params.sample_count, | ||||
|                                   in_params.node_id); | ||||
|             break; | ||||
|         case SampleFormat::Adpcm: | ||||
|             ASSERT(channel == 0 && in_params.channel_count == 1); | ||||
|             DecodeFromWaveBuffers(voice_info, GetChannelMixBuffer(0), dsp_state, 0, | ||||
|                                   worker_params.sample_rate, worker_params.sample_count, | ||||
|                                   in_params.node_id); | ||||
|             break; | ||||
|         default: | ||||
|             UNREACHABLE_MSG("Unimplemented sample format={}", in_params.sample_format); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| @ -281,6 +309,34 @@ void AudioCore::CommandGenerator::GenerateBiquadFilterCommand( | ||||
|     state = {s0, s1}; | ||||
| } | ||||
| 
 | ||||
| void CommandGenerator::GenerateDepopPrepareCommand(VoiceState& dsp_state, | ||||
|                                                    std::size_t mix_buffer_count, | ||||
|                                                    std::size_t mix_buffer_offset) { | ||||
|     for (std::size_t i = 0; i < mix_buffer_count; i++) { | ||||
|         auto& sample = dsp_state.previous_samples[i]; | ||||
|         if (sample != 0) { | ||||
|             depop_buffer[mix_buffer_offset + i] += sample; | ||||
|             sample = 0; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void CommandGenerator::GenerateDepopForMixBuffersCommand(std::size_t mix_buffer_count, | ||||
|                                                          std::size_t mix_buffer_offset, | ||||
|                                                          s32 sample_rate) { | ||||
|     const std::size_t end_offset = | ||||
|         std::min(mix_buffer_offset + mix_buffer_count, GetTotalMixBufferCount()); | ||||
|     const s32 delta = sample_rate == 48000 ? 0x7B29 : 0x78CB; | ||||
|     for (std::size_t i = mix_buffer_offset; i < end_offset; i++) { | ||||
|         if (depop_buffer[i] == 0) { | ||||
|             continue; | ||||
|         } | ||||
| 
 | ||||
|         depop_buffer[i] = | ||||
|             ApplyMixDepop(GetMixBuffer(i), depop_buffer[i], delta, worker_params.sample_count); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| ServerSplitterDestinationData* CommandGenerator::GetDestinationData(s32 splitter_id, s32 index) { | ||||
|     if (splitter_id == AudioCommon::NO_SPLITTER) { | ||||
|         return nullptr; | ||||
| @ -338,7 +394,9 @@ void CommandGenerator::GenerateSubMixCommand(ServerMixInfo& mix_info) { | ||||
|     if (dumping_frame) { | ||||
|         LOG_DEBUG(Audio, "(DSP_TRACE) GenerateSubMixCommand"); | ||||
|     } | ||||
|     // TODO(ogniK): Depop
 | ||||
|     auto& in_params = mix_info.GetInParams(); | ||||
|     GenerateDepopForMixBuffersCommand(in_params.buffer_count, in_params.buffer_offset, | ||||
|                                       in_params.sample_rate); | ||||
|     // TODO(ogniK): Effects
 | ||||
|     GenerateMixCommands(mix_info); | ||||
| } | ||||
| @ -412,10 +470,13 @@ void CommandGenerator::GenerateFinalMixCommand() { | ||||
|     if (dumping_frame) { | ||||
|         LOG_DEBUG(Audio, "(DSP_TRACE) GenerateFinalMixCommand"); | ||||
|     } | ||||
|     // TODO(ogniK): Depop
 | ||||
|     // TODO(ogniK): Effects
 | ||||
|     auto& mix_info = mix_context.GetFinalMixInfo(); | ||||
|     const auto in_params = mix_info.GetInParams(); | ||||
| 
 | ||||
|     GenerateDepopForMixBuffersCommand(in_params.buffer_count, in_params.buffer_offset, | ||||
|                                       in_params.sample_rate); | ||||
|     // TODO(ogniK): Effects
 | ||||
| 
 | ||||
|     for (s32 i = 0; i < in_params.buffer_count; i++) { | ||||
|         const s32 gain = static_cast<s32>(in_params.volume * 32768.0f); | ||||
|         if (dumping_frame) { | ||||
| @ -541,6 +602,10 @@ std::size_t CommandGenerator::GetMixChannelBufferOffset(s32 channel) const { | ||||
|     return worker_params.mix_buffer_count + channel; | ||||
| } | ||||
| 
 | ||||
| std::size_t CommandGenerator::GetTotalMixBufferCount() const { | ||||
|     return worker_params.mix_buffer_count + AudioCommon::MAX_CHANNEL_COUNT; | ||||
| } | ||||
| 
 | ||||
| s32* CommandGenerator::GetChannelMixBuffer(s32 channel) { | ||||
|     return GetMixBuffer(worker_params.mix_buffer_count + channel); | ||||
| } | ||||
|  | ||||
| @ -43,6 +43,8 @@ public: | ||||
|     const s32* GetMixBuffer(std::size_t index) const; | ||||
|     std::size_t GetMixChannelBufferOffset(s32 channel) const; | ||||
| 
 | ||||
|     std::size_t GetTotalMixBufferCount() const; | ||||
| 
 | ||||
| private: | ||||
|     void GenerateDataSourceCommand(ServerVoiceInfo& voice_info, VoiceState& dsp_state, s32 channel); | ||||
|     void GenerateBiquadFilterCommandForVoice(ServerVoiceInfo& voice_info, VoiceState& dsp_state, | ||||
| @ -61,7 +63,10 @@ private: | ||||
|     void GenerateBiquadFilterCommand(s32 mix_buffer, const BiquadFilterParameter& params, | ||||
|                                      std::array<s64, 2>& state, std::size_t input_offset, | ||||
|                                      std::size_t output_offset, s32 sample_count, s32 node_id); | ||||
|     void GenerateDepopPrepareCommand(VoiceState& dsp_state); | ||||
|     void GenerateDepopPrepareCommand(VoiceState& dsp_state, std::size_t mix_buffer_count, | ||||
|                                      std::size_t mix_buffer_offset); | ||||
|     void GenerateDepopForMixBuffersCommand(std::size_t mix_buffer_count, | ||||
|                                            std::size_t mix_buffer_offset, s32 sample_rate); | ||||
|     ServerSplitterDestinationData* GetDestinationData(s32 splitter_id, s32 index); | ||||
| 
 | ||||
|     // DSP Code
 | ||||
| @ -79,6 +84,7 @@ private: | ||||
|     Core::Memory::Memory& memory; | ||||
|     std::vector<s32> mix_buffer{}; | ||||
|     std::vector<s32> sample_buffer{}; | ||||
|     std::vector<s32> depop_buffer{}; | ||||
|     bool dumping_frame{false}; | ||||
| }; | ||||
| } // namespace AudioCore
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 David Marcec
						David Marcec