From 07ed12acd9473523727c239cff8c800fb4eb1c24 Mon Sep 17 00:00:00 2001 From: smix8 <52464204+smix8@users.noreply.github.com> Date: Wed, 3 Jun 2026 11:42:56 +0200 Subject: [PATCH] Improve performance of WAV parsing Improves performance of WAV parsing by avoiding Vector CoW. --- scene/resources/audio_stream_wav.cpp | 63 +++++++++++++++++++--------- 1 file changed, 44 insertions(+), 19 deletions(-) diff --git a/scene/resources/audio_stream_wav.cpp b/scene/resources/audio_stream_wav.cpp index 3cad3033a1..272d23bbc8 100644 --- a/scene/resources/audio_stream_wav.cpp +++ b/scene/resources/audio_stream_wav.cpp @@ -788,18 +788,20 @@ Ref AudioStreamWAV::load_from_buffer(const Vector &p_st ERR_FAIL_COND_V(data.resize(frames * format_channels) != OK, Ref()); + float *data_ptrw = data.ptrw(); + if (compression_code == 1) { if (format_bits == 8) { for (int64_t i = 0; i < frames * format_channels; i++) { // 8 bit samples are UNSIGNED - data.write[i] = int8_t(file->get_8() - 128) / 128.f; + data_ptrw[i] = int8_t(file->get_8() - 128) / 128.f; } } else if (format_bits == 16) { for (int64_t i = 0; i < frames * format_channels; i++) { //16 bit SIGNED - data.write[i] = int16_t(file->get_16()) / 32768.f; + data_ptrw[i] = int16_t(file->get_16()) / 32768.f; } } else { for (int64_t i = 0; i < frames * format_channels; i++) { @@ -812,7 +814,7 @@ Ref AudioStreamWAV::load_from_buffer(const Vector &p_st } s <<= (32 - format_bits); - data.write[i] = (int32_t(s) >> 16) / 32768.f; + data_ptrw[i] = (int32_t(s) >> 16) / 32768.f; } } } else if (compression_code == 3) { @@ -820,13 +822,13 @@ Ref AudioStreamWAV::load_from_buffer(const Vector &p_st for (int64_t i = 0; i < frames * format_channels; i++) { //32 bit IEEE Float - data.write[i] = file->get_float(); + data_ptrw[i] = file->get_float(); } } else if (format_bits == 64) { for (int64_t i = 0; i < frames * format_channels; i++) { //64 bit IEEE Float - data.write[i] = file->get_double(); + data_ptrw[i] = file->get_double(); } } } @@ -943,6 +945,10 @@ Ref AudioStreamWAV::load_from_buffer(const Vector &p_st Vector new_data; ERR_FAIL_COND_V(new_data.resize(new_data_frames * format_channels) != OK, Ref()); + + const float *data_ptr = data.ptr(); + float *new_data_ptrw = new_data.ptrw(); + for (int c = 0; c < format_channels; c++) { float frac = 0.0; int64_t ipos = 0; @@ -950,12 +956,12 @@ Ref AudioStreamWAV::load_from_buffer(const Vector &p_st for (int64_t i = 0; i < new_data_frames; i++) { // Cubic interpolation should be enough. - float y0 = data[MAX(0, ipos - 1) * format_channels + c]; - float y1 = data[ipos * format_channels + c]; - float y2 = data[MIN(frames - 1, ipos + 1) * format_channels + c]; - float y3 = data[MIN(frames - 1, ipos + 2) * format_channels + c]; + float y0 = data_ptr[MAX(0, ipos - 1) * format_channels + c]; + float y1 = data_ptr[ipos * format_channels + c]; + float y2 = data_ptr[MIN(frames - 1, ipos + 1) * format_channels + c]; + float y3 = data_ptr[MIN(frames - 1, ipos + 2) * format_channels + c]; - new_data.write[i * format_channels + c] = Math::cubic_interpolate(y1, y2, y0, y3, frac); + new_data_ptrw[i * format_channels + c] = Math::cubic_interpolate(y1, y2, y0, y3, frac); // update position and always keep fractional part within ]0...1] // in order to avoid 32bit floating point precision errors @@ -981,8 +987,12 @@ Ref AudioStreamWAV::load_from_buffer(const Vector &p_st if (normalize) { float max = 0.0; + + const float *data_ptr = data.ptr(); + float *data_ptrw = data.ptrw(); + for (int i = 0; i < data.size(); i++) { - float amp = Math::abs(data[i]); + float amp = Math::abs(data_ptr[i]); if (amp > max) { max = amp; } @@ -990,8 +1000,9 @@ Ref AudioStreamWAV::load_from_buffer(const Vector &p_st if (max > 0) { float mult = 1.0 / max; + for (int i = 0; i < data.size(); i++) { - data.write[i] *= mult; + data_ptrw[i] = data_ptr[i] * mult; } } } @@ -1004,10 +1015,12 @@ Ref AudioStreamWAV::load_from_buffer(const Vector &p_st bool found = false; float limit = Math::db_to_linear(TRIM_DB_LIMIT); + const float *data_ptr = data.ptr(); + for (int64_t i = 0; i < data.size() / format_channels; i++) { float amp_channel_sum = 0.0; 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_ptr[(i * format_channels) + j]); } float amp = Math::abs(amp_channel_sum / (float)format_channels); @@ -1025,6 +1038,9 @@ Ref AudioStreamWAV::load_from_buffer(const Vector &p_st if (first < last) { Vector new_data; ERR_FAIL_COND_V(new_data.resize((last - first) * format_channels) != OK, Ref()); + + float *new_data_ptrw = new_data.ptrw(); + for (int64_t i = first; i < last; i++) { float fade_out_mult = 1.0; @@ -1033,7 +1049,7 @@ Ref AudioStreamWAV::load_from_buffer(const Vector &p_st } 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_ptrw[((i - first) * format_channels) + j] = data_ptr[(i * format_channels) + j] * fade_out_mult; } } @@ -1061,8 +1077,12 @@ Ref AudioStreamWAV::load_from_buffer(const Vector &p_st if (force_mono && format_channels == 2) { Vector new_data; ERR_FAIL_COND_V(new_data.resize(data.size() / 2) != OK, Ref()); + + const float *data_ptr = data.ptr(); + float *new_data_ptrw = new_data.ptrw(); + for (int64_t i = 0; i < frames; i++) { - new_data.write[i] = (data[i * 2 + 0] + data[i * 2 + 1]) / 2.0; + new_data_ptrw[i] = (data_ptr[i * 2 + 0] + data_ptr[i * 2 + 1]) / 2.0; } data = new_data; @@ -1090,9 +1110,13 @@ Ref AudioStreamWAV::load_from_buffer(const Vector &p_st ERR_FAIL_COND_V(left.resize(tframes) != OK, Ref()); ERR_FAIL_COND_V(right.resize(tframes) != OK, Ref()); + const float *data_ptr = data.ptr(); + float *left_ptrw = left.ptrw(); + float *right_ptrw = right.ptrw(); + for (int64_t i = 0; i < tframes; i++) { - left.write[i] = data[i * 2 + 0]; - right.write[i] = data[i * 2 + 1]; + left_ptrw[i] = data_ptr[i * 2 + 0]; + right_ptrw[i] = data_ptr[i * 2 + 1]; } Vector bleft; @@ -1128,14 +1152,15 @@ Ref AudioStreamWAV::load_from_buffer(const Vector &p_st ERR_FAIL_COND_V(dst_data.resize(data.size() * (is16 ? 2 : 1)) != OK, Ref()); { uint8_t *w = dst_data.ptrw(); + const float *data_ptr = data.ptr(); int ds = data.size(); for (int i = 0; i < ds; i++) { if (is16) { - int16_t v = CLAMP(data[i] * 32768, -32768, 32767); + int16_t v = CLAMP(data_ptr[i] * 32768, -32768, 32767); encode_uint16(v, &w[i * 2]); } else { - int8_t v = CLAMP(data[i] * 128, -128, 127); + int8_t v = CLAMP(data_ptr[i] * 128, -128, 127); w[i] = v; } }