diff options
author | Adam Scott <ascott.ca@gmail.com> | 2024-04-18 10:50:34 -0400 |
---|---|---|
committer | Adam Scott <ascott.ca@gmail.com> | 2024-06-18 11:06:31 -0400 |
commit | 52fa4f05f3945fdf511c249adede9b6d07c51beb (patch) | |
tree | 2ac2aca86c09dd757fd4a8b5defab932f2b8eb5d /scene/resources | |
parent | eb20a68b323c1fcb75492f8132e1bd6d321713ec (diff) | |
download | redot-engine-52fa4f05f3945fdf511c249adede9b6d07c51beb.tar.gz |
Add samples playback support
Diffstat (limited to 'scene/resources')
-rw-r--r-- | scene/resources/audio_stream_polyphonic.compat.inc | 41 | ||||
-rw-r--r-- | scene/resources/audio_stream_polyphonic.cpp | 54 | ||||
-rw-r--r-- | scene/resources/audio_stream_polyphonic.h | 23 | ||||
-rw-r--r-- | scene/resources/audio_stream_wav.cpp | 43 | ||||
-rw-r--r-- | scene/resources/audio_stream_wav.h | 13 |
5 files changed, 171 insertions, 3 deletions
diff --git a/scene/resources/audio_stream_polyphonic.compat.inc b/scene/resources/audio_stream_polyphonic.compat.inc new file mode 100644 index 0000000000..31074218e1 --- /dev/null +++ b/scene/resources/audio_stream_polyphonic.compat.inc @@ -0,0 +1,41 @@ +/**************************************************************************/ +/* audio_stream_polyphonic.compat.inc */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* 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 DISABLE_DEPRECATED + +AudioStreamPlaybackPolyphonic::ID AudioStreamPlaybackPolyphonic::_play_stream_bind_compat_91382(const Ref<AudioStream> &p_stream, float p_from_offset, float p_volume_db, float p_pitch_scale) { + return play_stream(p_stream, p_from_offset, p_volume_db, p_pitch_scale, AudioServer::PlaybackType::PLAYBACK_TYPE_DEFAULT, SceneStringName(Master)); +} + +void AudioStreamPlaybackPolyphonic::_bind_compatibility_methods() { + ClassDB::bind_compatibility_method(D_METHOD("play_stream", "stream", "from_offset", "volume_db", "pitch_scale"), &AudioStreamPlaybackPolyphonic::_play_stream_bind_compat_91382, DEFVAL(0), DEFVAL(0), DEFVAL(1.0)); +} + +#endif diff --git a/scene/resources/audio_stream_polyphonic.cpp b/scene/resources/audio_stream_polyphonic.cpp index f7299b0789..45546d8dc7 100644 --- a/scene/resources/audio_stream_polyphonic.cpp +++ b/scene/resources/audio_stream_polyphonic.cpp @@ -29,7 +29,10 @@ /**************************************************************************/ #include "audio_stream_polyphonic.h" +#include "audio_stream_polyphonic.compat.inc" + #include "scene/main/scene_tree.h" +#include "servers/audio_server.h" Ref<AudioStreamPlayback> AudioStreamPolyphonic::instantiate_playback() { Ref<AudioStreamPlaybackPolyphonic> playback; @@ -136,6 +139,10 @@ int AudioStreamPlaybackPolyphonic::mix(AudioFrame *p_buffer, float p_rate_scale, continue; } + if (s.stream_playback->get_is_sample()) { + continue; + } + float volume_db = s.volume_db; // Copy because it can be overridden at any time. float next_volume = Math::db_to_linear(volume_db); s.prev_volume_db = volume_db; @@ -195,8 +202,13 @@ int AudioStreamPlaybackPolyphonic::mix(AudioFrame *p_buffer, float p_rate_scale, return p_frames; } -AudioStreamPlaybackPolyphonic::ID AudioStreamPlaybackPolyphonic::play_stream(const Ref<AudioStream> &p_stream, float p_from_offset, float p_volume_db, float p_pitch_scale) { +AudioStreamPlaybackPolyphonic::ID AudioStreamPlaybackPolyphonic::play_stream(const Ref<AudioStream> &p_stream, float p_from_offset, float p_volume_db, float p_pitch_scale, AudioServer::PlaybackType p_playback_type, const StringName &p_bus) { ERR_FAIL_COND_V(p_stream.is_null(), INVALID_ID); + + AudioServer::PlaybackType playback_type = p_playback_type == AudioServer::PlaybackType::PLAYBACK_TYPE_DEFAULT + ? AudioServer::get_singleton()->get_default_playback_type() + : p_playback_type; + for (uint32_t i = 0; i < streams.size(); i++) { if (!streams[i].active.is_set()) { // Can use this stream, as it's not active. @@ -210,6 +222,28 @@ AudioStreamPlaybackPolyphonic::ID AudioStreamPlaybackPolyphonic::play_stream(con streams[i].finish_request.clear(); streams[i].pending_play.set(); streams[i].active.set(); + + // Sample playback. + if (playback_type == AudioServer::PlaybackType::PLAYBACK_TYPE_SAMPLE && p_stream->can_be_sampled()) { + streams[i].stream_playback->set_is_sample(true); + if (!AudioServer::get_singleton()->is_stream_registered_as_sample(p_stream)) { + AudioServer::get_singleton()->register_stream_as_sample(p_stream); + } + float linear_volume = Math::db_to_linear(p_volume_db); + Ref<AudioSamplePlayback> sp; + sp.instantiate(); + sp->stream = streams[i].stream; + sp->offset = p_from_offset; + sp->volume_vector.resize(4); + sp->volume_vector.write[0] = AudioFrame(linear_volume, linear_volume); + sp->volume_vector.write[1] = AudioFrame(linear_volume, /* LFE= */ 1.0f); + sp->volume_vector.write[2] = AudioFrame(linear_volume, linear_volume); + sp->volume_vector.write[3] = AudioFrame(linear_volume, linear_volume); + sp->bus = p_bus; + streams[i].stream_playback->set_sample_playback(sp); + AudioServer::get_singleton()->start_sample_playback(sp); + } + return (ID(i) << INDEX_SHIFT) | ID(streams[i].id); } } @@ -260,8 +294,24 @@ void AudioStreamPlaybackPolyphonic::stop_stream(ID p_stream_id) { s->finish_request.set(); } +void AudioStreamPlaybackPolyphonic::set_is_sample(bool p_is_sample) { + _is_sample = p_is_sample; +} + +bool AudioStreamPlaybackPolyphonic::get_is_sample() const { + return _is_sample; +} + +Ref<AudioSamplePlayback> AudioStreamPlaybackPolyphonic::get_sample_playback() const { + return sample_playback; +} + +void AudioStreamPlaybackPolyphonic::set_sample_playback(const Ref<AudioSamplePlayback> &p_playback) { + sample_playback = p_playback; +} + void AudioStreamPlaybackPolyphonic::_bind_methods() { - ClassDB::bind_method(D_METHOD("play_stream", "stream", "from_offset", "volume_db", "pitch_scale"), &AudioStreamPlaybackPolyphonic::play_stream, DEFVAL(0), DEFVAL(0), DEFVAL(1.0)); + ClassDB::bind_method(D_METHOD("play_stream", "stream", "from_offset", "volume_db", "pitch_scale", "playback_type", "bus"), &AudioStreamPlaybackPolyphonic::play_stream, DEFVAL(0), DEFVAL(0), DEFVAL(1.0), DEFVAL(0), DEFVAL(SceneStringName(Master))); ClassDB::bind_method(D_METHOD("set_stream_volume", "stream", "volume_db"), &AudioStreamPlaybackPolyphonic::set_stream_volume); ClassDB::bind_method(D_METHOD("set_stream_pitch_scale", "stream", "pitch_scale"), &AudioStreamPlaybackPolyphonic::set_stream_pitch_scale); ClassDB::bind_method(D_METHOD("is_stream_playing", "stream"), &AudioStreamPlaybackPolyphonic::is_stream_playing); diff --git a/scene/resources/audio_stream_polyphonic.h b/scene/resources/audio_stream_polyphonic.h index e414401b6f..01d0176c44 100644 --- a/scene/resources/audio_stream_polyphonic.h +++ b/scene/resources/audio_stream_polyphonic.h @@ -32,12 +32,16 @@ #define AUDIO_STREAM_POLYPHONIC_H #include "core/templates/local_vector.h" +#include "scene/scene_string_names.h" #include "servers/audio/audio_stream.h" +#include "servers/audio_server.h" class AudioStreamPolyphonic : public AudioStream { GDCLASS(AudioStreamPolyphonic, AudioStream) int polyphony = 32; + AudioServer::PlaybackType playback_type; + static void _bind_methods(); public: @@ -48,6 +52,8 @@ public: void set_polyphony(int p_voices); int get_polyphony() const; + virtual bool is_meta_stream() const override { return true; } + AudioStreamPolyphonic(); }; @@ -81,6 +87,9 @@ class AudioStreamPlaybackPolyphonic : public AudioStreamPlayback { bool active = false; uint32_t id_counter = 1; + bool _is_sample = false; + Ref<AudioSamplePlayback> sample_playback; + _FORCE_INLINE_ Stream *_find_stream(int64_t p_id); friend class AudioStreamPolyphonic; @@ -107,12 +116,24 @@ public: virtual int mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) override; - ID play_stream(const Ref<AudioStream> &p_stream, float p_from_offset = 0, float p_volume_db = 0, float p_pitch_scale = 1.0); + ID play_stream(const Ref<AudioStream> &p_stream, float p_from_offset = 0, float p_volume_db = 0, float p_pitch_scale = 1.0, AudioServer::PlaybackType p_playback_type = AudioServer::PlaybackType::PLAYBACK_TYPE_DEFAULT, const StringName &p_bus = SceneStringName(Master)); void set_stream_volume(ID p_stream_id, float p_volume_db); void set_stream_pitch_scale(ID p_stream_id, float p_pitch_scale); bool is_stream_playing(ID p_stream_id) const; void stop_stream(ID p_stream_id); + virtual void set_is_sample(bool p_is_sample) override; + virtual bool get_is_sample() const override; + virtual Ref<AudioSamplePlayback> get_sample_playback() const override; + virtual void set_sample_playback(const Ref<AudioSamplePlayback> &p_playback) override; + +private: +#ifndef DISABLE_DEPRECATED + ID _play_stream_bind_compat_91382(const Ref<AudioStream> &p_stream, float p_from_offset = 0, float p_volume_db = 0, float p_pitch_scale = 1.0); + static void _bind_compatibility_methods(); +#endif // DISABLE_DEPRECATED + +public: AudioStreamPlaybackPolyphonic(); }; diff --git a/scene/resources/audio_stream_wav.cpp b/scene/resources/audio_stream_wav.cpp index db2564af22..e2ac0e6d26 100644 --- a/scene/resources/audio_stream_wav.cpp +++ b/scene/resources/audio_stream_wav.cpp @@ -465,6 +465,22 @@ void AudioStreamPlaybackWAV::tag_used_streams() { base->tag_used(get_playback_position()); } +void AudioStreamPlaybackWAV::set_is_sample(bool p_is_sample) { + _is_sample = p_is_sample; +} + +bool AudioStreamPlaybackWAV::get_is_sample() const { + return _is_sample; +} + +Ref<AudioSamplePlayback> AudioStreamPlaybackWAV::get_sample_playback() const { + return sample_playback; +} + +void AudioStreamPlaybackWAV::set_sample_playback(const Ref<AudioSamplePlayback> &p_playback) { + sample_playback = p_playback; +} + AudioStreamPlaybackWAV::AudioStreamPlaybackWAV() {} AudioStreamPlaybackWAV::~AudioStreamPlaybackWAV() { @@ -696,6 +712,33 @@ String AudioStreamWAV::get_stream_name() const { return ""; } +Ref<AudioSample> AudioStreamWAV::generate_sample() const { + Ref<AudioSample> sample; + sample.instantiate(); + sample->stream = this; + switch (loop_mode) { + case AudioStreamWAV::LoopMode::LOOP_DISABLED: { + sample->loop_mode = AudioSample::LoopMode::LOOP_DISABLED; + } break; + + case AudioStreamWAV::LoopMode::LOOP_FORWARD: { + sample->loop_mode = AudioSample::LoopMode::LOOP_FORWARD; + } break; + + case AudioStreamWAV::LoopMode::LOOP_PINGPONG: { + sample->loop_mode = AudioSample::LoopMode::LOOP_PINGPONG; + } break; + + case AudioStreamWAV::LoopMode::LOOP_BACKWARD: { + sample->loop_mode = AudioSample::LoopMode::LOOP_BACKWARD; + } break; + } + sample->loop_begin = loop_begin; + sample->loop_end = loop_end; + sample->sample_rate = mix_rate; + return sample; +} + void AudioStreamWAV::_bind_methods() { ClassDB::bind_method(D_METHOD("set_data", "data"), &AudioStreamWAV::set_data); ClassDB::bind_method(D_METHOD("get_data"), &AudioStreamWAV::get_data); diff --git a/scene/resources/audio_stream_wav.h b/scene/resources/audio_stream_wav.h index 146142d8a4..806db675b6 100644 --- a/scene/resources/audio_stream_wav.h +++ b/scene/resources/audio_stream_wav.h @@ -78,6 +78,9 @@ class AudioStreamPlaybackWAV : public AudioStreamPlayback { template <typename Depth, bool is_stereo, bool is_ima_adpcm, bool is_qoa> void do_resample(const Depth *p_src, AudioFrame *p_dst, int64_t &p_offset, int32_t &p_increment, uint32_t p_amount, IMA_ADPCM_State *p_ima_adpcm, QOA_State *p_qoa); + bool _is_sample = false; + Ref<AudioSamplePlayback> sample_playback; + public: virtual void start(double p_from_pos = 0.0) override; virtual void stop() override; @@ -92,6 +95,11 @@ public: virtual void tag_used_streams() override; + virtual void set_is_sample(bool p_is_sample) override; + virtual bool get_is_sample() const override; + virtual Ref<AudioSamplePlayback> get_sample_playback() const override; + virtual void set_sample_playback(const Ref<AudioSamplePlayback> &p_playback) override; + AudioStreamPlaybackWAV(); ~AudioStreamPlaybackWAV(); }; @@ -166,6 +174,11 @@ public: virtual Ref<AudioStreamPlayback> instantiate_playback() override; virtual String get_stream_name() const override; + virtual bool can_be_sampled() const override { + return true; + } + virtual Ref<AudioSample> generate_sample() const override; + AudioStreamWAV(); ~AudioStreamWAV(); }; |