diff options
Diffstat (limited to 'servers/audio/audio_stream.cpp')
-rw-r--r-- | servers/audio/audio_stream.cpp | 110 |
1 files changed, 97 insertions, 13 deletions
diff --git a/servers/audio/audio_stream.cpp b/servers/audio/audio_stream.cpp index ae07f999ed..5544a09ac0 100644 --- a/servers/audio/audio_stream.cpp +++ b/servers/audio/audio_stream.cpp @@ -33,6 +33,63 @@ #include "core/config/project_settings.h" #include "core/os/os.h" +void AudioStreamPlayback::start(float p_from_pos) { + if (GDVIRTUAL_CALL(_start, p_from_pos)) { + return; + } + ERR_FAIL_MSG("AudioStreamPlayback::start unimplemented!"); +} +void AudioStreamPlayback::stop() { + if (GDVIRTUAL_CALL(_stop)) { + return; + } + ERR_FAIL_MSG("AudioStreamPlayback::stop unimplemented!"); +} +bool AudioStreamPlayback::is_playing() const { + bool ret; + if (GDVIRTUAL_CALL(_is_playing, ret)) { + return ret; + } + ERR_FAIL_V_MSG(false, "AudioStreamPlayback::is_playing unimplemented!"); +} + +int AudioStreamPlayback::get_loop_count() const { + int ret; + if (GDVIRTUAL_CALL(_get_loop_count, ret)) { + return ret; + } + return 0; +} + +float AudioStreamPlayback::get_playback_position() const { + float ret; + if (GDVIRTUAL_CALL(_get_playback_position, ret)) { + return ret; + } + ERR_FAIL_V_MSG(0, "AudioStreamPlayback::get_playback_position unimplemented!"); +} +void AudioStreamPlayback::seek(float p_time) { + if (GDVIRTUAL_CALL(_seek, p_time)) { + return; + } +} + +void AudioStreamPlayback::mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) { + if (GDVIRTUAL_CALL(_mix, p_buffer, p_rate_scale, p_frames)) { + return; + } + WARN_PRINT_ONCE("AudioStreamPlayback::mix unimplemented!"); +} + +void AudioStreamPlayback::_bind_methods() { + GDVIRTUAL_BIND(_start, "from_pos") + GDVIRTUAL_BIND(_stop) + GDVIRTUAL_BIND(_is_playing) + GDVIRTUAL_BIND(_get_loop_count) + GDVIRTUAL_BIND(_get_playback_position) + GDVIRTUAL_BIND(_seek, "position") + GDVIRTUAL_BIND(_mix, "buffer", "rate_scale", "frames"); +} ////////////////////////////// void AudioStreamPlaybackResampled::_begin_resample() { @@ -48,27 +105,27 @@ void AudioStreamPlaybackResampled::_begin_resample() { void AudioStreamPlaybackResampled::mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) { float target_rate = AudioServer::get_singleton()->get_mix_rate(); - float global_rate_scale = AudioServer::get_singleton()->get_global_rate_scale(); + float playback_speed_scale = AudioServer::get_singleton()->get_playback_speed_scale(); - uint64_t mix_increment = uint64_t(((get_stream_sampling_rate() * p_rate_scale) / double(target_rate * global_rate_scale)) * double(FP_LEN)); + uint64_t mix_increment = uint64_t(((get_stream_sampling_rate() * p_rate_scale * playback_speed_scale) / double(target_rate)) * double(FP_LEN)); for (int i = 0; i < p_frames; i++) { uint32_t idx = CUBIC_INTERP_HISTORY + uint32_t(mix_offset >> FP_BITS); - // 4 point, 4th order optimal resampling algorithm from: http://yehar.com/blog/wp-content/uploads/2009/08/deip.pdf + //standard cubic interpolation (great quality/performance ratio) + //this used to be moved to a LUT for greater performance, but nowadays CPU speed is generally faster than memory. float mu = (mix_offset & FP_MASK) / float(FP_LEN); AudioFrame y0 = internal_buffer[idx - 3]; AudioFrame y1 = internal_buffer[idx - 2]; AudioFrame y2 = internal_buffer[idx - 1]; AudioFrame y3 = internal_buffer[idx - 0]; - AudioFrame even1 = y2 + y1, odd1 = y2 - y1; - AudioFrame even2 = y3 + y0, odd2 = y3 - y0; - AudioFrame c0 = even1 * 0.46835497211269561 + even2 * 0.03164502784253309; - AudioFrame c1 = odd1 * 0.56001293337091440 + odd2 * 0.14666238593949288; - AudioFrame c2 = even1 * -0.250038759826233691 + even2 * 0.25003876124297131; - AudioFrame c3 = odd1 * -0.49949850957839148 + odd2 * 0.16649935475113800; - AudioFrame c4 = even1 * 0.00016095224137360 + even2 * -0.00016095810460478; - p_buffer[i] = (((c4 * mu + c3) * mu + c2) * mu + c1) * mu + c0; + float mu2 = mu * mu; + AudioFrame a0 = 3 * y1 - 3 * y2 + y3 - y0; + AudioFrame a1 = 2 * y0 - 5 * y1 + 4 * y2 - y3; + AudioFrame a2 = y2 - y0; + AudioFrame a3 = 2 * y1; + + p_buffer[i] = (a0 * mu * mu2 + a1 * mu2 + a2 * mu + a3) / 2; mix_offset += mix_increment; @@ -92,15 +149,41 @@ void AudioStreamPlaybackResampled::mix(AudioFrame *p_buffer, float p_rate_scale, //////////////////////////////// +Ref<AudioStreamPlayback> AudioStream::instance_playback() { + Ref<AudioStreamPlayback> ret; + if (GDVIRTUAL_CALL(_instance_playback, ret)) { + return ret; + } + ERR_FAIL_V_MSG(Ref<AudioStreamPlayback>(), "Method must be implemented!"); +} +String AudioStream::get_stream_name() const { + String ret; + if (GDVIRTUAL_CALL(_get_stream_name, ret)) { + return ret; + } + return String(); +} + +float AudioStream::get_length() const { + float ret; + if (GDVIRTUAL_CALL(_get_length, ret)) { + return ret; + } + return 0; +} + void AudioStream::_bind_methods() { ClassDB::bind_method(D_METHOD("get_length"), &AudioStream::get_length); + GDVIRTUAL_BIND(_instance_playback); + GDVIRTUAL_BIND(_get_stream_name); + GDVIRTUAL_BIND(_get_length); } //////////////////////////////// Ref<AudioStreamPlayback> AudioStreamMicrophone::instance_playback() { Ref<AudioStreamPlaybackMicrophone> playback; - playback.instance(); + playback.instantiate(); playbacks.insert(playback.ptr()); @@ -256,7 +339,7 @@ float AudioStreamRandomPitch::get_random_pitch() const { Ref<AudioStreamPlayback> AudioStreamRandomPitch::instance_playback() { Ref<AudioStreamPlaybackRandomPitch> playback; - playback.instance(); + playback.instantiate(); if (audio_stream.is_valid()) { playback->playback = audio_stream->instance_playback(); } @@ -358,3 +441,4 @@ void AudioStreamPlaybackRandomPitch::mix(AudioFrame *p_buffer, float p_rate_scal AudioStreamPlaybackRandomPitch::~AudioStreamPlaybackRandomPitch() { random_pitch->playbacks.erase(this); } +///////////////////////////////////////////// |