Use 64-bit offset/loop points in AudioStreamWAV
This commit is contained in:
@ -174,7 +174,7 @@ void AudioStreamPlaybackWAV::decode_samples(const Depth *p_src, AudioFrame *p_ds
|
|||||||
}
|
}
|
||||||
|
|
||||||
} else if (is_qoa) {
|
} else if (is_qoa) {
|
||||||
uint32_t new_data_ofs = 8 + pos / QOA_FRAME_LEN * p_qoa->frame_len;
|
uint64_t new_data_ofs = 8 + pos / QOA_FRAME_LEN * p_qoa->frame_len;
|
||||||
|
|
||||||
if (p_qoa->data_ofs != new_data_ofs) {
|
if (p_qoa->data_ofs != new_data_ofs) {
|
||||||
p_qoa->data_ofs = new_data_ofs;
|
p_qoa->data_ofs = new_data_ofs;
|
||||||
@ -222,7 +222,7 @@ int AudioStreamPlaybackWAV::_mix_internal(AudioFrame *p_buffer, int p_frames) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t len = base->data_bytes;
|
uint64_t len = base->data_bytes;
|
||||||
switch (base->format) {
|
switch (base->format) {
|
||||||
case AudioStreamWAV::FORMAT_8_BITS:
|
case AudioStreamWAV::FORMAT_8_BITS:
|
||||||
len /= 1;
|
len /= 1;
|
||||||
@ -327,7 +327,7 @@ int AudioStreamPlaybackWAV::_mix_internal(AudioFrame *p_buffer, int p_frames) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* no loop, check for end of sample */
|
/* no loop, check for end of sample */
|
||||||
if (offset >= len) {
|
if ((uint64_t)offset >= len) {
|
||||||
active = false;
|
active = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -486,7 +486,7 @@ Dictionary AudioStreamWAV::get_tags() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
double AudioStreamWAV::get_length() const {
|
double AudioStreamWAV::get_length() const {
|
||||||
int len = data_bytes;
|
uint64_t len = data_bytes;
|
||||||
switch (format) {
|
switch (format) {
|
||||||
case AudioStreamWAV::FORMAT_8_BITS:
|
case AudioStreamWAV::FORMAT_8_BITS:
|
||||||
len /= 1;
|
len /= 1;
|
||||||
@ -587,14 +587,14 @@ Error AudioStreamWAV::save_to_wav(const String &p_path) {
|
|||||||
const uint8_t *read_data = data.ptr();
|
const uint8_t *read_data = data.ptr();
|
||||||
switch (format) {
|
switch (format) {
|
||||||
case AudioStreamWAV::FORMAT_8_BITS:
|
case AudioStreamWAV::FORMAT_8_BITS:
|
||||||
for (unsigned int i = 0; i < data_bytes; i++) {
|
for (uint64_t i = 0; i < data_bytes; i++) {
|
||||||
uint8_t data_point = (read_data[i] + 128);
|
uint8_t data_point = (read_data[i] + 128);
|
||||||
file->store_8(data_point);
|
file->store_8(data_point);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case AudioStreamWAV::FORMAT_16_BITS:
|
case AudioStreamWAV::FORMAT_16_BITS:
|
||||||
case AudioStreamWAV::FORMAT_QOA:
|
case AudioStreamWAV::FORMAT_QOA:
|
||||||
for (unsigned int i = 0; i < data_bytes / 2; i++) {
|
for (uint64_t i = 0; i < data_bytes / 2; i++) {
|
||||||
uint16_t data_point = decode_uint16(&read_data[i * 2]);
|
uint16_t data_point = decode_uint16(&read_data[i * 2]);
|
||||||
file->store_16(data_point);
|
file->store_16(data_point);
|
||||||
}
|
}
|
||||||
@ -616,8 +616,8 @@ Ref<AudioStreamPlayback> AudioStreamWAV::instantiate_playback() {
|
|||||||
uint32_t ffp = qoa_decode_header(data.ptr(), data_bytes, &sample->qoa.desc);
|
uint32_t ffp = qoa_decode_header(data.ptr(), data_bytes, &sample->qoa.desc);
|
||||||
ERR_FAIL_COND_V(ffp != 8, Ref<AudioStreamPlaybackWAV>());
|
ERR_FAIL_COND_V(ffp != 8, Ref<AudioStreamPlaybackWAV>());
|
||||||
sample->qoa.frame_len = qoa_max_frame_size(&sample->qoa.desc);
|
sample->qoa.frame_len = qoa_max_frame_size(&sample->qoa.desc);
|
||||||
int samples_len = sample->qoa.desc.samples > QOA_FRAME_LEN ? QOA_FRAME_LEN : (sample->qoa.desc.samples + 1);
|
uint32_t samples_len = MIN(sample->qoa.desc.samples + 1, (uint32_t)QOA_FRAME_LEN);
|
||||||
int dec_len = sample->qoa.desc.channels * samples_len;
|
uint32_t dec_len = sample->qoa.desc.channels * samples_len;
|
||||||
sample->qoa.dec.resize(dec_len);
|
sample->qoa.dec.resize(dec_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -697,17 +697,17 @@ Ref<AudioStreamWAV> AudioStreamWAV::load_from_buffer(const Vector<uint8_t> &p_st
|
|||||||
// We parse the WAV loop points only with "Detect From WAV" (0).
|
// We parse the WAV loop points only with "Detect From WAV" (0).
|
||||||
int import_loop_mode = p_options["edit/loop_mode"];
|
int import_loop_mode = p_options["edit/loop_mode"];
|
||||||
|
|
||||||
int format_bits = 0;
|
uint16_t format_bits = 0;
|
||||||
int format_channels = 0;
|
uint16_t format_channels = 0;
|
||||||
|
|
||||||
AudioStreamWAV::LoopMode loop_mode = AudioStreamWAV::LOOP_DISABLED;
|
AudioStreamWAV::LoopMode loop_mode = AudioStreamWAV::LOOP_DISABLED;
|
||||||
uint16_t compression_code = 1;
|
uint16_t compression_code = 1;
|
||||||
bool format_found = false;
|
bool format_found = false;
|
||||||
bool data_found = false;
|
bool data_found = false;
|
||||||
int format_freq = 0;
|
uint32_t format_freq = 0;
|
||||||
int loop_begin = 0;
|
int64_t loop_begin = 0;
|
||||||
int loop_end = 0;
|
int64_t loop_end = 0;
|
||||||
int frames = 0;
|
int64_t frames = 0;
|
||||||
|
|
||||||
Vector<float> data;
|
Vector<float> data;
|
||||||
|
|
||||||
@ -785,23 +785,23 @@ Ref<AudioStreamWAV> AudioStreamWAV::load_from_buffer(const Vector<uint8_t> &p_st
|
|||||||
print_line("bits: "+itos(format_bits));
|
print_line("bits: "+itos(format_bits));
|
||||||
*/
|
*/
|
||||||
|
|
||||||
data.resize(frames * format_channels);
|
ERR_FAIL_COND_V(data.resize(frames * format_channels) != OK, Ref<AudioStreamWAV>());
|
||||||
|
|
||||||
if (compression_code == 1) {
|
if (compression_code == 1) {
|
||||||
if (format_bits == 8) {
|
if (format_bits == 8) {
|
||||||
for (int i = 0; i < frames * format_channels; i++) {
|
for (int64_t i = 0; i < frames * format_channels; i++) {
|
||||||
// 8 bit samples are UNSIGNED
|
// 8 bit samples are UNSIGNED
|
||||||
|
|
||||||
data.write[i] = int8_t(file->get_8() - 128) / 128.f;
|
data.write[i] = int8_t(file->get_8() - 128) / 128.f;
|
||||||
}
|
}
|
||||||
} else if (format_bits == 16) {
|
} else if (format_bits == 16) {
|
||||||
for (int i = 0; i < frames * format_channels; i++) {
|
for (int64_t i = 0; i < frames * format_channels; i++) {
|
||||||
//16 bit SIGNED
|
//16 bit SIGNED
|
||||||
|
|
||||||
data.write[i] = int16_t(file->get_16()) / 32768.f;
|
data.write[i] = int16_t(file->get_16()) / 32768.f;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (int i = 0; i < frames * format_channels; i++) {
|
for (int64_t i = 0; i < frames * format_channels; i++) {
|
||||||
//16+ bits samples are SIGNED
|
//16+ bits samples are SIGNED
|
||||||
// if sample is > 16 bits, just read extra bytes
|
// if sample is > 16 bits, just read extra bytes
|
||||||
|
|
||||||
@ -816,13 +816,13 @@ Ref<AudioStreamWAV> AudioStreamWAV::load_from_buffer(const Vector<uint8_t> &p_st
|
|||||||
}
|
}
|
||||||
} else if (compression_code == 3) {
|
} else if (compression_code == 3) {
|
||||||
if (format_bits == 32) {
|
if (format_bits == 32) {
|
||||||
for (int i = 0; i < frames * format_channels; i++) {
|
for (int64_t i = 0; i < frames * format_channels; i++) {
|
||||||
//32 bit IEEE Float
|
//32 bit IEEE Float
|
||||||
|
|
||||||
data.write[i] = file->get_float();
|
data.write[i] = file->get_float();
|
||||||
}
|
}
|
||||||
} else if (format_bits == 64) {
|
} else if (format_bits == 64) {
|
||||||
for (int i = 0; i < frames * format_channels; i++) {
|
for (int64_t i = 0; i < frames * format_channels; i++) {
|
||||||
//64 bit IEEE Float
|
//64 bit IEEE Float
|
||||||
|
|
||||||
data.write[i] = file->get_double();
|
data.write[i] = file->get_double();
|
||||||
@ -855,7 +855,7 @@ Ref<AudioStreamWAV> AudioStreamWAV::load_from_buffer(const Vector<uint8_t> &p_st
|
|||||||
// only read 0x00 (loop forward), 0x01 (loop ping-pong) and 0x02 (loop backward)
|
// only read 0x00 (loop forward), 0x01 (loop ping-pong) and 0x02 (loop backward)
|
||||||
// Skip anything else because it's not supported, reserved for future uses or sampler specific
|
// Skip anything else because it's not supported, reserved for future uses or sampler specific
|
||||||
// from https://sites.google.com/site/musicgapi/technical-documents/wav-file-format#smpl (loop type values table)
|
// from https://sites.google.com/site/musicgapi/technical-documents/wav-file-format#smpl (loop type values table)
|
||||||
int loop_type = file->get_32();
|
uint32_t loop_type = file->get_32();
|
||||||
if (loop_type == 0x00 || loop_type == 0x01 || loop_type == 0x02) {
|
if (loop_type == 0x00 || loop_type == 0x01 || loop_type == 0x02) {
|
||||||
if (loop_type == 0x00) {
|
if (loop_type == 0x00) {
|
||||||
loop_mode = AudioStreamWAV::LOOP_FORWARD;
|
loop_mode = AudioStreamWAV::LOOP_FORWARD;
|
||||||
@ -890,7 +890,7 @@ Ref<AudioStreamWAV> AudioStreamWAV::load_from_buffer(const Vector<uint8_t> &p_st
|
|||||||
}
|
}
|
||||||
|
|
||||||
Vector<char> text;
|
Vector<char> text;
|
||||||
text.resize(text_size);
|
ERR_FAIL_COND_V(text.resize(text_size) != OK, Ref<AudioStreamWAV>());
|
||||||
file->get_buffer((uint8_t *)&text[0], text_size);
|
file->get_buffer((uint8_t *)&text[0], text_size);
|
||||||
|
|
||||||
// Skip padding byte if text_size is odd
|
// Skip padding byte if text_size is odd
|
||||||
@ -918,7 +918,7 @@ Ref<AudioStreamWAV> AudioStreamWAV::load_from_buffer(const Vector<uint8_t> &p_st
|
|||||||
// STEP 2, APPLY CONVERSIONS
|
// STEP 2, APPLY CONVERSIONS
|
||||||
|
|
||||||
bool is16 = format_bits != 8;
|
bool is16 = format_bits != 8;
|
||||||
int rate = format_freq;
|
uint32_t rate = format_freq;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
print_line("Input Sample: ");
|
print_line("Input Sample: ");
|
||||||
@ -934,18 +934,18 @@ Ref<AudioStreamWAV> AudioStreamWAV::load_from_buffer(const Vector<uint8_t> &p_st
|
|||||||
//apply frequency limit
|
//apply frequency limit
|
||||||
|
|
||||||
bool limit_rate = p_options["force/max_rate"];
|
bool limit_rate = p_options["force/max_rate"];
|
||||||
int limit_rate_hz = p_options["force/max_rate_hz"];
|
uint32_t limit_rate_hz = p_options["force/max_rate_hz"];
|
||||||
if (limit_rate && rate > limit_rate_hz && rate > 0 && frames > 0) {
|
if (limit_rate && rate > limit_rate_hz && rate > 0 && frames > 0) {
|
||||||
// resample!
|
// resample!
|
||||||
int new_data_frames = (int)(frames * (float)limit_rate_hz / (float)rate);
|
int64_t new_data_frames = (int64_t)(frames * (float)limit_rate_hz / (float)rate);
|
||||||
|
|
||||||
Vector<float> new_data;
|
Vector<float> new_data;
|
||||||
new_data.resize(new_data_frames * format_channels);
|
ERR_FAIL_COND_V(new_data.resize(new_data_frames * format_channels) != OK, Ref<AudioStreamWAV>());
|
||||||
for (int c = 0; c < format_channels; c++) {
|
for (int c = 0; c < format_channels; c++) {
|
||||||
float frac = 0.0;
|
float frac = 0.0;
|
||||||
int ipos = 0;
|
int64_t ipos = 0;
|
||||||
|
|
||||||
for (int i = 0; i < new_data_frames; i++) {
|
for (int64_t i = 0; i < new_data_frames; i++) {
|
||||||
// Cubic interpolation should be enough.
|
// Cubic interpolation should be enough.
|
||||||
|
|
||||||
float y0 = data[MAX(0, ipos - 1) * format_channels + c];
|
float y0 = data[MAX(0, ipos - 1) * format_channels + c];
|
||||||
@ -959,15 +959,15 @@ Ref<AudioStreamWAV> AudioStreamWAV::load_from_buffer(const Vector<uint8_t> &p_st
|
|||||||
// in order to avoid 32bit floating point precision errors
|
// in order to avoid 32bit floating point precision errors
|
||||||
|
|
||||||
frac += (float)rate / (float)limit_rate_hz;
|
frac += (float)rate / (float)limit_rate_hz;
|
||||||
int tpos = (int)Math::floor(frac);
|
int64_t tpos = (int64_t)Math::floor(frac);
|
||||||
ipos += tpos;
|
ipos += tpos;
|
||||||
frac -= tpos;
|
frac -= tpos;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (loop_mode) {
|
if (loop_mode) {
|
||||||
loop_begin = (int)(loop_begin * (float)new_data_frames / (float)frames);
|
loop_begin = (int64_t)(loop_begin * (float)new_data_frames / (float)frames);
|
||||||
loop_end = (int)(loop_end * (float)new_data_frames / (float)frames);
|
loop_end = (int64_t)(loop_end * (float)new_data_frames / (float)frames);
|
||||||
}
|
}
|
||||||
|
|
||||||
data = new_data;
|
data = new_data;
|
||||||
@ -997,14 +997,14 @@ Ref<AudioStreamWAV> AudioStreamWAV::load_from_buffer(const Vector<uint8_t> &p_st
|
|||||||
bool trim = p_options["edit/trim"];
|
bool trim = p_options["edit/trim"];
|
||||||
|
|
||||||
if (trim && (loop_mode == AudioStreamWAV::LOOP_DISABLED) && format_channels > 0) {
|
if (trim && (loop_mode == AudioStreamWAV::LOOP_DISABLED) && format_channels > 0) {
|
||||||
int first = 0;
|
int64_t first = 0;
|
||||||
int last = (frames / format_channels) - 1;
|
int64_t last = (frames / format_channels) - 1;
|
||||||
bool found = false;
|
bool found = false;
|
||||||
float limit = Math::db_to_linear(TRIM_DB_LIMIT);
|
float limit = Math::db_to_linear(TRIM_DB_LIMIT);
|
||||||
|
|
||||||
for (int i = 0; i < data.size() / format_channels; i++) {
|
for (int64_t i = 0; i < data.size() / format_channels; i++) {
|
||||||
float amp_channel_sum = 0.0;
|
float amp_channel_sum = 0.0;
|
||||||
for (int j = 0; j < format_channels; j++) {
|
for (uint16_t j = 0; j < format_channels; j++) {
|
||||||
amp_channel_sum += Math::abs(data[(i * format_channels) + j]);
|
amp_channel_sum += Math::abs(data[(i * format_channels) + j]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1022,15 +1022,15 @@ Ref<AudioStreamWAV> AudioStreamWAV::load_from_buffer(const Vector<uint8_t> &p_st
|
|||||||
|
|
||||||
if (first < last) {
|
if (first < last) {
|
||||||
Vector<float> new_data;
|
Vector<float> new_data;
|
||||||
new_data.resize((last - first) * format_channels);
|
ERR_FAIL_COND_V(new_data.resize((last - first) * format_channels) != OK, Ref<AudioStreamWAV>());
|
||||||
for (int i = first; i < last; i++) {
|
for (int64_t i = first; i < last; i++) {
|
||||||
float fade_out_mult = 1.0;
|
float fade_out_mult = 1.0;
|
||||||
|
|
||||||
if (last - i < TRIM_FADE_OUT_FRAMES) {
|
if (last - i < TRIM_FADE_OUT_FRAMES) {
|
||||||
fade_out_mult = ((float)(last - i - 1) / (float)TRIM_FADE_OUT_FRAMES);
|
fade_out_mult = ((float)(last - i - 1) / (float)TRIM_FADE_OUT_FRAMES);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int j = 0; j < format_channels; j++) {
|
for (uint16_t j = 0; j < format_channels; j++) {
|
||||||
new_data.write[((i - first) * format_channels) + j] = data[(i * format_channels) + j] * fade_out_mult;
|
new_data.write[((i - first) * format_channels) + j] = data[(i * format_channels) + j] * fade_out_mult;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1058,8 +1058,8 @@ Ref<AudioStreamWAV> AudioStreamWAV::load_from_buffer(const Vector<uint8_t> &p_st
|
|||||||
|
|
||||||
if (force_mono && format_channels == 2) {
|
if (force_mono && format_channels == 2) {
|
||||||
Vector<float> new_data;
|
Vector<float> new_data;
|
||||||
new_data.resize(data.size() / 2);
|
ERR_FAIL_COND_V(new_data.resize(data.size() / 2) != OK, Ref<AudioStreamWAV>());
|
||||||
for (int i = 0; i < frames; i++) {
|
for (int64_t i = 0; i < frames; i++) {
|
||||||
new_data.write[i] = (data[i * 2 + 0] + data[i * 2 + 1]) / 2.0;
|
new_data.write[i] = (data[i * 2 + 0] + data[i * 2 + 1]) / 2.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1084,11 +1084,11 @@ Ref<AudioStreamWAV> AudioStreamWAV::load_from_buffer(const Vector<uint8_t> &p_st
|
|||||||
Vector<float> left;
|
Vector<float> left;
|
||||||
Vector<float> right;
|
Vector<float> right;
|
||||||
|
|
||||||
int tframes = data.size() / 2;
|
int64_t tframes = data.size() / 2;
|
||||||
left.resize(tframes);
|
ERR_FAIL_COND_V(left.resize(tframes) != OK, Ref<AudioStreamWAV>());
|
||||||
right.resize(tframes);
|
ERR_FAIL_COND_V(right.resize(tframes) != OK, Ref<AudioStreamWAV>());
|
||||||
|
|
||||||
for (int i = 0; i < tframes; i++) {
|
for (int64_t i = 0; i < tframes; i++) {
|
||||||
left.write[i] = data[i * 2 + 0];
|
left.write[i] = data[i * 2 + 0];
|
||||||
right.write[i] = data[i * 2 + 1];
|
right.write[i] = data[i * 2 + 1];
|
||||||
}
|
}
|
||||||
@ -1100,7 +1100,7 @@ Ref<AudioStreamWAV> AudioStreamWAV::load_from_buffer(const Vector<uint8_t> &p_st
|
|||||||
_compress_ima_adpcm(right, bright);
|
_compress_ima_adpcm(right, bright);
|
||||||
|
|
||||||
int dl = bleft.size();
|
int dl = bleft.size();
|
||||||
dst_data.resize(dl * 2);
|
ERR_FAIL_COND_V(dst_data.resize(dl * 2) != OK, Ref<AudioStreamWAV>());
|
||||||
|
|
||||||
uint8_t *w = dst_data.ptrw();
|
uint8_t *w = dst_data.ptrw();
|
||||||
const uint8_t *rl = bleft.ptr();
|
const uint8_t *rl = bleft.ptr();
|
||||||
@ -1123,7 +1123,7 @@ Ref<AudioStreamWAV> AudioStreamWAV::load_from_buffer(const Vector<uint8_t> &p_st
|
|||||||
_compress_qoa(data, dst_data, &desc);
|
_compress_qoa(data, dst_data, &desc);
|
||||||
} else {
|
} else {
|
||||||
dst_format = is16 ? AudioStreamWAV::FORMAT_16_BITS : AudioStreamWAV::FORMAT_8_BITS;
|
dst_format = is16 ? AudioStreamWAV::FORMAT_16_BITS : AudioStreamWAV::FORMAT_8_BITS;
|
||||||
dst_data.resize(data.size() * (is16 ? 2 : 1));
|
ERR_FAIL_COND_V(dst_data.resize(data.size() * (is16 ? 2 : 1)) != OK, Ref<AudioStreamWAV>());
|
||||||
{
|
{
|
||||||
uint8_t *w = dst_data.ptrw();
|
uint8_t *w = dst_data.ptrw();
|
||||||
|
|
||||||
|
|||||||
@ -52,7 +52,7 @@ class AudioStreamPlaybackWAV : public AudioStreamPlaybackResampled {
|
|||||||
|
|
||||||
struct QOA_State {
|
struct QOA_State {
|
||||||
qoa_desc desc = {};
|
qoa_desc desc = {};
|
||||||
uint32_t data_ofs = 0;
|
uint64_t data_ofs = 0;
|
||||||
uint32_t frame_len = 0;
|
uint32_t frame_len = 0;
|
||||||
TightLocalVector<int16_t> dec;
|
TightLocalVector<int16_t> dec;
|
||||||
uint32_t dec_len = 0;
|
uint32_t dec_len = 0;
|
||||||
@ -118,10 +118,10 @@ private:
|
|||||||
Format format = FORMAT_8_BITS;
|
Format format = FORMAT_8_BITS;
|
||||||
LoopMode loop_mode = LOOP_DISABLED;
|
LoopMode loop_mode = LOOP_DISABLED;
|
||||||
bool stereo = false;
|
bool stereo = false;
|
||||||
int loop_begin = 0;
|
int64_t loop_begin = 0;
|
||||||
int loop_end = 0;
|
int64_t loop_end = 0;
|
||||||
int mix_rate = 44100;
|
uint32_t mix_rate = 44100;
|
||||||
TightLocalVector<uint8_t> data;
|
TightLocalVector<uint8_t, uint64_t> data;
|
||||||
uint32_t data_bytes = 0;
|
uint32_t data_bytes = 0;
|
||||||
|
|
||||||
Dictionary tags;
|
Dictionary tags;
|
||||||
|
|||||||
Reference in New Issue
Block a user