|
@@ -54,15 +54,23 @@ RefPtr<Buffer> WavLoaderPlugin::get_more_samples(size_t max_bytes_to_read_from_i
|
|
if (!m_stream)
|
|
if (!m_stream)
|
|
return nullptr;
|
|
return nullptr;
|
|
|
|
|
|
- size_t bytes_per_sample = (m_num_channels * (pcm_bits_per_sample(m_sample_format) / 8));
|
|
|
|
|
|
+ int remaining_samples = m_total_samples - m_loaded_samples;
|
|
|
|
+ if (remaining_samples <= 0) {
|
|
|
|
+ return nullptr;
|
|
|
|
+ }
|
|
|
|
|
|
- // Might truncate if not evenly divisible
|
|
|
|
- size_t samples_to_read = static_cast<int>(max_bytes_to_read_from_input) / bytes_per_sample;
|
|
|
|
|
|
+ // One "sample" contains data from all channels.
|
|
|
|
+ // In the Wave spec, this is also called a block.
|
|
|
|
+ size_t bytes_per_sample = m_num_channels * pcm_bits_per_sample(m_sample_format) / 8;
|
|
|
|
+
|
|
|
|
+ // Might truncate if not evenly divisible by the sample size
|
|
|
|
+ int max_samples_to_read = static_cast<int>(max_bytes_to_read_from_input) / bytes_per_sample;
|
|
|
|
+ int samples_to_read = min(max_samples_to_read, remaining_samples);
|
|
size_t bytes_to_read = samples_to_read * bytes_per_sample;
|
|
size_t bytes_to_read = samples_to_read * bytes_per_sample;
|
|
|
|
|
|
- dbgln_if(AWAVLOADER_DEBUG, "Read {} bytes ({} samples) WAV with num_channels {} sample rate {}, "
|
|
|
|
|
|
+ dbgln_if(AWAVLOADER_DEBUG, "Read {} bytes WAV with num_channels {} sample rate {}, "
|
|
"bits per sample {}, sample format {}",
|
|
"bits per sample {}, sample format {}",
|
|
- bytes_to_read, samples_to_read, m_num_channels, m_sample_rate,
|
|
|
|
|
|
+ bytes_to_read, m_num_channels, m_sample_rate,
|
|
pcm_bits_per_sample(m_sample_format), sample_format_name(m_sample_format));
|
|
pcm_bits_per_sample(m_sample_format), sample_format_name(m_sample_format));
|
|
|
|
|
|
ByteBuffer sample_data = ByteBuffer::create_zeroed(bytes_to_read);
|
|
ByteBuffer sample_data = ByteBuffer::create_zeroed(bytes_to_read);
|
|
@@ -79,7 +87,6 @@ RefPtr<Buffer> WavLoaderPlugin::get_more_samples(size_t max_bytes_to_read_from_i
|
|
|
|
|
|
// m_loaded_samples should contain the amount of actually loaded samples
|
|
// m_loaded_samples should contain the amount of actually loaded samples
|
|
m_loaded_samples += samples_to_read;
|
|
m_loaded_samples += samples_to_read;
|
|
- m_loaded_samples = min(m_total_samples, m_loaded_samples);
|
|
|
|
return buffer;
|
|
return buffer;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -89,15 +96,16 @@ void WavLoaderPlugin::seek(const int sample_index)
|
|
if (sample_index < 0 || sample_index >= m_total_samples)
|
|
if (sample_index < 0 || sample_index >= m_total_samples)
|
|
return;
|
|
return;
|
|
|
|
|
|
- m_loaded_samples = sample_index;
|
|
|
|
- size_t byte_position = m_byte_offset_of_data_samples + sample_index * m_num_channels * (pcm_bits_per_sample(m_sample_format) / 8);
|
|
|
|
|
|
+ size_t sample_offset = m_byte_offset_of_data_samples + (sample_index * m_num_channels * (pcm_bits_per_sample(m_sample_format) / 8));
|
|
|
|
|
|
- // AK::InputStream does not define seek.
|
|
|
|
|
|
+ // AK::InputStream does not define seek, hence the special-cases for file and stream.
|
|
if (m_file) {
|
|
if (m_file) {
|
|
- m_file->seek(byte_position);
|
|
|
|
|
|
+ m_file->seek(sample_offset);
|
|
} else {
|
|
} else {
|
|
- m_memory_stream->seek(byte_position);
|
|
|
|
|
|
+ m_memory_stream->seek(sample_offset);
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ m_loaded_samples = sample_index;
|
|
}
|
|
}
|
|
|
|
|
|
// Specification reference: http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/WAVE.html
|
|
// Specification reference: http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/WAVE.html
|
|
@@ -180,11 +188,11 @@ bool WavLoaderPlugin::parse_header()
|
|
read_u32();
|
|
read_u32();
|
|
CHECK_OK("Data rate");
|
|
CHECK_OK("Data rate");
|
|
|
|
|
|
- read_u16();
|
|
|
|
|
|
+ u16 block_size_bytes = read_u16();
|
|
CHECK_OK("Block size");
|
|
CHECK_OK("Block size");
|
|
|
|
|
|
u16 bits_per_sample = read_u16();
|
|
u16 bits_per_sample = read_u16();
|
|
- CHECK_OK("Bits per sample"); // incomplete read check
|
|
|
|
|
|
+ CHECK_OK("Bits per sample");
|
|
|
|
|
|
if (audio_format == WAVE_FORMAT_EXTENSIBLE) {
|
|
if (audio_format == WAVE_FORMAT_EXTENSIBLE) {
|
|
ok = ok && (fmt_size == 40);
|
|
ok = ok && (fmt_size == 40);
|
|
@@ -228,6 +236,9 @@ bool WavLoaderPlugin::parse_header()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ ok = ok && (block_size_bytes == (m_num_channels * (bits_per_sample / 8)));
|
|
|
|
+ CHECK_OK("Block size sanity check");
|
|
|
|
+
|
|
dbgln_if(AWAVLOADER_DEBUG, "WAV format {} at {} bit, {} channels, rate {}Hz ",
|
|
dbgln_if(AWAVLOADER_DEBUG, "WAV format {} at {} bit, {} channels, rate {}Hz ",
|
|
sample_format_name(m_sample_format), pcm_bits_per_sample(m_sample_format), m_num_channels, m_sample_rate);
|
|
sample_format_name(m_sample_format), pcm_bits_per_sample(m_sample_format), m_num_channels, m_sample_rate);
|
|
|
|
|
|
@@ -262,12 +273,11 @@ bool WavLoaderPlugin::parse_header()
|
|
ok = ok && data_sz < maximum_wav_size;
|
|
ok = ok && data_sz < maximum_wav_size;
|
|
CHECK_OK("Data was too large");
|
|
CHECK_OK("Data was too large");
|
|
|
|
|
|
- int bytes_per_sample = (bits_per_sample / 8) * m_num_channels;
|
|
|
|
- m_total_samples = data_sz / bytes_per_sample;
|
|
|
|
|
|
+ m_total_samples = data_sz / block_size_bytes;
|
|
|
|
|
|
dbgln_if(AWAVLOADER_DEBUG, "WAV data size {}, bytes per sample {}, total samples {}",
|
|
dbgln_if(AWAVLOADER_DEBUG, "WAV data size {}, bytes per sample {}, total samples {}",
|
|
data_sz,
|
|
data_sz,
|
|
- bytes_per_sample,
|
|
|
|
|
|
+ block_size_bytes,
|
|
m_total_samples);
|
|
m_total_samples);
|
|
|
|
|
|
m_byte_offset_of_data_samples = bytes_read;
|
|
m_byte_offset_of_data_samples = bytes_read;
|