mirror of
https://github.com/yuzu-emu/yuzu.git
synced 2024-07-04 23:31:19 +01:00
Support more PCM formats. Fixes Ys IX audio.
This commit is contained in:
parent
bf50345d4c
commit
dbcc093d88
2 changed files with 51 additions and 18 deletions
|
@ -400,7 +400,10 @@ void CommandGenerator::GenerateDataSourceCommand(ServerVoiceInfo& voice_info, Vo
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
switch (in_params.sample_format) {
|
switch (in_params.sample_format) {
|
||||||
|
case SampleFormat::Pcm8:
|
||||||
case SampleFormat::Pcm16:
|
case SampleFormat::Pcm16:
|
||||||
|
case SampleFormat::Pcm32:
|
||||||
|
case SampleFormat::PcmFloat:
|
||||||
DecodeFromWaveBuffers(voice_info, GetChannelMixBuffer(channel), dsp_state, channel,
|
DecodeFromWaveBuffers(voice_info, GetChannelMixBuffer(channel), dsp_state, channel,
|
||||||
worker_params.sample_rate, worker_params.sample_count,
|
worker_params.sample_rate, worker_params.sample_count,
|
||||||
in_params.node_id);
|
in_params.node_id);
|
||||||
|
@ -1003,9 +1006,10 @@ void CommandGenerator::GenerateFinalMixCommand() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 CommandGenerator::DecodePcm16(ServerVoiceInfo& voice_info, VoiceState& dsp_state,
|
template <typename T>
|
||||||
s32 sample_start_offset, s32 sample_end_offset, s32 sample_count,
|
s32 CommandGenerator::DecodePcm(ServerVoiceInfo& voice_info, VoiceState& dsp_state,
|
||||||
s32 channel, std::size_t mix_offset) {
|
s32 sample_start_offset, s32 sample_end_offset, s32 sample_count,
|
||||||
|
s32 channel, std::size_t mix_offset) {
|
||||||
const auto& in_params = voice_info.GetInParams();
|
const auto& in_params = voice_info.GetInParams();
|
||||||
const auto& wave_buffer = in_params.wave_buffer[dsp_state.wave_buffer_index];
|
const auto& wave_buffer = in_params.wave_buffer[dsp_state.wave_buffer_index];
|
||||||
if (wave_buffer.buffer_address == 0) {
|
if (wave_buffer.buffer_address == 0) {
|
||||||
|
@ -1019,24 +1023,37 @@ s32 CommandGenerator::DecodePcm16(ServerVoiceInfo& voice_info, VoiceState& dsp_s
|
||||||
}
|
}
|
||||||
const auto samples_remaining = (sample_end_offset - sample_start_offset) - dsp_state.offset;
|
const auto samples_remaining = (sample_end_offset - sample_start_offset) - dsp_state.offset;
|
||||||
const auto start_offset =
|
const auto start_offset =
|
||||||
((dsp_state.offset + sample_start_offset) * in_params.channel_count) * sizeof(s16);
|
((dsp_state.offset + sample_start_offset) * in_params.channel_count) * sizeof(T);
|
||||||
const auto buffer_pos = wave_buffer.buffer_address + start_offset;
|
const auto buffer_pos = wave_buffer.buffer_address + start_offset;
|
||||||
const auto samples_processed = std::min(sample_count, samples_remaining);
|
const auto samples_processed = std::min(sample_count, samples_remaining);
|
||||||
|
|
||||||
if (in_params.channel_count == 1) {
|
const auto channel_count = in_params.channel_count;
|
||||||
std::vector<s16> buffer(samples_processed);
|
std::vector<T> buffer(samples_processed * channel_count);
|
||||||
memory.ReadBlock(buffer_pos, buffer.data(), buffer.size() * sizeof(s16));
|
memory.ReadBlock(buffer_pos, buffer.data(), buffer.size() * sizeof(T));
|
||||||
for (std::size_t i = 0; i < buffer.size(); i++) {
|
|
||||||
sample_buffer[mix_offset + i] = buffer[i];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const auto channel_count = in_params.channel_count;
|
|
||||||
std::vector<s16> buffer(samples_processed * channel_count);
|
|
||||||
memory.ReadBlock(buffer_pos, buffer.data(), buffer.size() * sizeof(s16));
|
|
||||||
|
|
||||||
|
if constexpr (std::is_floating_point_v<T>) {
|
||||||
|
for (std::size_t i = 0; i < static_cast<std::size_t>(samples_processed); i++) {
|
||||||
|
sample_buffer[mix_offset + i] = static_cast<s32>(buffer[i * channel_count + channel] *
|
||||||
|
std::numeric_limits<s16>::max());
|
||||||
|
}
|
||||||
|
} else if constexpr (sizeof(T) == 1) {
|
||||||
|
for (std::size_t i = 0; i < static_cast<std::size_t>(samples_processed); i++) {
|
||||||
|
sample_buffer[mix_offset + i] =
|
||||||
|
static_cast<s32>(static_cast<f32>(buffer[i * channel_count + channel] /
|
||||||
|
std::numeric_limits<s8>::max()) *
|
||||||
|
std::numeric_limits<s16>::max());
|
||||||
|
}
|
||||||
|
} else if constexpr (sizeof(T) == 2) {
|
||||||
for (std::size_t i = 0; i < static_cast<std::size_t>(samples_processed); i++) {
|
for (std::size_t i = 0; i < static_cast<std::size_t>(samples_processed); i++) {
|
||||||
sample_buffer[mix_offset + i] = buffer[i * channel_count + channel];
|
sample_buffer[mix_offset + i] = buffer[i * channel_count + channel];
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
for (std::size_t i = 0; i < static_cast<std::size_t>(samples_processed); i++) {
|
||||||
|
sample_buffer[mix_offset + i] =
|
||||||
|
static_cast<s32>(static_cast<f32>(buffer[i * channel_count + channel] /
|
||||||
|
std::numeric_limits<s32>::max()) *
|
||||||
|
std::numeric_limits<s16>::max());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return samples_processed;
|
return samples_processed;
|
||||||
|
@ -1249,10 +1266,25 @@ void CommandGenerator::DecodeFromWaveBuffers(ServerVoiceInfo& voice_info, s32* o
|
||||||
|
|
||||||
s32 samples_decoded{0};
|
s32 samples_decoded{0};
|
||||||
switch (in_params.sample_format) {
|
switch (in_params.sample_format) {
|
||||||
|
case SampleFormat::Pcm8:
|
||||||
|
samples_decoded =
|
||||||
|
DecodePcm<s8>(voice_info, dsp_state, samples_offset_start, samples_offset_end,
|
||||||
|
samples_to_read - samples_read, channel, temp_mix_offset);
|
||||||
|
break;
|
||||||
case SampleFormat::Pcm16:
|
case SampleFormat::Pcm16:
|
||||||
samples_decoded =
|
samples_decoded =
|
||||||
DecodePcm16(voice_info, dsp_state, samples_offset_start, samples_offset_end,
|
DecodePcm<s16>(voice_info, dsp_state, samples_offset_start, samples_offset_end,
|
||||||
samples_to_read - samples_read, channel, temp_mix_offset);
|
samples_to_read - samples_read, channel, temp_mix_offset);
|
||||||
|
break;
|
||||||
|
case SampleFormat::Pcm32:
|
||||||
|
samples_decoded =
|
||||||
|
DecodePcm<s32>(voice_info, dsp_state, samples_offset_start, samples_offset_end,
|
||||||
|
samples_to_read - samples_read, channel, temp_mix_offset);
|
||||||
|
break;
|
||||||
|
case SampleFormat::PcmFloat:
|
||||||
|
samples_decoded =
|
||||||
|
DecodePcm<f32>(voice_info, dsp_state, samples_offset_start, samples_offset_end,
|
||||||
|
samples_to_read - samples_read, channel, temp_mix_offset);
|
||||||
break;
|
break;
|
||||||
case SampleFormat::Adpcm:
|
case SampleFormat::Adpcm:
|
||||||
samples_decoded =
|
samples_decoded =
|
||||||
|
|
|
@ -86,8 +86,9 @@ private:
|
||||||
std::vector<u8>& work_buffer);
|
std::vector<u8>& work_buffer);
|
||||||
void UpdateI3dl2Reverb(I3dl2ReverbParams& info, I3dl2ReverbState& state, bool should_clear);
|
void UpdateI3dl2Reverb(I3dl2ReverbParams& info, I3dl2ReverbState& state, bool should_clear);
|
||||||
// DSP Code
|
// DSP Code
|
||||||
s32 DecodePcm16(ServerVoiceInfo& voice_info, VoiceState& dsp_state, s32 sample_start_offset,
|
template <typename T>
|
||||||
s32 sample_end_offset, s32 sample_count, s32 channel, std::size_t mix_offset);
|
s32 DecodePcm(ServerVoiceInfo& voice_info, VoiceState& dsp_state, s32 sample_start_offset,
|
||||||
|
s32 sample_end_offset, s32 sample_count, s32 channel, std::size_t mix_offset);
|
||||||
s32 DecodeAdpcm(ServerVoiceInfo& voice_info, VoiceState& dsp_state, s32 sample_start_offset,
|
s32 DecodeAdpcm(ServerVoiceInfo& voice_info, VoiceState& dsp_state, s32 sample_start_offset,
|
||||||
s32 sample_end_offset, s32 sample_count, s32 channel, std::size_t mix_offset);
|
s32 sample_end_offset, s32 sample_count, s32 channel, std::size_t mix_offset);
|
||||||
void DecodeFromWaveBuffers(ServerVoiceInfo& voice_info, s32* output, VoiceState& dsp_state,
|
void DecodeFromWaveBuffers(ServerVoiceInfo& voice_info, s32* output, VoiceState& dsp_state,
|
||||||
|
|
Loading…
Reference in a new issue