MpegAudioStream.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 #include "MpegAudioStream.hxx"
00023 #include "AudioFile.hxx"
00024 #include "Assert.hxx"
00025 #include <iostream>
00026 
00027 namespace CLAM
00028 {
00029 
00030 namespace AudioCodecs
00031 {
00032         // A reasonable multiple of four
00033         const TSize MpegAudioStream::mMaxDecodedBlockSize = 8192;
00034 
00035         MpegAudioStream::MpegAudioStream()
00036                 : mpHandle( NULL )
00037         {
00038         }
00039 
00040         MpegAudioStream::MpegAudioStream( const AudioFile& file )
00041                 : mpHandle( NULL )
00042         {
00043                 SetFOI( file );
00044         }
00045 
00046         MpegAudioStream::~MpegAudioStream()
00047         {
00048                 
00049                 if ( mpHandle )
00050                 {
00051                         if ( fclose(mpHandle) )
00052                         {
00053                                 std::string msgString = "Could not close ";
00054                                 msgString += mName;
00055 
00056                                 CLAM_ASSERT( false, msgString.c_str() );
00057                         }                       
00058                 }
00059                 
00060         }
00061         
00062         void MpegAudioStream::SetFOI( const AudioFile& file )
00063         {
00064                 AudioFileToNative( file );              
00065         }
00066 
00067         void MpegAudioStream::AudioFileToNative( const AudioFile& file )
00068         {
00069                 mName = file.GetLocation();
00070                 mEncodedSampleRate = (int)file.GetHeader().GetSampleRate();
00071                 mEncodedChannels = (int)file.GetHeader().GetChannels();
00072 
00073                 mDecodeBuffer.resize( mEncodedChannels );
00074         }
00075 
00076         void MpegAudioStream::PrepareReading()
00077         {
00078                 mpHandle = fopen( mName.c_str(), "rb");
00079 
00080                 if ( !mpHandle )
00081                 {
00082                         std::string msgString = "Could not open ";
00083                         msgString += mName;
00084                         msgString += " for reading!";
00085 
00086                         CLAM_ASSERT( false, msgString.c_str() );
00087                         
00088                 }
00089 
00090                 mBitstream.Init( mpHandle );
00091 
00092                 SetChannels( mEncodedChannels );
00093                 MarkAllChannelsAsConsumed();
00094 
00095                 mSamplesDecoded = 0;
00096                 mSamplesTransferred = 0;
00097         }
00098 
00099         void MpegAudioStream::PrepareWriting()
00100         {
00101                 CLAM_ASSERT( false, "CLAM does not encode Mpeg Audio!!!");
00102         }
00103 
00104         void MpegAudioStream::PrepareReadWrite()
00105         {
00106                 CLAM_ASSERT( false, "CLAM does not encode Mpeg Audio!!!");
00107         }
00108 
00109         void MpegAudioStream::Dispose()
00110         {
00111                 mBitstream.Finish();
00112         }
00113 
00114         void MpegAudioStream::DiskToMemoryTransfer()
00115         {
00116                 unsigned samplesToRead = mInterleavedData.Size()/mEncodedChannels;
00117 
00118                 while( mDecodeBuffer[0].size() < samplesToRead
00119                        && mBitstream.NextFrame() )
00120                 {
00121                         mBitstream.SynthesizeCurrent();
00122                         
00123                         CLAM_ASSERT( mEncodedChannels == MAD_NCHANNELS( &mBitstream.CurrentFrame().header ),
00124                                      "This frame hasn't mEncodedChannels channels!" );
00125                         
00126                         CLAM_ASSERT( mEncodedChannels == mBitstream.CurrentSynthesis().pcm.channels,
00127                                      "Synthesis result does not have the expected number of channels" );
00128                         
00129                         TSize samplesDecodedThisTime = mBitstream.CurrentSynthesis().pcm.length;
00130                         
00131                         for( int i = 0; i < mEncodedChannels; i++ )
00132                         {
00133                                 mad_fixed_t* channelData = mBitstream.CurrentSynthesis().pcm.samples[i];
00134                                 
00135                                 mDecodeBuffer[i].insert( mDecodeBuffer[i].end(),
00136                                                          channelData,
00137                                                          channelData + samplesDecodedThisTime );
00138                         }
00139                         
00140                         mSamplesDecoded += mBitstream.CurrentSynthesis().pcm.length;
00141 
00142                 }
00143                 
00144                 mFramesLastRead = mDecodeBuffer[0].size();
00145 
00146                 if ( !mDecodeBuffer[0].empty() )
00147                 {
00148 
00149                         for ( int i = 0; i < mEncodedChannels; i++ )
00150                                 if ( mDecodeBuffer[i].size() < samplesToRead )
00151                                 {
00152                                         mDecodeBuffer[i].insert( mDecodeBuffer[i].end(),
00153                                                                  samplesToRead - mDecodeBuffer[i].size(),
00154                                                                  mad_fixed_t(0) );
00155                                         
00156                                 }
00157                         
00158                         ConsumeDecodedSamples();
00159                 }
00160 
00161                 mEOFReached = mBitstream.EOS() && mDecodeBuffer[0].empty();
00162         }
00163 
00164         void MpegAudioStream::ConsumeDecodedSamples()
00165         {
00166                 TSize samplesToRead = mInterleavedData.Size()/mEncodedChannels;
00167 
00168                 for ( int i = 0; i < mEncodedChannels; i++ )
00169                 {
00170                         TIndex currOffset = 0;
00171 
00172                         for ( std::deque<mad_fixed_t>::iterator j = mDecodeBuffer[i].begin();
00173                               currOffset < mInterleavedData.Size(); 
00174                               j++, currOffset+=mEncodedChannels )
00175                         {
00176                                 double sampleValue = mad_f_todouble(*j);
00177 
00178                                 // :TODO: Finding a nicer way to clamp things
00179                                 // to the -1,1 could be necessary
00180                                 // clipping
00181                                 if ( sampleValue > 1.0 )
00182                                         sampleValue = 1.0;
00183                                 else if ( sampleValue < -1.0 )
00184                                         sampleValue = -1.0;
00185                                         
00186                                 
00187                                 mInterleavedData[ currOffset + i ] = TData(sampleValue);
00188                         }
00189                         
00190                         mDecodeBuffer[i].erase( mDecodeBuffer[i].begin(),
00191                                                 mDecodeBuffer[i].begin() + samplesToRead );
00192                 }
00193 
00194                 mSamplesTransferred += samplesToRead;
00195                 
00196 
00197         }
00198 
00199         void MpegAudioStream::MemoryToDiskTransfer()
00200         {
00201                 CLAM_ASSERT( false, "CLAM does not encode Mpeg Audio!!!");
00202         }
00203 }
00204         
00205 }
00206 

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