OggVorbisCodec.cxx
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
00069
00070
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
00084
00085 ov_clear( &vorbisFile );
00086
00087 return true;
00088
00089 }
00090
00091 bool OggVorbisCodec::IsWritable( std::string uri, const AudioFileHeader& hdr ) const
00092 {
00093
00094
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 )
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
00148
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 )
00169 return;
00170
00171
00172 vorbis_comment* fileComments = ov_comment( &vorbisFile, -1 );
00173
00174 if ( !fileComments )
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
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
00239 }
00240 }
00241
00242 }
00243
00244 ov_clear( &vorbisFile );
00245 }
00246 }
00247
00248 }
00249