diff options
Diffstat (limited to 'servers/audio/audio_stream.cpp')
| -rw-r--r-- | servers/audio/audio_stream.cpp | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/servers/audio/audio_stream.cpp b/servers/audio/audio_stream.cpp new file mode 100644 index 0000000000..f4214838a1 --- /dev/null +++ b/servers/audio/audio_stream.cpp @@ -0,0 +1,86 @@ +/*************************************************************************/ +/* audio_stream.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#include "audio_stream.h" + +////////////////////////////// + + + +void AudioStreamPlaybackResampled::_begin_resample() { + + //clear cubic interpolation history + internal_buffer[0]=AudioFrame(0.0,0.0); + internal_buffer[1]=AudioFrame(0.0,0.0); + internal_buffer[2]=AudioFrame(0.0,0.0); + internal_buffer[3]=AudioFrame(0.0,0.0); + //mix buffer + _mix_internal(internal_buffer+4,INTERNAL_BUFFER_LEN); + mix_offset=0; +} + +void AudioStreamPlaybackResampled::mix(AudioFrame* p_buffer,float p_rate_scale,int p_frames) { + + float target_rate = AudioServer::get_singleton()->get_mix_rate() * p_rate_scale; + + uint64_t mix_increment = uint64_t((get_stream_sampling_rate() / 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); + //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]; + + float mu2 = mu*mu; + AudioFrame a0 = y3 - y2 - y0 + y1; + AudioFrame a1 = y0 - y1 - a0; + AudioFrame a2 = y2 - y0; + AudioFrame a3 = y1; + + p_buffer[i] = (a0*mu*mu2 + a1*mu2 + a2*mu + a3); + + mix_offset+=mix_increment; + + while ( (mix_offset >> FP_BITS) >= INTERNAL_BUFFER_LEN ) { + + internal_buffer[0]=internal_buffer[INTERNAL_BUFFER_LEN+0]; + internal_buffer[1]=internal_buffer[INTERNAL_BUFFER_LEN+1]; + internal_buffer[2]=internal_buffer[INTERNAL_BUFFER_LEN+2]; + internal_buffer[3]=internal_buffer[INTERNAL_BUFFER_LEN+3]; + _mix_internal(internal_buffer+4,INTERNAL_BUFFER_LEN); + mix_offset-=(INTERNAL_BUFFER_LEN<<FP_BITS); + } + } +} |