From d1ddee225830b28171de031bd1f1918ced21b38f Mon Sep 17 00:00:00 2001 From: reduz Date: Thu, 21 Jul 2022 01:00:58 +0200 Subject: [PATCH] Implement BPM support Based on #62896, only implements the BPM support part. * Implements BPM support in the AudioStreamOGG/MP3 importers. * Can select BPM/Bar Size and total beats in a song file, as well as edit looping points. * Looping is now BPM aware * Added a special importer UI for configuring this. * Added a special preview showing the audio waveform as well as the playback position in the resource picker. * Renamed `AudioStream::instance` to `instantiate` for correctness. --- doc/classes/AudioServer.xml | 6 + doc/classes/AudioStream.xml | 16 +- doc/classes/AudioStreamPlayback.xml | 5 + editor/audio_stream_preview.cpp | 4 +- editor/audio_stream_preview.h | 2 + editor/editor_node.cpp | 8 +- editor/editor_node.h | 2 + editor/editor_properties.cpp | 3 + editor/editor_resource_picker.cpp | 279 ++++++-- editor/editor_resource_picker.h | 35 +- editor/filesystem_dock.cpp | 25 +- .../import/audio_stream_import_settings.cpp | 650 ++++++++++++++++++ .../audio_stream_import_settings.h} | 73 +- editor/plugins/audio_stream_editor_plugin.cpp | 285 -------- editor/plugins/editor_preview_plugins.cpp | 2 +- modules/minimp3/audio_stream_mp3.cpp | 71 +- modules/minimp3/audio_stream_mp3.h | 25 +- .../minimp3/doc_classes/AudioStreamMP3.xml | 6 + modules/minimp3/resource_importer_mp3.cpp | 46 +- modules/minimp3/resource_importer_mp3.h | 6 + modules/ogg/ogg_packet_sequence.cpp | 2 +- modules/ogg/ogg_packet_sequence.h | 2 +- modules/theora/video_stream_theora.h | 2 +- modules/vorbis/audio_stream_ogg_vorbis.cpp | 134 +++- modules/vorbis/audio_stream_ogg_vorbis.h | 26 +- .../doc_classes/AudioStreamOGGVorbis.xml | 6 + .../vorbis/resource_importer_ogg_vorbis.cpp | 70 +- modules/vorbis/resource_importer_ogg_vorbis.h | 7 + scene/2d/audio_stream_player_2d.cpp | 2 +- scene/3d/audio_stream_player_3d.cpp | 2 +- scene/audio/audio_stream_player.cpp | 2 +- scene/gui/video_stream_player.cpp | 2 +- scene/resources/audio_stream_sample.cpp | 6 +- scene/resources/audio_stream_sample.h | 4 +- scene/resources/video_stream.h | 2 +- servers/audio/audio_stream.cpp | 96 ++- servers/audio/audio_stream.h | 43 +- .../audio/effects/audio_stream_generator.cpp | 6 +- .../audio/effects/audio_stream_generator.h | 4 +- servers/audio_server.cpp | 14 + servers/audio_server.h | 5 + 41 files changed, 1548 insertions(+), 438 deletions(-) create mode 100644 editor/import/audio_stream_import_settings.cpp rename editor/{plugins/audio_stream_editor_plugin.h => import/audio_stream_import_settings.h} (67%) delete mode 100644 editor/plugins/audio_stream_editor_plugin.cpp diff --git a/doc/classes/AudioServer.xml b/doc/classes/AudioServer.xml index 1e076654fb5..28dcd2794e6 100644 --- a/doc/classes/AudioServer.xml +++ b/doc/classes/AudioServer.xml @@ -275,6 +275,12 @@ Sets the volume of the bus at index [code]bus_idx[/code] to [code]volume_db[/code]. + + + + + + diff --git a/doc/classes/AudioStream.xml b/doc/classes/AudioStream.xml index 6343da6eedf..68f64505d07 100644 --- a/doc/classes/AudioStream.xml +++ b/doc/classes/AudioStream.xml @@ -13,6 +13,16 @@ https://godotengine.org/asset-library/asset/528 + + + + + + + + + + @@ -23,7 +33,7 @@ - + @@ -39,10 +49,10 @@ Returns the length of the audio stream in seconds. - + - Returns an AudioStreamPlayback. Useful for when you want to extend `_instance_playback` but call `instance_playback` from an internally held AudioStream subresource. An example of this can be found in the source files for `AudioStreamRandomPitch::instance_playback`. + Returns an AudioStreamPlayback. Useful for when you want to extend [method _instantiate_playback] but call [method instantiate_playback] from an internally held AudioStream subresource. An example of this can be found in the source files for [code]AudioStreamRandomPitch::instantiate_playback[/code]. diff --git a/doc/classes/AudioStreamPlayback.xml b/doc/classes/AudioStreamPlayback.xml index 1909c4b6218..d3d97e0c8a2 100644 --- a/doc/classes/AudioStreamPlayback.xml +++ b/doc/classes/AudioStreamPlayback.xml @@ -50,5 +50,10 @@ + + + + + diff --git a/editor/audio_stream_preview.cpp b/editor/audio_stream_preview.cpp index bea95d873ec..fc47e1ef5cb 100644 --- a/editor/audio_stream_preview.cpp +++ b/editor/audio_stream_preview.cpp @@ -153,6 +153,8 @@ void AudioStreamPreviewGenerator::_preview_thread(void *p_preview) { singleton->call_deferred(SNAME("_update_emit"), preview->id); } + preview->preview->version++; + preview->playback->stop(); preview->generating.clear(); @@ -171,7 +173,7 @@ Ref AudioStreamPreviewGenerator::generate_preview(const Ref< Preview *preview = &previews[p_stream->get_instance_id()]; preview->base_stream = p_stream; - preview->playback = preview->base_stream->instance_playback(); + preview->playback = preview->base_stream->instantiate_playback(); preview->generating.set(); preview->id = p_stream->get_instance_id(); diff --git a/editor/audio_stream_preview.h b/editor/audio_stream_preview.h index 307dd93b348..0e3c8f70d2d 100644 --- a/editor/audio_stream_preview.h +++ b/editor/audio_stream_preview.h @@ -43,8 +43,10 @@ class AudioStreamPreview : public RefCounted { float length; friend class AudioStreamPreviewGenerator; + uint64_t version = 1; public: + uint64_t get_version() const { return version; } float get_length() const; float get_max(float p_time, float p_time_next) const; float get_min(float p_time, float p_time_next) const; diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 166dcf19c8e..108b0dc1775 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -104,6 +104,7 @@ #include "editor/editor_translation_parser.h" #include "editor/export_template_manager.h" #include "editor/filesystem_dock.h" +#include "editor/import/audio_stream_import_settings.h" #include "editor/import/dynamic_font_import_settings.h" #include "editor/import/editor_import_collada.h" #include "editor/import/resource_importer_bitmask.h" @@ -131,7 +132,6 @@ #include "editor/plugins/animation_state_machine_editor.h" #include "editor/plugins/animation_tree_editor_plugin.h" #include "editor/plugins/asset_library_editor_plugin.h" -#include "editor/plugins/audio_stream_editor_plugin.h" #include "editor/plugins/audio_stream_randomizer_editor_plugin.h" #include "editor/plugins/bit_map_editor_plugin.h" #include "editor/plugins/bone_map_editor_plugin.h" @@ -5899,6 +5899,8 @@ EditorNode::EditorNode() { RenderingServer::get_singleton()->set_debug_generate_wireframes(true); + AudioServer::get_singleton()->set_enable_tagging_used_audio_streams(true); + // No navigation server by default if in editor. NavigationServer3D::get_singleton()->set_active(false); @@ -6443,6 +6445,9 @@ EditorNode::EditorNode() { scene_import_settings = memnew(SceneImportSettings); gui_base->add_child(scene_import_settings); + audio_stream_import_settings = memnew(AudioStreamImportSettings); + gui_base->add_child(audio_stream_import_settings); + fontdata_import_settings = memnew(DynamicFontImportSettings); gui_base->add_child(fontdata_import_settings); @@ -7079,7 +7084,6 @@ EditorNode::EditorNode() { // This list is alphabetized, and plugins that depend on Node2D are in their own section below. add_editor_plugin(memnew(AnimationTreeEditorPlugin)); add_editor_plugin(memnew(AudioBusesEditorPlugin(audio_bus_editor))); - add_editor_plugin(memnew(AudioStreamEditorPlugin)); add_editor_plugin(memnew(AudioStreamRandomizerEditorPlugin)); add_editor_plugin(memnew(BitMapEditorPlugin)); add_editor_plugin(memnew(BoneMapEditorPlugin)); diff --git a/editor/editor_node.h b/editor/editor_node.h index 07d565314d7..1bf559f79a4 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -88,6 +88,7 @@ class ProjectExportDialog; class ProjectSettingsEditor; class RunSettingsDialog; class SceneImportSettings; +class AudioStreamImportSettings; class ScriptCreateDialog; class SubViewport; class TabBar; @@ -468,6 +469,7 @@ private: DynamicFontImportSettings *fontdata_import_settings = nullptr; SceneImportSettings *scene_import_settings = nullptr; + AudioStreamImportSettings *audio_stream_import_settings = nullptr; String import_reload_fn; diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index aaa518362c2..dccc51829aa 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -3517,6 +3517,9 @@ void EditorPropertyResource::setup(Object *p_object, const String &p_path, const shader_picker->set_edited_material(Object::cast_to(p_object)); resource_picker = shader_picker; connect(SNAME("ready"), callable_mp(this, &EditorPropertyResource::_update_preferred_shader)); + } else if (p_base_type == "AudioStream") { + EditorAudioStreamPicker *astream_picker = memnew(EditorAudioStreamPicker); + resource_picker = astream_picker; } else { resource_picker = memnew(EditorResourcePicker); } diff --git a/editor/editor_resource_picker.cpp b/editor/editor_resource_picker.cpp index 40e16bf717a..da5ab08d494 100644 --- a/editor/editor_resource_picker.cpp +++ b/editor/editor_resource_picker.cpp @@ -30,6 +30,7 @@ #include "editor_resource_picker.h" +#include "editor/audio_stream_preview.h" #include "editor/editor_file_dialog.h" #include "editor/editor_node.h" #include "editor/editor_resource_preview.h" @@ -47,32 +48,37 @@ void EditorResourcePicker::clear_caches() { } void EditorResourcePicker::_update_resource() { - preview_rect->set_texture(Ref()); - assign_button->set_custom_minimum_size(Size2(1, 1)); + String resource_path; + if (edited_resource.is_valid() && edited_resource->get_path().is_resource_file()) { + resource_path = edited_resource->get_path() + "\n"; + } - if (edited_resource == Ref()) { - assign_button->set_icon(Ref()); - assign_button->set_text(TTR("[empty]")); - assign_button->set_tooltip(""); - } else { - assign_button->set_icon(EditorNode::get_singleton()->get_object_icon(edited_resource.operator->(), "Object")); + if (preview_rect) { + preview_rect->set_texture(Ref()); - if (!edited_resource->get_name().is_empty()) { - assign_button->set_text(edited_resource->get_name()); - } else if (edited_resource->get_path().is_resource_file()) { - assign_button->set_text(edited_resource->get_path().get_file()); + assign_button->set_custom_minimum_size(assign_button_min_size); + + if (edited_resource == Ref()) { + assign_button->set_icon(Ref()); + assign_button->set_text(TTR("[empty]")); + assign_button->set_tooltip(""); } else { - assign_button->set_text(edited_resource->get_class()); - } + assign_button->set_icon(EditorNode::get_singleton()->get_object_icon(edited_resource.operator->(), "Object")); - String resource_path; - if (edited_resource->get_path().is_resource_file()) { - resource_path = edited_resource->get_path() + "\n"; + if (!edited_resource->get_name().is_empty()) { + assign_button->set_text(edited_resource->get_name()); + } else if (edited_resource->get_path().is_resource_file()) { + assign_button->set_text(edited_resource->get_path().get_file()); + } else { + assign_button->set_text(edited_resource->get_class()); + } + assign_button->set_tooltip(resource_path + TTR("Type:") + " " + edited_resource->get_class()); + + // Preview will override the above, so called at the end. + EditorResourcePreview::get_singleton()->queue_edited_resource_preview(edited_resource, this, "_update_resource_preview", edited_resource->get_instance_id()); } + } else if (edited_resource.is_valid()) { assign_button->set_tooltip(resource_path + TTR("Type:") + " " + edited_resource->get_class()); - - // Preview will override the above, so called at the end. - EditorResourcePreview::get_singleton()->queue_edited_resource_preview(edited_resource, this, "_update_resource_preview", edited_resource->get_instance_id()); } } @@ -81,28 +87,30 @@ void EditorResourcePicker::_update_resource_preview(const String &p_path, const return; } - Ref