Merge pull request #414 from DrChat/xma_fixes
XMA can only decode entire frames at a time.
This commit is contained in:
commit
65d91e30ca
|
@ -93,8 +93,6 @@ int XmaContext::Setup(uint32_t id, Memory* memory, uint32_t guest_ptr) {
|
||||||
// Current frame stuff whatever
|
// Current frame stuff whatever
|
||||||
// samples per frame * 2 max channels * output bytes
|
// samples per frame * 2 max channels * output bytes
|
||||||
current_frame_ = new uint8_t[kSamplesPerFrame * kBytesPerSample * 2];
|
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.
|
// FYI: We're purposely not opening the context here. That is done later.
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -345,35 +343,15 @@ void XmaContext::DecodePackets(XMA_CONTEXT_DATA* data) {
|
||||||
output_rb.set_read_offset(output_read_offset);
|
output_rb.set_read_offset(output_read_offset);
|
||||||
output_rb.set_write_offset(output_write_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();
|
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.
|
// Decode until we can't write any more data.
|
||||||
while (output_remaining_bytes > 0) {
|
while (output_remaining_bytes > 0) {
|
||||||
int num_channels = data->is_stereo ? 2 : 1;
|
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) {
|
if (!data->input_buffer_0_valid && !data->input_buffer_1_valid) {
|
||||||
// Out of data.
|
// Out of data.
|
||||||
break;
|
break;
|
||||||
|
@ -581,8 +559,6 @@ void XmaContext::DecodePackets(XMA_CONTEXT_DATA* data) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
last_input_read_pos_ = data->input_buffer_read_offset;
|
|
||||||
|
|
||||||
if (got_frame) {
|
if (got_frame) {
|
||||||
// Successfully decoded a frame.
|
// Successfully decoded a frame.
|
||||||
// Copy to the output buffer.
|
// Copy to the output buffer.
|
||||||
|
@ -601,22 +577,11 @@ void XmaContext::DecodePackets(XMA_CONTEXT_DATA* data) {
|
||||||
// Convert the frame.
|
// Convert the frame.
|
||||||
ConvertFrame((const uint8_t**)decoded_frame_->data, context_->channels,
|
ConvertFrame((const uint8_t**)decoded_frame_->data, context_->channels,
|
||||||
decoded_frame_->nb_samples, current_frame_);
|
decoded_frame_->nb_samples, current_frame_);
|
||||||
current_frame_pos_ = 0;
|
|
||||||
|
|
||||||
if (output_remaining_bytes < kBytesPerFrame * num_channels) {
|
assert_true(output_remaining_bytes >= kBytesPerFrame * num_channels);
|
||||||
// Output buffer isn't big enough to store the entire frame! Write out a
|
output_rb.Write(current_frame_, kBytesPerFrame * num_channels);
|
||||||
// part of it.
|
written_bytes = kBytesPerFrame * num_channels;
|
||||||
current_frame_pos_ = output_remaining_bytes;
|
|
||||||
output_rb.Write(current_frame_, output_remaining_bytes);
|
|
||||||
|
|
||||||
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;
|
output_remaining_bytes -= written_bytes;
|
||||||
data->output_buffer_write_offset = output_rb.write_offset() / 256;
|
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.
|
// 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!!
|
// 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;
|
data->output_buffer_valid = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -210,12 +210,7 @@ class XmaContext {
|
||||||
size_t partial_frame_offset_bits_ = 0; // blah internal don't use this
|
size_t partial_frame_offset_bits_ = 0; // blah internal don't use this
|
||||||
std::vector<uint8_t> partial_frame_buffer_;
|
std::vector<uint8_t> 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;
|
uint8_t* current_frame_ = nullptr;
|
||||||
uint32_t frame_samples_size_ = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace apu
|
} // namespace apu
|
||||||
|
|
Loading…
Reference in New Issue