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 <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
00068
00069
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
00083
00084 ov_clear( &vorbisFile );
00085
00086 return true;
00087
00088 }
00089
00090 bool OggVorbisCodec::IsWritable( std::string uri, const AudioFileHeader& hdr ) const
00091 {
00092
00093
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 )
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
00147
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 )
00168 return;
00169
00170
00171 vorbis_comment* fileComments = ov_comment( &vorbisFile, -1 );
00172
00173 if ( !fileComments )
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
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
00238 }
00239 }
00240
00241 }
00242
00243 ov_clear( &vorbisFile );
00244 }
00245 }
00246
00247 }
00248