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 <string>
00028 #include <algorithm>
00029 #include <vorbis/vorbisfile.h>
00030 #include <iostream>
00031 #include "AudioFileFormats.hxx"
00032 #include "AudioFile.hxx"
00033 #include "OggVorbisCodec.hxx"
00034 #include "OggVorbisAudioStream.hxx"
00035 
00036 namespace CLAM
00037 {
00038 
00039 namespace AudioCodecs
00040 {
00041         OggVorbisCodec::OggVorbisCodec()
00042         {
00043         }
00044 
00045         OggVorbisCodec::~OggVorbisCodec()
00046         {
00047         }
00048 
00049         OggVorbisCodec& OggVorbisCodec::Instantiate()
00050         {
00051                 static OggVorbisCodec theInstance;
00052 
00053                 return theInstance;
00054         }
00055 
00056         bool OggVorbisCodec::IsReadable( std::string uri ) const
00057         {
00058                 FILE*          fileHandle;
00059                 OggVorbis_File vorbisFile;
00060 
00061                 memset( &vorbisFile, 0, sizeof(OggVorbis_File) );
00062 
00063                 fileHandle = fopen( uri.c_str(), "rb" );
00064                 
00065                 if (  !fileHandle || ferror(fileHandle) != 0  )
00066                 {
00067                         //:TODO: possible exception throwing
00068                         //std::cerr << uri << std::endl;
00069                         //std::cerr << "Open failed! " << strerror( errno ) << std::endl;
00070                         return false;
00071                 }
00072 
00073                 int retval = ov_open( fileHandle, &vorbisFile, NULL, 0 );
00074 
00075                 if (  retval < 0 )              
00076                 {
00077                         fclose( fileHandle );
00078                         
00079                         return false;
00080                 }
00081 
00082                 // MRJ: No need to close the fileHandle since libvorbisfile takes
00083                 // its ownership if the ov_open call is successful
00084                 ov_clear( &vorbisFile );
00085 
00086                 return true;
00087 
00088         }
00089 
00090         bool OggVorbisCodec::IsWritable( std::string uri, const AudioFileHeader& hdr ) const
00091         {
00092                 // MRJ: These values were documented ( sort of ) in
00093                 // the Vorbis I specification document
00094 
00095                 if ( (hdr.GetChannels() < 0) || ( hdr.GetChannels() > 255) )
00096                         return false;
00097                 if ( (hdr.GetSampleRate() < 8000.) || ( hdr.GetSampleRate() > 192000.) )
00098                         return false;
00099                 
00100                 return true;    
00101         }
00102 
00103         Stream* OggVorbisCodec::GetStreamFor( const AudioFile& file )
00104         {
00105                 return new OggVorbisAudioStream(file);
00106         }
00107 
00108         void OggVorbisCodec::RetrieveHeaderData( std::string uri, AudioFileHeader& hdr )
00109         {
00110                 FILE*          fileHandle;
00111                 OggVorbis_File vorbisFile;
00112                 
00113                 if ( ( fileHandle = fopen( uri.c_str(), "rb" ) ) == NULL )
00114                      return;
00115 
00116                 if ( ov_open( fileHandle, &vorbisFile, NULL, 0 ) < 0 )          
00117                 {
00118                         fclose( fileHandle );                   
00119                         return;
00120                 }
00121 
00122                 vorbis_info* fileInfo = ov_info( &vorbisFile, -1 );
00123                 
00124                 if ( !fileInfo ) // File was encoded improperly
00125                         return;
00126 
00127                 hdr.AddSampleRate();
00128                 hdr.AddChannels();
00129         hdr.AddSamples();
00130                 hdr.AddFormat();
00131                 hdr.AddEncoding();
00132                 hdr.AddEndianess();
00133                 hdr.AddLength();
00134                 hdr.UpdateData();
00135 
00136                 hdr.SetSampleRate( (TData)fileInfo->rate );
00137                 hdr.SetChannels( (TSize)fileInfo->channels );
00138                 hdr.SetLength( (TTime)ov_time_total( &vorbisFile, -1) * 1000. );
00139                 hdr.SetFormat( EAudioFileFormat::eVorbisMk1 );
00140                 hdr.SetEncoding( EAudioFileEncoding::eDefault );
00141                 hdr.SetEndianess( EAudioFileEndianess::eDefault );
00142 
00143         double duration = hdr.GetLength()/1000.;
00144         hdr.SetSamples( TSize(duration*hdr.GetSampleRate()) );
00145         
00146                 // MRJ: No need to close the fileHandle since libvorbisfile takes
00147                 // its ownership if the ov_open call is successful
00148                 ov_clear( &vorbisFile );
00149         }
00150 
00151         void    OggVorbisCodec::RetrieveTextDescriptors( std::string uri, AudioTextDescriptors&  txtDesc )
00152         {
00153                 FILE*          fileHandle;
00154                 OggVorbis_File vorbisFile;
00155                 
00156                 if ( ( fileHandle = fopen( uri.c_str(), "rb" ) ) == NULL )
00157                      return;
00158 
00159                 if ( ov_open( fileHandle, &vorbisFile, NULL, 0 ) < 0 )          
00160                 {
00161                         fclose( fileHandle );                   
00162                         return;
00163                 }
00164 
00165                 vorbis_info* fileInfo = ov_info( &vorbisFile, -1 );
00166                 
00167                 if ( !fileInfo ) // File was encoded improperly
00168                         return;
00169 
00170 
00171                 vorbis_comment* fileComments = ov_comment( &vorbisFile, -1 );
00172 
00173                 if ( !fileComments ) // there were no comments in the file!
00174                 {
00175                         return;
00176                 }
00177                 
00178                 int nComments = fileComments->comments;
00179                 char** commentVector = fileComments->user_comments;
00180                 int*   commentLenVector = fileComments->comment_lengths;
00181 
00182                 for ( int i = 0; i < nComments; i++ )
00183                 {
00184                         // convert the current comment string into a std::string
00185                         std::string currentComment;
00186                         currentComment.assign( commentVector[i], 
00187                                                commentVector[i]+commentLenVector[i] );
00188                         
00189                         std::string::iterator eqPos = std::find( currentComment.begin(),
00190                                                                  currentComment.end(), '=' );
00191 
00192                         if ( eqPos < currentComment.end() )
00193                         {
00194                                 std::string fieldName;
00195                                 fieldName.assign( currentComment.begin(), eqPos );
00196 
00197                                 if( fieldName == "ARTIST" )
00198                                 {
00199                                         txtDesc.AddArtist();
00200                                         txtDesc.UpdateData();
00201                                         txtDesc.GetArtist().assign( eqPos+1, currentComment.end() );
00202                                 }
00203                                 else if ( fieldName == "TITLE" )
00204                                 {
00205                                         txtDesc.AddTitle();
00206                                         txtDesc.UpdateData();
00207                                         txtDesc.GetTitle().assign( eqPos+1, currentComment.end() );
00208                                 }
00209                                 else if ( fieldName == "ALBUM" )
00210                                 {
00211                                         txtDesc.AddAlbum();
00212                                         txtDesc.UpdateData();
00213                                         txtDesc.GetAlbum().assign( eqPos+1, currentComment.end() );
00214                                 }
00215                                 else if ( fieldName == "TRACKNUMBER" )
00216                                 {
00217                                         txtDesc.AddTrackNumber();
00218                                         txtDesc.UpdateData();
00219                                         txtDesc.GetTrackNumber().assign( eqPos+1, currentComment.end() );
00220                                 }
00221                                 else if ( fieldName == "PERFORMER" )
00222                                 {
00223                                         txtDesc.AddPerformer();
00224                                         txtDesc.UpdateData();
00225                                         txtDesc.GetPerformer().assign( eqPos+1, currentComment.end() );
00226                                 }
00227                                 else if ( fieldName == "COMPOSER" )
00228                                 {
00229                                         txtDesc.AddComposer();
00230                                         txtDesc.UpdateData();
00231                                         txtDesc.GetComposer().assign( eqPos+1, currentComment.end() );
00232                                 }
00233                                 else
00234                                 {
00235                                         std::string msg = fieldName;
00236                                         msg+= ":  Ignored comment field!";
00237                                         //CLAM_WARNING( false, msg.c_str() );
00238                                 }
00239                         }
00240                         
00241                 }
00242 
00243                 ov_clear( &vorbisFile );
00244         }
00245 }
00246 
00247 }
00248 

Generated on Tue Aug 12 22:33:43 2008 for CLAM by  doxygen 1.5.5