diff --git a/doc/classes/AudioStreamWAV.xml b/doc/classes/AudioStreamWAV.xml index 566109c0437..7440b558c1c 100644 --- a/doc/classes/AudioStreamWAV.xml +++ b/doc/classes/AudioStreamWAV.xml @@ -13,11 +13,11 @@ - + - Creates a new [AudioStreamWAV] instance from the given buffer. The keys and values of [param options] match the properties of [ResourceImporterWAV]. - The usage of [param options] is identical to [method AudioStreamWAV.load_from_file]. + Creates a new [AudioStreamWAV] instance from the given buffer. The buffer must contain WAV data. + The keys and values of [param options] match the properties of [ResourceImporterWAV]. The usage of [param options] is identical to [method AudioStreamWAV.load_from_file]. @@ -25,7 +25,8 @@ - Creates a new [AudioStreamWAV] instance from the given file path. The keys and values of [param options] match the properties of [ResourceImporterWAV]. + Creates a new [AudioStreamWAV] instance from the given file path. The file must be in WAV format. + The keys and values of [param options] match the properties of [ResourceImporterWAV]. [b]Example:[/b] Load the first file dropped as a WAV and play it: [codeblock] @onready var audio_player = $AudioStreamPlayer diff --git a/modules/minimp3/audio_stream_mp3.cpp b/modules/minimp3/audio_stream_mp3.cpp index 06f6d3e72e5..0cdbfeb7c28 100644 --- a/modules/minimp3/audio_stream_mp3.cpp +++ b/modules/minimp3/audio_stream_mp3.cpp @@ -312,7 +312,24 @@ Ref AudioStreamMP3::generate_sample() const { return sample; } +Ref AudioStreamMP3::load_from_buffer(const Vector &p_stream_data) { + Ref mp3_stream; + mp3_stream.instantiate(); + mp3_stream->set_data(p_stream_data); + ERR_FAIL_COND_V_MSG(mp3_stream->get_data().is_empty(), Ref(), "MP3 decoding failed. Check that your data is a valid MP3 audio stream."); + return mp3_stream; +} + +Ref AudioStreamMP3::load_from_file(const String &p_path) { + const Vector stream_data = FileAccess::get_file_as_bytes(p_path); + ERR_FAIL_COND_V_MSG(stream_data.is_empty(), Ref(), vformat("Cannot open file '%s'.", p_path)); + return load_from_buffer(stream_data); +} + void AudioStreamMP3::_bind_methods() { + ClassDB::bind_static_method("AudioStreamMP3", D_METHOD("load_from_buffer", "stream_data"), &AudioStreamMP3::load_from_buffer); + ClassDB::bind_static_method("AudioStreamMP3", D_METHOD("load_from_file", "path"), &AudioStreamMP3::load_from_file); + ClassDB::bind_method(D_METHOD("set_data", "data"), &AudioStreamMP3::set_data); ClassDB::bind_method(D_METHOD("get_data"), &AudioStreamMP3::get_data); diff --git a/modules/minimp3/audio_stream_mp3.h b/modules/minimp3/audio_stream_mp3.h index c2e557dd450..d675549285a 100644 --- a/modules/minimp3/audio_stream_mp3.h +++ b/modules/minimp3/audio_stream_mp3.h @@ -113,6 +113,9 @@ protected: static void _bind_methods(); public: + static Ref load_from_buffer(const Vector &p_stream_data); + static Ref load_from_file(const String &p_path); + void set_loop(bool p_enable); virtual bool has_loop() const override; diff --git a/modules/minimp3/doc_classes/AudioStreamMP3.xml b/modules/minimp3/doc_classes/AudioStreamMP3.xml index 14676a4545b..25ca6ebdf50 100644 --- a/modules/minimp3/doc_classes/AudioStreamMP3.xml +++ b/modules/minimp3/doc_classes/AudioStreamMP3.xml @@ -5,9 +5,26 @@ MP3 audio stream driver. See [member data] if you want to load an MP3 file at run-time. + [b]Note:[/b] This class can optionally support legacy MP1 and MP2 formats, provided that the engine is compiled with the [code]minimp3_extra_formats=yes[/code] SCons option. These extra formats are not enabled by default. + + + + + + Creates a new [AudioStreamMP3] instance from the given buffer. The buffer must contain MP3 data. + + + + + + + Creates a new [AudioStreamMP3] instance from the given file path. The file must be in MP3 format. + + + diff --git a/modules/minimp3/resource_importer_mp3.cpp b/modules/minimp3/resource_importer_mp3.cpp index 153c05b559d..10ec7bf5f47 100644 --- a/modules/minimp3/resource_importer_mp3.cpp +++ b/modules/minimp3/resource_importer_mp3.cpp @@ -85,35 +85,15 @@ void ResourceImporterMP3::get_import_options(const String &p_path, List mp3_stream = import_mp3(p_path); + Ref mp3_stream = AudioStreamMP3::load_from_file(p_path); if (mp3_stream.is_valid()) { AudioStreamImportSettingsDialog::get_singleton()->edit(p_path, "mp3", mp3_stream); } } #endif -Ref ResourceImporterMP3::import_mp3(const String &p_path) { - Ref f = FileAccess::open(p_path, FileAccess::READ); - ERR_FAIL_COND_V(f.is_null(), Ref()); - - uint64_t len = f->get_length(); - - Vector data; - data.resize(len); - uint8_t *w = data.ptrw(); - - f->get_buffer(w, len); - - Ref mp3_stream; - mp3_stream.instantiate(); - - mp3_stream->set_data(data); - ERR_FAIL_COND_V(mp3_stream->get_data().is_empty(), Ref()); - - return mp3_stream; -} - Error ResourceImporterMP3::import(ResourceUID::ID p_source_id, const String &p_source_file, const String &p_save_path, const HashMap &p_options, List *r_platform_variants, List *r_gen_files, Variant *r_metadata) { bool loop = p_options["loop"]; float loop_offset = p_options["loop_offset"]; @@ -121,10 +101,11 @@ Error ResourceImporterMP3::import(ResourceUID::ID p_source_id, const String &p_s float beat_count = p_options["beat_count"]; float bar_beats = p_options["bar_beats"]; - Ref mp3_stream = import_mp3(p_source_file); + Ref mp3_stream = AudioStreamMP3::load_from_file(p_source_file); if (mp3_stream.is_null()) { return ERR_CANT_OPEN; } + mp3_stream->set_loop(loop); mp3_stream->set_loop_offset(loop_offset); mp3_stream->set_bpm(bpm); diff --git a/modules/minimp3/resource_importer_mp3.h b/modules/minimp3/resource_importer_mp3.h index 35cc761eb40..9e21c23c4d8 100644 --- a/modules/minimp3/resource_importer_mp3.h +++ b/modules/minimp3/resource_importer_mp3.h @@ -55,7 +55,6 @@ public: virtual bool has_advanced_options() const override; virtual void show_advanced_options(const String &p_path) override; #endif - static Ref import_mp3(const String &p_path); virtual Error import(ResourceUID::ID p_source_id, const String &p_source_file, const String &p_save_path, const HashMap &p_options, List *r_platform_variants, List *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; diff --git a/modules/vorbis/audio_stream_ogg_vorbis.cpp b/modules/vorbis/audio_stream_ogg_vorbis.cpp index 2fb965df108..c3e7746b8b5 100644 --- a/modules/vorbis/audio_stream_ogg_vorbis.cpp +++ b/modules/vorbis/audio_stream_ogg_vorbis.cpp @@ -30,8 +30,6 @@ #include "audio_stream_ogg_vorbis.h" -#include "modules/vorbis/resource_importer_ogg_vorbis.h" - #include int AudioStreamPlaybackOggVorbis::_mix_internal(AudioFrame *p_buffer, int p_frames) { @@ -546,8 +544,134 @@ Ref AudioStreamOggVorbis::generate_sample() const { return sample; } +Ref AudioStreamOggVorbis::load_from_buffer(const Vector &p_stream_data) { + Ref ogg_vorbis_stream; + ogg_vorbis_stream.instantiate(); + + Ref ogg_packet_sequence; + ogg_packet_sequence.instantiate(); + + ogg_stream_state stream_state; + ogg_sync_state sync_state; + ogg_page page; + ogg_packet packet; + bool initialized_stream = false; + + ogg_sync_init(&sync_state); + const long OGG_SYNC_BUFFER_SIZE = 8192; + int err; + size_t cursor = 0; + size_t packet_count = 0; + bool done = false; + while (!done) { + err = ogg_sync_check(&sync_state); + ERR_FAIL_COND_V_MSG(err != 0, Ref(), "Ogg sync error " + itos(err)); + while (ogg_sync_pageout(&sync_state, &page) != 1) { + if (cursor >= size_t(p_stream_data.size())) { + done = true; + break; + } + err = ogg_sync_check(&sync_state); + ERR_FAIL_COND_V_MSG(err != 0, Ref(), "Ogg sync error " + itos(err)); + char *sync_buf = ogg_sync_buffer(&sync_state, OGG_SYNC_BUFFER_SIZE); + err = ogg_sync_check(&sync_state); + ERR_FAIL_COND_V_MSG(err != 0, Ref(), "Ogg sync error " + itos(err)); + size_t copy_size = p_stream_data.size() - cursor; + if (copy_size > OGG_SYNC_BUFFER_SIZE) { + copy_size = OGG_SYNC_BUFFER_SIZE; + } + memcpy(sync_buf, &p_stream_data[cursor], copy_size); + ogg_sync_wrote(&sync_state, copy_size); + cursor += copy_size; + err = ogg_sync_check(&sync_state); + ERR_FAIL_COND_V_MSG(err != 0, Ref(), "Ogg sync error " + itos(err)); + } + if (done) { + break; + } + err = ogg_sync_check(&sync_state); + ERR_FAIL_COND_V_MSG(err != 0, Ref(), "Ogg sync error " + itos(err)); + + // Have a page now. + if (!initialized_stream) { + if (ogg_stream_init(&stream_state, ogg_page_serialno(&page))) { + ERR_FAIL_V_MSG(Ref(), "Failed allocating memory for Ogg Vorbis stream."); + } + initialized_stream = true; + } + ogg_stream_pagein(&stream_state, &page); + err = ogg_stream_check(&stream_state); + ERR_FAIL_COND_V_MSG(err != 0, Ref(), "Ogg stream error " + itos(err)); + int desync_iters = 0; + + RBMap>> sorted_packets; + int64_t granule_pos = 0; + + while (true) { + err = ogg_stream_packetout(&stream_state, &packet); + if (err == -1) { + // According to the docs this is usually recoverable, but don't sit here spinning forever. + desync_iters++; + WARN_PRINT_ONCE("Desync during ogg import."); + ERR_FAIL_COND_V_MSG(desync_iters > 100, Ref(), "Packet sync issue during Ogg import"); + continue; + } else if (err == 0) { + // Not enough data to fully reconstruct a packet. Go on to the next page. + break; + } + if (packet_count == 0 && vorbis_synthesis_idheader(&packet) == 0) { + print_verbose("Found a non-vorbis-header packet in a header position"); + // Clearly this logical stream is not a vorbis stream, so destroy it and try again with the next page. + if (initialized_stream) { + ogg_stream_clear(&stream_state); + initialized_stream = false; + } + break; + } + if (packet.granulepos > granule_pos) { + granule_pos = packet.granulepos; + } + + if (packet.bytes > 0) { + PackedByteArray data; + data.resize(packet.bytes); + memcpy(data.ptrw(), packet.packet, packet.bytes); + sorted_packets[granule_pos].push_back(data); + packet_count++; + } + } + Vector> packet_data; + for (const KeyValue>> &pair : sorted_packets) { + for (const Vector &packets : pair.value) { + packet_data.push_back(packets); + } + } + if (initialized_stream && packet_data.size() > 0) { + ogg_packet_sequence->push_page(ogg_page_granulepos(&page), packet_data); + } + } + if (initialized_stream) { + ogg_stream_clear(&stream_state); + } + ogg_sync_clear(&sync_state); + + if (ogg_packet_sequence->get_packet_granule_positions().is_empty()) { + ERR_FAIL_V_MSG(Ref(), "Ogg Vorbis decoding failed. Check that your data is a valid Ogg Vorbis audio stream."); + } + + ogg_vorbis_stream->set_packet_sequence(ogg_packet_sequence); + + return ogg_vorbis_stream; +} + +Ref AudioStreamOggVorbis::load_from_file(const String &p_path) { + const Vector stream_data = FileAccess::get_file_as_bytes(p_path); + ERR_FAIL_COND_V_MSG(stream_data.is_empty(), Ref(), vformat("Cannot open file '%s'.", p_path)); + return load_from_buffer(stream_data); +} + void AudioStreamOggVorbis::_bind_methods() { - ClassDB::bind_static_method("AudioStreamOggVorbis", D_METHOD("load_from_buffer", "buffer"), &AudioStreamOggVorbis::load_from_buffer); + ClassDB::bind_static_method("AudioStreamOggVorbis", D_METHOD("load_from_buffer", "stream_data"), &AudioStreamOggVorbis::load_from_buffer); ClassDB::bind_static_method("AudioStreamOggVorbis", D_METHOD("load_from_file", "path"), &AudioStreamOggVorbis::load_from_file); ClassDB::bind_method(D_METHOD("set_packet_sequence", "packet_sequence"), &AudioStreamOggVorbis::set_packet_sequence); @@ -579,11 +703,3 @@ void AudioStreamOggVorbis::_bind_methods() { AudioStreamOggVorbis::AudioStreamOggVorbis() {} AudioStreamOggVorbis::~AudioStreamOggVorbis() {} - -Ref AudioStreamOggVorbis::load_from_buffer(const Vector &file_data) { - return ResourceImporterOggVorbis::load_from_buffer(file_data); -} - -Ref AudioStreamOggVorbis::load_from_file(const String &p_path) { - return ResourceImporterOggVorbis::load_from_file(p_path); -} diff --git a/modules/vorbis/audio_stream_ogg_vorbis.h b/modules/vorbis/audio_stream_ogg_vorbis.h index 5f13d4e9262..45fb75e0c83 100644 --- a/modules/vorbis/audio_stream_ogg_vorbis.h +++ b/modules/vorbis/audio_stream_ogg_vorbis.h @@ -140,7 +140,8 @@ protected: public: static Ref load_from_file(const String &p_path); - static Ref load_from_buffer(const Vector &file_data); + static Ref load_from_buffer(const Vector &p_stream_data); + void set_loop(bool p_enable); virtual bool has_loop() const override; diff --git a/modules/vorbis/doc_classes/AudioStreamOggVorbis.xml b/modules/vorbis/doc_classes/AudioStreamOggVorbis.xml index d2f6745e2f6..fa5abe4b86e 100644 --- a/modules/vorbis/doc_classes/AudioStreamOggVorbis.xml +++ b/modules/vorbis/doc_classes/AudioStreamOggVorbis.xml @@ -12,16 +12,16 @@ - + - Creates a new AudioStreamOggVorbis instance from the given buffer. The buffer must contain Ogg Vorbis data. + Creates a new [AudioStreamOggVorbis] instance from the given buffer. The buffer must contain Ogg Vorbis data. - Creates a new AudioStreamOggVorbis instance from the given file path. The file must be in Ogg Vorbis format. + Creates a new [AudioStreamOggVorbis] instance from the given file path. The file must be in Ogg Vorbis format. diff --git a/modules/vorbis/doc_classes/ResourceImporterOggVorbis.xml b/modules/vorbis/doc_classes/ResourceImporterOggVorbis.xml index cede03c73a2..87f8b726704 100644 --- a/modules/vorbis/doc_classes/ResourceImporterOggVorbis.xml +++ b/modules/vorbis/doc_classes/ResourceImporterOggVorbis.xml @@ -12,18 +12,18 @@ $DOCS_URL/tutorials/assets_pipeline/importing_audio_samples.html - + - + - This method loads audio data from a PackedByteArray buffer into an AudioStreamOggVorbis object. + Creates a new [AudioStreamOggVorbis] instance from the given buffer. The buffer must contain Ogg Vorbis data. - + - This method loads audio data from a file into an AudioStreamOggVorbis object. The file path is provided as a string. + Creates a new [AudioStreamOggVorbis] instance from the given file path. The file must be in Ogg Vorbis format. diff --git a/modules/vorbis/resource_importer_ogg_vorbis.cpp b/modules/vorbis/resource_importer_ogg_vorbis.cpp index 0e43a6bd409..ea94661607e 100644 --- a/modules/vorbis/resource_importer_ogg_vorbis.cpp +++ b/modules/vorbis/resource_importer_ogg_vorbis.cpp @@ -81,13 +81,12 @@ void ResourceImporterOggVorbis::get_import_options(const String &p_path, List ogg_stream = load_from_file(p_path); + Ref ogg_stream = AudioStreamOggVorbis::load_from_file(p_path); if (ogg_stream.is_valid()) { AudioStreamImportSettingsDialog::get_singleton()->edit(p_path, "oggvorbisstr", ogg_stream); } @@ -101,7 +100,7 @@ Error ResourceImporterOggVorbis::import(ResourceUID::ID p_source_id, const Strin int beat_count = p_options["beat_count"]; int bar_beats = p_options["bar_beats"]; - Ref ogg_vorbis_stream = load_from_file(p_source_file); + Ref ogg_vorbis_stream = AudioStreamOggVorbis::load_from_file(p_source_file); if (ogg_vorbis_stream.is_null()) { return ERR_CANT_OPEN; } @@ -115,135 +114,22 @@ Error ResourceImporterOggVorbis::import(ResourceUID::ID p_source_id, const Strin return ResourceSaver::save(ogg_vorbis_stream, p_save_path + ".oggvorbisstr"); } -ResourceImporterOggVorbis::ResourceImporterOggVorbis() { -} - -void ResourceImporterOggVorbis::_bind_methods() { - ClassDB::bind_static_method("ResourceImporterOggVorbis", D_METHOD("load_from_buffer", "buffer"), &ResourceImporterOggVorbis::load_from_buffer); - ClassDB::bind_static_method("ResourceImporterOggVorbis", D_METHOD("load_from_file", "path"), &ResourceImporterOggVorbis::load_from_file); -} - -Ref ResourceImporterOggVorbis::load_from_buffer(const Vector &file_data) { - Ref ogg_vorbis_stream; - ogg_vorbis_stream.instantiate(); - - Ref ogg_packet_sequence; - ogg_packet_sequence.instantiate(); - - ogg_stream_state stream_state; - ogg_sync_state sync_state; - ogg_page page; - ogg_packet packet; - bool initialized_stream = false; - - ogg_sync_init(&sync_state); - int err; - size_t cursor = 0; - size_t packet_count = 0; - bool done = false; - while (!done) { - err = ogg_sync_check(&sync_state); - ERR_FAIL_COND_V_MSG(err != 0, Ref(), "Ogg sync error " + itos(err)); - while (ogg_sync_pageout(&sync_state, &page) != 1) { - if (cursor >= size_t(file_data.size())) { - done = true; - break; - } - err = ogg_sync_check(&sync_state); - ERR_FAIL_COND_V_MSG(err != 0, Ref(), "Ogg sync error " + itos(err)); - char *sync_buf = ogg_sync_buffer(&sync_state, OGG_SYNC_BUFFER_SIZE); - err = ogg_sync_check(&sync_state); - ERR_FAIL_COND_V_MSG(err != 0, Ref(), "Ogg sync error " + itos(err)); - size_t copy_size = file_data.size() - cursor; - if (copy_size > OGG_SYNC_BUFFER_SIZE) { - copy_size = OGG_SYNC_BUFFER_SIZE; - } - memcpy(sync_buf, &file_data[cursor], copy_size); - ogg_sync_wrote(&sync_state, copy_size); - cursor += copy_size; - err = ogg_sync_check(&sync_state); - ERR_FAIL_COND_V_MSG(err != 0, Ref(), "Ogg sync error " + itos(err)); - } - if (done) { - break; - } - err = ogg_sync_check(&sync_state); - ERR_FAIL_COND_V_MSG(err != 0, Ref(), "Ogg sync error " + itos(err)); - - // Have a page now. - if (!initialized_stream) { - if (ogg_stream_init(&stream_state, ogg_page_serialno(&page))) { - ERR_FAIL_V_MSG(Ref(), "Failed allocating memory for Ogg Vorbis stream."); - } - initialized_stream = true; - } - ogg_stream_pagein(&stream_state, &page); - err = ogg_stream_check(&stream_state); - ERR_FAIL_COND_V_MSG(err != 0, Ref(), "Ogg stream error " + itos(err)); - int desync_iters = 0; - - RBMap>> sorted_packets; - int64_t granule_pos = 0; - - while (true) { - err = ogg_stream_packetout(&stream_state, &packet); - if (err == -1) { - // According to the docs this is usually recoverable, but don't sit here spinning forever. - desync_iters++; - WARN_PRINT_ONCE("Desync during ogg import."); - ERR_FAIL_COND_V_MSG(desync_iters > 100, Ref(), "Packet sync issue during Ogg import"); - continue; - } else if (err == 0) { - // Not enough data to fully reconstruct a packet. Go on to the next page. - break; - } - if (packet_count == 0 && vorbis_synthesis_idheader(&packet) == 0) { - print_verbose("Found a non-vorbis-header packet in a header position"); - // Clearly this logical stream is not a vorbis stream, so destroy it and try again with the next page. - if (initialized_stream) { - ogg_stream_clear(&stream_state); - initialized_stream = false; - } - break; - } - if (packet.granulepos > granule_pos) { - granule_pos = packet.granulepos; - } - - if (packet.bytes > 0) { - PackedByteArray data; - data.resize(packet.bytes); - memcpy(data.ptrw(), packet.packet, packet.bytes); - sorted_packets[granule_pos].push_back(data); - packet_count++; - } - } - Vector> packet_data; - for (const KeyValue>> &pair : sorted_packets) { - for (const Vector &packets : pair.value) { - packet_data.push_back(packets); - } - } - if (initialized_stream && packet_data.size() > 0) { - ogg_packet_sequence->push_page(ogg_page_granulepos(&page), packet_data); - } - } - if (initialized_stream) { - ogg_stream_clear(&stream_state); - } - ogg_sync_clear(&sync_state); - - if (ogg_packet_sequence->get_packet_granule_positions().is_empty()) { - ERR_FAIL_V_MSG(Ref(), "Ogg Vorbis decoding failed. Check that your data is a valid Ogg Vorbis audio stream."); - } - - ogg_vorbis_stream->set_packet_sequence(ogg_packet_sequence); - - return ogg_vorbis_stream; +#ifndef DISABLE_DEPRECATED +Ref ResourceImporterOggVorbis::load_from_buffer(const Vector &p_stream_data) { + return AudioStreamOggVorbis::load_from_buffer(p_stream_data); } Ref ResourceImporterOggVorbis::load_from_file(const String &p_path) { - Vector file_data = FileAccess::get_file_as_bytes(p_path); - ERR_FAIL_COND_V_MSG(file_data.is_empty(), Ref(), "Cannot open file '" + p_path + "'."); - return load_from_buffer(file_data); + return AudioStreamOggVorbis::load_from_file(p_path); +} +#endif + +void ResourceImporterOggVorbis::_bind_methods() { +#ifndef DISABLE_DEPRECATED + ClassDB::bind_static_method("ResourceImporterOggVorbis", D_METHOD("load_from_buffer", "stream_data"), &ResourceImporterOggVorbis::load_from_buffer); + ClassDB::bind_static_method("ResourceImporterOggVorbis", D_METHOD("load_from_file", "path"), &ResourceImporterOggVorbis::load_from_file); +#endif +} + +ResourceImporterOggVorbis::ResourceImporterOggVorbis() { } diff --git a/modules/vorbis/resource_importer_ogg_vorbis.h b/modules/vorbis/resource_importer_ogg_vorbis.h index a4e4441d82c..e737831a234 100644 --- a/modules/vorbis/resource_importer_ogg_vorbis.h +++ b/modules/vorbis/resource_importer_ogg_vorbis.h @@ -38,10 +38,6 @@ class ResourceImporterOggVorbis : public ResourceImporter { GDCLASS(ResourceImporterOggVorbis, ResourceImporter); - enum { - OGG_SYNC_BUFFER_SIZE = 8192, - }; - protected: static void _bind_methods(); @@ -51,8 +47,11 @@ public: virtual void show_advanced_options(const String &p_path) override; #endif +#ifndef DISABLE_DEPRECATED static Ref load_from_file(const String &p_path); - static Ref load_from_buffer(const Vector &file_data); + static Ref load_from_buffer(const Vector &p_stream_data); +#endif + virtual void get_recognized_extensions(List *p_extensions) const override; virtual String get_save_extension() const override; virtual String get_resource_type() const override; diff --git a/scene/resources/audio_stream_wav.cpp b/scene/resources/audio_stream_wav.cpp index 0043e076e42..29ff142ff69 100644 --- a/scene/resources/audio_stream_wav.cpp +++ b/scene/resources/audio_stream_wav.cpp @@ -723,58 +723,12 @@ Ref AudioStreamWAV::generate_sample() const { return sample; } -void AudioStreamWAV::_bind_methods() { - ClassDB::bind_static_method("AudioStreamWAV", D_METHOD("load_from_file", "path", "options"), &AudioStreamWAV::load_from_file, DEFVAL(Dictionary())); - ClassDB::bind_static_method("AudioStreamWAV", D_METHOD("load_from_buffer", "buffer", "options"), &AudioStreamWAV::load_from_buffer, DEFVAL(Dictionary())); - - ClassDB::bind_method(D_METHOD("set_data", "data"), &AudioStreamWAV::set_data); - ClassDB::bind_method(D_METHOD("get_data"), &AudioStreamWAV::get_data); - - ClassDB::bind_method(D_METHOD("set_format", "format"), &AudioStreamWAV::set_format); - ClassDB::bind_method(D_METHOD("get_format"), &AudioStreamWAV::get_format); - - ClassDB::bind_method(D_METHOD("set_loop_mode", "loop_mode"), &AudioStreamWAV::set_loop_mode); - ClassDB::bind_method(D_METHOD("get_loop_mode"), &AudioStreamWAV::get_loop_mode); - - ClassDB::bind_method(D_METHOD("set_loop_begin", "loop_begin"), &AudioStreamWAV::set_loop_begin); - ClassDB::bind_method(D_METHOD("get_loop_begin"), &AudioStreamWAV::get_loop_begin); - - ClassDB::bind_method(D_METHOD("set_loop_end", "loop_end"), &AudioStreamWAV::set_loop_end); - ClassDB::bind_method(D_METHOD("get_loop_end"), &AudioStreamWAV::get_loop_end); - - ClassDB::bind_method(D_METHOD("set_mix_rate", "mix_rate"), &AudioStreamWAV::set_mix_rate); - ClassDB::bind_method(D_METHOD("get_mix_rate"), &AudioStreamWAV::get_mix_rate); - - ClassDB::bind_method(D_METHOD("set_stereo", "stereo"), &AudioStreamWAV::set_stereo); - ClassDB::bind_method(D_METHOD("is_stereo"), &AudioStreamWAV::is_stereo); - - ClassDB::bind_method(D_METHOD("save_to_wav", "path"), &AudioStreamWAV::save_to_wav); - - ADD_PROPERTY(PropertyInfo(Variant::PACKED_BYTE_ARRAY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_data", "get_data"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "format", PROPERTY_HINT_ENUM, "8-Bit,16-Bit,IMA ADPCM,Quite OK Audio"), "set_format", "get_format"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "loop_mode", PROPERTY_HINT_ENUM, "Disabled,Forward,Ping-Pong,Backward"), "set_loop_mode", "get_loop_mode"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "loop_begin"), "set_loop_begin", "get_loop_begin"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "loop_end"), "set_loop_end", "get_loop_end"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "mix_rate"), "set_mix_rate", "get_mix_rate"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "stereo"), "set_stereo", "is_stereo"); - - BIND_ENUM_CONSTANT(FORMAT_8_BITS); - BIND_ENUM_CONSTANT(FORMAT_16_BITS); - BIND_ENUM_CONSTANT(FORMAT_IMA_ADPCM); - BIND_ENUM_CONSTANT(FORMAT_QOA); - - BIND_ENUM_CONSTANT(LOOP_DISABLED); - BIND_ENUM_CONSTANT(LOOP_FORWARD); - BIND_ENUM_CONSTANT(LOOP_PINGPONG); - BIND_ENUM_CONSTANT(LOOP_BACKWARD); -} - -Ref AudioStreamWAV::load_from_buffer(const Vector &p_file_data, const Dictionary &p_options) { +Ref AudioStreamWAV::load_from_buffer(const Vector &p_stream_data, const Dictionary &p_options) { // /* STEP 1, READ WAVE FILE */ Ref file; file.instantiate(); - Error err = file->open_custom(p_file_data.ptr(), p_file_data.size()); + Error err = file->open_custom(p_stream_data.ptr(), p_stream_data.size()); ERR_FAIL_COND_V_MSG(err != OK, Ref(), "Cannot create memfile for WAV file buffer."); /* CHECK RIFF */ @@ -1223,9 +1177,55 @@ Ref AudioStreamWAV::load_from_buffer(const Vector &p_fi } Ref AudioStreamWAV::load_from_file(const String &p_path, const Dictionary &p_options) { - Vector file_data = FileAccess::get_file_as_bytes(p_path); - ERR_FAIL_COND_V_MSG(file_data.is_empty(), Ref(), vformat("Cannot open file '%s'.", p_path)); - return load_from_buffer(file_data, p_options); + const Vector stream_data = FileAccess::get_file_as_bytes(p_path); + ERR_FAIL_COND_V_MSG(stream_data.is_empty(), Ref(), vformat("Cannot open file '%s'.", p_path)); + return load_from_buffer(stream_data, p_options); +} + +void AudioStreamWAV::_bind_methods() { + ClassDB::bind_static_method("AudioStreamWAV", D_METHOD("load_from_buffer", "stream_data", "options"), &AudioStreamWAV::load_from_buffer, DEFVAL(Dictionary())); + ClassDB::bind_static_method("AudioStreamWAV", D_METHOD("load_from_file", "path", "options"), &AudioStreamWAV::load_from_file, DEFVAL(Dictionary())); + + ClassDB::bind_method(D_METHOD("set_data", "data"), &AudioStreamWAV::set_data); + ClassDB::bind_method(D_METHOD("get_data"), &AudioStreamWAV::get_data); + + ClassDB::bind_method(D_METHOD("set_format", "format"), &AudioStreamWAV::set_format); + ClassDB::bind_method(D_METHOD("get_format"), &AudioStreamWAV::get_format); + + ClassDB::bind_method(D_METHOD("set_loop_mode", "loop_mode"), &AudioStreamWAV::set_loop_mode); + ClassDB::bind_method(D_METHOD("get_loop_mode"), &AudioStreamWAV::get_loop_mode); + + ClassDB::bind_method(D_METHOD("set_loop_begin", "loop_begin"), &AudioStreamWAV::set_loop_begin); + ClassDB::bind_method(D_METHOD("get_loop_begin"), &AudioStreamWAV::get_loop_begin); + + ClassDB::bind_method(D_METHOD("set_loop_end", "loop_end"), &AudioStreamWAV::set_loop_end); + ClassDB::bind_method(D_METHOD("get_loop_end"), &AudioStreamWAV::get_loop_end); + + ClassDB::bind_method(D_METHOD("set_mix_rate", "mix_rate"), &AudioStreamWAV::set_mix_rate); + ClassDB::bind_method(D_METHOD("get_mix_rate"), &AudioStreamWAV::get_mix_rate); + + ClassDB::bind_method(D_METHOD("set_stereo", "stereo"), &AudioStreamWAV::set_stereo); + ClassDB::bind_method(D_METHOD("is_stereo"), &AudioStreamWAV::is_stereo); + + ClassDB::bind_method(D_METHOD("save_to_wav", "path"), &AudioStreamWAV::save_to_wav); + + ADD_PROPERTY(PropertyInfo(Variant::PACKED_BYTE_ARRAY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_data", "get_data"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "format", PROPERTY_HINT_ENUM, "8-Bit,16-Bit,IMA ADPCM,Quite OK Audio"), "set_format", "get_format"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "loop_mode", PROPERTY_HINT_ENUM, "Disabled,Forward,Ping-Pong,Backward"), "set_loop_mode", "get_loop_mode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "loop_begin"), "set_loop_begin", "get_loop_begin"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "loop_end"), "set_loop_end", "get_loop_end"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "mix_rate"), "set_mix_rate", "get_mix_rate"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "stereo"), "set_stereo", "is_stereo"); + + BIND_ENUM_CONSTANT(FORMAT_8_BITS); + BIND_ENUM_CONSTANT(FORMAT_16_BITS); + BIND_ENUM_CONSTANT(FORMAT_IMA_ADPCM); + BIND_ENUM_CONSTANT(FORMAT_QOA); + + BIND_ENUM_CONSTANT(LOOP_DISABLED); + BIND_ENUM_CONSTANT(LOOP_FORWARD); + BIND_ENUM_CONSTANT(LOOP_PINGPONG); + BIND_ENUM_CONSTANT(LOOP_BACKWARD); } AudioStreamWAV::AudioStreamWAV() {} diff --git a/scene/resources/audio_stream_wav.h b/scene/resources/audio_stream_wav.h index e36d33cfa93..cd4e4319c36 100644 --- a/scene/resources/audio_stream_wav.h +++ b/scene/resources/audio_stream_wav.h @@ -32,6 +32,7 @@ #define AUDIO_STREAM_WAV_H #include "servers/audio/audio_stream.h" + #include "thirdparty/misc/qoa.h" class AudioStreamWAV; @@ -141,8 +142,8 @@ protected: static void _bind_methods(); public: + static Ref load_from_buffer(const Vector &p_stream_data, const Dictionary &p_options); static Ref load_from_file(const String &p_path, const Dictionary &p_options); - static Ref load_from_buffer(const Vector &p_file_data, const Dictionary &p_options); void set_format(Format p_format); Format get_format() const;