forked from suyu/suyu
Merge pull request #11467 from Kelebek1/fix_decode
[audio] Fix data source version 1 command looping
This commit is contained in:
commit
3b7d112c83
4 changed files with 71 additions and 51 deletions
|
@ -20,6 +20,12 @@ void AdpcmDataSourceVersion1Command::Process(const AudioRenderer::CommandListPro
|
||||||
auto out_buffer{processor.mix_buffers.subspan(output_index * processor.sample_count,
|
auto out_buffer{processor.mix_buffers.subspan(output_index * processor.sample_count,
|
||||||
processor.sample_count)};
|
processor.sample_count)};
|
||||||
|
|
||||||
|
for (auto& wave_buffer : wave_buffers) {
|
||||||
|
wave_buffer.loop_start_offset = wave_buffer.start_offset;
|
||||||
|
wave_buffer.loop_end_offset = wave_buffer.end_offset;
|
||||||
|
wave_buffer.loop_count = wave_buffer.loop ? -1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
DecodeFromWaveBuffersArgs args{
|
DecodeFromWaveBuffersArgs args{
|
||||||
.sample_format{SampleFormat::Adpcm},
|
.sample_format{SampleFormat::Adpcm},
|
||||||
.output{out_buffer},
|
.output{out_buffer},
|
||||||
|
|
|
@ -123,11 +123,13 @@ static u32 DecodeAdpcm(Core::Memory::Memory& memory, std::span<s16> out_buffer,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto samples_to_process{
|
auto start_pos{req.start_offset + req.offset};
|
||||||
std::min(req.end_offset - req.start_offset - req.offset, req.samples_to_read)};
|
auto samples_to_process{std::min(req.end_offset - start_pos, req.samples_to_read)};
|
||||||
|
if (samples_to_process == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
auto samples_to_read{samples_to_process};
|
auto samples_to_read{samples_to_process};
|
||||||
auto start_pos{req.start_offset + req.offset};
|
|
||||||
auto samples_remaining_in_frame{start_pos % SamplesPerFrame};
|
auto samples_remaining_in_frame{start_pos % SamplesPerFrame};
|
||||||
auto position_in_frame{(start_pos / SamplesPerFrame) * NibblesPerFrame +
|
auto position_in_frame{(start_pos / SamplesPerFrame) * NibblesPerFrame +
|
||||||
samples_remaining_in_frame};
|
samples_remaining_in_frame};
|
||||||
|
@ -225,13 +227,24 @@ static u32 DecodeAdpcm(Core::Memory::Memory& memory, std::span<s16> out_buffer,
|
||||||
* @param args - The wavebuffer data, and information for how to decode it.
|
* @param args - The wavebuffer data, and information for how to decode it.
|
||||||
*/
|
*/
|
||||||
void DecodeFromWaveBuffers(Core::Memory::Memory& memory, const DecodeFromWaveBuffersArgs& args) {
|
void DecodeFromWaveBuffers(Core::Memory::Memory& memory, const DecodeFromWaveBuffersArgs& args) {
|
||||||
|
static constexpr auto EndWaveBuffer = [](auto& voice_state, auto& wavebuffer, auto& index,
|
||||||
|
auto& played_samples, auto& consumed) -> void {
|
||||||
|
voice_state.wave_buffer_valid[index] = false;
|
||||||
|
voice_state.loop_count = 0;
|
||||||
|
|
||||||
|
if (wavebuffer.stream_ended) {
|
||||||
|
played_samples = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
index = (index + 1) % MaxWaveBuffers;
|
||||||
|
consumed++;
|
||||||
|
};
|
||||||
auto& voice_state{*args.voice_state};
|
auto& voice_state{*args.voice_state};
|
||||||
auto remaining_sample_count{args.sample_count};
|
auto remaining_sample_count{args.sample_count};
|
||||||
auto fraction{voice_state.fraction};
|
auto fraction{voice_state.fraction};
|
||||||
|
|
||||||
const auto sample_rate_ratio{
|
const auto sample_rate_ratio{Common::FixedPoint<49, 15>(
|
||||||
(Common::FixedPoint<49, 15>(args.source_sample_rate) / args.target_sample_rate) *
|
(f32)args.source_sample_rate / (f32)args.target_sample_rate * (f32)args.pitch)};
|
||||||
args.pitch};
|
|
||||||
const auto size_required{fraction + remaining_sample_count * sample_rate_ratio};
|
const auto size_required{fraction + remaining_sample_count * sample_rate_ratio};
|
||||||
|
|
||||||
if (size_required < 0) {
|
if (size_required < 0) {
|
||||||
|
@ -298,22 +311,23 @@ void DecodeFromWaveBuffers(Core::Memory::Memory& memory, const DecodeFromWaveBuf
|
||||||
auto end_offset{wavebuffer.end_offset};
|
auto end_offset{wavebuffer.end_offset};
|
||||||
|
|
||||||
if (wavebuffer.loop && voice_state.loop_count > 0 &&
|
if (wavebuffer.loop && voice_state.loop_count > 0 &&
|
||||||
wavebuffer.loop_start_offset != 0 && wavebuffer.loop_end_offset != 0 &&
|
|
||||||
wavebuffer.loop_start_offset <= wavebuffer.loop_end_offset) {
|
wavebuffer.loop_start_offset <= wavebuffer.loop_end_offset) {
|
||||||
start_offset = wavebuffer.loop_start_offset;
|
start_offset = wavebuffer.loop_start_offset;
|
||||||
end_offset = wavebuffer.loop_end_offset;
|
end_offset = wavebuffer.loop_end_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
DecodeArg decode_arg{.buffer{wavebuffer.buffer},
|
DecodeArg decode_arg{
|
||||||
.buffer_size{wavebuffer.buffer_size},
|
.buffer{wavebuffer.buffer},
|
||||||
.start_offset{start_offset},
|
.buffer_size{wavebuffer.buffer_size},
|
||||||
.end_offset{end_offset},
|
.start_offset{start_offset},
|
||||||
.channel_count{args.channel_count},
|
.end_offset{end_offset},
|
||||||
.coefficients{},
|
.channel_count{args.channel_count},
|
||||||
.adpcm_context{nullptr},
|
.coefficients{},
|
||||||
.target_channel{args.channel},
|
.adpcm_context{nullptr},
|
||||||
.offset{offset},
|
.target_channel{args.channel},
|
||||||
.samples_to_read{samples_to_read - samples_read}};
|
.offset{offset},
|
||||||
|
.samples_to_read{samples_to_read - samples_read},
|
||||||
|
};
|
||||||
|
|
||||||
s32 samples_decoded{0};
|
s32 samples_decoded{0};
|
||||||
|
|
||||||
|
@ -350,42 +364,30 @@ void DecodeFromWaveBuffers(Core::Memory::Memory& memory, const DecodeFromWaveBuf
|
||||||
temp_buffer_pos += samples_decoded;
|
temp_buffer_pos += samples_decoded;
|
||||||
offset += samples_decoded;
|
offset += samples_decoded;
|
||||||
|
|
||||||
if (samples_decoded == 0 || offset >= end_offset - start_offset) {
|
if (samples_decoded && offset < end_offset - start_offset) {
|
||||||
offset = 0;
|
continue;
|
||||||
if (!wavebuffer.loop) {
|
}
|
||||||
voice_state.wave_buffer_valid[wavebuffer_index] = false;
|
|
||||||
voice_state.loop_count = 0;
|
|
||||||
|
|
||||||
if (wavebuffer.stream_ended) {
|
offset = 0;
|
||||||
played_sample_count = 0;
|
if (wavebuffer.loop) {
|
||||||
}
|
voice_state.loop_count++;
|
||||||
|
if (wavebuffer.loop_count >= 0 &&
|
||||||
wavebuffer_index = (wavebuffer_index + 1) % MaxWaveBuffers;
|
(voice_state.loop_count > wavebuffer.loop_count || samples_decoded == 0)) {
|
||||||
wavebuffers_consumed++;
|
EndWaveBuffer(voice_state, wavebuffer, wavebuffer_index, played_sample_count,
|
||||||
} else {
|
wavebuffers_consumed);
|
||||||
voice_state.loop_count++;
|
|
||||||
if (wavebuffer.loop_count >= 0 &&
|
|
||||||
(voice_state.loop_count > wavebuffer.loop_count || samples_decoded == 0)) {
|
|
||||||
voice_state.wave_buffer_valid[wavebuffer_index] = false;
|
|
||||||
voice_state.loop_count = 0;
|
|
||||||
|
|
||||||
if (wavebuffer.stream_ended) {
|
|
||||||
played_sample_count = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
wavebuffer_index = (wavebuffer_index + 1) % MaxWaveBuffers;
|
|
||||||
wavebuffers_consumed++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (samples_decoded == 0) {
|
|
||||||
is_buffer_starved = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args.IsVoicePlayedSampleCountResetAtLoopPointSupported) {
|
|
||||||
played_sample_count = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (samples_decoded == 0) {
|
||||||
|
is_buffer_starved = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.IsVoicePlayedSampleCountResetAtLoopPointSupported) {
|
||||||
|
played_sample_count = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
EndWaveBuffer(voice_state, wavebuffer, wavebuffer_index, played_sample_count,
|
||||||
|
wavebuffers_consumed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,12 @@ void PcmFloatDataSourceVersion1Command::Process(
|
||||||
auto out_buffer = processor.mix_buffers.subspan(output_index * processor.sample_count,
|
auto out_buffer = processor.mix_buffers.subspan(output_index * processor.sample_count,
|
||||||
processor.sample_count);
|
processor.sample_count);
|
||||||
|
|
||||||
|
for (auto& wave_buffer : wave_buffers) {
|
||||||
|
wave_buffer.loop_start_offset = wave_buffer.start_offset;
|
||||||
|
wave_buffer.loop_end_offset = wave_buffer.end_offset;
|
||||||
|
wave_buffer.loop_count = wave_buffer.loop ? -1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
DecodeFromWaveBuffersArgs args{
|
DecodeFromWaveBuffersArgs args{
|
||||||
.sample_format{SampleFormat::PcmFloat},
|
.sample_format{SampleFormat::PcmFloat},
|
||||||
.output{out_buffer},
|
.output{out_buffer},
|
||||||
|
|
|
@ -23,6 +23,12 @@ void PcmInt16DataSourceVersion1Command::Process(
|
||||||
auto out_buffer = processor.mix_buffers.subspan(output_index * processor.sample_count,
|
auto out_buffer = processor.mix_buffers.subspan(output_index * processor.sample_count,
|
||||||
processor.sample_count);
|
processor.sample_count);
|
||||||
|
|
||||||
|
for (auto& wave_buffer : wave_buffers) {
|
||||||
|
wave_buffer.loop_start_offset = wave_buffer.start_offset;
|
||||||
|
wave_buffer.loop_end_offset = wave_buffer.end_offset;
|
||||||
|
wave_buffer.loop_count = wave_buffer.loop ? -1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
DecodeFromWaveBuffersArgs args{
|
DecodeFromWaveBuffersArgs args{
|
||||||
.sample_format{SampleFormat::PcmInt16},
|
.sample_format{SampleFormat::PcmInt16},
|
||||||
.output{out_buffer},
|
.output{out_buffer},
|
||||||
|
|
Loading…
Reference in a new issue