Skip to content

Commit

Permalink
Merge pull request #78084 from V-Sekai/load-ogg-bytes-remake
Browse files Browse the repository at this point in the history
Implement loading OGG files from buffer and file path
  • Loading branch information
YuriSizov authored Jul 16, 2023
2 parents 93d180b + e391eae commit 7bc8a52
Show file tree
Hide file tree
Showing 7 changed files with 103 additions and 51 deletions.
12 changes: 12 additions & 0 deletions modules/vorbis/audio_stream_ogg_vorbis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include "core/io/file_access.h"
#include "core/variant/typed_array.h"

#include "modules/vorbis/resource_importer_ogg_vorbis.h"
#include <ogg/ogg.h>

int AudioStreamPlaybackOggVorbis::_mix_internal(AudioFrame *p_buffer, int p_frames) {
Expand Down Expand Up @@ -520,6 +521,9 @@ bool AudioStreamOggVorbis::is_monophonic() const {
}

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_file", "path"), &AudioStreamOggVorbis::load_from_file);

ClassDB::bind_method(D_METHOD("set_packet_sequence", "packet_sequence"), &AudioStreamOggVorbis::set_packet_sequence);
ClassDB::bind_method(D_METHOD("get_packet_sequence"), &AudioStreamOggVorbis::get_packet_sequence);

Expand Down Expand Up @@ -549,3 +553,11 @@ void AudioStreamOggVorbis::_bind_methods() {
AudioStreamOggVorbis::AudioStreamOggVorbis() {}

AudioStreamOggVorbis::~AudioStreamOggVorbis() {}

Ref<AudioStreamOggVorbis> AudioStreamOggVorbis::load_from_buffer(const Vector<uint8_t> &file_data) {
return ResourceImporterOggVorbis::load_from_buffer(file_data);
}

Ref<AudioStreamOggVorbis> AudioStreamOggVorbis::load_from_file(const String &p_path) {
return ResourceImporterOggVorbis::load_from_file(p_path);
}
2 changes: 2 additions & 0 deletions modules/vorbis/audio_stream_ogg_vorbis.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ class AudioStreamOggVorbis : public AudioStream {
static void _bind_methods();

public:
static Ref<AudioStreamOggVorbis> load_from_file(const String &p_path);
static Ref<AudioStreamOggVorbis> load_from_buffer(const Vector<uint8_t> &file_data);
void set_loop(bool p_enable);
virtual bool has_loop() const override;

Expand Down
18 changes: 18 additions & 0 deletions modules/vorbis/doc_classes/AudioStreamOggVorbis.xml
Original file line number Diff line number Diff line change
@@ -1,11 +1,29 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="AudioStreamOggVorbis" inherits="AudioStream" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd">
<brief_description>
A class representing an Ogg Vorbis audio stream.
</brief_description>
<description>
The AudioStreamOggVorbis class is a specialized [AudioStream] for handling Ogg Vorbis file formats. It offers functionality for loading and playing back Ogg Vorbis files, as well as managing looping and other playback properties. This class is part of the audio stream system, which also supports WAV files through the [AudioStreamWAV] class.
</description>
<tutorials>
</tutorials>
<methods>
<method name="load_from_buffer" qualifiers="static">
<return type="AudioStreamOggVorbis" />
<param index="0" name="buffer" type="PackedByteArray" />
<description>
Creates a new AudioStreamOggVorbis instance from the given buffer. The buffer must contain Ogg Vorbis data.
</description>
</method>
<method name="load_from_file" qualifiers="static">
<return type="AudioStreamOggVorbis" />
<param index="0" name="path" type="String" />
<description>
Creates a new AudioStreamOggVorbis instance from the given file path. The file must be in Ogg Vorbis format.
</description>
</method>
</methods>
<members>
<member name="bar_beats" type="int" setter="set_bar_beats" getter="get_bar_beats" default="4">
</member>
Expand Down
16 changes: 16 additions & 0 deletions modules/vorbis/doc_classes/ResourceImporterOggVorbis.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,22 @@
</description>
<tutorials>
</tutorials>
<methods>
<method name="load_from_buffer" qualifiers="static">
<return type="AudioStreamOggVorbis" />
<param index="0" name="buffer" type="PackedByteArray" />
<description>
This method loads audio data from a PackedByteArray buffer into an AudioStreamOggVorbis object.
</description>
</method>
<method name="load_from_file" qualifiers="static">
<return type="AudioStreamOggVorbis" />
<param index="0" name="path" type="String" />
<description>
This method loads audio data from a file into an AudioStreamOggVorbis object. The file path is provided as a string.
</description>
</method>
</methods>
<members>
<member name="bar_beats" type="int" setter="" getter="" default="4">
</member>
Expand Down
3 changes: 3 additions & 0 deletions modules/vorbis/register_types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@
#include "register_types.h"

#include "audio_stream_ogg_vorbis.h"

#ifdef TOOLS_ENABLED
#include "resource_importer_ogg_vorbis.h"
#endif

void initialize_vorbis_module(ModuleInitializationLevel p_level) {
if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) {
Expand Down
94 changes: 47 additions & 47 deletions modules/vorbis/resource_importer_ogg_vorbis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,18 +81,50 @@ void ResourceImporterOggVorbis::get_import_options(const String &p_path, List<Im
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "bar_beats", PROPERTY_HINT_RANGE, "2,32,or_greater"), 4));
}

Ref<AudioStreamOggVorbis> ResourceImporterOggVorbis::import_ogg_vorbis(const String &p_path) {
Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
ERR_FAIL_COND_V_MSG(f.is_null(), Ref<AudioStreamOggVorbis>(), "Cannot open file '" + p_path + "'.");
#ifdef TOOLS_ENABLED

bool ResourceImporterOggVorbis::has_advanced_options() const {
return true;
}

void ResourceImporterOggVorbis::show_advanced_options(const String &p_path) {
Ref<AudioStreamOggVorbis> ogg_stream = load_from_file(p_path);
if (ogg_stream.is_valid()) {
AudioStreamImportSettings::get_singleton()->edit(p_path, "oggvorbisstr", ogg_stream);
}
}
#endif

Error ResourceImporterOggVorbis::import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) {
bool loop = p_options["loop"];
float loop_offset = p_options["loop_offset"];
double bpm = p_options["bpm"];
int beat_count = p_options["beat_count"];
int bar_beats = p_options["bar_beats"];

uint64_t len = f->get_length();
Ref<AudioStreamOggVorbis> ogg_vorbis_stream = load_from_file(p_source_file);
if (ogg_vorbis_stream.is_null()) {
return ERR_CANT_OPEN;
}

Vector<uint8_t> file_data;
file_data.resize(len);
uint8_t *w = file_data.ptrw();
ogg_vorbis_stream->set_loop(loop);
ogg_vorbis_stream->set_loop_offset(loop_offset);
ogg_vorbis_stream->set_bpm(bpm);
ogg_vorbis_stream->set_beat_count(beat_count);
ogg_vorbis_stream->set_bar_beats(bar_beats);

return ResourceSaver::save(ogg_vorbis_stream, p_save_path + ".oggvorbisstr");
}

f->get_buffer(w, len);
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<AudioStreamOggVorbis> ResourceImporterOggVorbis::load_from_buffer(const Vector<uint8_t> &file_data) {
Ref<AudioStreamOggVorbis> ogg_vorbis_stream;
ogg_vorbis_stream.instantiate();

Expand All @@ -114,7 +146,7 @@ Ref<AudioStreamOggVorbis> ResourceImporterOggVorbis::import_ogg_vorbis(const Str
err = ogg_sync_check(&sync_state);
ERR_FAIL_COND_V_MSG(err != 0, Ref<AudioStreamOggVorbis>(), "Ogg sync error " + itos(err));
while (ogg_sync_pageout(&sync_state, &page) != 1) {
if (cursor >= len) {
if (cursor >= size_t(file_data.size())) {
done = true;
break;
}
Expand All @@ -123,8 +155,8 @@ Ref<AudioStreamOggVorbis> ResourceImporterOggVorbis::import_ogg_vorbis(const Str
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<AudioStreamOggVorbis>(), "Ogg sync error " + itos(err));
ERR_FAIL_COND_V(cursor > len, Ref<AudioStreamOggVorbis>());
size_t copy_size = len - cursor;
ERR_FAIL_COND_V(cursor > size_t(file_data.size()), Ref<AudioStreamOggVorbis>());
size_t copy_size = file_data.size() - cursor;
if (copy_size > OGG_SYNC_BUFFER_SIZE) {
copy_size = OGG_SYNC_BUFFER_SIZE;
}
Expand Down Expand Up @@ -201,40 +233,8 @@ Ref<AudioStreamOggVorbis> ResourceImporterOggVorbis::import_ogg_vorbis(const Str
return ogg_vorbis_stream;
}

#ifdef TOOLS_ENABLED

bool ResourceImporterOggVorbis::has_advanced_options() const {
return true;
}

void ResourceImporterOggVorbis::show_advanced_options(const String &p_path) {
Ref<AudioStreamOggVorbis> ogg_stream = import_ogg_vorbis(p_path);
if (ogg_stream.is_valid()) {
AudioStreamImportSettings::get_singleton()->edit(p_path, "oggvorbisstr", ogg_stream);
}
}
#endif

Error ResourceImporterOggVorbis::import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) {
bool loop = p_options["loop"];
float loop_offset = p_options["loop_offset"];
double bpm = p_options["bpm"];
int beat_count = p_options["beat_count"];
int bar_beats = p_options["bar_beats"];

Ref<AudioStreamOggVorbis> ogg_vorbis_stream = import_ogg_vorbis(p_source_file);
if (ogg_vorbis_stream.is_null()) {
return ERR_CANT_OPEN;
}

ogg_vorbis_stream->set_loop(loop);
ogg_vorbis_stream->set_loop_offset(loop_offset);
ogg_vorbis_stream->set_bpm(bpm);
ogg_vorbis_stream->set_beat_count(beat_count);
ogg_vorbis_stream->set_bar_beats(bar_beats);

return ResourceSaver::save(ogg_vorbis_stream, p_save_path + ".oggvorbisstr");
}

ResourceImporterOggVorbis::ResourceImporterOggVorbis() {
Ref<AudioStreamOggVorbis> ResourceImporterOggVorbis::load_from_file(const String &p_path) {
Vector<uint8_t> file_data = FileAccess::get_file_as_bytes(p_path);
ERR_FAIL_COND_V_MSG(file_data.is_empty(), Ref<AudioStreamOggVorbis>(), "Cannot open file '" + p_path + "'.");
return load_from_buffer(file_data);
}
9 changes: 5 additions & 4 deletions modules/vorbis/resource_importer_ogg_vorbis.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,17 @@ class ResourceImporterOggVorbis : public ResourceImporter {
OGG_SYNC_BUFFER_SIZE = 8192,
};

private:
// virtual int get_samples_in_packet(Vector<uint8_t> p_packet) = 0;

static Ref<AudioStreamOggVorbis> import_ogg_vorbis(const String &p_path);
protected:
static void _bind_methods();

public:
#ifdef TOOLS_ENABLED
virtual bool has_advanced_options() const override;
virtual void show_advanced_options(const String &p_path) override;
#endif

static Ref<AudioStreamOggVorbis> load_from_file(const String &p_path);
static Ref<AudioStreamOggVorbis> load_from_buffer(const Vector<uint8_t> &file_data);
virtual void get_recognized_extensions(List<String> *p_extensions) const override;
virtual String get_save_extension() const override;
virtual String get_resource_type() const override;
Expand Down

0 comments on commit 7bc8a52

Please sign in to comment.