MultiChannelAudioFileReader.cxx

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2001-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 "MultiChannelAudioFileReader.hxx"
00023 #include "AudioCodecs_Stream.hxx"
00024 #include "AudioOutPort.hxx"
00025 #include "ProcessingFactory.hxx"
00026 
00027 
00028 namespace CLAM
00029 {
00030 
00031 namespace Hidden
00032 {
00033         static const char * metadata[] = {
00034                 "key", "MultiChannelAudioFileReader",
00035                 "category", "Audio File I/O",
00036                 "description", "MultiChannelAudioFileReader",
00037                 0
00038         };
00039         static FactoryRegistrator<ProcessingFactory, MultiChannelAudioFileReader> reg = metadata;
00040 }
00041         
00042         
00043         MultiChannelAudioFileReader::MultiChannelAudioFileReader()
00044                 : mTimeOutput( "Current Time Position", this)
00045                 , mNativeStream( NULL )
00046         {
00047                 Configure(MultiChannelAudioFileReaderConfig());
00048         }
00049 
00050         MultiChannelAudioFileReader::MultiChannelAudioFileReader( const ProcessingConfig& cfg )
00051                 : mTimeOutput( "Current Time Position", this)
00052                 , mNativeStream( NULL )
00053         {
00054                 Configure( cfg );
00055         }
00056 
00057         MultiChannelAudioFileReader::~MultiChannelAudioFileReader()
00058         {
00059                 if ( mNativeStream )
00060                         delete mNativeStream;
00061                 
00062                 DestroyOldOutputs();
00063         }
00064 
00065         const char* MultiChannelAudioFileReader::GetClassName() const
00066         {
00067                 return "MultiChannelAudioFileReader";
00068         }
00069 
00070         bool MultiChannelAudioFileReader::ModifiesPortsAndControlsAtConfiguration()
00071         {
00072                 return true;
00073         }
00074 
00075         const ProcessingConfig& MultiChannelAudioFileReader::GetConfig() const
00076         {
00077                 return mConfig;
00078         }
00079 
00080         //TODO remove Do() and Do(vector<Audio>) duplication
00081         bool MultiChannelAudioFileReader::Do( std::vector<Audio>& outputs )
00082         {
00083                 typedef std::vector<Audio> OutputVec;
00084 
00085                 if ( !AbleToExecute() )
00086                         return false;
00087 
00088                 // Check all outputs sizes
00089                 bool allOutputsSameSize = true;
00090                 
00091                 TSize sizeTmp = 0;
00092 
00093                 // MRJ: We have to keep internally references to
00094                 // the Audio objects yield by Flow Control, since
00095                 // the GetData operation not just returns a reference
00096                 // to writable/readable data, but also performs
00097                 // several checks ( as well as advancing reading/writing
00098                 // zones, etc. )
00099                 // TODO: update this code, because GetData doesn't modifies state anymore
00100                 
00101                 sizeTmp = outputs[0].GetSize(); 
00102                 
00103                 for( OutputVec::iterator i = outputs.begin();
00104                      i!= outputs.end(); i++ )
00105                 {
00106                         allOutputsSameSize &= ( sizeTmp == i->GetSize() );
00107                 }
00108 
00109 
00110                 CLAM_ASSERT( allOutputsSameSize, "Outputs sizes differ!" );
00111 
00112                 // build the samples matrix
00113                 int j = 0;
00114                 for ( OutputVec::iterator i = outputs.begin(); i != outputs.end(); i++ )
00115                         mSamplesMatrix[ j++ ] = (*i).GetBuffer().GetPtr();
00116 
00117                 // read the data
00118                 if ( !mEOFReached && !mIsPaused ) 
00119                 {
00120                         mEOFReached = mNativeStream->ReadData( mSelectedChannels.GetPtr(),
00121                                                mSelectedChannels.Size(),
00122                                                mSamplesMatrix.GetPtr(),
00123                                                sizeTmp );
00124                 }
00125                 else
00126                 {
00127                         if ( mEOFReached ) 
00128                                 mCurrentBeginTime = GetHeader().GetLength()/1000;
00129                         for ( int i = 0; i != mSamplesMatrix.Size(); i++ ) 
00130                                 memset ((void *)mSamplesMatrix[i], 0, sizeTmp*sizeof(TData));
00131                 }
00132                 // Audio 'simple meta-data' setup
00133                 for ( OutputVec::iterator i = outputs.begin();
00134                                 i != outputs.end(); i++ )
00135                 {
00136                         (*i).SetSampleRate( mAudioFile.GetHeader().GetSampleRate() );
00137                         (*i).SetBeginTime( mCurrentBeginTime );
00138                 }
00139                 
00140                 
00141                 if ( !mEOFReached && !mIsPaused )
00142                 {
00143                         mDeltaTime = TData(sizeTmp)/mAudioFile.GetHeader().GetSampleRate()*1000;
00144                         mCurrentBeginTime += mDeltaTime;
00145                 }
00146                 mTimeOutput.SendControl( mCurrentBeginTime );
00147                 
00148                 return !mEOFReached;
00149         }
00150         //TODO remove Do() and Do(vector<Audio>) duplication
00151         bool MultiChannelAudioFileReader::Do()
00152         {
00153                 if ( !AbleToExecute() )
00154                         return false;
00155 
00156                 // Check all outputs sizes
00157                 bool allOutputsSameSize = true;
00158                 
00159                 TSize sizeTmp = 0;
00160 
00161                 // MRJ: We have to keep internally references to
00162                 // the Audio objects yield by Flow Control, since
00163                 // the GetData operation not just returns a reference
00164                 // to writable/readable data, but also performs
00165                 // several checks ( as well as advancing reading/writing
00166                 // zones, etc. )
00167                 // TODO: update this code, because GetData doesn't modifies state anymore
00168                 OutRefsVector outRefs;
00169 
00170                 for ( OutputVector::iterator i = mOutputs.begin();
00171                       i!= mOutputs.end();
00172                       i++ )
00173                         outRefs.push_back( &((*i)->GetAudio()) );
00174                 
00175                 
00176                 sizeTmp = outRefs[0]->GetSize();        
00177                 
00178                 for( OutRefsVector::iterator i = outRefs.begin();
00179                      i!= outRefs.end(); i++ )
00180                 {
00181                         allOutputsSameSize = ( sizeTmp == (*i)->GetSize() );
00182                 }
00183 
00184 
00185                 CLAM_ASSERT( allOutputsSameSize, "Outputs sizes differ!" );
00186 
00187                 // build the samples matrix
00188 
00189                 int j = 0;
00190                 for ( OutRefsVector::iterator i = outRefs.begin();
00191                       i != outRefs.end(); i++ )
00192                         mSamplesMatrix[ j++ ] = (*i)->GetBuffer().GetPtr();
00193 
00194                 // read the data
00195                 
00196                 if ( !mEOFReached && !mIsPaused ) 
00197                 {
00198                         mEOFReached = mNativeStream->ReadData( mSelectedChannels.GetPtr(),
00199                                                mSelectedChannels.Size(),
00200                                                mSamplesMatrix.GetPtr(),
00201                                                sizeTmp );
00202                 }
00203                 else 
00204                 {
00205                         if ( mEOFReached ) 
00206                                 mCurrentBeginTime = GetHeader().GetLength()/1000;
00207                         for ( int i = 0; i != mSamplesMatrix.Size(); i++) 
00208                         {
00209                                 memset ((void *)mSamplesMatrix[i], 0, sizeTmp*sizeof(TData));
00210                         }
00211                 }
00212 
00213                 // Audio 'simple meta-data' setup
00214                 
00215                 for ( OutRefsVector::iterator i = outRefs.begin();
00216                                 i != outRefs.end(); i++ )
00217                 {
00218                         (*i)->SetSampleRate( mAudioFile.GetHeader().GetSampleRate() );
00219                         (*i)->SetBeginTime( mCurrentBeginTime );
00220                 }
00221                 
00222                 if (!mEOFReached && !mIsPaused)
00223                 {
00224                         mDeltaTime = TData(sizeTmp)/mAudioFile.GetHeader().GetSampleRate()*1000;
00225                         mCurrentBeginTime += mDeltaTime;
00226                 }
00227                         
00228                 mTimeOutput.SendControl( mCurrentBeginTime );
00229                 
00230                 for ( OutputVector::iterator i = mOutputs.begin();
00231                       i!= mOutputs.end(); i++ )
00232                 {       
00233                         (*i)->Produce();
00234                 }
00235 
00236                 return !mEOFReached;
00237         }
00238 
00239         bool MultiChannelAudioFileReader::ConcreteConfigure( const ProcessingConfig& cfgObj )
00240         {
00241                 CopyAsConcreteConfig( mConfig, cfgObj );
00242 
00243                 if ( !mConfig.HasSourceFile() )
00244                 {
00245                         AddConfigErrorMessage("No 'source file' was specified in the configuration!");
00246                         return false;
00247                 }
00248 
00249                 if ( mConfig.GetSourceFile() == "" )
00250                 {
00251                         AddConfigErrorMessage("No file selected");
00252                         return false;
00253                 }
00254 
00255                 mAudioFile.OpenExisting(mConfig.GetSourceFile());
00256                 if ( !mAudioFile.IsReadable() )
00257                 {
00258                         AddConfigErrorMessage("The audio file '" + mConfig.GetSourceFile() + "' could not be opened!");
00259                         return false;
00260                 }
00261 
00262                 if ( !mConfig.HasSelectedChannels() )
00263                 {
00264                         mSelectedChannels.Resize( mAudioFile.GetHeader().GetChannels() );
00265                         mSelectedChannels.SetSize( mAudioFile.GetHeader().GetChannels() );
00266 
00267                         DestroyOldOutputs();
00268 
00269                         for ( int i = 0; i < mSelectedChannels.Size(); i++ )
00270                         {
00271                                 std::stringstream sstr;
00272                                 sstr << i;
00273 
00274                                 mOutputs.push_back(
00275                                         new AudioOutPort( "Channel #" + sstr.str(), this )
00276                                         );
00277 
00278                                 mSelectedChannels[ i ] = i;
00279                         }
00280 
00281                         mSamplesMatrix.Resize( mSelectedChannels.Size() );
00282                         mSamplesMatrix.SetSize( mSelectedChannels.Size() );
00283 
00284                 }
00285                 else
00286                 {
00287                         // Checking selected channels validity
00288                         mSelectedChannels = mConfig.GetSelectedChannels();
00289 
00290                         if ( mSelectedChannels.Size() != mAudioFile.GetHeader().GetChannels() )
00291                         {
00292                                 AddConfigErrorMessage("The configuration asked for more channels than the audio file has.");
00293                                 return false;
00294                         }
00295 
00296                         int maxChannels = mAudioFile.GetHeader().GetChannels();
00297 
00298                         for ( int i = 0; i < mSelectedChannels.Size(); i++ )
00299                                 if ( mSelectedChannels[i] < 0
00300                                      || mSelectedChannels[i] >= maxChannels )
00301                                 {
00302                                         AddConfigErrorMessage("Invalid channel index in configuration!");
00303                                         return false;
00304                                 }
00305 
00306 
00307                         DestroyOldOutputs();
00308 
00309                         for ( int i = 0; i < mSelectedChannels.Size(); i++ )
00310                         {
00311                                 std::stringstream sstr;
00312                                 sstr << mSelectedChannels[i];
00313 
00314                                 mOutputs.push_back(
00315                                         new AudioOutPort( "Channel #" + sstr.str(), this )
00316                                         );
00317                         }
00318 
00319                         mSamplesMatrix.Resize( maxChannels );
00320                         mSamplesMatrix.SetSize( maxChannels );
00321                 }
00322 
00323                 mNativeStream = mAudioFile.GetStream();
00324 
00325                 if (!mNativeStream )
00326                 {
00327                         AddConfigErrorMessage("Could not get a valid audio file stream!");
00328                         return false;
00329                 }
00330 
00331                 return true;
00332         }
00333 
00334         void MultiChannelAudioFileReader::DestroyOldOutputs()
00335         {
00336                 for( OutputVector::iterator i = mOutputs.begin();
00337                      i != mOutputs.end(); i++ )
00338                         if( *i ) delete *i;
00339 
00340                 mOutputs.clear();
00341                 GetOutPorts().Clear();
00342         }
00343 
00344         bool MultiChannelAudioFileReader::ConcreteStart()
00345         {
00346                 if (mNativeStream == NULL) 
00347                         mNativeStream = mAudioFile.GetStream();
00348                 mNativeStream->PrepareReading();
00349                 mCurrentBeginTime = 0.0;
00350                 mEOFReached = false;
00351                 mIsPaused = false;
00352 
00353                 return true;
00354         }
00355 
00356         bool MultiChannelAudioFileReader::ConcreteStop()
00357         {
00358                 mNativeStream->Dispose();
00359                 delete mNativeStream;
00360                 mNativeStream = NULL;
00361 
00362                 return true;
00363         }
00364 }
00365 

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