OggVorbisCodec.cxx

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2004 MUSIC TECHNOLOGY GROUP (MTG)
00003  *                         UNIVERSITAT POMPEU FABRA
00004  *
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  *
00020  */
00021 
00022 #if USE_OGGVORBIS != 1
00023 #error USE_OGGVORBIS was not set to 1 in your settings.cfg file, but you are including files that require this. Please fix your settings.cfg
00024 #endif
00025 
00026 #include <cstdio>
00027 #include <cstring>
00028 #include <string>
00029 #include <algorithm>
00030 #include <vorbis/vorbisfile.h>
00031 #include <iostream>
00032 #include "AudioFileFormats.hxx"
00033 #include "AudioFile.hxx"
00034 #include "OggVorbisCodec.hxx"
00035 #include "OggVorbisAudioStream.hxx"
00036 
00037 namespace CLAM
00038 {
00039 
00040 namespace AudioCodecs
00041 {
00042         OggVorbisCodec::OggVorbisCodec()
00043         {
00044         }
00045 
00046         OggVorbisCodec::~OggVorbisCodec()
00047         {
00048         }
00049 
00050         OggVorbisCodec& OggVorbisCodec::Instantiate()
00051         {
00052                 static OggVorbisCodec theInstance;
00053 
00054                 return theInstance;
00055         }
00056 
00057         bool OggVorbisCodec::IsReadable( std::string uri ) const
00058         {
00059                 FILE*          fileHandle;
00060                 OggVorbis_File vorbisFile;
00061 
00062                 memset( &vorbisFile, 0, sizeof(OggVorbis_File) );
00063 
00064                 fileHandle = fopen( uri.c_str(), "rb" );
00065                 
00066                 if (  !fileHandle || ferror(fileHandle) != 0  )
00067                 {
00068                         //:TODO: possible exception throwing
00069                         //std::cerr << uri << std::endl;
00070                         //std::cerr << "Open failed! " << strerror( errno ) << std::endl;
00071                         return false;
00072                 }
00073 
00074                 int retval = ov_open( fileHandle, &vorbisFile, NULL, 0 );
00075 
00076                 if (  retval < 0 )              
00077                 {
00078                         fclose( fileHandle );
00079                         
00080                         return false;
00081                 }
00082 
00083                 // MRJ: No need to close the fileHandle since libvorbisfile takes
00084                 // its ownership if the ov_open call is successful
00085                 ov_clear( &vorbisFile );
00086 
00087                 return true;
00088 
00089         }
00090 
00091         bool OggVorbisCodec::IsWritable( std::string uri, const AudioFileHeader& hdr ) const
00092         {
00093                 // MRJ: These values were documented ( sort of ) in
00094                 // the Vorbis I specification document
00095 
00096                 if ( (hdr.GetChannels() < 0) || ( hdr.GetChannels() > 255) )
00097                         return false;
00098                 if ( (hdr.GetSampleRate() < 8000.) || ( hdr.GetSampleRate() > 192000.) )
00099                         return false;
00100                 
00101                 return true;    
00102         }
00103 
00104         Stream* OggVorbisCodec::GetStreamFor( const AudioFile& file )
00105         {
00106                 return new OggVorbisAudioStream(file);
00107         }
00108 
00109         void OggVorbisCodec::RetrieveHeaderData( std::string uri, AudioFileHeader& hdr )
00110         {
00111                 FILE*          fileHandle;
00112                 OggVorbis_File vorbisFile;
00113                 
00114                 if ( ( fileHandle = fopen( uri.c_str(), "rb" ) ) == NULL )
00115                      return;
00116 
00117                 if ( ov_open( fileHandle, &vorbisFile, NULL, 0 ) < 0 )          
00118                 {
00119                         fclose( fileHandle );                   
00120                         return;
00121                 }
00122 
00123                 vorbis_info* fileInfo = ov_info( &vorbisFile, -1 );
00124                 
00125                 if ( !fileInfo ) // File was encoded improperly
00126                         return;
00127 
00128                 hdr.AddSampleRate();
00129                 hdr.AddChannels();
00130         hdr.AddSamples();
00131                 hdr.AddFormat();
00132                 hdr.AddEncoding();
00133                 hdr.AddEndianess();
00134                 hdr.AddLength();
00135                 hdr.UpdateData();
00136 
00137                 hdr.SetSampleRate( (TData)fileInfo->rate );
00138                 hdr.SetChannels( (TSize)fileInfo->channels );
00139                 hdr.SetLength( (TTime)ov_time_total( &vorbisFile, -1) * 1000. );
00140                 hdr.SetFormat( EAudioFileFormat::eVorbisMk1 );
00141                 hdr.SetEncoding( EAudioFileEncoding::eDefault );
00142                 hdr.SetEndianess( EAudioFileEndianess::eDefault );
00143 
00144         double duration = hdr.GetLength()/1000.;
00145         hdr.SetSamples( TSize(duration*hdr.GetSampleRate()) );
00146         
00147                 // MRJ: No need to close the fileHandle since libvorbisfile takes
00148                 // its ownership if the ov_open call is successful
00149                 ov_clear( &vorbisFile );
00150         }
00151 
00152         void    OggVorbisCodec::RetrieveTextDescriptors( std::string uri, AudioTextDescriptors&  txtDesc )
00153         {
00154                 FILE*          fileHandle;
00155                 OggVorbis_File vorbisFile;
00156                 
00157                 if ( ( fileHandle = fopen( uri.c_str(), "rb" ) ) == NULL )
00158                      return;
00159 
00160                 if ( ov_open( fileHandle, &vorbisFile, NULL, 0 ) < 0 )          
00161                 {
00162                         fclose( fileHandle );                   
00163                         return;
00164                 }
00165 
00166                 vorbis_info* fileInfo = ov_info( &vorbisFile, -1 );
00167                 
00168                 if ( !fileInfo ) // File was encoded improperly
00169                         return;
00170 
00171 
00172                 vorbis_comment* fileComments = ov_comment( &vorbisFile, -1 );
00173 
00174                 if ( !fileComments ) // there were no comments in the file!
00175                 {
00176                         return;
00177                 }
00178                 
00179                 int nComments = fileComments->comments;
00180                 char** commentVector = fileComments->user_comments;
00181                 int*   commentLenVector = fileComments->comment_lengths;
00182 
00183                 for ( int i = 0; i < nComments; i++ )
00184                 {
00185                         // convert the current comment string into a std::string
00186                         std::string currentComment;
00187                         currentComment.assign( commentVector[i], 
00188                                                commentVector[i]+commentLenVector[i] );
00189                         
00190                         std::string::iterator eqPos = std::find( currentComment.begin(),
00191                                                                  currentComment.end(), '=' );
00192 
00193                         if ( eqPos < currentComment.end() )
00194                         {
00195                                 std::string fieldName;
00196                                 fieldName.assign( currentComment.begin(), eqPos );
00197 
00198                                 if( fieldName == "ARTIST" )
00199                                 {
00200                                         txtDesc.AddArtist();
00201                                         txtDesc.UpdateData();
00202                                         txtDesc.GetArtist().assign( eqPos+1, currentComment.end() );
00203                                 }
00204                                 else if ( fieldName == "TITLE" )
00205                                 {
00206                                         txtDesc.AddTitle();
00207                                         txtDesc.UpdateData();
00208                                         txtDesc.GetTitle().assign( eqPos+1, currentComment.end() );
00209                                 }
00210                                 else if ( fieldName == "ALBUM" )
00211                                 {
00212                                         txtDesc.AddAlbum();
00213                                         txtDesc.UpdateData();
00214                                         txtDesc.GetAlbum().assign( eqPos+1, currentComment.end() );
00215                                 }
00216                                 else if ( fieldName == "TRACKNUMBER" )
00217                                 {
00218                                         txtDesc.AddTrackNumber();
00219                                         txtDesc.UpdateData();
00220                                         txtDesc.GetTrackNumber().assign( eqPos+1, currentComment.end() );
00221                                 }
00222                                 else if ( fieldName == "PERFORMER" )
00223                                 {
00224                                         txtDesc.AddPerformer();
00225                                         txtDesc.UpdateData();
00226                                         txtDesc.GetPerformer().assign( eqPos+1, currentComment.end() );
00227                                 }
00228                                 else if ( fieldName == "COMPOSER" )
00229                                 {
00230                                         txtDesc.AddComposer();
00231                                         txtDesc.UpdateData();
00232                                         txtDesc.GetComposer().assign( eqPos+1, currentComment.end() );
00233                                 }
00234                                 else
00235                                 {
00236                                         std::string msg = fieldName;
00237                                         msg+= ":  Ignored comment field!";
00238                                         //CLAM_WARNING( false, msg.c_str() );
00239                                 }
00240                         }
00241                         
00242                 }
00243 
00244                 ov_clear( &vorbisFile );
00245         }
00246 }
00247 
00248 }
00249 
Generated by  doxygen 1.6.3