summaryrefslogtreecommitdiff
path: root/servers/audio
diff options
context:
space:
mode:
authorJuan Linietsky <reduzio@gmail.com>2017-07-15 01:23:10 -0300
committerJuan Linietsky <reduzio@gmail.com>2017-07-15 08:32:34 -0300
commit2e73be99d8d86d9dad7bcb99518a4d3cbb5c373c (patch)
treed863db50852afe5d4b0bc15b8452054498004cb1 /servers/audio
parente64b82ebfcc3475c7a7d2a9196bfe20d6c9e3614 (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.cpp37
-rw-r--r--servers/audio/audio_filter_sw.h25
-rw-r--r--servers/audio/audio_stream.cpp131
-rw-r--r--servers/audio/audio_stream.h55
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