diff options
author | RĂ©mi Verschelde <remi@verschelde.fr> | 2016-10-16 11:52:09 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-10-16 11:52:09 +0200 |
commit | 89132224a651c0e0d4121270f63decb9a678ff88 (patch) | |
tree | 224a008705391b6e5b560d2c0426380651756383 /modules/vorbis | |
parent | eb8d19ba740c11acf0f26080405fc5cd827a2d41 (diff) | |
parent | e57042e8a93e4f3d65cc91633f5af0daedf69a2a (diff) |
Merge pull request #6830 from akien-mga/thirdparty
Move most "drivers" as toggleable "modules" and split their thirdparty libraries in an own tree
Diffstat (limited to 'modules/vorbis')
-rw-r--r-- | modules/vorbis/SCsub | 47 | ||||
-rw-r--r-- | modules/vorbis/audio_stream_ogg_vorbis.cpp | 430 | ||||
-rw-r--r-- | modules/vorbis/audio_stream_ogg_vorbis.h | 142 | ||||
-rw-r--r-- | modules/vorbis/config.py | 6 | ||||
-rw-r--r-- | modules/vorbis/register_types.cpp | 45 | ||||
-rw-r--r-- | modules/vorbis/register_types.h | 30 |
6 files changed, 700 insertions, 0 deletions
diff --git a/modules/vorbis/SCsub b/modules/vorbis/SCsub new file mode 100644 index 0000000000..f3dbc893fc --- /dev/null +++ b/modules/vorbis/SCsub @@ -0,0 +1,47 @@ +Import('env') +Import('env_modules') + +env_vorbis = env_modules.Clone() + +# Thirdparty source files +if (env["libvorbis"] != "system"): # builtin + thirdparty_dir = "#thirdparty/libvorbis/" + thirdparty_sources = [ + #"analysis.c", + #"barkmel.c", + "bitrate.c", + "block.c", + "codebook.c", + "envelope.c", + "floor0.c", + "floor1.c", + "info.c", + "lookup.c", + "lpc.c", + "lsp.c", + "mapping0.c", + "mdct.c", + "psy.c", + #"psytune.c", + "registry.c", + "res0.c", + "sharedbook.c", + "smallft.c", + "synthesis.c", + #"tone.c", + #"vorbisenc.c", + "vorbisfile.c", + "window.c", + ] + + thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] + + env_vorbis.add_source_files(env.modules_sources, thirdparty_sources) + env_vorbis.Append(CPPPATH = [thirdparty_dir]) + + # also requires libogg + if (env["libogg"] != "system"): # builtin + env_vorbis.Append(CPPPATH = ["#thirdparty/libogg"]) + +# Godot source files +env_vorbis.add_source_files(env.modules_sources, "*.cpp") diff --git a/modules/vorbis/audio_stream_ogg_vorbis.cpp b/modules/vorbis/audio_stream_ogg_vorbis.cpp new file mode 100644 index 0000000000..4ce7940a01 --- /dev/null +++ b/modules/vorbis/audio_stream_ogg_vorbis.cpp @@ -0,0 +1,430 @@ +/*************************************************************************/ +/* audio_stream_ogg_vorbis.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 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. */ +/*************************************************************************/ +#include "audio_stream_ogg_vorbis.h" + + + +size_t AudioStreamPlaybackOGGVorbis::_ov_read_func(void *p_dst,size_t p_data, size_t p_count, void *_f) { + + //printf("read to %p, %i bytes, %i nmemb, %p\n",p_dst,p_data,p_count,_f); + FileAccess *fa=(FileAccess*)_f; + size_t read_total = p_data*p_count; + + if (fa->eof_reached()) + return 0; + + uint8_t *dst=(uint8_t*)p_dst; + + int read = fa->get_buffer(dst, read_total); + + return read; +} + +int AudioStreamPlaybackOGGVorbis::_ov_seek_func(void *_f,ogg_int64_t offs, int whence) { + + //printf("seek to %p, offs %i, whence %i\n",_f,(int)offs,whence); + +#ifdef SEEK_SET + //printf("seek set defined\n"); + FileAccess *fa=(FileAccess*)_f; + + if (whence==SEEK_SET) { + + fa->seek(offs); + } else if (whence==SEEK_CUR) { + + fa->seek(fa->get_pos()+offs); + } else if (whence==SEEK_END) { + + fa->seek_end(offs); + } else { + + ERR_PRINT("BUG, wtf was whence set to?\n"); + } + int ret=fa->eof_reached()?-1:0; + //printf("returning %i\n",ret); + return ret; + +#else + return -1; // no seeking +#endif + +} +int AudioStreamPlaybackOGGVorbis::_ov_close_func(void *_f) { + +// printf("close %p\n",_f); + if (!_f) + return 0; + FileAccess *fa=(FileAccess*)_f; + if (fa->is_open()) + fa->close(); + return 0; +} +long AudioStreamPlaybackOGGVorbis::_ov_tell_func(void *_f) { + + //printf("close %p\n",_f); + + FileAccess *fa=(FileAccess*)_f; + return fa->get_pos(); +} + + + +int AudioStreamPlaybackOGGVorbis::mix(int16_t* p_bufer,int p_frames) { + + if (!playing) + return 0; + + int total=p_frames; + while (true) { + + int todo = p_frames; + + if (todo==0 || todo<MIN_MIX) { + break; + } + + //printf("to mix %i - mix me %i bytes\n",to_mix,to_mix*stream_channels*sizeof(int16_t)); + + #ifdef BIG_ENDIAN_ENABLED + long ret=ov_read(&vf,(char*)p_bufer,todo*stream_channels*sizeof(int16_t), 1, 2, 1, ¤t_section); + #else + long ret=ov_read(&vf,(char*)p_bufer,todo*stream_channels*sizeof(int16_t), 0, 2, 1, ¤t_section); + #endif + + if (ret<0) { + + playing = false; + ERR_EXPLAIN("Error reading OGG Vorbis File: "+file); + ERR_BREAK(ret<0); + } else if (ret==0) { // end of song, reload? + + ov_clear(&vf); + + _close_file(); + + if (!has_loop()) { + + playing=false; + repeats=1; + break; + } + + f=FileAccess::open(file,FileAccess::READ); + + int errv = ov_open_callbacks(f,&vf,NULL,0,_ov_callbacks); + if (errv!=0) { + playing=false; + break;; // :( + } + + if (loop_restart_time) { + bool ok = ov_time_seek(&vf,loop_restart_time)==0; + if (!ok) { + playing=false; + //ERR_EXPLAIN("loop restart time rejected"); + ERR_PRINT("loop restart time rejected") + } + + frames_mixed=stream_srate*loop_restart_time; + } else { + + frames_mixed=0; + } + repeats++; + continue; + + } + + ret/=stream_channels; + ret/=sizeof(int16_t); + + frames_mixed+=ret; + + p_bufer+=ret*stream_channels; + p_frames-=ret; + + } + + return total-p_frames; + +} + + + +void AudioStreamPlaybackOGGVorbis::play(float p_from) { + + if (playing) + stop(); + + if (_load_stream()!=OK) + return; + + + frames_mixed=0; + playing=true; + if (p_from>0) { + seek_pos(p_from); + } +} + +void AudioStreamPlaybackOGGVorbis::_close_file() { + + if (f) { + + memdelete(f); + f=NULL; + } +} + +bool AudioStreamPlaybackOGGVorbis::is_playing() const { + return playing; +} +void AudioStreamPlaybackOGGVorbis::stop() { + + _clear_stream(); + playing=false; + //_clear(); +} + + + +float AudioStreamPlaybackOGGVorbis::get_pos() const { + + int32_t frames = int32_t(frames_mixed); + if (frames < 0) + frames=0; + return double(frames) / stream_srate; +} + +void AudioStreamPlaybackOGGVorbis::seek_pos(float p_time) { + + + + if (!playing) + return; + bool ok = ov_time_seek(&vf,p_time)==0; + ERR_FAIL_COND(!ok); + frames_mixed=stream_srate*p_time; +} + +String AudioStreamPlaybackOGGVorbis::get_stream_name() const { + + return ""; +} + +void AudioStreamPlaybackOGGVorbis::set_loop(bool p_enable) { + + loops=p_enable; +} + +bool AudioStreamPlaybackOGGVorbis::has_loop() const { + + return loops; +} + +int AudioStreamPlaybackOGGVorbis::get_loop_count() const { + return repeats; +} + + +Error AudioStreamPlaybackOGGVorbis::set_file(const String& p_file) { + + file=p_file; + stream_valid=false; + Error err; + f=FileAccess::open(file,FileAccess::READ,&err); + + if (err) { + ERR_FAIL_COND_V( err, err ); + } + + int errv = ov_open_callbacks(f,&vf,NULL,0,_ov_callbacks); + switch(errv) { + + case OV_EREAD: { // - A read from media returned an error. + memdelete(f); f=NULL; + ERR_FAIL_V( ERR_FILE_CANT_READ ); + } break; + case OV_EVERSION: // - Vorbis version mismatch. + case OV_ENOTVORBIS: { // - Bitstream is not Vorbis data. + memdelete(f); f=NULL; + ERR_FAIL_V( ERR_FILE_UNRECOGNIZED ); + } break; + case OV_EBADHEADER: { // - Invalid Vorbis bitstream header. + memdelete(f); f=NULL; + ERR_FAIL_V( ERR_FILE_CORRUPT ); + } break; + case OV_EFAULT: { // - Internal logic fault; indicates a bug or heap/stack corruption. + memdelete(f); f=NULL; + ERR_FAIL_V( ERR_BUG ); + } break; + } + const vorbis_info *vinfo=ov_info(&vf,-1); + stream_channels=vinfo->channels; + stream_srate=vinfo->rate; + length = ov_time_total(&vf,-1); + ov_clear(&vf); + memdelete(f); + f=NULL; + stream_valid=true; + + + return OK; +} + +Error AudioStreamPlaybackOGGVorbis::_load_stream() { + + ERR_FAIL_COND_V(!stream_valid,ERR_UNCONFIGURED); + + _clear_stream(); + if (file=="") + return ERR_INVALID_DATA; + + Error err; + f=FileAccess::open(file,FileAccess::READ,&err); + if (err) { + ERR_FAIL_COND_V( err, err ); + } + + int errv = ov_open_callbacks(f,&vf,NULL,0,_ov_callbacks); + switch(errv) { + + case OV_EREAD: { // - A read from media returned an error. + memdelete(f); f=NULL; + ERR_FAIL_V( ERR_FILE_CANT_READ ); + } break; + case OV_EVERSION: // - Vorbis version mismatch. + case OV_ENOTVORBIS: { // - Bitstream is not Vorbis data. + memdelete(f); f=NULL; + ERR_FAIL_V( ERR_FILE_UNRECOGNIZED ); + } break; + case OV_EBADHEADER: { // - Invalid Vorbis bitstream header. + memdelete(f); f=NULL; + ERR_FAIL_V( ERR_FILE_CORRUPT ); + } break; + case OV_EFAULT: { // - Internal logic fault; indicates a bug or heap/stack corruption. + memdelete(f); f=NULL; + ERR_FAIL_V( ERR_BUG ); + } break; + } + repeats=0; + stream_loaded=true; + + + return OK; +} + + +float AudioStreamPlaybackOGGVorbis::get_length() const { + + if (!stream_loaded) { + if (const_cast<AudioStreamPlaybackOGGVorbis*>(this)->_load_stream()!=OK) + return 0; + } + return length; +} + +void AudioStreamPlaybackOGGVorbis::_clear_stream() { + + if (!stream_loaded) + return; + + ov_clear(&vf); + _close_file(); + + stream_loaded=false; + //stream_channels=1; + playing=false; +} + +void AudioStreamPlaybackOGGVorbis::set_paused(bool p_paused) { + + paused=p_paused; +} + +bool AudioStreamPlaybackOGGVorbis::is_paused(bool p_paused) const { + + return paused; +} + + +AudioStreamPlaybackOGGVorbis::AudioStreamPlaybackOGGVorbis() { + + loops=false; + playing=false; + _ov_callbacks.read_func=_ov_read_func; + _ov_callbacks.seek_func=_ov_seek_func; + _ov_callbacks.close_func=_ov_close_func; + _ov_callbacks.tell_func=_ov_tell_func; + f = NULL; + stream_loaded=false; + stream_valid=false; + repeats=0; + paused=true; + stream_channels=0; + stream_srate=0; + current_section=0; + length=0; + loop_restart_time=0; +} + + +AudioStreamPlaybackOGGVorbis::~AudioStreamPlaybackOGGVorbis() { + + _clear_stream(); + +} + + + +RES ResourceFormatLoaderAudioStreamOGGVorbis::load(const String &p_path, const String& p_original_path, Error *r_error) { + if (r_error) + *r_error=OK; + + AudioStreamOGGVorbis *ogg_stream = memnew(AudioStreamOGGVorbis); + ogg_stream->set_file(p_path); + return Ref<AudioStreamOGGVorbis>(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.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"); +} + diff --git a/modules/vorbis/audio_stream_ogg_vorbis.h b/modules/vorbis/audio_stream_ogg_vorbis.h new file mode 100644 index 0000000000..8d8d7392b5 --- /dev/null +++ b/modules/vorbis/audio_stream_ogg_vorbis.h @@ -0,0 +1,142 @@ +/*************************************************************************/ +/* audio_stream_ogg_vorbis.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 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 AUDIO_STREAM_OGG_VORBIS_H +#define AUDIO_STREAM_OGG_VORBIS_H + +#include "io/resource_loader.h" +#include "os/file_access.h" +#include "os/thread_safe.h" +#include "scene/resources/audio_stream.h" + +#include <vorbis/vorbisfile.h> + +class AudioStreamPlaybackOGGVorbis : public AudioStreamPlayback { + + OBJ_TYPE(AudioStreamPlaybackOGGVorbis,AudioStreamPlayback); + + enum { + MIN_MIX=1024 + }; + + FileAccess *f; + + ov_callbacks _ov_callbacks; + float length; + static size_t _ov_read_func(void *p_dst,size_t p_data, size_t p_count, void *_f); + static int _ov_seek_func(void *_f,ogg_int64_t offs, int whence); + static int _ov_close_func(void *_f); + static long _ov_tell_func(void *_f); + + String file; + int64_t frames_mixed; + + bool stream_loaded; + volatile bool playing; + OggVorbis_File vf; + int stream_channels; + int stream_srate; + int current_section; + + + bool paused; + bool loops; + int repeats; + + Error _load_stream(); + void _clear_stream(); + void _close_file(); + + bool stream_valid; + float loop_restart_time; + + +public: + + + Error set_file(const String& p_file); + + virtual void play(float p_from=0); + virtual void stop(); + virtual bool is_playing() const; + + virtual void set_loop_restart_time(float p_time) { loop_restart_time=p_time; } + + virtual void set_paused(bool p_paused); + virtual bool is_paused(bool p_paused) const; + + virtual void set_loop(bool p_enable); + virtual bool has_loop() const; + + virtual float get_length() const; + + virtual String get_stream_name() const; + + virtual int get_loop_count() const; + + virtual float get_pos() const; + virtual void seek_pos(float p_time); + + virtual int get_channels() const { return stream_channels; } + virtual int get_mix_rate() const { return stream_srate; } + + virtual int get_minimum_buffer_size() const { return 0; } + virtual int mix(int16_t* p_bufer,int p_frames); + + AudioStreamPlaybackOGGVorbis(); + ~AudioStreamPlaybackOGGVorbis(); +}; + + +class AudioStreamOGGVorbis : public AudioStream { + + OBJ_TYPE(AudioStreamOGGVorbis,AudioStream); + + String file; +public: + + Ref<AudioStreamPlayback> instance_playback() { + Ref<AudioStreamPlaybackOGGVorbis> pb = memnew( AudioStreamPlaybackOGGVorbis ); + pb->set_file(file); + return pb; + } + + void set_file(const String& p_file) { file=p_file; } + +}; + +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 // AUDIO_STREAM_OGG_H diff --git a/modules/vorbis/config.py b/modules/vorbis/config.py new file mode 100644 index 0000000000..368e97e152 --- /dev/null +++ b/modules/vorbis/config.py @@ -0,0 +1,6 @@ + +def can_build(platform): + return True + +def configure(env): + pass diff --git a/modules/vorbis/register_types.cpp b/modules/vorbis/register_types.cpp new file mode 100644 index 0000000000..ae63b5af3c --- /dev/null +++ b/modules/vorbis/register_types.cpp @@ -0,0 +1,45 @@ +/*************************************************************************/ +/* register_types.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 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. */ +/*************************************************************************/ +#include "register_types.h" + +#include "audio_stream_ogg_vorbis.h" + +static ResourceFormatLoaderAudioStreamOGGVorbis *vorbis_stream_loader = NULL; + +void register_vorbis_types() { + + vorbis_stream_loader = memnew( ResourceFormatLoaderAudioStreamOGGVorbis ); + ResourceLoader::add_resource_format_loader(vorbis_stream_loader); + ObjectTypeDB::register_type<AudioStreamOGGVorbis>(); +} + +void unregister_vorbis_types() { + + memdelete( vorbis_stream_loader ); +} diff --git a/modules/vorbis/register_types.h b/modules/vorbis/register_types.h new file mode 100644 index 0000000000..6baaed7ce8 --- /dev/null +++ b/modules/vorbis/register_types.h @@ -0,0 +1,30 @@ +/*************************************************************************/ +/* register_types.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 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. */ +/*************************************************************************/ +void register_vorbis_types(); +void unregister_vorbis_types(); |