diff options
Diffstat (limited to 'servers/audio')
-rw-r--r-- | servers/audio/audio_driver_dummy.cpp | 2 | ||||
-rw-r--r-- | servers/audio/audio_effect.h | 1 | ||||
-rw-r--r-- | servers/audio/audio_rb_resampler.cpp | 2 | ||||
-rw-r--r-- | servers/audio/audio_stream.cpp | 114 | ||||
-rw-r--r-- | servers/audio/audio_stream.h | 57 | ||||
-rw-r--r-- | servers/audio/effects/audio_effect_chorus.cpp | 4 | ||||
-rw-r--r-- | servers/audio/effects/audio_effect_eq.cpp | 6 | ||||
-rw-r--r-- | servers/audio/effects/audio_effect_record.cpp | 264 | ||||
-rw-r--r-- | servers/audio/effects/audio_effect_record.h | 103 | ||||
-rw-r--r-- | servers/audio/effects/eq.cpp | 8 |
10 files changed, 551 insertions, 10 deletions
diff --git a/servers/audio/audio_driver_dummy.cpp b/servers/audio/audio_driver_dummy.cpp index 1ca2334392..be36c3b748 100644 --- a/servers/audio/audio_driver_dummy.cpp +++ b/servers/audio/audio_driver_dummy.cpp @@ -44,7 +44,7 @@ Error AudioDriverDummy::init() { speaker_mode = SPEAKER_MODE_STEREO; channels = 2; - int latency = GLOBAL_DEF("audio/output_latency", DEFAULT_OUTPUT_LATENCY); + int latency = GLOBAL_DEF_RST("audio/output_latency", DEFAULT_OUTPUT_LATENCY); buffer_frames = closest_power_of_2(latency * mix_rate / 1000); samples_in = memnew_arr(int32_t, buffer_frames * channels); diff --git a/servers/audio/audio_effect.h b/servers/audio/audio_effect.h index cf732d4bdd..b950e824c0 100644 --- a/servers/audio/audio_effect.h +++ b/servers/audio/audio_effect.h @@ -39,6 +39,7 @@ class AudioEffectInstance : public Reference { public: virtual void process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count) = 0; + virtual bool process_silence() const { return false; } }; class AudioEffect : public Resource { diff --git a/servers/audio/audio_rb_resampler.cpp b/servers/audio/audio_rb_resampler.cpp index 9faa4056c3..3414351681 100644 --- a/servers/audio/audio_rb_resampler.cpp +++ b/servers/audio/audio_rb_resampler.cpp @@ -100,6 +100,8 @@ uint32_t AudioRBResampler::_resample(AudioFrame *p_dest, int p_todo, int32_t p_i if (C == 6) { + // FIXME: Lot of unused assignments here, but it seems like intermediate calculations + // should be done as for C == 2 (C == 4 also has some unused assignments). float v0 = rb[(pos * 6) + 0]; float v1 = rb[(pos * 6) + 1]; float v2 = rb[(pos * 6) + 2]; diff --git a/servers/audio/audio_stream.cpp b/servers/audio/audio_stream.cpp index 113f23f8f2..eef8aba0c4 100644 --- a/servers/audio/audio_stream.cpp +++ b/servers/audio/audio_stream.cpp @@ -29,6 +29,7 @@ /*************************************************************************/ #include "audio_stream.h" +#include "os/os.h" ////////////////////////////// @@ -99,6 +100,119 @@ void AudioStream::_bind_methods() { //////////////////////////////// +Ref<AudioStreamPlayback> AudioStreamMicrophone::instance_playback() { + Ref<AudioStreamPlaybackMicrophone> playback; + playback.instance(); + + playbacks.insert(playback.ptr()); + + playback->microphone = Ref<AudioStreamMicrophone>((AudioStreamMicrophone *)this); + playback->active = false; + + return playback; +} + +String AudioStreamMicrophone::get_stream_name() const { + + //if (audio_stream.is_valid()) { + //return "Random: " + audio_stream->get_name(); + //} + return "Microphone"; +} + +float AudioStreamMicrophone::get_length() const { + return 0; +} + +void AudioStreamMicrophone::_bind_methods() { +} + +AudioStreamMicrophone::AudioStreamMicrophone() { +} + +void AudioStreamPlaybackMicrophone::_mix_internal(AudioFrame *p_buffer, int p_frames) { + + AudioDriver::get_singleton()->lock(); + + Vector<int32_t> buf = AudioDriver::get_singleton()->get_input_buffer(); + unsigned int input_size = AudioDriver::get_singleton()->get_input_size(); + + // p_frames is multipled by two since an AudioFrame is stereo + if ((p_frames + MICROPHONE_PLAYBACK_DELAY * 2) > input_size) { + for (int i = 0; i < p_frames; i++) { + p_buffer[i] = AudioFrame(0.0f, 0.0f); + } + input_ofs = 0; + } else { + for (int i = 0; i < p_frames; i++) { + if (input_size >= input_ofs) { + float l = (buf[input_ofs++] >> 16) / 32768.f; + if (input_ofs >= buf.size()) { + input_ofs = 0; + } + float r = (buf[input_ofs++] >> 16) / 32768.f; + if (input_ofs >= buf.size()) { + input_ofs = 0; + } + + p_buffer[i] = AudioFrame(l, r); + } else { + p_buffer[i] = AudioFrame(0.0f, 0.0f); + } + } + } + + AudioDriver::get_singleton()->unlock(); +} + +void AudioStreamPlaybackMicrophone::mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) { + AudioStreamPlaybackResampled::mix(p_buffer, p_rate_scale, p_frames); +} + +float AudioStreamPlaybackMicrophone::get_stream_sampling_rate() { + return AudioDriver::get_singleton()->get_mix_rate(); +} + +void AudioStreamPlaybackMicrophone::start(float p_from_pos) { + input_ofs = 0; + + AudioDriver::get_singleton()->capture_start(); + + active = true; + _begin_resample(); +} + +void AudioStreamPlaybackMicrophone::stop() { + AudioDriver::get_singleton()->capture_stop(); + active = false; +} + +bool AudioStreamPlaybackMicrophone::is_playing() const { + return active; +} + +int AudioStreamPlaybackMicrophone::get_loop_count() const { + return 0; +} + +float AudioStreamPlaybackMicrophone::get_playback_position() const { + return 0; +} + +void AudioStreamPlaybackMicrophone::seek(float p_time) { + return; // Can't seek a microphone input +} + +AudioStreamPlaybackMicrophone::~AudioStreamPlaybackMicrophone() { + microphone->playbacks.erase(this); + stop(); +} + +AudioStreamPlaybackMicrophone::AudioStreamPlaybackMicrophone() { +} + +//////////////////////////////// + void AudioStreamRandomPitch::set_audio_stream(const Ref<AudioStream> &p_audio_stream) { audio_stream = p_audio_stream; diff --git a/servers/audio/audio_stream.h b/servers/audio/audio_stream.h index 3312ce1ff6..66e1b6ee2f 100644 --- a/servers/audio/audio_stream.h +++ b/servers/audio/audio_stream.h @@ -94,6 +94,63 @@ public: virtual float get_length() const = 0; //if supported, otherwise return 0 }; +// Microphone + +class AudioStreamPlaybackMicrophone; + +class AudioStreamMicrophone : public AudioStream { + + GDCLASS(AudioStreamMicrophone, AudioStream) + friend class AudioStreamPlaybackMicrophone; + + Set<AudioStreamPlaybackMicrophone *> playbacks; + +protected: + static void _bind_methods(); + +public: + virtual Ref<AudioStreamPlayback> instance_playback(); + virtual String get_stream_name() const; + + virtual float get_length() const; //if supported, otherwise return 0 + + AudioStreamMicrophone(); +}; + +class AudioStreamPlaybackMicrophone : public AudioStreamPlaybackResampled { + + GDCLASS(AudioStreamPlaybackMicrophone, AudioStreamPlayback) + friend class AudioStreamMicrophone; + + const int MICROPHONE_PLAYBACK_DELAY = 256; + + bool active; + unsigned int input_ofs; + + Ref<AudioStreamMicrophone> microphone; + +protected: + virtual void _mix_internal(AudioFrame *p_buffer, int p_frames); + virtual float get_stream_sampling_rate(); + +public: + virtual void mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames); + + 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); + + ~AudioStreamPlaybackMicrophone(); + AudioStreamPlaybackMicrophone(); +}; + +// + class AudioStreamPlaybackRandomPitch; class AudioStreamRandomPitch : public AudioStream { diff --git a/servers/audio/effects/audio_effect_chorus.cpp b/servers/audio/effects/audio_effect_chorus.cpp index f2f554a09b..fd9e3311e7 100644 --- a/servers/audio/effects/audio_effect_chorus.cpp +++ b/servers/audio/effects/audio_effect_chorus.cpp @@ -53,7 +53,7 @@ void AudioEffectChorusInstance::_process_chunk(const AudioFrame *p_src_frames, A //fill ringbuffer for (int i = 0; i < p_frame_count; i++) { - audio_buffer[(buffer_pos + i) & buffer_mask] = p_src_frames[i]; + audio_buffer.write[(buffer_pos + i) & buffer_mask] = p_src_frames[i]; p_dst_frames[i] = p_src_frames[i] * base->dry; } @@ -175,7 +175,7 @@ Ref<AudioEffectInstance> AudioEffectChorus::instance() { ins->buffer_pos = 0; ins->audio_buffer.resize(ringbuff_size); for (int i = 0; i < ringbuff_size; i++) { - ins->audio_buffer[i] = AudioFrame(0, 0); + ins->audio_buffer.write[i] = AudioFrame(0, 0); } return ins; diff --git a/servers/audio/effects/audio_effect_eq.cpp b/servers/audio/effects/audio_effect_eq.cpp index a30fca4e8d..cf8f7d3e16 100644 --- a/servers/audio/effects/audio_effect_eq.cpp +++ b/servers/audio/effects/audio_effect_eq.cpp @@ -70,7 +70,7 @@ Ref<AudioEffectInstance> AudioEffectEQ::instance() { for (int i = 0; i < 2; i++) { ins->bands[i].resize(eq.get_band_count()); for (int j = 0; j < ins->bands[i].size(); j++) { - ins->bands[i][j] = eq.get_band_processor(j); + ins->bands[i].write[j] = eq.get_band_processor(j); } } @@ -79,7 +79,7 @@ Ref<AudioEffectInstance> AudioEffectEQ::instance() { void AudioEffectEQ::set_band_gain_db(int p_band, float p_volume) { ERR_FAIL_INDEX(p_band, gain.size()); - gain[p_band] = p_volume; + gain.write[p_band] = p_volume; } float AudioEffectEQ::get_band_gain_db(int p_band) const { @@ -134,7 +134,7 @@ AudioEffectEQ::AudioEffectEQ(EQ::Preset p_preset) { eq.set_preset_band_mode(p_preset); gain.resize(eq.get_band_count()); for (int i = 0; i < gain.size(); i++) { - gain[i] = 0.0; + gain.write[i] = 0.0; String name = "band_db/" + itos(eq.get_band_frequency(i)) + "_hz"; prop_band_map[name] = i; band_names.push_back(name); diff --git a/servers/audio/effects/audio_effect_record.cpp b/servers/audio/effects/audio_effect_record.cpp new file mode 100644 index 0000000000..74a6838d1a --- /dev/null +++ b/servers/audio/effects/audio_effect_record.cpp @@ -0,0 +1,264 @@ +/*************************************************************************/ +/* audio_effect_record.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ +/* "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_effect_record.h" + +void AudioEffectRecordInstance::process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count) { + if (!is_recording) { + return; + } + + //Add incoming audio frames to the IO ring buffer + const AudioFrame *src = p_src_frames; + AudioFrame *rb_buf = ring_buffer.ptrw(); + for (int i = 0; i < p_frame_count; i++) { + rb_buf[ring_buffer_pos & ring_buffer_mask] = src[i]; + ring_buffer_pos++; + } +} + +bool AudioEffectRecordInstance::process_silence() { + 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) { + 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) { + //Wait to avoid too much busy-wait + OS::get_singleton()->delay_usec(500); + } + } + + thread_active = false; +} + +void AudioEffectRecordInstance::_io_store_buffer() { + int to_read = ring_buffer_pos - ring_buffer_read_pos; + + AudioFrame *rb_buf = ring_buffer.ptrw(); + + while (to_read) { + AudioFrame buffered_frame = rb_buf[ring_buffer_read_pos & ring_buffer_mask]; + recording_data.push_back(buffered_frame.l); + recording_data.push_back(buffered_frame.r); + + ring_buffer_read_pos++; + to_read--; + } +} + +void AudioEffectRecordInstance::_thread_callback(void *_instance) { + + AudioEffectRecordInstance *aeri = reinterpret_cast<AudioEffectRecordInstance *>(_instance); + + aeri->_io_thread_process(); +} + +void AudioEffectRecordInstance::init() { + io_thread = Thread::create(_thread_callback, this); +} + +Ref<AudioEffectInstance> AudioEffectRecord::instance() { + Ref<AudioEffectRecordInstance> ins; + ins.instance(); + ins->base = Ref<AudioEffectRecord>(this); + ins->is_recording = false; + + //Re-using the buffer size calculations from audio_effect_delay.cpp + float ring_buffer_max_size = IO_BUFFER_SIZE_MS; + ring_buffer_max_size /= 1000.0; //convert to seconds + ring_buffer_max_size *= AudioServer::get_singleton()->get_mix_rate(); + + int ringbuff_size = ring_buffer_max_size; + + int bits = 0; + + while (ringbuff_size > 0) { + bits++; + ringbuff_size /= 2; + } + + ringbuff_size = 1 << bits; + ins->ring_buffer_mask = ringbuff_size - 1; + ins->ring_buffer_pos = 0; + + ins->ring_buffer.resize(ringbuff_size); + + ins->ring_buffer_read_pos = 0; + + ensure_thread_stopped(); + current_instance = ins; + if (recording_active) { + ins->init(); + } + + return ins; +} + +void AudioEffectRecord::ensure_thread_stopped() { + recording_active = false; + if (current_instance != 0 && current_instance->thread_active) { + Thread::wait_to_finish(current_instance->io_thread); + } +} + +void AudioEffectRecord::set_recording_active(bool p_record) { + if (p_record) { + if (current_instance == 0) { + WARN_PRINTS("Recording should not be set as active before Godot has initialized."); + recording_active = false; + return; + } + + ensure_thread_stopped(); + current_instance->init(); + } + + recording_active = p_record; +} + +bool AudioEffectRecord::is_recording_active() const { + return recording_active; +} + +void AudioEffectRecord::set_format(AudioStreamSample::Format p_format) { + format = p_format; +} + +AudioStreamSample::Format AudioEffectRecord::get_format() const { + return format; +} + +Ref<AudioStreamSample> AudioEffectRecord::get_recording() const { + AudioStreamSample::Format dst_format = format; + bool stereo = true; //forcing mono is not implemented + + PoolVector<uint8_t> dst_data; + + if (dst_format == AudioStreamSample::FORMAT_8_BITS) { + int data_size = current_instance->recording_data.size(); + dst_data.resize(data_size); + PoolVector<uint8_t>::Write w = dst_data.write(); + + for (int i = 0; i < data_size; i++) { + int8_t v = CLAMP(current_instance->recording_data[i] * 128, -128, 127); + w[i] = v; + } + } else if (dst_format == AudioStreamSample::FORMAT_16_BITS) { + int data_size = current_instance->recording_data.size(); + dst_data.resize(data_size * 2); + PoolVector<uint8_t>::Write w = dst_data.write(); + + for (int i = 0; i < data_size; i++) { + int16_t v = CLAMP(current_instance->recording_data[i] * 32768, -32768, 32767); + encode_uint16(v, &w[i * 2]); + } + } else if (dst_format == AudioStreamSample::FORMAT_IMA_ADPCM) { + //byte interleave + Vector<float> left; + Vector<float> right; + + int tframes = current_instance->recording_data.size() / 2; + left.resize(tframes); + right.resize(tframes); + + for (int i = 0; i < tframes; i++) { + left.set(i, current_instance->recording_data[i * 2 + 0]); + right.set(i, current_instance->recording_data[i * 2 + 1]); + } + + PoolVector<uint8_t> bleft; + PoolVector<uint8_t> bright; + + ResourceImporterWAV::_compress_ima_adpcm(left, bleft); + ResourceImporterWAV::_compress_ima_adpcm(right, bright); + + int dl = bleft.size(); + dst_data.resize(dl * 2); + + PoolVector<uint8_t>::Write w = dst_data.write(); + PoolVector<uint8_t>::Read rl = bleft.read(); + PoolVector<uint8_t>::Read rr = bright.read(); + + for (int i = 0; i < dl; i++) { + w[i * 2 + 0] = rl[i]; + w[i * 2 + 1] = rr[i]; + } + } else { + ERR_EXPLAIN("format not implemented"); + } + + Ref<AudioStreamSample> sample; + sample.instance(); + sample->set_data(dst_data); + sample->set_format(dst_format); + sample->set_mix_rate(AudioServer::get_singleton()->get_mix_rate()); + sample->set_loop_mode(AudioStreamSample::LOOP_DISABLED); + sample->set_loop_begin(0); + sample->set_loop_end(0); + sample->set_stereo(stereo); + + return sample; +} + +void AudioEffectRecord::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_recording_active", "record"), &AudioEffectRecord::set_recording_active); + ClassDB::bind_method(D_METHOD("is_recording_active"), &AudioEffectRecord::is_recording_active); + ClassDB::bind_method(D_METHOD("set_format", "format"), &AudioEffectRecord::set_format); + ClassDB::bind_method(D_METHOD("get_format"), &AudioEffectRecord::get_format); + ClassDB::bind_method(D_METHOD("get_recording"), &AudioEffectRecord::get_recording); + + ADD_PROPERTY(PropertyInfo(Variant::INT, "format", PROPERTY_HINT_ENUM, "8-Bit,16-Bit,IMA-ADPCM"), "set_format", "get_format"); +} + +AudioEffectRecord::AudioEffectRecord() { + format = AudioStreamSample::FORMAT_16_BITS; +} diff --git a/servers/audio/effects/audio_effect_record.h b/servers/audio/effects/audio_effect_record.h new file mode 100644 index 0000000000..e4f5ba8a23 --- /dev/null +++ b/servers/audio/effects/audio_effect_record.h @@ -0,0 +1,103 @@ +/*************************************************************************/ +/* audio_effect_record.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 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 */ +/* "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. */ +/*************************************************************************/ + +#ifndef AUDIOEFFECTRECORD_H +#define AUDIOEFFECTRECORD_H + +#include "core/os/thread.h" +#include "editor/import/resource_importer_wav.h" +#include "io/marshalls.h" +#include "os/file_access.h" +#include "os/os.h" +#include "scene/resources/audio_stream_sample.h" +#include "servers/audio/audio_effect.h" +#include "servers/audio_server.h" + +class AudioEffectRecord; + +class AudioEffectRecordInstance : public AudioEffectInstance { + GDCLASS(AudioEffectRecordInstance, AudioEffectInstance) + friend class AudioEffectRecord; + Ref<AudioEffectRecord> base; + + bool is_recording; + Thread *io_thread; + bool thread_active = false; + + Vector<AudioFrame> ring_buffer; + Vector<float> recording_data; + + unsigned int ring_buffer_pos; + unsigned int ring_buffer_mask; + unsigned int ring_buffer_read_pos; + + void _io_thread_process(); + void _io_store_buffer(); + static void _thread_callback(void *_instance); + void _init_recording(); + +public: + void init(); + virtual void process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count); + virtual bool process_silence(); +}; + +class AudioEffectRecord : public AudioEffect { + GDCLASS(AudioEffectRecord, AudioEffect) + + friend class AudioEffectRecordInstance; + + enum { + IO_BUFFER_SIZE_MS = 1500 + }; + + bool recording_active; + Ref<AudioEffectRecordInstance> current_instance; + + AudioStreamSample::Format format; + + void ensure_thread_stopped(); + +protected: + static void _bind_methods(); + static void debug(uint64_t time_diff, int p_frame_count); + +public: + Ref<AudioEffectInstance> instance(); + void set_recording_active(bool p_record); + bool is_recording_active() const; + void set_format(AudioStreamSample::Format p_format); + AudioStreamSample::Format get_format() const; + Ref<AudioStreamSample> get_recording() const; + + AudioEffectRecord(); +}; + +#endif // AUDIOEFFECTRECORD_H diff --git a/servers/audio/effects/eq.cpp b/servers/audio/effects/eq.cpp index 9ef41191f5..b15fc7ecf4 100644 --- a/servers/audio/effects/eq.cpp +++ b/servers/audio/effects/eq.cpp @@ -108,9 +108,9 @@ void EQ::recalculate_band_coefficients() { ERR_CONTINUE(roots == 0); - band[i].c1 = 2.0 * ((0.5 - r1) / 2.0); - band[i].c2 = 2.0 * r1; - band[i].c3 = 2.0 * (0.5 + r1) * cos(th); + band.write[i].c1 = 2.0 * ((0.5 - r1) / 2.0); + band.write[i].c2 = 2.0 * r1; + band.write[i].c3 = 2.0 * (0.5 + r1) * cos(th); //printf("band %i, coefs = %f,%f,%f\n",i,(float)bands[i].c1,(float)bands[i].c2,(float)bands[i].c3); } } @@ -180,7 +180,7 @@ void EQ::set_bands(const Vector<float> &p_bands) { band.resize(p_bands.size()); for (int i = 0; i < p_bands.size(); i++) { - band[i].freq = p_bands[i]; + band.write[i].freq = p_bands[i]; } recalculate_band_coefficients(); |