Changed OGG Vorbis type to be imported, so it's possible to specify loop

This commit is contained in:
Juan Linietsky 2017-02-03 08:55:29 -03:00
parent 9ce2ab9749
commit d2b2d6801f
5 changed files with 193 additions and 85 deletions

View File

@ -17,7 +17,7 @@ void AudioStreamPlaybackOGGVorbis::_mix_internal(AudioFrame* p_buffer,int p_fram
if (todo) {
//end of file!
if (false) {
if (vorbis_stream->loop) {
//loop
seek_pos(0);
loops++;
@ -120,9 +120,9 @@ String AudioStreamOGGVorbis::get_stream_name() const {
return "";//return stream_name;
}
Error AudioStreamOGGVorbis::setup(const uint8_t *p_data,uint32_t p_data_len) {
void AudioStreamOGGVorbis::set_data(const PoolVector<uint8_t>& p_data) {
int src_data_len=p_data.size();
#define MAX_TEST_MEM (1<<20)
uint32_t alloc_try=1024;
@ -139,37 +139,81 @@ Error AudioStreamOGGVorbis::setup(const uint8_t *p_data,uint32_t p_data_len) {
ogg_alloc.alloc_buffer=w.ptr();
ogg_alloc.alloc_buffer_length_in_bytes=alloc_try;
PoolVector<uint8_t>::Read src_datar = p_data.read();
int error;
ogg_stream = stb_vorbis_open_memory( (const unsigned char*)p_data, p_data_len, &error, &ogg_alloc );
ogg_stream = stb_vorbis_open_memory( (const unsigned char*)src_datar.ptr(), src_data_len, &error, &ogg_alloc );
if (!ogg_stream && error==VORBIS_outofmem) {
w = PoolVector<char>::Write();
alloc_try*=2;
} else {
ERR_FAIL_COND(alloc_try==MAX_TEST_MEM);
ERR_FAIL_COND(ogg_stream==NULL);
stb_vorbis_info info = stb_vorbis_get_info(ogg_stream);
channels = info.channels;
sample_rate = info.sample_rate;
decode_mem_size = alloc_try;
//does this work? (it's less mem..)
//decode_mem_size = ogg_alloc.alloc_buffer_length_in_bytes + info.setup_memory_required + info.temp_memory_required + info.max_frame_size;
//print_line("succeded "+itos(ogg_alloc.alloc_buffer_length_in_bytes)+" setup "+itos(info.setup_memory_required)+" setup temp "+itos(info.setup_temp_memory_required)+" temp "+itos(info.temp_memory_required)+" maxframe"+itos(info.max_frame_size));
length=stb_vorbis_stream_length_in_seconds(ogg_stream);
stb_vorbis_close(ogg_stream);
data = AudioServer::get_singleton()->audio_data_alloc(src_data_len,src_datar.ptr());
data_len=src_data_len;
break;
}
}
ERR_FAIL_COND_V(alloc_try==MAX_TEST_MEM,ERR_OUT_OF_MEMORY);
ERR_FAIL_COND_V(ogg_stream==NULL,ERR_FILE_CORRUPT);
stb_vorbis_info info = stb_vorbis_get_info(ogg_stream);
channels = info.channels;
sample_rate = info.sample_rate;
decode_mem_size = alloc_try;
//does this work? (it's less mem..)
//decode_mem_size = ogg_alloc.alloc_buffer_length_in_bytes + info.setup_memory_required + info.temp_memory_required + info.max_frame_size;
//print_line("succeded "+itos(ogg_alloc.alloc_buffer_length_in_bytes)+" setup "+itos(info.setup_memory_required)+" setup temp "+itos(info.setup_temp_memory_required)+" temp "+itos(info.temp_memory_required)+" maxframe"+itos(info.max_frame_size));
length=stb_vorbis_stream_length_in_seconds(ogg_stream);
stb_vorbis_close(ogg_stream);
data = AudioServer::get_singleton()->audio_data_alloc(p_data_len,p_data);
data_len=p_data_len;
printf("create at %p, data %p\n",this,data);
return OK;
}
PoolVector<uint8_t> AudioStreamOGGVorbis::get_data() const {
PoolVector<uint8_t> vdata;
if (data_len && data) {
vdata.resize(data_len);
{
PoolVector<uint8_t>::Write w = vdata.write();
copymem(w.ptr(),data,data_len);
}
}
return vdata;
}
void AudioStreamOGGVorbis::set_loop(bool p_enable) {
loop=p_enable;
}
bool AudioStreamOGGVorbis::has_loop() const {
return loop;
}
void AudioStreamOGGVorbis::_bind_methods() {
ClassDB::bind_method(_MD("set_data","data"),&AudioStreamOGGVorbis::set_data);
ClassDB::bind_method(_MD("get_data"),&AudioStreamOGGVorbis::get_data);
ClassDB::bind_method(_MD("set_loop","enable"),&AudioStreamOGGVorbis::set_loop);
ClassDB::bind_method(_MD("has_loop"),&AudioStreamOGGVorbis::has_loop);
ADD_PROPERTY(PropertyInfo(Variant::POOL_BYTE_ARRAY,"data",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("set_data"),_SCS("get_data"));
ADD_PROPERTY(PropertyInfo(Variant::BOOL,"loop",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("set_loop"),_SCS("has_loop"));
}
AudioStreamOGGVorbis::AudioStreamOGGVorbis() {
@ -180,57 +224,9 @@ AudioStreamOGGVorbis::AudioStreamOGGVorbis() {
sample_rate=1;
channels=1;
decode_mem_size=0;
loop=false;
}
RES ResourceFormatLoaderAudioStreamOGGVorbis::load(const String &p_path, const String& p_original_path, Error *r_error) {
if (r_error)
*r_error=OK;
FileAccess *f = FileAccess::open(p_path,FileAccess::READ);
if (!f) {
*r_error=ERR_CANT_OPEN;
ERR_FAIL_COND_V(!f,RES());
}
size_t len = f->get_len();
PoolVector<uint8_t> data;
data.resize(len);
PoolVector<uint8_t>::Write w = data.write();
f->get_buffer(w.ptr(),len);
memdelete(f);
Ref<AudioStreamOGGVorbis> ogg_stream;
ogg_stream.instance();
Error err = ogg_stream->setup(w.ptr(),len);
if (err!=OK) {
*r_error=err;
ogg_stream.unref();
ERR_FAIL_V(RES());
}
return ogg_stream;
}
void ResourceFormatLoaderAudioStreamOGGVorbis::get_recognized_extensions(List<String> *p_extensions) const {
p_extensions->push_back("ogg");
}
String ResourceFormatLoaderAudioStreamOGGVorbis::get_resource_type(const String &p_path) const {
if (p_path.get_extension().to_lower()=="ogg")
return "AudioStreamOGGVorbis";
return "";
}
bool ResourceFormatLoaderAudioStreamOGGVorbis::handles_type(const String& p_type) const {
return (p_type=="AudioStream" || p_type=="AudioStreamOGG" || p_type=="AudioStreamOGGVorbis");
}

View File

@ -49,6 +49,7 @@ class AudioStreamOGGVorbis : public AudioStream {
GDCLASS( AudioStreamOGGVorbis, AudioStream )
OBJ_SAVE_TYPE( AudioStream ) //children are all saved as AudioStream, so they can be exchanged
RES_BASE_EXTENSION("asogg");
friend class AudioStreamPlaybackOGGVorbis;
@ -59,26 +60,24 @@ friend class AudioStreamPlaybackOGGVorbis;
float sample_rate;
int channels;
float length;
bool loop;
protected:
static void _bind_methods();
public:
void set_loop(bool p_enable);
bool has_loop() const;
virtual Ref<AudioStreamPlayback> instance_playback();
virtual String get_stream_name() const;
Error setup(const uint8_t *p_data, uint32_t p_data_len);
void set_data(const PoolVector<uint8_t>& p_data);
PoolVector<uint8_t> get_data() const;
AudioStreamOGGVorbis();
};
class ResourceFormatLoaderAudioStreamOGGVorbis : public ResourceFormatLoader {
public:
virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String& p_type) const;
virtual String get_resource_type(const String &p_path) const;
};
#endif

View File

@ -28,17 +28,18 @@
/*************************************************************************/
#include "register_types.h"
#include "audio_stream_ogg_vorbis.h"
static ResourceFormatLoaderAudioStreamOGGVorbis *vorbis_stream_loader = NULL;
#include "resource_importer_ogg_vorbis.h"
void register_stb_vorbis_types() {
vorbis_stream_loader = memnew( ResourceFormatLoaderAudioStreamOGGVorbis );
ResourceLoader::add_resource_format_loader(vorbis_stream_loader);
#ifdef TOOLS_ENABLED
Ref<ResourceImporterOGGVorbis> ogg_import;
ogg_import.instance();
ResourceFormatImporter::get_singleton()->add_importer(ogg_import);
#endif
ClassDB::register_class<AudioStreamOGGVorbis>();
}
void unregister_stb_vorbis_types() {
memdelete( vorbis_stream_loader );
}

View File

@ -0,0 +1,84 @@
#include "resource_importer_ogg_vorbis.h"
#include "io/resource_saver.h"
#include "os/file_access.h"
#include "scene/resources/texture.h"
String ResourceImporterOGGVorbis::get_importer_name() const {
return "ogg_vorbis";
}
String ResourceImporterOGGVorbis::get_visible_name() const{
return "OGGVorbis";
}
void ResourceImporterOGGVorbis::get_recognized_extensions(List<String> *p_extensions) const{
p_extensions->push_back("ogg");
}
String ResourceImporterOGGVorbis::get_save_extension() const {
return "asogg";
}
String ResourceImporterOGGVorbis::get_resource_type() const{
return "AudioStreamOGGVorbis";
}
bool ResourceImporterOGGVorbis::get_option_visibility(const String& p_option,const Map<StringName,Variant>& p_options) const {
return true;
}
int ResourceImporterOGGVorbis::get_preset_count() const {
return 0;
}
String ResourceImporterOGGVorbis::get_preset_name(int p_idx) const {
return String();
}
void ResourceImporterOGGVorbis::get_import_options(List<ImportOption> *r_options,int p_preset) const {
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"loop"),true));
}
Error ResourceImporterOGGVorbis::import(const String& p_source_file, const String& p_save_path, const Map<StringName,Variant>& p_options, List<String>* r_platform_variants, List<String> *r_gen_files) {
bool loop = p_options["loop"];
FileAccess *f = FileAccess::open(p_source_file,FileAccess::READ);
if (!f) {
ERR_FAIL_COND_V(!f,ERR_CANT_OPEN);
}
size_t len = f->get_len();
PoolVector<uint8_t> data;
data.resize(len);
PoolVector<uint8_t>::Write w = data.write();
f->get_buffer(w.ptr(),len);
memdelete(f);
Ref<AudioStreamOGGVorbis> ogg_stream;
ogg_stream.instance();
ogg_stream->set_data(data);
ogg_stream->set_loop(loop);
return ResourceSaver::save(p_save_path+".asogg",ogg_stream);
}
ResourceImporterOGGVorbis::ResourceImporterOGGVorbis()
{
}

View File

@ -0,0 +1,28 @@
#ifndef RESOURCEIMPORTEROGGVORBIS_H
#define RESOURCEIMPORTEROGGVORBIS_H
#include "io/resource_import.h"
#include "audio_stream_ogg_vorbis.h"
class ResourceImporterOGGVorbis : public ResourceImporter {
GDCLASS(ResourceImporterOGGVorbis,ResourceImporter)
public:
virtual String get_importer_name() const;
virtual String get_visible_name() const;
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual String get_save_extension() const;
virtual String get_resource_type() const;
virtual int get_preset_count() const;
virtual String get_preset_name(int p_idx) const;
virtual void get_import_options(List<ImportOption> *r_options,int p_preset=0) const;
virtual bool get_option_visibility(const String& p_option,const Map<StringName,Variant>& p_options) const;
virtual Error import(const String& p_source_file,const String& p_save_path,const Map<StringName,Variant>& p_options,List<String>* r_platform_variants,List<String>* r_gen_files=NULL);
ResourceImporterOGGVorbis();
};
#endif // RESOURCEIMPORTEROGGVORBIS_H