summaryrefslogtreecommitdiffstats
path: root/platform/web/audio_driver_web.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'platform/web/audio_driver_web.cpp')
-rw-r--r--platform/web/audio_driver_web.cpp176
1 files changed, 176 insertions, 0 deletions
diff --git a/platform/web/audio_driver_web.cpp b/platform/web/audio_driver_web.cpp
index ec3c22bf7c..dd986e650c 100644
--- a/platform/web/audio_driver_web.cpp
+++ b/platform/web/audio_driver_web.cpp
@@ -33,6 +33,7 @@
#include "godot_audio.h"
#include "core/config/project_settings.h"
+#include "servers/audio/audio_stream.h"
#include <emscripten.h>
@@ -186,6 +187,181 @@ Error AudioDriverWeb::input_stop() {
return OK;
}
+bool AudioDriverWeb::is_stream_registered_as_sample(const Ref<AudioStream> &p_stream) const {
+ ERR_FAIL_COND_V_MSG(p_stream.is_null(), false, "Parameter p_stream is null.");
+ return godot_audio_sample_stream_is_registered(itos(p_stream->get_instance_id()).utf8().get_data()) != 0;
+}
+
+void AudioDriverWeb::register_sample(const Ref<AudioSample> &p_sample) {
+ ERR_FAIL_COND_MSG(p_sample.is_null(), "Parameter p_sample is null.");
+ ERR_FAIL_COND_MSG(p_sample->stream.is_null(), "Parameter p_sample->stream is null.");
+
+ String loop_mode;
+ switch (p_sample->loop_mode) {
+ case AudioSample::LoopMode::LOOP_DISABLED: {
+ loop_mode = "disabled";
+ } break;
+
+ case AudioSample::LoopMode::LOOP_FORWARD: {
+ loop_mode = "forward";
+ } break;
+
+ case AudioSample::LoopMode::LOOP_PINGPONG: {
+ loop_mode = "pingpong";
+ } break;
+
+ case AudioSample::LoopMode::LOOP_BACKWARD: {
+ loop_mode = "backward";
+ } break;
+ }
+
+ double length = p_sample->stream->get_length();
+
+ Vector<AudioFrame> frames;
+ int frames_total = mix_rate * length;
+ {
+ Ref<AudioStreamPlayback> stream_playback = p_sample->stream->instantiate_playback();
+ frames.resize(frames_total);
+ AudioFrame *frames_ptr = frames.ptrw();
+ stream_playback->start();
+ stream_playback->mix(frames_ptr, 1.0f, frames_total);
+ }
+
+ PackedFloat32Array data;
+ data.resize(frames_total * 2);
+ float *data_ptrw = data.ptrw();
+ for (int i = 0; i < frames_total; i++) {
+ data_ptrw[i] = frames[i].left;
+ data_ptrw[i + frames_total] = frames[i].right;
+ }
+
+ godot_audio_sample_register_stream(
+ itos(p_sample->stream->get_instance_id()).utf8().get_data(),
+ data_ptrw,
+ frames_total,
+ loop_mode.utf8().get_data(),
+ p_sample->loop_begin,
+ p_sample->loop_end);
+}
+
+void AudioDriverWeb::unregister_sample(const Ref<AudioSample> &p_sample) {
+ ERR_FAIL_COND_MSG(p_sample.is_null(), "Parameter p_sample is null.");
+ ERR_FAIL_COND_MSG(p_sample->stream.is_null(), "Parameter p_sample->stream is null.");
+
+ godot_audio_sample_unregister_stream(itos(p_sample->stream->get_instance_id()).utf8().get_data());
+}
+
+void AudioDriverWeb::start_sample_playback(const Ref<AudioSamplePlayback> &p_playback) {
+ ERR_FAIL_COND_MSG(p_playback.is_null(), "Parameter p_playback is null.");
+ ERR_FAIL_COND_MSG(p_playback->stream.is_null(), "Parameter p_playback->stream is null.");
+
+ constexpr int real_max_channels = AudioServer::MAX_CHANNELS_PER_BUS * 2;
+ PackedFloat32Array volume;
+ volume.resize(real_max_channels);
+ float *volume_ptrw = volume.ptrw();
+ for (int i = 0; i < real_max_channels; i += 2) {
+ if (p_playback->volume_vector.is_empty()) {
+ volume_ptrw[i] = 0;
+ volume_ptrw[i + 1] = 0;
+ } else {
+ const AudioFrame &frame = p_playback->volume_vector[i / 2];
+ volume_ptrw[i] = frame.left;
+ volume_ptrw[i + 1] = frame.right;
+ }
+ }
+ godot_audio_sample_start(
+ itos(p_playback->get_instance_id()).utf8().get_data(),
+ itos(p_playback->stream->get_instance_id()).utf8().get_data(),
+ AudioServer::get_singleton()->get_bus_index(p_playback->bus),
+ p_playback->offset,
+ volume_ptrw);
+}
+
+void AudioDriverWeb::stop_sample_playback(const Ref<AudioSamplePlayback> &p_playback) {
+ ERR_FAIL_COND_MSG(p_playback.is_null(), "Parameter p_playback is null.");
+ godot_audio_sample_stop(itos(p_playback->get_instance_id()).utf8().get_data());
+}
+
+void AudioDriverWeb::set_sample_playback_pause(const Ref<AudioSamplePlayback> &p_playback, bool p_paused) {
+ ERR_FAIL_COND_MSG(p_playback.is_null(), "Parameter p_playback is null.");
+ godot_audio_sample_set_pause(itos(p_playback->get_instance_id()).utf8().get_data(), p_paused);
+}
+
+bool AudioDriverWeb::is_sample_playback_active(const Ref<AudioSamplePlayback> &p_playback) {
+ ERR_FAIL_COND_V_MSG(p_playback.is_null(), false, "Parameter p_playback is null.");
+ return godot_audio_sample_is_active(itos(p_playback->get_instance_id()).utf8().get_data()) != 0;
+}
+
+void AudioDriverWeb::update_sample_playback_pitch_scale(const Ref<AudioSamplePlayback> &p_playback, float p_pitch_scale) {
+ ERR_FAIL_COND_MSG(p_playback.is_null(), "Parameter p_playback is null.");
+ godot_audio_sample_update_pitch_scale(
+ itos(p_playback->get_instance_id()).utf8().get_data(),
+ p_pitch_scale);
+}
+
+void AudioDriverWeb::set_sample_playback_bus_volumes_linear(const Ref<AudioSamplePlayback> &p_playback, const HashMap<StringName, Vector<AudioFrame>> &p_bus_volumes) {
+ ERR_FAIL_COND_MSG(p_playback.is_null(), "Parameter p_playback is null.");
+
+ constexpr int real_max_channels = AudioServer::MAX_CHANNELS_PER_BUS * 2;
+
+ PackedInt32Array buses;
+ buses.resize(p_bus_volumes.size());
+ int32_t *buses_ptrw = buses.ptrw();
+ PackedFloat32Array values;
+ values.resize(p_bus_volumes.size() * AudioServer::MAX_CHANNELS_PER_BUS * 2);
+ float *values_ptrw = values.ptrw();
+ int idx = 0;
+ for (KeyValue<StringName, Vector<AudioFrame>> pair : p_bus_volumes) {
+ int bus_index = AudioServer::get_singleton()->get_bus_index(pair.key);
+ buses_ptrw[idx] = bus_index;
+ ERR_FAIL_COND(pair.value.size() != AudioServer::MAX_CHANNELS_PER_BUS);
+ for (int i = 0; i < real_max_channels; i += 2) {
+ const AudioFrame &frame = pair.value[i / 2];
+ values_ptrw[(idx * real_max_channels) + i] = frame.left;
+ values_ptrw[(idx * real_max_channels) + i + 1] = frame.right;
+ }
+ idx++;
+ }
+ godot_audio_sample_set_volumes_linear(
+ itos(p_playback->get_instance_id()).utf8().get_data(),
+ buses_ptrw,
+ buses.size(),
+ values_ptrw,
+ values.size());
+}
+
+void AudioDriverWeb::set_sample_bus_count(int p_count) {
+ godot_audio_sample_bus_set_count(p_count);
+}
+
+void AudioDriverWeb::remove_sample_bus(int p_index) {
+ godot_audio_sample_bus_remove(p_index);
+}
+
+void AudioDriverWeb::add_sample_bus(int p_at_pos) {
+ godot_audio_sample_bus_add(p_at_pos);
+}
+
+void AudioDriverWeb::move_sample_bus(int p_bus, int p_to_pos) {
+ godot_audio_sample_bus_move(p_bus, p_to_pos);
+}
+
+void AudioDriverWeb::set_sample_bus_send(int p_bus, const StringName &p_send) {
+ godot_audio_sample_bus_set_send(p_bus, AudioServer::get_singleton()->get_bus_index(p_send));
+}
+
+void AudioDriverWeb::set_sample_bus_volume_db(int p_bus, float p_volume_db) {
+ godot_audio_sample_bus_set_volume_db(p_bus, p_volume_db);
+}
+
+void AudioDriverWeb::set_sample_bus_solo(int p_bus, bool p_enable) {
+ godot_audio_sample_bus_set_solo(p_bus, p_enable);
+}
+
+void AudioDriverWeb::set_sample_bus_mute(int p_bus, bool p_enable) {
+ godot_audio_sample_bus_set_mute(p_bus, p_enable);
+}
+
#ifdef THREADS_ENABLED
/// AudioWorkletNode implementation (threads)