diff options
Diffstat (limited to 'servers/audio')
49 files changed, 749 insertions, 128 deletions
diff --git a/servers/audio/audio_driver_dummy.cpp b/servers/audio/audio_driver_dummy.cpp index 512ff5da7b..c151326e5e 100644 --- a/servers/audio/audio_driver_dummy.cpp +++ b/servers/audio/audio_driver_dummy.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 */ diff --git a/servers/audio/audio_driver_dummy.h b/servers/audio/audio_driver_dummy.h index ba4f69edf4..1a2839d9cb 100644 --- a/servers/audio/audio_driver_dummy.h +++ b/servers/audio/audio_driver_dummy.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 */ diff --git a/servers/audio/audio_effect.cpp b/servers/audio/audio_effect.cpp index b061dad259..dc73596952 100644 --- a/servers/audio/audio_effect.cpp +++ b/servers/audio/audio_effect.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 */ diff --git a/servers/audio/audio_effect.h b/servers/audio/audio_effect.h index bbabedbc30..1274e06740 100644 --- a/servers/audio/audio_effect.h +++ b/servers/audio/audio_effect.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 */ diff --git a/servers/audio/audio_filter_sw.cpp b/servers/audio/audio_filter_sw.cpp index 551ca01109..392938a2be 100644 --- a/servers/audio/audio_filter_sw.cpp +++ b/servers/audio/audio_filter_sw.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 */ diff --git a/servers/audio/audio_filter_sw.h b/servers/audio/audio_filter_sw.h index d137ed8ff9..6b51a1d9ef 100644 --- a/servers/audio/audio_filter_sw.h +++ b/servers/audio/audio_filter_sw.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 */ diff --git a/servers/audio/audio_rb_resampler.cpp b/servers/audio/audio_rb_resampler.cpp index d9b3579812..ad5bcde382 100644 --- a/servers/audio/audio_rb_resampler.cpp +++ b/servers/audio/audio_rb_resampler.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 */ @@ -201,10 +201,8 @@ void AudioRBResampler::clear() { return; //should be stopped at this point but just in case - if (rb) { - memdelete_arr(rb); - memdelete_arr(read_buf); - } + memdelete_arr(rb); + memdelete_arr(read_buf); rb = NULL; offset = 0; rb_read_pos = 0; diff --git a/servers/audio/audio_rb_resampler.h b/servers/audio/audio_rb_resampler.h index b21c480fc4..5b945cd953 100644 --- a/servers/audio/audio_rb_resampler.h +++ b/servers/audio/audio_rb_resampler.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 */ diff --git a/servers/audio/audio_stream.cpp b/servers/audio/audio_stream.cpp index 02a0bed964..1a6430c499 100644 --- a/servers/audio/audio_stream.cpp +++ b/servers/audio/audio_stream.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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,6 +30,7 @@ #include "audio_stream.h" #include "core/os/os.h" +#include "core/project_settings.h" ////////////////////////////// @@ -82,8 +83,8 @@ void AudioStreamPlaybackResampled::mix(AudioFrame *p_buffer, float p_rate_scale, _mix_internal(internal_buffer + 4, INTERNAL_BUFFER_LEN); } else { //fill with silence, not playing - for (int i = 0; i < INTERNAL_BUFFER_LEN; ++i) { - internal_buffer[i + 4] = AudioFrame(0, 0); + for (int j = 0; j < INTERNAL_BUFFER_LEN; ++j) { + internal_buffer[j + 4] = AudioFrame(0, 0); } } mix_offset -= (INTERNAL_BUFFER_LEN << FP_BITS); @@ -137,7 +138,7 @@ void AudioStreamPlaybackMicrophone::_mix_internal(AudioFrame *p_buffer, int p_fr Vector<int32_t> buf = AudioDriver::get_singleton()->get_input_buffer(); unsigned int input_size = AudioDriver::get_singleton()->get_input_size(); int mix_rate = AudioDriver::get_singleton()->get_mix_rate(); - int playback_delay = MIN(((50 * mix_rate) / 1000) * 2, buf.size() >> 1); + unsigned int playback_delay = MIN(((50 * mix_rate) / 1000) * 2, buf.size() >> 1); #ifdef DEBUG_ENABLED unsigned int input_position = AudioDriver::get_singleton()->get_input_position(); #endif @@ -149,13 +150,13 @@ void AudioStreamPlaybackMicrophone::_mix_internal(AudioFrame *p_buffer, int p_fr input_ofs = 0; } else { for (int i = 0; i < p_frames; i++) { - if (input_size > input_ofs) { + if (input_size > input_ofs && (int)input_ofs < buf.size()) { float l = (buf[input_ofs++] >> 16) / 32768.f; - if (input_ofs >= buf.size()) { + if ((int)input_ofs >= buf.size()) { input_ofs = 0; } float r = (buf[input_ofs++] >> 16) / 32768.f; - if (input_ofs >= buf.size()) { + if ((int)input_ofs >= buf.size()) { input_ofs = 0; } @@ -167,7 +168,7 @@ void AudioStreamPlaybackMicrophone::_mix_internal(AudioFrame *p_buffer, int p_fr } #ifdef DEBUG_ENABLED - if (input_ofs > input_position && (input_ofs - input_position) < (p_frames * 2)) { + if (input_ofs > input_position && (int)(input_ofs - input_position) < (p_frames * 2)) { print_verbose(String(get_class_name()) + " buffer underrun: input_position=" + itos(input_position) + " input_ofs=" + itos(input_ofs) + " input_size=" + itos(input_size)); } #endif @@ -184,17 +185,29 @@ float AudioStreamPlaybackMicrophone::get_stream_sampling_rate() { } void AudioStreamPlaybackMicrophone::start(float p_from_pos) { - input_ofs = 0; - AudioDriver::get_singleton()->capture_start(); + if (active) { + return; + } + + if (!GLOBAL_GET("audio/enable_audio_input")) { + WARN_PRINTS("Need to enable Project settings > Audio > Enable Audio Input option to use capturing."); + return; + } + + input_ofs = 0; - active = true; - _begin_resample(); + if (AudioDriver::get_singleton()->capture_start() == OK) { + active = true; + _begin_resample(); + } } void AudioStreamPlaybackMicrophone::stop() { - AudioDriver::get_singleton()->capture_stop(); - active = false; + if (active) { + AudioDriver::get_singleton()->capture_stop(); + active = false; + } } bool AudioStreamPlaybackMicrophone::is_playing() const { diff --git a/servers/audio/audio_stream.h b/servers/audio/audio_stream.h index f6ed45cc9c..ab4ef5f91b 100644 --- a/servers/audio/audio_stream.h +++ b/servers/audio/audio_stream.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 */ diff --git a/servers/audio/effects/audio_effect_amplify.cpp b/servers/audio/effects/audio_effect_amplify.cpp index 9c8dfa8cb9..21a09297b2 100644 --- a/servers/audio/effects/audio_effect_amplify.cpp +++ b/servers/audio/effects/audio_effect_amplify.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 */ diff --git a/servers/audio/effects/audio_effect_amplify.h b/servers/audio/effects/audio_effect_amplify.h index 1096dc04df..b6e2a1d4d8 100644 --- a/servers/audio/effects/audio_effect_amplify.h +++ b/servers/audio/effects/audio_effect_amplify.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 */ diff --git a/servers/audio/effects/audio_effect_chorus.cpp b/servers/audio/effects/audio_effect_chorus.cpp index 3c88d050f6..c2f8b97c1a 100644 --- a/servers/audio/effects/audio_effect_chorus.cpp +++ b/servers/audio/effects/audio_effect_chorus.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 */ diff --git a/servers/audio/effects/audio_effect_chorus.h b/servers/audio/effects/audio_effect_chorus.h index a4646df7d7..9cad2906ff 100644 --- a/servers/audio/effects/audio_effect_chorus.h +++ b/servers/audio/effects/audio_effect_chorus.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 */ diff --git a/servers/audio/effects/audio_effect_compressor.cpp b/servers/audio/effects/audio_effect_compressor.cpp index 8c70b51f8d..10f883d16c 100644 --- a/servers/audio/effects/audio_effect_compressor.cpp +++ b/servers/audio/effects/audio_effect_compressor.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 */ diff --git a/servers/audio/effects/audio_effect_compressor.h b/servers/audio/effects/audio_effect_compressor.h index ef11249415..3ea3a58cb2 100644 --- a/servers/audio/effects/audio_effect_compressor.h +++ b/servers/audio/effects/audio_effect_compressor.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 */ diff --git a/servers/audio/effects/audio_effect_delay.cpp b/servers/audio/effects/audio_effect_delay.cpp index abc10ee096..8d34d46313 100644 --- a/servers/audio/effects/audio_effect_delay.cpp +++ b/servers/audio/effects/audio_effect_delay.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 */ diff --git a/servers/audio/effects/audio_effect_delay.h b/servers/audio/effects/audio_effect_delay.h index f173bd6dfc..131b8714a0 100644 --- a/servers/audio/effects/audio_effect_delay.h +++ b/servers/audio/effects/audio_effect_delay.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 */ diff --git a/servers/audio/effects/audio_effect_distortion.cpp b/servers/audio/effects/audio_effect_distortion.cpp index 0422083363..37305bd7f4 100644 --- a/servers/audio/effects/audio_effect_distortion.cpp +++ b/servers/audio/effects/audio_effect_distortion.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 */ diff --git a/servers/audio/effects/audio_effect_distortion.h b/servers/audio/effects/audio_effect_distortion.h index 8d9ff1c03f..2cbffc81a1 100644 --- a/servers/audio/effects/audio_effect_distortion.h +++ b/servers/audio/effects/audio_effect_distortion.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 */ diff --git a/servers/audio/effects/audio_effect_eq.cpp b/servers/audio/effects/audio_effect_eq.cpp index cf8f7d3e16..150f9db78f 100644 --- a/servers/audio/effects/audio_effect_eq.cpp +++ b/servers/audio/effects/audio_effect_eq.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 */ diff --git a/servers/audio/effects/audio_effect_eq.h b/servers/audio/effects/audio_effect_eq.h index c45fb753ea..c9735b9073 100644 --- a/servers/audio/effects/audio_effect_eq.h +++ b/servers/audio/effects/audio_effect_eq.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 */ diff --git a/servers/audio/effects/audio_effect_filter.cpp b/servers/audio/effects/audio_effect_filter.cpp index 75a43d2d41..dc86d6ffbb 100644 --- a/servers/audio/effects/audio_effect_filter.cpp +++ b/servers/audio/effects/audio_effect_filter.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 */ diff --git a/servers/audio/effects/audio_effect_filter.h b/servers/audio/effects/audio_effect_filter.h index e8f12e5efa..fd9a4bcf07 100644 --- a/servers/audio/effects/audio_effect_filter.h +++ b/servers/audio/effects/audio_effect_filter.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 */ diff --git a/servers/audio/effects/audio_effect_limiter.cpp b/servers/audio/effects/audio_effect_limiter.cpp index 77454dc57b..9eaab11106 100644 --- a/servers/audio/effects/audio_effect_limiter.cpp +++ b/servers/audio/effects/audio_effect_limiter.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 */ diff --git a/servers/audio/effects/audio_effect_limiter.h b/servers/audio/effects/audio_effect_limiter.h index 8077d2da23..d629166f42 100644 --- a/servers/audio/effects/audio_effect_limiter.h +++ b/servers/audio/effects/audio_effect_limiter.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 */ diff --git a/servers/audio/effects/audio_effect_panner.cpp b/servers/audio/effects/audio_effect_panner.cpp index 6b6ca405e0..95212fee78 100644 --- a/servers/audio/effects/audio_effect_panner.cpp +++ b/servers/audio/effects/audio_effect_panner.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 */ diff --git a/servers/audio/effects/audio_effect_panner.h b/servers/audio/effects/audio_effect_panner.h index cdab11c445..4256d05a2f 100644 --- a/servers/audio/effects/audio_effect_panner.h +++ b/servers/audio/effects/audio_effect_panner.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 */ diff --git a/servers/audio/effects/audio_effect_phaser.cpp b/servers/audio/effects/audio_effect_phaser.cpp index 3151111ec8..b8768501e9 100644 --- a/servers/audio/effects/audio_effect_phaser.cpp +++ b/servers/audio/effects/audio_effect_phaser.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 */ diff --git a/servers/audio/effects/audio_effect_phaser.h b/servers/audio/effects/audio_effect_phaser.h index 96ba2b0abf..264e792be5 100644 --- a/servers/audio/effects/audio_effect_phaser.h +++ b/servers/audio/effects/audio_effect_phaser.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 */ diff --git a/servers/audio/effects/audio_effect_pitch_shift.cpp b/servers/audio/effects/audio_effect_pitch_shift.cpp index f5ca8f2da4..ca2a88f858 100644 --- a/servers/audio/effects/audio_effect_pitch_shift.cpp +++ b/servers/audio/effects/audio_effect_pitch_shift.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 */ diff --git a/servers/audio/effects/audio_effect_pitch_shift.h b/servers/audio/effects/audio_effect_pitch_shift.h index 78f92a0261..febc20e9d5 100644 --- a/servers/audio/effects/audio_effect_pitch_shift.h +++ b/servers/audio/effects/audio_effect_pitch_shift.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 */ diff --git a/servers/audio/effects/audio_effect_record.cpp b/servers/audio/effects/audio_effect_record.cpp index a0094f66b8..96d5c9df89 100644 --- a/servers/audio/effects/audio_effect_record.cpp +++ b/servers/audio/effects/audio_effect_record.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 */ @@ -44,34 +44,35 @@ void AudioEffectRecordInstance::process(const AudioFrame *p_src_frames, AudioFra } } +void AudioEffectRecordInstance::_update_buffer() { + //Case: Frames are remaining in the buffer + while (ring_buffer_read_pos < ring_buffer_pos) { + //Read from the buffer into recording_data + _io_store_buffer(); + } +} + +void AudioEffectRecordInstance::_update(void *userdata) { + AudioEffectRecordInstance *ins = (AudioEffectRecordInstance *)userdata; + ins->_update_buffer(); +} + bool AudioEffectRecordInstance::process_silence() const { return true; } void AudioEffectRecordInstance::_io_thread_process() { - - //Reset recorder status thread_active = true; - ring_buffer_pos = 0; - ring_buffer_read_pos = 0; - - //We start a new recording - recording_data.resize(0); //Clear data completely and reset length - is_recording = true; while (is_recording) { //Check: The current recording has been requested to stop - if (is_recording && !base->recording_active) { + if (!base->recording_active) { is_recording = false; } - //Case: Frames are remaining in the buffer - if (ring_buffer_read_pos < ring_buffer_pos) { - //Read from the buffer into recording_data - _io_store_buffer(); - } - //Case: The buffer is empty - else if (is_recording) { + _update_buffer(); + + if (is_recording) { //Wait to avoid too much busy-wait OS::get_singleton()->delay_usec(500); } @@ -103,7 +104,35 @@ void AudioEffectRecordInstance::_thread_callback(void *_instance) { } void AudioEffectRecordInstance::init() { + //Reset recorder status + ring_buffer_pos = 0; + ring_buffer_read_pos = 0; + + //We start a new recording + recording_data.resize(0); //Clear data completely and reset length + is_recording = true; + +#ifdef NO_THREADS + AudioServer::get_singleton()->add_update_callback(&AudioEffectRecordInstance::_update, this); +#else io_thread = Thread::create(_thread_callback, this); +#endif +} + +void AudioEffectRecordInstance::finish() { + +#ifdef NO_THREADS + AudioServer::get_singleton()->remove_update_callback(&AudioEffectRecordInstance::_update, this); +#else + if (thread_active) { + Thread::wait_to_finish(io_thread); + } +#endif +} + +AudioEffectRecordInstance::~AudioEffectRecordInstance() { + + finish(); } Ref<AudioEffectInstance> AudioEffectRecord::instance() { @@ -145,8 +174,8 @@ Ref<AudioEffectInstance> AudioEffectRecord::instance() { void AudioEffectRecord::ensure_thread_stopped() { recording_active = false; - if (current_instance != 0 && current_instance->thread_active) { - Thread::wait_to_finish(current_instance->io_thread); + if (current_instance != 0) { + current_instance->finish(); } } diff --git a/servers/audio/effects/audio_effect_record.h b/servers/audio/effects/audio_effect_record.h index 4b8ee2bcdd..528c7dbd7c 100644 --- a/servers/audio/effects/audio_effect_record.h +++ b/servers/audio/effects/audio_effect_record.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 */ @@ -62,14 +62,18 @@ class AudioEffectRecordInstance : public AudioEffectInstance { void _io_store_buffer(); static void _thread_callback(void *_instance); void _init_recording(); + void _update_buffer(); + static void _update(void *userdata); public: void init(); + void finish(); virtual void process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count); virtual bool process_silence() const; AudioEffectRecordInstance() : thread_active(false) {} + ~AudioEffectRecordInstance(); }; class AudioEffectRecord : public AudioEffect { diff --git a/servers/audio/effects/audio_effect_reverb.cpp b/servers/audio/effects/audio_effect_reverb.cpp index 162c0a1445..003ac452d2 100644 --- a/servers/audio/effects/audio_effect_reverb.cpp +++ b/servers/audio/effects/audio_effect_reverb.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 */ diff --git a/servers/audio/effects/audio_effect_reverb.h b/servers/audio/effects/audio_effect_reverb.h index 5646fd2238..ed76050f24 100644 --- a/servers/audio/effects/audio_effect_reverb.h +++ b/servers/audio/effects/audio_effect_reverb.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 */ diff --git a/servers/audio/effects/audio_effect_spectrum_analyzer.cpp b/servers/audio/effects/audio_effect_spectrum_analyzer.cpp new file mode 100644 index 0000000000..01a52aa01f --- /dev/null +++ b/servers/audio/effects/audio_effect_spectrum_analyzer.cpp @@ -0,0 +1,256 @@ +#include "audio_effect_spectrum_analyzer.h" +#include "servers/audio_server.h" + +static void smbFft(float *fftBuffer, long fftFrameSize, long sign) +/* + FFT routine, (C)1996 S.M.Bernsee. Sign = -1 is FFT, 1 is iFFT (inverse) + Fills fftBuffer[0...2*fftFrameSize-1] with the Fourier transform of the + time domain data in fftBuffer[0...2*fftFrameSize-1]. The FFT array takes + and returns the cosine and sine parts in an interleaved manner, ie. + fftBuffer[0] = cosPart[0], fftBuffer[1] = sinPart[0], asf. fftFrameSize + must be a power of 2. It expects a complex input signal (see footnote 2), + ie. when working with 'common' audio signals our input signal has to be + passed as {in[0],0.,in[1],0.,in[2],0.,...} asf. In that case, the transform + of the frequencies of interest is in fftBuffer[0...fftFrameSize]. +*/ +{ + float wr, wi, arg, *p1, *p2, temp; + float tr, ti, ur, ui, *p1r, *p1i, *p2r, *p2i; + long i, bitm, j, le, le2, k; + + for (i = 2; i < 2 * fftFrameSize - 2; i += 2) { + for (bitm = 2, j = 0; bitm < 2 * fftFrameSize; bitm <<= 1) { + if (i & bitm) j++; + j <<= 1; + } + if (i < j) { + p1 = fftBuffer + i; + p2 = fftBuffer + j; + temp = *p1; + *(p1++) = *p2; + *(p2++) = temp; + temp = *p1; + *p1 = *p2; + *p2 = temp; + } + } + for (k = 0, le = 2; k < (long)(log((double)fftFrameSize) / log(2.) + .5); k++) { + le <<= 1; + le2 = le >> 1; + ur = 1.0; + ui = 0.0; + arg = Math_PI / (le2 >> 1); + wr = cos(arg); + wi = sign * sin(arg); + for (j = 0; j < le2; j += 2) { + p1r = fftBuffer + j; + p1i = p1r + 1; + p2r = p1r + le2; + p2i = p2r + 1; + for (i = j; i < 2 * fftFrameSize; i += le) { + tr = *p2r * ur - *p2i * ui; + ti = *p2r * ui + *p2i * ur; + *p2r = *p1r - tr; + *p2i = *p1i - ti; + *p1r += tr; + *p1i += ti; + p1r += le; + p1i += le; + p2r += le; + p2i += le; + } + tr = ur * wr - ui * wi; + ui = ur * wi + ui * wr; + ur = tr; + } + } +} +void AudioEffectSpectrumAnalyzerInstance::process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count) { + + uint64_t time = OS::get_singleton()->get_ticks_usec(); + + //copy everything over first, since this only really does capture + for (int i = 0; i < p_frame_count; i++) { + p_dst_frames[i] = p_src_frames[i]; + } + + //capture spectrum + while (p_frame_count) { + int to_fill = fft_size * 2 - temporal_fft_pos; + to_fill = MIN(to_fill, p_frame_count); + + float *fftw = temporal_fft.ptrw(); + for (int i = 0; i < to_fill; i++) { //left and right buffers + fftw[(i + temporal_fft_pos) * 2] = p_src_frames[i].l; + fftw[(i + temporal_fft_pos) * 2 + 1] = 0; + fftw[(i + temporal_fft_pos + fft_size * 2) * 2] = p_src_frames[i].r; + fftw[(i + temporal_fft_pos + fft_size * 2) * 2 + 1] = 0; + } + + p_src_frames += to_fill; + temporal_fft_pos += to_fill; + p_frame_count -= to_fill; + + if (temporal_fft_pos == fft_size * 2) { + //time to do a FFT + smbFft(fftw, fft_size * 2, -1); + smbFft(fftw + fft_size * 4, fft_size * 2, -1); + int next = (fft_pos + 1) % fft_count; + + AudioFrame *hw = (AudioFrame *)fft_history[next].ptr(); //do not use write, avoid cow + + for (int i = 0; i < fft_size; i++) { + //abs(vec)/fft_size normalizes each frequency + float window = 1.0; //-.5 * Math::cos(2. * Math_PI * (double)i / (double)fft_size) + .5; + hw[i].l = window * Vector2(fftw[i * 2], fftw[i * 2 + 1]).length() / float(fft_size); + hw[i].r = window * Vector2(fftw[fft_size * 4 + i * 2], fftw[fft_size * 4 + i * 2 + 1]).length() / float(fft_size); + } + + fft_pos = next; //swap + temporal_fft_pos = 0; + } + } + + //determine time of capture + double remainer_sec = (temporal_fft_pos / mix_rate); //substract remainder from mix time + last_fft_time = time - uint64_t(remainer_sec * 1000000.0); +} + +void AudioEffectSpectrumAnalyzerInstance::_bind_methods() { + + ClassDB::bind_method(D_METHOD("get_magnitude_for_frequency_range", "from_hz", "to_hz", "mode"), &AudioEffectSpectrumAnalyzerInstance::get_magnitude_for_frequency_range, DEFVAL(MAGNITUDE_MAX)); + BIND_ENUM_CONSTANT(MAGNITUDE_AVERAGE); + BIND_ENUM_CONSTANT(MAGNITUDE_MAX); +} + +Vector2 AudioEffectSpectrumAnalyzerInstance::get_magnitude_for_frequency_range(float p_begin, float p_end, MagnitudeMode p_mode) const { + + if (last_fft_time == 0) { + return Vector2(); + } + uint64_t time = OS::get_singleton()->get_ticks_usec(); + float diff = double(time - last_fft_time) / 1000000.0 + base->get_tap_back_pos(); + diff -= AudioServer::get_singleton()->get_output_delay(); + float fft_time_size = float(fft_size) / mix_rate; + + int fft_index = fft_pos; + + while (diff > fft_time_size) { + diff -= fft_time_size; + fft_index -= 1; + if (fft_index < 0) { + fft_index = fft_count - 1; + } + } + + int begin_pos = p_begin * fft_size / (mix_rate * 0.5); + int end_pos = p_end * fft_size / (mix_rate * 0.5); + + begin_pos = CLAMP(begin_pos, 0, fft_size - 1); + end_pos = CLAMP(end_pos, 0, fft_size - 1); + + if (begin_pos > end_pos) { + SWAP(begin_pos, end_pos); + } + const AudioFrame *r = fft_history[fft_index].ptr(); + + if (p_mode == MAGNITUDE_AVERAGE) { + Vector2 avg; + + for (int i = begin_pos; i <= end_pos; i++) { + avg += Vector2(r[i]); + } + + avg /= float(end_pos - begin_pos + 1); + + return avg; + } else { + + Vector2 max; + + for (int i = begin_pos; i <= end_pos; i++) { + max.x = MAX(max.x, r[i].l); + max.y = MAX(max.x, r[i].r); + } + + return max; + } +} + +Ref<AudioEffectInstance> AudioEffectSpectrumAnalyzer::instance() { + + Ref<AudioEffectSpectrumAnalyzerInstance> ins; + ins.instance(); + ins->base = Ref<AudioEffectSpectrumAnalyzer>(this); + static const int fft_sizes[FFT_SIZE_MAX] = { 256, 512, 1024, 2048, 4096 }; + ins->fft_size = fft_sizes[fft_size]; + ins->mix_rate = AudioServer::get_singleton()->get_mix_rate(); + ins->fft_count = (buffer_length / (float(ins->fft_size) / ins->mix_rate)) + 1; + ins->fft_pos = 0; + ins->last_fft_time = 0; + ins->fft_history.resize(ins->fft_count); + ins->temporal_fft.resize(ins->fft_size * 8); //x2 stereo, x2 amount of samples for freqs, x2 for input + ins->temporal_fft_pos = 0; + for (int i = 0; i < ins->fft_count; i++) { + ins->fft_history.write[i].resize(ins->fft_size); //only magnitude matters + for (int j = 0; j < ins->fft_size; j++) { + ins->fft_history.write[i].write[j] = AudioFrame(0, 0); + } + } + return ins; +} + +void AudioEffectSpectrumAnalyzer::set_buffer_length(float p_volume) { + buffer_length = p_volume; +} + +float AudioEffectSpectrumAnalyzer::get_buffer_length() const { + + return buffer_length; +} + +void AudioEffectSpectrumAnalyzer::set_tap_back_pos(float p_seconds) { + tapback_pos = p_seconds; +} + +float AudioEffectSpectrumAnalyzer::get_tap_back_pos() const { + return tapback_pos; +} + +void AudioEffectSpectrumAnalyzer::set_fft_size(FFT_Size p_fft_size) { + ERR_FAIL_INDEX(p_fft_size, FFT_SIZE_MAX); + fft_size = p_fft_size; +} + +AudioEffectSpectrumAnalyzer::FFT_Size AudioEffectSpectrumAnalyzer::get_fft_size() const { + return fft_size; +} + +void AudioEffectSpectrumAnalyzer::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_buffer_length", "seconds"), &AudioEffectSpectrumAnalyzer::set_buffer_length); + ClassDB::bind_method(D_METHOD("get_buffer_length"), &AudioEffectSpectrumAnalyzer::get_buffer_length); + + ClassDB::bind_method(D_METHOD("set_tap_back_pos", "seconds"), &AudioEffectSpectrumAnalyzer::set_tap_back_pos); + ClassDB::bind_method(D_METHOD("get_tap_back_pos"), &AudioEffectSpectrumAnalyzer::get_tap_back_pos); + + ClassDB::bind_method(D_METHOD("set_fft_size", "size"), &AudioEffectSpectrumAnalyzer::set_fft_size); + ClassDB::bind_method(D_METHOD("get_fft_size"), &AudioEffectSpectrumAnalyzer::get_fft_size); + + ADD_PROPERTY(PropertyInfo(Variant::REAL, "buffer_length", PROPERTY_HINT_RANGE, "0.1,4,0.1"), "set_buffer_length", "get_buffer_length"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "tap_back_pos", PROPERTY_HINT_RANGE, "0.1,4,0.1"), "set_tap_back_pos", "get_tap_back_pos"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "fft_size", PROPERTY_HINT_ENUM, "256,512,1024,2048,4096"), "set_fft_size", "get_fft_size"); + + BIND_ENUM_CONSTANT(FFT_SIZE_256); + BIND_ENUM_CONSTANT(FFT_SIZE_512); + BIND_ENUM_CONSTANT(FFT_SIZE_1024); + BIND_ENUM_CONSTANT(FFT_SIZE_2048); + BIND_ENUM_CONSTANT(FFT_SIZE_4096); + BIND_ENUM_CONSTANT(FFT_SIZE_MAX); +} + +AudioEffectSpectrumAnalyzer::AudioEffectSpectrumAnalyzer() { + buffer_length = 2; + tapback_pos = 0.01; + fft_size = FFT_SIZE_1024; +} diff --git a/servers/audio/effects/audio_effect_spectrum_analyzer.h b/servers/audio/effects/audio_effect_spectrum_analyzer.h new file mode 100644 index 0000000000..0534426da3 --- /dev/null +++ b/servers/audio/effects/audio_effect_spectrum_analyzer.h @@ -0,0 +1,76 @@ +#ifndef AUDIO_EFFECT_SPECTRUM_ANALYZER_H +#define AUDIO_EFFECT_SPECTRUM_ANALYZER_H + +#include "servers/audio/audio_effect.h" + +class AudioEffectSpectrumAnalyzer; + +class AudioEffectSpectrumAnalyzerInstance : public AudioEffectInstance { + GDCLASS(AudioEffectSpectrumAnalyzerInstance, AudioEffectInstance) + +public: + enum MagnitudeMode { + MAGNITUDE_AVERAGE, + MAGNITUDE_MAX, + }; + +private: + friend class AudioEffectSpectrumAnalyzer; + Ref<AudioEffectSpectrumAnalyzer> base; + + Vector<Vector<AudioFrame> > fft_history; + Vector<float> temporal_fft; + int temporal_fft_pos; + int fft_size; + int fft_count; + int fft_pos; + float mix_rate; + uint64_t last_fft_time; + +protected: + static void _bind_methods(); + +public: + virtual void process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count); + Vector2 get_magnitude_for_frequency_range(float p_begin, float p_end, MagnitudeMode p_mode = MAGNITUDE_MAX) const; +}; + +VARIANT_ENUM_CAST(AudioEffectSpectrumAnalyzerInstance::MagnitudeMode) + +class AudioEffectSpectrumAnalyzer : public AudioEffect { + GDCLASS(AudioEffectSpectrumAnalyzer, AudioEffect) +public: + enum FFT_Size { + FFT_SIZE_256, + FFT_SIZE_512, + FFT_SIZE_1024, + FFT_SIZE_2048, + FFT_SIZE_4096, + FFT_SIZE_MAX + }; + +public: + friend class AudioEffectSpectrumAnalyzerInstance; + float buffer_length; + float tapback_pos; + FFT_Size fft_size; + +protected: + static void _bind_methods(); + +public: + Ref<AudioEffectInstance> instance(); + void set_buffer_length(float p_seconds); + float get_buffer_length() const; + void set_tap_back_pos(float p_seconds); + float get_tap_back_pos() const; + + void set_fft_size(FFT_Size); + FFT_Size get_fft_size() const; + + AudioEffectSpectrumAnalyzer(); +}; + +VARIANT_ENUM_CAST(AudioEffectSpectrumAnalyzer::FFT_Size); + +#endif // AUDIO_EFFECT_SPECTRUM_ANALYZER_H diff --git a/servers/audio/effects/audio_effect_stereo_enhance.cpp b/servers/audio/effects/audio_effect_stereo_enhance.cpp index cf5228f8b6..8945675e07 100644 --- a/servers/audio/effects/audio_effect_stereo_enhance.cpp +++ b/servers/audio/effects/audio_effect_stereo_enhance.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 */ diff --git a/servers/audio/effects/audio_effect_stereo_enhance.h b/servers/audio/effects/audio_effect_stereo_enhance.h index 13dd4ac042..787c351a03 100644 --- a/servers/audio/effects/audio_effect_stereo_enhance.h +++ b/servers/audio/effects/audio_effect_stereo_enhance.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 */ diff --git a/servers/audio/effects/audio_stream_generator.cpp b/servers/audio/effects/audio_stream_generator.cpp new file mode 100644 index 0000000000..f4a66b5643 --- /dev/null +++ b/servers/audio/effects/audio_stream_generator.cpp @@ -0,0 +1,182 @@ +#include "audio_stream_generator.h" + +void AudioStreamGenerator::set_mix_rate(float p_mix_rate) { + mix_rate = p_mix_rate; +} + +float AudioStreamGenerator::get_mix_rate() const { + + return mix_rate; +} + +void AudioStreamGenerator::set_buffer_length(float p_seconds) { + + buffer_len = p_seconds; +} +float AudioStreamGenerator::get_buffer_length() const { + + return buffer_len; +} + +Ref<AudioStreamPlayback> AudioStreamGenerator::instance_playback() { + + Ref<AudioStreamGeneratorPlayback> playback; + playback.instance(); + playback->generator = this; + int target_buffer_size = mix_rate * buffer_len; + playback->buffer.resize(nearest_shift(target_buffer_size)); + playback->buffer.clear(); + return playback; +} +String AudioStreamGenerator::get_stream_name() const { + + return "UserFeed"; +} + +float AudioStreamGenerator::get_length() const { + return 0; +} + +void AudioStreamGenerator::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_mix_rate", "hz"), &AudioStreamGenerator::set_mix_rate); + ClassDB::bind_method(D_METHOD("get_mix_rate"), &AudioStreamGenerator::get_mix_rate); + + ClassDB::bind_method(D_METHOD("set_buffer_length", "seconds"), &AudioStreamGenerator::set_buffer_length); + ClassDB::bind_method(D_METHOD("get_buffer_length"), &AudioStreamGenerator::get_buffer_length); + + ADD_PROPERTY(PropertyInfo(Variant::REAL, "mix_rate", PROPERTY_HINT_RANGE, "20,192000,1"), "set_mix_rate", "get_mix_rate"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "buffer_length", PROPERTY_HINT_RANGE, "0.01,10,0.01"), "set_buffer_length", "get_buffer_length"); +} + +AudioStreamGenerator::AudioStreamGenerator() { + mix_rate = 44100; + buffer_len = 0.5; +} + +//////////////// + +bool AudioStreamGeneratorPlayback::push_frame(const Vector2 &p_frame) { + if (buffer.space_left() < 1) { + return false; + } + + AudioFrame f = p_frame; + + buffer.write(&f, 1); + return true; +} + +bool AudioStreamGeneratorPlayback::can_push_buffer(int p_frames) const { + return buffer.space_left() >= p_frames; +} +bool AudioStreamGeneratorPlayback::push_buffer(const PoolVector2Array &p_frames) { + + int to_write = p_frames.size(); + if (buffer.space_left() < to_write) { + return false; + } + + PoolVector2Array::Read r = p_frames.read(); + if (sizeof(real_t) == 4) { + //write directly + buffer.write((const AudioFrame *)r.ptr(), to_write); + } else { + //convert from double + AudioFrame buf[2048]; + int ofs = 0; + while (to_write) { + + int w = MIN(to_write, 2048); + for (int i = 0; i < w; i++) { + buf[i] = r[i + ofs]; + } + buffer.write(buf, w); + ofs += w; + to_write -= w; + } + } + return true; +} + +int AudioStreamGeneratorPlayback::get_frames_available() const { + return buffer.space_left(); +} + +int AudioStreamGeneratorPlayback::get_skips() const { + return skips; +} + +void AudioStreamGeneratorPlayback::clear_buffer() { + ERR_FAIL_COND(active); + buffer.clear(); + mixed = 0; +} + +void AudioStreamGeneratorPlayback::_mix_internal(AudioFrame *p_buffer, int p_frames) { + + int read_amount = buffer.data_left(); + if (p_frames < read_amount) { + read_amount = p_frames; + } + + buffer.read(p_buffer, read_amount); + + if (read_amount < p_frames) { + //skipped, not ideal + for (int i = read_amount; i < p_frames; i++) { + p_buffer[i] = AudioFrame(0, 0); + } + + skips++; + } + + mixed += p_frames / generator->get_mix_rate(); +} +float AudioStreamGeneratorPlayback::get_stream_sampling_rate() { + return generator->get_mix_rate(); +} + +void AudioStreamGeneratorPlayback::start(float p_from_pos) { + + if (mixed == 0.0) { + _begin_resample(); + } + skips = 0; + active = true; + mixed = 0.0; +} + +void AudioStreamGeneratorPlayback::stop() { + active = false; +} +bool AudioStreamGeneratorPlayback::is_playing() const { + + return active; //always playing, can't be stopped +} + +int AudioStreamGeneratorPlayback::get_loop_count() const { + return 0; +} + +float AudioStreamGeneratorPlayback::get_playback_position() const { + return mixed; +} +void AudioStreamGeneratorPlayback::seek(float p_time) { + //no seek possible +} + +void AudioStreamGeneratorPlayback::_bind_methods() { + ClassDB::bind_method(D_METHOD("push_frame", "frame"), &AudioStreamGeneratorPlayback::push_frame); + ClassDB::bind_method(D_METHOD("can_push_buffer", "amount"), &AudioStreamGeneratorPlayback::can_push_buffer); + ClassDB::bind_method(D_METHOD("push_buffer", "frames"), &AudioStreamGeneratorPlayback::push_buffer); + ClassDB::bind_method(D_METHOD("get_frames_available"), &AudioStreamGeneratorPlayback::get_frames_available); + ClassDB::bind_method(D_METHOD("get_skips"), &AudioStreamGeneratorPlayback::get_skips); + ClassDB::bind_method(D_METHOD("clear_buffer"), &AudioStreamGeneratorPlayback::clear_buffer); +} + +AudioStreamGeneratorPlayback::AudioStreamGeneratorPlayback() { + generator = NULL; + skips = 0; + active = false; + mixed = 0; +} diff --git a/servers/audio/effects/audio_stream_generator.h b/servers/audio/effects/audio_stream_generator.h new file mode 100644 index 0000000000..2082682907 --- /dev/null +++ b/servers/audio/effects/audio_stream_generator.h @@ -0,0 +1,66 @@ +#ifndef AUDIO_STREAM_USER_FED_H +#define AUDIO_STREAM_USER_FED_H + +#include "core/ring_buffer.h" +#include "servers/audio/audio_stream.h" + +class AudioStreamGenerator : public AudioStream { + GDCLASS(AudioStreamGenerator, AudioStream) + + float mix_rate; + float buffer_len; + +protected: + static void _bind_methods(); + +public: + void set_mix_rate(float p_mix_rate); + float get_mix_rate() const; + + void set_buffer_length(float p_seconds); + float get_buffer_length() const; + + virtual Ref<AudioStreamPlayback> instance_playback(); + virtual String get_stream_name() const; + + virtual float get_length() const; + AudioStreamGenerator(); +}; + +class AudioStreamGeneratorPlayback : public AudioStreamPlaybackResampled { + + GDCLASS(AudioStreamGeneratorPlayback, AudioStreamPlaybackResampled) + friend class AudioStreamGenerator; + RingBuffer<AudioFrame> buffer; + int skips; + bool active; + float mixed; + AudioStreamGenerator *generator; + +protected: + virtual void _mix_internal(AudioFrame *p_buffer, int p_frames); + virtual float get_stream_sampling_rate(); + + static void _bind_methods(); + +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_playback_position() const; + virtual void seek(float p_time); + + bool push_frame(const Vector2 &p_frame); + bool can_push_buffer(int p_frames) const; + bool push_buffer(const PoolVector2Array &p_frames); + int get_frames_available() const; + int get_skips() const; + + void clear_buffer(); + + AudioStreamGeneratorPlayback(); +}; +#endif // AUDIO_STREAM_USER_FED_H diff --git a/servers/audio/effects/eq.cpp b/servers/audio/effects/eq.cpp index 70ac70a5a8..e8f247d3bc 100644 --- a/servers/audio/effects/eq.cpp +++ b/servers/audio/effects/eq.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 */ diff --git a/servers/audio/effects/eq.h b/servers/audio/effects/eq.h index c06f1f8bf8..2c407ee60e 100644 --- a/servers/audio/effects/eq.h +++ b/servers/audio/effects/eq.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 */ diff --git a/servers/audio/effects/reverb.cpp b/servers/audio/effects/reverb.cpp index b032c91da2..1f9fa23763 100644 --- a/servers/audio/effects/reverb.cpp +++ b/servers/audio/effects/reverb.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 */ diff --git a/servers/audio/effects/reverb.h b/servers/audio/effects/reverb.h index 03cf197456..6a2e291466 100644 --- a/servers/audio/effects/reverb.h +++ b/servers/audio/effects/reverb.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 */ diff --git a/servers/audio/reverb_sw.cpp b/servers/audio/reverb_sw.cpp index d078da38b4..63bf1a7eaa 100644 --- a/servers/audio/reverb_sw.cpp +++ b/servers/audio/reverb_sw.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 */ @@ -39,9 +39,6 @@ #define rangeloop(c, min, max) \ for ((c) = (min); (c) < (max); (c)++) -#define ABSDIFF(x, y) \ - (((x) < (y)) ? ((y) - (x)) : ((x) - (y))) - #define MULSHIFT_S32(Factor1, Factor2, Bits) \ ((int)(((int64_t)(Factor1) * (Factor2)) >> (Bits))) diff --git a/servers/audio/reverb_sw.h b/servers/audio/reverb_sw.h index 01977d1f61..1a2e2e2bb8 100644 --- a/servers/audio/reverb_sw.h +++ b/servers/audio/reverb_sw.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 */ diff --git a/servers/audio/voice_rb_sw.h b/servers/audio/voice_rb_sw.h index fc02cc1827..0a39c536ae 100644 --- a/servers/audio/voice_rb_sw.h +++ b/servers/audio/voice_rb_sw.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 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 */ |