diff options
author | Juan Linietsky <reduzio@gmail.com> | 2017-07-15 01:23:10 -0300 |
---|---|---|
committer | Juan Linietsky <reduzio@gmail.com> | 2017-07-15 08:32:34 -0300 |
commit | 2e73be99d8d86d9dad7bcb99518a4d3cbb5c373c (patch) | |
tree | d863db50852afe5d4b0bc15b8452054498004cb1 /servers/audio | |
parent | e64b82ebfcc3475c7a7d2a9196bfe20d6c9e3614 (diff) |
Lots of work on Audio & Physics engine:
-Added new 3D stream player node
-Added ability for Area to capture sound from streams
-Added small features in physics to be able to properly guess distance to areas for sound
-Fixed 3D CollisionObject so shapes are added the same as in 2D, directly from children
-Fixed KinematicBody API to make it the same as 2D.
Diffstat (limited to 'servers/audio')
-rw-r--r-- | servers/audio/audio_filter_sw.cpp | 37 | ||||
-rw-r--r-- | servers/audio/audio_filter_sw.h | 25 | ||||
-rw-r--r-- | servers/audio/audio_stream.cpp | 131 | ||||
-rw-r--r-- | servers/audio/audio_stream.h | 55 |
4 files changed, 237 insertions, 11 deletions
diff --git a/servers/audio/audio_filter_sw.cpp b/servers/audio/audio_filter_sw.cpp index 1210312ac5..4bf1cebf12 100644 --- a/servers/audio/audio_filter_sw.cpp +++ b/servers/audio/audio_filter_sw.cpp @@ -242,28 +242,49 @@ AudioFilterSW::Processor::Processor() { set_filter(NULL); } -void AudioFilterSW::Processor::set_filter(AudioFilterSW *p_filter) { +void AudioFilterSW::Processor::set_filter(AudioFilterSW *p_filter, bool p_clear_history) { - ha1 = ha2 = hb1 = hb2 = 0; + if (p_clear_history) { + ha1 = ha2 = hb1 = hb2 = 0; + } filter = p_filter; } -void AudioFilterSW::Processor::update_coeffs() { +void AudioFilterSW::Processor::update_coeffs(int p_interp_buffer_len) { if (!filter) return; - filter->prepare_coefficients(&coeffs); + if (p_interp_buffer_len) { //interpolate + Coeffs old_coeffs = coeffs; + filter->prepare_coefficients(&coeffs); + incr_coeffs.a1 = (coeffs.a1 - old_coeffs.a1) / p_interp_buffer_len; + incr_coeffs.a2 = (coeffs.a2 - old_coeffs.a2) / p_interp_buffer_len; + incr_coeffs.b0 = (coeffs.b0 - old_coeffs.b0) / p_interp_buffer_len; + incr_coeffs.b1 = (coeffs.b1 - old_coeffs.b1) / p_interp_buffer_len; + incr_coeffs.b2 = (coeffs.b2 - old_coeffs.b2) / p_interp_buffer_len; + coeffs = old_coeffs; + } else { + filter->prepare_coefficients(&coeffs); + } } -void AudioFilterSW::Processor::process(float *p_samples, int p_amount, int p_stride) { +void AudioFilterSW::Processor::process(float *p_samples, int p_amount, int p_stride, bool p_interpolate) { if (!filter) return; - for (int i = 0; i < p_amount; i++) { + if (p_interpolate) { + for (int i = 0; i < p_amount; i++) { + + process_one_interp(*p_samples); + p_samples += p_stride; + } + } else { + for (int i = 0; i < p_amount; i++) { - process_one(*p_samples); - p_samples += p_stride; + process_one(*p_samples); + p_samples += p_stride; + } } } diff --git a/servers/audio/audio_filter_sw.h b/servers/audio/audio_filter_sw.h index e1dd5e5c0e..f5a07c4c8f 100644 --- a/servers/audio/audio_filter_sw.h +++ b/servers/audio/audio_filter_sw.h @@ -60,11 +60,14 @@ public: AudioFilterSW *filter; Coeffs coeffs; float ha1, ha2, hb1, hb2; //history + Coeffs incr_coeffs; + public: - void set_filter(AudioFilterSW *p_filter); - void process(float *p_samples, int p_amount, int p_stride = 1); - void update_coeffs(); + void set_filter(AudioFilterSW *p_filter, bool p_clear_history = true); + void process(float *p_samples, int p_amount, int p_stride = 1, bool p_interpolate = false); + void update_coeffs(int p_interp_buffer_len = 0); _ALWAYS_INLINE_ void process_one(float &p_sample); + _ALWAYS_INLINE_ void process_one_interp(float &p_sample); Processor(); }; @@ -104,4 +107,20 @@ void AudioFilterSW::Processor::process_one(float &p_val) { ha1 = p_val; } +void AudioFilterSW::Processor::process_one_interp(float &p_val) { + + float pre = p_val; + p_val = (p_val * coeffs.b0 + hb1 * coeffs.b1 + hb2 * coeffs.b2 + ha1 * coeffs.a1 + ha2 * coeffs.a2); + ha2 = ha1; + hb2 = hb1; + hb1 = pre; + ha1 = p_val; + + coeffs.b0 += incr_coeffs.b0; + coeffs.b1 += incr_coeffs.b1; + coeffs.b2 += incr_coeffs.b2; + coeffs.a1 += incr_coeffs.a1; + coeffs.a2 += incr_coeffs.a2; +} + #endif // AUDIO_FILTER_SW_H diff --git a/servers/audio/audio_stream.cpp b/servers/audio/audio_stream.cpp index 14a091e27c..aa498cccad 100644 --- a/servers/audio/audio_stream.cpp +++ b/servers/audio/audio_stream.cpp @@ -81,3 +81,134 @@ void AudioStreamPlaybackResampled::mix(AudioFrame *p_buffer, float p_rate_scale, } } } +//////////////////////////////// + +void AudioStreamRandomPitch::set_audio_stream(const Ref<AudioStream> &p_audio_stream) { + + audio_stream = p_audio_stream; + if (audio_stream.is_valid()) { + for (Set<AudioStreamPlaybackRandomPitch *>::Element *E = playbacks.front(); E; E = E->next()) { + E->get()->playback = audio_stream->instance_playback(); + } + } +} + +Ref<AudioStream> AudioStreamRandomPitch::get_audio_stream() const { + + return audio_stream; +} + +void AudioStreamRandomPitch::set_random_pitch(float p_pitch) { + + if (p_pitch < 1) + p_pitch = 1; + random_pitch = p_pitch; +} + +float AudioStreamRandomPitch::get_random_pitch() const { + return random_pitch; +} + +Ref<AudioStreamPlayback> AudioStreamRandomPitch::instance_playback() { + Ref<AudioStreamPlaybackRandomPitch> playback; + playback.instance(); + if (audio_stream.is_valid()) + playback->playback = audio_stream->instance_playback(); + + playbacks.insert(playback.ptr()); + playback->random_pitch = Ref<AudioStreamRandomPitch>((AudioStreamRandomPitch *)this); + return playback; +} + +String AudioStreamRandomPitch::get_stream_name() const { + + if (audio_stream.is_valid()) { + return "Random: " + audio_stream->get_name(); + } + return "RandomPitch"; +} + +void AudioStreamRandomPitch::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_audio_stream", "stream"), &AudioStreamRandomPitch::set_audio_stream); + ClassDB::bind_method(D_METHOD("get_audio_stream"), &AudioStreamRandomPitch::get_audio_stream); + + ClassDB::bind_method(D_METHOD("set_random_pitch", "scale"), &AudioStreamRandomPitch::set_random_pitch); + ClassDB::bind_method(D_METHOD("get_random_pitch"), &AudioStreamRandomPitch::get_random_pitch); + + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "audio_stream", PROPERTY_HINT_RESOURCE_TYPE, "AudioStream"), "set_audio_stream", "get_audio_stream"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "random_pitch", PROPERTY_HINT_RANGE, "1,16,0.01"), "set_random_pitch", "get_random_pitch"); +} + +AudioStreamRandomPitch::AudioStreamRandomPitch() { + random_pitch = 1.1; +} + +void AudioStreamPlaybackRandomPitch::start(float p_from_pos) { + playing = playback; + float range_from = 1.0 / random_pitch->random_pitch; + float range_to = random_pitch->random_pitch; + + pitch_scale = range_from + Math::randf() * (range_to - range_from); + + if (playing.is_valid()) { + playing->start(p_from_pos); + } +} + +void AudioStreamPlaybackRandomPitch::stop() { + if (playing.is_valid()) { + playing->stop(); + ; + } +} +bool AudioStreamPlaybackRandomPitch::is_playing() const { + if (playing.is_valid()) { + return playing->is_playing(); + } + + return false; +} + +int AudioStreamPlaybackRandomPitch::get_loop_count() const { + if (playing.is_valid()) { + return playing->get_loop_count(); + } + + return 0; +} + +float AudioStreamPlaybackRandomPitch::get_pos() const { + if (playing.is_valid()) { + return playing->get_pos(); + } + + return 0; +} +void AudioStreamPlaybackRandomPitch::seek_pos(float p_time) { + if (playing.is_valid()) { + playing->seek_pos(p_time); + } +} + +void AudioStreamPlaybackRandomPitch::mix(AudioFrame *p_bufer, float p_rate_scale, int p_frames) { + if (playing.is_valid()) { + playing->mix(p_bufer, p_rate_scale * pitch_scale, p_frames); + } else { + for (int i = 0; i < p_frames; i++) { + p_bufer[i] = AudioFrame(0, 0); + } + } +} + +float AudioStreamPlaybackRandomPitch::get_length() const { + if (playing.is_valid()) { + return playing->get_length(); + } + + return 0; +} + +AudioStreamPlaybackRandomPitch::~AudioStreamPlaybackRandomPitch() { + random_pitch->playbacks.erase(this); +} diff --git a/servers/audio/audio_stream.h b/servers/audio/audio_stream.h index 1cf3cd294d..a35826be21 100644 --- a/servers/audio/audio_stream.h +++ b/servers/audio/audio_stream.h @@ -31,6 +31,7 @@ #define AUDIO_STREAM_H #include "resource.h" +#include "servers/audio/audio_filter_sw.h" #include "servers/audio_server.h" class AudioStreamPlayback : public Reference { @@ -88,4 +89,58 @@ public: virtual String get_stream_name() const = 0; }; +class AudioStreamPlaybackRandomPitch; + +class AudioStreamRandomPitch : public AudioStream { + + GDCLASS(AudioStreamRandomPitch, AudioStream) + friend class AudioStreamPlaybackRandomPitch; + + Set<AudioStreamPlaybackRandomPitch *> playbacks; + Ref<AudioStream> audio_stream; + float random_pitch; + +protected: + static void _bind_methods(); + +public: + void set_audio_stream(const Ref<AudioStream> &audio_stream); + Ref<AudioStream> get_audio_stream() const; + + void set_random_pitch(float p_pitch); + float get_random_pitch() const; + + virtual Ref<AudioStreamPlayback> instance_playback(); + virtual String get_stream_name() const; + + AudioStreamRandomPitch(); +}; + +class AudioStreamPlaybackRandomPitch : public AudioStreamPlayback { + + GDCLASS(AudioStreamPlaybackRandomPitch, AudioStreamPlayback) + friend class AudioStreamRandomPitch; + + Ref<AudioStreamRandomPitch> random_pitch; + Ref<AudioStreamPlayback> playback; + Ref<AudioStreamPlayback> playing; + float pitch_scale; + +public: + virtual void start(float p_from_pos = 0.0); + virtual void stop(); + virtual bool is_playing() const; + + virtual int get_loop_count() const; //times it looped + + virtual float get_pos() const; + virtual void seek_pos(float p_time); + + virtual void mix(AudioFrame *p_bufer, float p_rate_scale, int p_frames); + + virtual float get_length() const; //if supported, otherwise return 0 + + ~AudioStreamPlaybackRandomPitch(); +}; + #endif // AUDIO_STREAM_H |