diff options
Diffstat (limited to 'scene/resources/audio_stream_sample.cpp')
-rw-r--r-- | scene/resources/audio_stream_sample.cpp | 184 |
1 files changed, 91 insertions, 93 deletions
diff --git a/scene/resources/audio_stream_sample.cpp b/scene/resources/audio_stream_sample.cpp index d630a1f3ee..d018103e64 100644 --- a/scene/resources/audio_stream_sample.cpp +++ b/scene/resources/audio_stream_sample.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,11 +30,10 @@ #include "audio_stream_sample.h" +#include "core/io/file_access.h" #include "core/io/marshalls.h" -#include "core/os/file_access.h" void AudioStreamPlaybackSample::start(float p_from_pos) { - if (base->format == AudioStreamSample::FORMAT_IMA_ADPCM) { //no seeking in IMA_ADPCM for (int i = 0; i < 2; i++) { @@ -57,28 +56,25 @@ void AudioStreamPlaybackSample::start(float p_from_pos) { } void AudioStreamPlaybackSample::stop() { - active = false; } bool AudioStreamPlaybackSample::is_playing() const { - return active; } int AudioStreamPlaybackSample::get_loop_count() const { - return 0; } float AudioStreamPlaybackSample::get_playback_position() const { - return float(offset >> MIX_FRAC_BITS) / base->mix_rate; } -void AudioStreamPlaybackSample::seek(float p_time) { - if (base->format == AudioStreamSample::FORMAT_IMA_ADPCM) +void AudioStreamPlaybackSample::seek(float p_time) { + if (base->format == AudioStreamSample::FORMAT_IMA_ADPCM) { return; //no seeking in ima-adpcm + } float max = base->get_length(); if (p_time < 0) { @@ -92,22 +88,20 @@ void AudioStreamPlaybackSample::seek(float p_time) { template <class Depth, bool is_stereo, bool is_ima_adpcm> void AudioStreamPlaybackSample::do_resample(const Depth *p_src, AudioFrame *p_dst, int64_t &offset, int32_t &increment, uint32_t amount, IMA_ADPCM_State *ima_adpcm) { - // this function will be compiled branchless by any decent compiler int32_t final, final_r, next, next_r; while (amount) { amount--; int64_t pos = offset >> MIX_FRAC_BITS; - if (is_stereo && !is_ima_adpcm) + if (is_stereo && !is_ima_adpcm) { pos <<= 1; + } if (is_ima_adpcm) { - int64_t sample_pos = pos + ima_adpcm[0].window_ofs; while (sample_pos > ima_adpcm[0].last_nibble) { - static const int16_t _ima_adpcm_step_table[89] = { 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, @@ -126,7 +120,6 @@ void AudioStreamPlaybackSample::do_resample(const Depth *p_src, AudioFrame *p_ds }; for (int i = 0; i < (is_stereo ? 2 : 1); i++) { - int16_t nibble, diff, step; ima_adpcm[i].last_nibble++; @@ -138,30 +131,36 @@ void AudioStreamPlaybackSample::do_resample(const Depth *p_src, AudioFrame *p_ds step = _ima_adpcm_step_table[ima_adpcm[i].step_index]; ima_adpcm[i].step_index += _ima_adpcm_index_table[nibble]; - if (ima_adpcm[i].step_index < 0) + if (ima_adpcm[i].step_index < 0) { ima_adpcm[i].step_index = 0; - if (ima_adpcm[i].step_index > 88) + } + if (ima_adpcm[i].step_index > 88) { ima_adpcm[i].step_index = 88; + } diff = step >> 3; - if (nibble & 1) + if (nibble & 1) { diff += step >> 2; - if (nibble & 2) + } + if (nibble & 2) { diff += step >> 1; - if (nibble & 4) + } + if (nibble & 4) { diff += step; - if (nibble & 8) + } + if (nibble & 8) { diff = -diff; + } ima_adpcm[i].predictor += diff; - if (ima_adpcm[i].predictor < -0x8000) + if (ima_adpcm[i].predictor < -0x8000) { ima_adpcm[i].predictor = -0x8000; - else if (ima_adpcm[i].predictor > 0x7FFF) + } else if (ima_adpcm[i].predictor > 0x7FFF) { ima_adpcm[i].predictor = 0x7FFF; + } /* store loop if there */ if (ima_adpcm[i].last_nibble == ima_adpcm[i].loop_pos) { - ima_adpcm[i].loop_step_index = ima_adpcm[i].step_index; ima_adpcm[i].loop_predictor = ima_adpcm[i].predictor; } @@ -177,17 +176,18 @@ void AudioStreamPlaybackSample::do_resample(const Depth *p_src, AudioFrame *p_ds } else { final = p_src[pos]; - if (is_stereo) + if (is_stereo) { final_r = p_src[pos + 1]; + } if (sizeof(Depth) == 1) { /* conditions will not exist anymore when compiled! */ final <<= 8; - if (is_stereo) + if (is_stereo) { final_r <<= 8; + } } if (is_stereo) { - next = p_src[pos + 2]; next_r = p_src[pos + 3]; } else { @@ -196,15 +196,17 @@ void AudioStreamPlaybackSample::do_resample(const Depth *p_src, AudioFrame *p_ds if (sizeof(Depth) == 1) { next <<= 8; - if (is_stereo) + if (is_stereo) { next_r <<= 8; + } } int32_t frac = int64_t(offset & MIX_FRAC_MASK); final = final + ((next - final) * frac >> MIX_FRAC_BITS); - if (is_stereo) + if (is_stereo) { final_r = final_r + ((next_r - final_r) * frac >> MIX_FRAC_BITS); + } } if (!is_stereo) { @@ -219,20 +221,25 @@ void AudioStreamPlaybackSample::do_resample(const Depth *p_src, AudioFrame *p_ds } } -void AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) { - +int AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) { if (!base->data || !active) { for (int i = 0; i < p_frames; i++) { p_buffer[i] = AudioFrame(0, 0); } - return; + return 0; } int len = base->data_bytes; switch (base->format) { - case AudioStreamSample::FORMAT_8_BITS: len /= 1; break; - case AudioStreamSample::FORMAT_16_BITS: len /= 2; break; - case AudioStreamSample::FORMAT_IMA_ADPCM: len *= 2; break; + case AudioStreamSample::FORMAT_8_BITS: + len /= 1; + break; + case AudioStreamSample::FORMAT_16_BITS: + len /= 2; + break; + case AudioStreamSample::FORMAT_IMA_ADPCM: + len *= 2; + break; } if (base->stereo) { @@ -257,7 +264,8 @@ void AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, in float base_rate = AudioServer::get_singleton()->get_mix_rate(); float srate = base->mix_rate; srate *= p_rate_scale; - float fincrement = srate / base_rate; + float playback_speed_scale = AudioServer::get_singleton()->get_playback_speed_scale(); + float fincrement = (srate * playback_speed_scale) / base_rate; int32_t increment = int32_t(MAX(fincrement * MIX_FRAC_LEN, 1)); increment *= sign; @@ -273,7 +281,6 @@ void AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, in AudioFrame *dst_buff = p_buffer; if (format == AudioStreamSample::FORMAT_IMA_ADPCM) { - if (loop_format != AudioStreamSample::LOOP_DISABLED) { ima_adpcm[0].loop_pos = loop_begin_fp >> MIX_FRAC_BITS; ima_adpcm[1].loop_pos = loop_begin_fp >> MIX_FRAC_BITS; @@ -282,7 +289,6 @@ void AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, in } while (todo > 0) { - int64_t limit = 0; int32_t target = 0, aux = 0; @@ -305,7 +311,6 @@ void AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, in } else { /* check for sample not reaching beginning */ if (offset < 0) { - active = false; break; } @@ -337,7 +342,6 @@ void AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, in } else { /* no loop, check for end of sample */ if (offset >= length_fp) { - active = false; break; } @@ -363,24 +367,26 @@ void AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, in switch (base->format) { case AudioStreamSample::FORMAT_8_BITS: { - - if (is_stereo) + if (is_stereo) { do_resample<int8_t, true, false>((int8_t *)data, dst_buff, offset, increment, target, ima_adpcm); - else + } else { do_resample<int8_t, false, false>((int8_t *)data, dst_buff, offset, increment, target, ima_adpcm); + } } break; case AudioStreamSample::FORMAT_16_BITS: { - if (is_stereo) + if (is_stereo) { do_resample<int16_t, true, false>((int16_t *)data, dst_buff, offset, increment, target, ima_adpcm); - else + } else { do_resample<int16_t, false, false>((int16_t *)data, dst_buff, offset, increment, target, ima_adpcm); + } } break; case AudioStreamSample::FORMAT_IMA_ADPCM: { - if (is_stereo) + if (is_stereo) { do_resample<int8_t, true, true>((int8_t *)data, dst_buff, offset, increment, target, ima_adpcm); - else + } else { do_resample<int8_t, false, true>((int8_t *)data, dst_buff, offset, increment, target, ima_adpcm); + } } break; } @@ -389,85 +395,82 @@ void AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, in } if (todo) { + int mixed_frames = p_frames - todo; //bit was missing from mix int todo_ofs = p_frames - todo; for (int i = todo_ofs; i < p_frames; i++) { p_buffer[i] = AudioFrame(0, 0); } + return mixed_frames; } + return p_frames; } -AudioStreamPlaybackSample::AudioStreamPlaybackSample() { - - active = false; - offset = 0; - sign = 1; -} +AudioStreamPlaybackSample::AudioStreamPlaybackSample() {} ///////////////////// void AudioStreamSample::set_format(Format p_format) { - format = p_format; } AudioStreamSample::Format AudioStreamSample::get_format() const { - return format; } void AudioStreamSample::set_loop_mode(LoopMode p_loop_mode) { - loop_mode = p_loop_mode; } -AudioStreamSample::LoopMode AudioStreamSample::get_loop_mode() const { +AudioStreamSample::LoopMode AudioStreamSample::get_loop_mode() const { return loop_mode; } void AudioStreamSample::set_loop_begin(int p_frame) { - loop_begin = p_frame; } -int AudioStreamSample::get_loop_begin() const { +int AudioStreamSample::get_loop_begin() const { return loop_begin; } void AudioStreamSample::set_loop_end(int p_frame) { - loop_end = p_frame; } -int AudioStreamSample::get_loop_end() const { +int AudioStreamSample::get_loop_end() const { return loop_end; } void AudioStreamSample::set_mix_rate(int p_hz) { - ERR_FAIL_COND(p_hz == 0); mix_rate = p_hz; } -int AudioStreamSample::get_mix_rate() const { +int AudioStreamSample::get_mix_rate() const { return mix_rate; } -void AudioStreamSample::set_stereo(bool p_enable) { +void AudioStreamSample::set_stereo(bool p_enable) { stereo = p_enable; } -bool AudioStreamSample::is_stereo() const { +bool AudioStreamSample::is_stereo() const { return stereo; } float AudioStreamSample::get_length() const { - int len = data_bytes; switch (format) { - case AudioStreamSample::FORMAT_8_BITS: len /= 1; break; - case AudioStreamSample::FORMAT_16_BITS: len /= 2; break; - case AudioStreamSample::FORMAT_IMA_ADPCM: len *= 2; break; + case AudioStreamSample::FORMAT_8_BITS: + len /= 1; + break; + case AudioStreamSample::FORMAT_16_BITS: + len /= 2; + break; + case AudioStreamSample::FORMAT_IMA_ADPCM: + len *= 2; + break; } if (stereo) { @@ -477,8 +480,11 @@ float AudioStreamSample::get_length() const { return float(len) / mix_rate; } -void AudioStreamSample::set_data(const Vector<uint8_t> &p_data) { +bool AudioStreamSample::is_monophonic() const { + return false; +} +void AudioStreamSample::set_data(const Vector<uint8_t> &p_data) { AudioServer::get_singleton()->lock(); if (data) { memfree(data); @@ -488,29 +494,27 @@ void AudioStreamSample::set_data(const Vector<uint8_t> &p_data) { int datalen = p_data.size(); if (datalen) { - const uint8_t *r = p_data.ptr(); int alloc_len = datalen + DATA_PAD * 2; data = memalloc(alloc_len); //alloc with some padding for interpolation - zeromem(data, alloc_len); + memset(data, 0, alloc_len); uint8_t *dataptr = (uint8_t *)data; - copymem(dataptr + DATA_PAD, r, datalen); + memcpy(dataptr + DATA_PAD, r, datalen); data_bytes = datalen; } AudioServer::get_singleton()->unlock(); } -Vector<uint8_t> AudioStreamSample::get_data() const { +Vector<uint8_t> AudioStreamSample::get_data() const { Vector<uint8_t> pv; if (data) { pv.resize(data_bytes); { - uint8_t *w = pv.ptrw(); uint8_t *dataptr = (uint8_t *)data; - copymem(w, dataptr + DATA_PAD, data_bytes); + memcpy(w, dataptr + DATA_PAD, data_bytes); } } @@ -536,9 +540,15 @@ Error AudioStreamSample::save_to_wav(const String &p_path) { int byte_pr_sample = 0; switch (format) { - case AudioStreamSample::FORMAT_8_BITS: byte_pr_sample = 1; break; - case AudioStreamSample::FORMAT_16_BITS: byte_pr_sample = 2; break; - case AudioStreamSample::FORMAT_IMA_ADPCM: byte_pr_sample = 4; break; + case AudioStreamSample::FORMAT_8_BITS: + byte_pr_sample = 1; + break; + case AudioStreamSample::FORMAT_16_BITS: + byte_pr_sample = 2; + break; + case AudioStreamSample::FORMAT_IMA_ADPCM: + byte_pr_sample = 4; + break; } String file_path = p_path; @@ -592,20 +602,17 @@ Error AudioStreamSample::save_to_wav(const String &p_path) { } Ref<AudioStreamPlayback> AudioStreamSample::instance_playback() { - Ref<AudioStreamPlaybackSample> sample; - sample.instance(); + sample.instantiate(); sample->base = Ref<AudioStreamSample>(this); return sample; } String AudioStreamSample::get_stream_name() const { - return ""; } void AudioStreamSample::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_data", "data"), &AudioStreamSample::set_data); ClassDB::bind_method(D_METHOD("get_data"), &AudioStreamSample::get_data); @@ -647,16 +654,7 @@ void AudioStreamSample::_bind_methods() { BIND_ENUM_CONSTANT(LOOP_BACKWARD); } -AudioStreamSample::AudioStreamSample() { - format = FORMAT_8_BITS; - loop_mode = LOOP_DISABLED; - stereo = false; - loop_begin = 0; - loop_end = 0; - mix_rate = 44100; - data = nullptr; - data_bytes = 0; -} +AudioStreamSample::AudioStreamSample() {} AudioStreamSample::~AudioStreamSample() { if (data) { |