diff --git a/timeline/src/Engine/Audio_File.C b/timeline/src/Engine/Audio_File.C index eeea756..285380e 100644 --- a/timeline/src/Engine/Audio_File.C +++ b/timeline/src/Engine/Audio_File.C @@ -88,6 +88,21 @@ Audio_File::filename ( void ) const return _path; } +static bool is_poor_seeker ( const char * filename ) +{ + if ( ( strlen(filename) > 4 && + ! strcasecmp( &filename[strlen(filename)-4], ".ogg" ) ) + || + ( strlen(filename) > 5 && + ! strcasecmp( &filename[strlen(filename)-5], ".flac" ) ) + ) + { + return true; + } + + return false; +} + /** attempt to open any supported filetype */ Audio_File * Audio_File::from_file ( const char * filename ) @@ -96,11 +111,21 @@ Audio_File::from_file ( const char * filename ) Audio_File *a; - if ( ( a = _open_files[ std::string( filename ) ] ) ) + if ( is_poor_seeker(filename) ) { - ++a->_refs; - - return a; + /* OGG and FLAC have poor seek performance, so they require + * separate file descriptors to be useful */ + } + else + { + /* WAV are quick enough to seek that we can save + * filedescriptors by sharing them between regions */ + if ( ( a = _open_files[ std::string( filename ) ] ) ) + { + ++a->_refs; + + return a; + } } if ( ( a = Audio_File_SF::from_file( filename ) ) ) @@ -118,7 +143,7 @@ Audio_File::from_file ( const char * filename ) done: - ASSERT( ! _open_files[ std::string( filename ) ], "Programming errror" ); + /* ASSERT( ! _open_files[ std::string( filename ) ], "Programming errror" ); */ _open_files[ std::string( filename ) ] = a; @@ -130,8 +155,15 @@ done: Audio_File * Audio_File::duplicate ( void ) { - ++_refs; - return this; + if ( is_poor_seeker( _filename ) ) + { + return from_file(_filename); + } + else + { + ++_refs; + return this; + } } /** release the resources assoicated with this audio file if no other diff --git a/timeline/src/Engine/Audio_File.H b/timeline/src/Engine/Audio_File.H index 29a2f88..068074b 100644 --- a/timeline/src/Engine/Audio_File.H +++ b/timeline/src/Engine/Audio_File.H @@ -49,6 +49,7 @@ protected: const char *name; const char *extension; unsigned long id; + int quality; }; char *_filename; diff --git a/timeline/src/Engine/Audio_File_SF.C b/timeline/src/Engine/Audio_File_SF.C index 70f9edd..a7258d9 100644 --- a/timeline/src/Engine/Audio_File_SF.C +++ b/timeline/src/Engine/Audio_File_SF.C @@ -42,11 +42,13 @@ const Audio_File::format_desc Audio_File_SF::supported_formats[] = { "Wav 24", "wav", SF_FORMAT_WAV | SF_FORMAT_PCM_24 | SF_ENDIAN_FILE }, { "Wav 16", "wav", SF_FORMAT_WAV | SF_FORMAT_PCM_16 | SF_ENDIAN_FILE }, { "Wav f32", "wav", SF_FORMAT_WAV | SF_FORMAT_FLOAT | SF_ENDIAN_FILE }, - { "Au 24", "au", SF_FORMAT_AU | SF_FORMAT_PCM_24 | SF_ENDIAN_FILE }, - { "Au 16", "au", SF_FORMAT_AU | SF_FORMAT_PCM_16 | SF_ENDIAN_FILE }, - { "FLAC", "flac", SF_FORMAT_FLAC | SF_FORMAT_PCM_24 }, -#ifdef HAS_SF_FORMAT_VORBIS - { "Ogg Vorbis", "ogg", SF_FORMAT_OGG | SF_FORMAT_VORBIS | SF_FORMAT_PCM_16 }, + { "Au 24", "au", SF_FORMAT_AU | SF_FORMAT_PCM_24 | SF_ENDIAN_FILE }, + { "Au 16", "au", SF_FORMAT_AU | SF_FORMAT_PCM_16 | SF_ENDIAN_FILE }, + { "FLAC", "flac", SF_FORMAT_FLAC | SF_FORMAT_PCM_24 }, +#ifdef HAVE_SF_FORMAT_VORBIS + { "Vorbis q10", "ogg", SF_FORMAT_OGG | SF_FORMAT_VORBIS, 10 }, + { "Vorbis q6", "ogg", SF_FORMAT_OGG | SF_FORMAT_VORBIS, 6 }, + { "Vorbis q3", "ogg", SF_FORMAT_OGG | SF_FORMAT_VORBIS, 3 }, #endif { 0, 0 } }; @@ -125,6 +127,14 @@ Audio_File_SF::create ( const char *filename, nframes_t samplerate, int channels return NULL; } + if ( !strcmp( fd->extension, "ogg" ) ) + { + /* set high quality encoding for vorbis */ + double quality = ( fd->quality + 1 ) / (float)11; + + sf_command( out, SFC_SET_VBR_ENCODING_QUALITY, &quality, sizeof( double ) ); + } + Audio_File_SF *c = new Audio_File_SF; c->_path = filepath; diff --git a/timeline/wscript b/timeline/wscript index b7a45fa..6a7762a 100644 --- a/timeline/wscript +++ b/timeline/wscript @@ -31,7 +31,12 @@ def configure(conf): # conf.env.append_value('CXXFLAGS', '-D_FILE_OFFSET_BITS=64') conf.check_cfg(package='sndfile', uselib_store='SNDFILE',args="--cflags --libs", - atleast_version='1.0.17', mandatory=True) + atleast_version='1.0.18', mandatory=True) + + conf.check(msg='Checking for SF_FORMAT_VORBIS', + define_name='HAVE_SF_FORMAT_VORBIS', + fragment='#include \nint main ( int argc, char **argv ) { return SF_FORMAT_VORBIS; }', + execute=False, mandatory=False) conf.define('VERSION', PACKAGE_VERSION) conf.define('SYSTEM_PATH', '/'.join( [ conf.env.DATADIR, APPNAME ] ) )