From 8024e4fd20bb4764f4cc298aeeb576b4389c2823 Mon Sep 17 00:00:00 2001 From: "Dr. Chat" Date: Wed, 2 Sep 2015 20:20:45 -0500 Subject: [PATCH] XMA: We can only decode an entire frame and write it out at a time! Saving samples is bad. --- src/xenia/apu/xma_context.cc | 51 ++++++------------------------------ src/xenia/apu/xma_context.h | 5 ---- 2 files changed, 8 insertions(+), 48 deletions(-) diff --git a/src/xenia/apu/xma_context.cc b/src/xenia/apu/xma_context.cc index f6df1f9fa..42eed6eda 100644 --- a/src/xenia/apu/xma_context.cc +++ b/src/xenia/apu/xma_context.cc @@ -93,8 +93,6 @@ int XmaContext::Setup(uint32_t id, Memory* memory, uint32_t guest_ptr) { // Current frame stuff whatever // samples per frame * 2 max channels * output bytes current_frame_ = new uint8_t[kSamplesPerFrame * kBytesPerSample * 2]; - current_frame_pos_ = 0; - frame_samples_size_ = 0; // FYI: We're purposely not opening the context here. That is done later. return 0; @@ -345,35 +343,15 @@ void XmaContext::DecodePackets(XMA_CONTEXT_DATA* data) { output_rb.set_read_offset(output_read_offset); output_rb.set_write_offset(output_write_offset); + // We can only decode an entire frame and write it out at a time, so + // don't save any samples. size_t output_remaining_bytes = output_rb.write_count(); - bool output_written = false; + output_remaining_bytes -= data->is_stereo ? (output_remaining_bytes % 2048) + : (output_remaining_bytes % 1024); // Decode until we can't write any more data. while (output_remaining_bytes > 0) { int num_channels = data->is_stereo ? 2 : 1; - - // Check if we have part of a frame waiting (and the game hasn't jumped - // around) - if (current_frame_pos_ && - last_input_read_pos_ == data->input_buffer_read_offset) { - size_t to_write = std::min( - output_remaining_bytes, - ((size_t)kBytesPerFrame * num_channels - current_frame_pos_)); - output_rb.Write(current_frame_ + current_frame_pos_, to_write); - output_written = true; - XELOGAPU("XmaContext %d: wrote out %d bytes of left-over samples", id(), - to_write); - - current_frame_pos_ += to_write; - if (current_frame_pos_ >= kBytesPerFrame * num_channels) { - current_frame_pos_ = 0; - } - - data->output_buffer_write_offset = output_rb.write_offset() / 256; - output_remaining_bytes -= to_write; - continue; - } - if (!data->input_buffer_0_valid && !data->input_buffer_1_valid) { // Out of data. break; @@ -581,8 +559,6 @@ void XmaContext::DecodePackets(XMA_CONTEXT_DATA* data) { return; } - last_input_read_pos_ = data->input_buffer_read_offset; - if (got_frame) { // Successfully decoded a frame. // Copy to the output buffer. @@ -601,22 +577,11 @@ void XmaContext::DecodePackets(XMA_CONTEXT_DATA* data) { // Convert the frame. ConvertFrame((const uint8_t**)decoded_frame_->data, context_->channels, decoded_frame_->nb_samples, current_frame_); - current_frame_pos_ = 0; - if (output_remaining_bytes < kBytesPerFrame * num_channels) { - // Output buffer isn't big enough to store the entire frame! Write out a - // part of it. - current_frame_pos_ = output_remaining_bytes; - output_rb.Write(current_frame_, output_remaining_bytes); + assert_true(output_remaining_bytes >= kBytesPerFrame * num_channels); + output_rb.Write(current_frame_, kBytesPerFrame * num_channels); + written_bytes = kBytesPerFrame * num_channels; - written_bytes = output_remaining_bytes; - } else { - output_rb.Write(current_frame_, kBytesPerFrame * num_channels); - - written_bytes = kBytesPerFrame * num_channels; - } - - output_written = true; output_remaining_bytes -= written_bytes; data->output_buffer_write_offset = output_rb.write_offset() / 256; } @@ -624,7 +589,7 @@ void XmaContext::DecodePackets(XMA_CONTEXT_DATA* data) { // The game will kick us again with a new output buffer later. // It's important that we only invalidate this if we actually wrote to it!! - if (output_written) { + if (output_rb.write_offset() == output_rb.read_offset()) { data->output_buffer_valid = 0; } } diff --git a/src/xenia/apu/xma_context.h b/src/xenia/apu/xma_context.h index 96d059188..53b7fd78f 100644 --- a/src/xenia/apu/xma_context.h +++ b/src/xenia/apu/xma_context.h @@ -210,12 +210,7 @@ class XmaContext { size_t partial_frame_offset_bits_ = 0; // blah internal don't use this std::vector partial_frame_buffer_; - // If we didn't finish writing a frame to the output buffer, this is the - // offset. - size_t current_frame_pos_ = 0; - uint32_t last_input_read_pos_ = 0; // Last seen read buffer pos uint8_t* current_frame_ = nullptr; - uint32_t frame_samples_size_ = 0; }; } // namespace apu