MultiChannelAudioFileReader.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 #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 ResizePorts(0);
00062 }
00063
00064 const char* MultiChannelAudioFileReader::GetClassName() const
00065 {
00066 return "MultiChannelAudioFileReader";
00067 }
00068
00069 bool MultiChannelAudioFileReader::ModifiesPortsAndControlsAtConfiguration()
00070 {
00071 return true;
00072 }
00073
00074 const ProcessingConfig& MultiChannelAudioFileReader::GetConfig() const
00075 {
00076 return mConfig;
00077 }
00078
00079
00080 bool MultiChannelAudioFileReader::Do( std::vector<Audio>& outputs )
00081 {
00082 typedef std::vector<Audio> OutputVec;
00083
00084 if ( !AbleToExecute() )
00085 return false;
00086
00087
00088 bool allOutputsSameSize = true;
00089
00090 TSize sizeTmp = 0;
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100 sizeTmp = outputs[0].GetSize();
00101
00102 for( OutputVec::iterator i = outputs.begin();
00103 i!= outputs.end(); i++ )
00104 {
00105 allOutputsSameSize &= ( sizeTmp == i->GetSize() );
00106 }
00107
00108
00109 CLAM_ASSERT( allOutputsSameSize, "Outputs sizes differ!" );
00110
00111
00112 int j = 0;
00113 for ( OutputVec::iterator i = outputs.begin(); i != outputs.end(); i++ )
00114 mSamplesMatrix[ j++ ] = (*i).GetBuffer().GetPtr();
00115
00116
00117 if ( !mEOFReached && !mIsPaused )
00118 {
00119 mEOFReached = mNativeStream->ReadData(
00120 &mSelectedChannels[0],
00121 mSelectedChannels.size(),
00122 &mSamplesMatrix[0],
00123 sizeTmp );
00124 }
00125 else
00126 {
00127 if ( mEOFReached )
00128 mCurrentBeginTime = GetHeader().GetLength()/1000;
00129 for (unsigned i = 0; i != mSamplesMatrix.size(); i++ )
00130 memset ((void *)mSamplesMatrix[i], 0, sizeTmp*sizeof(TData));
00131 }
00132
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
00151 bool MultiChannelAudioFileReader::Do()
00152 {
00153 if ( !AbleToExecute() )
00154 return false;
00155
00156
00157 bool allOutputsSameSize = true;
00158
00159 TSize sizeTmp = 0;
00160
00161
00162
00163
00164
00165
00166
00167
00168 OutRefsVector outRefs;
00169
00170 for ( OutputVector::iterator i = _outputs.begin();
00171 i!= _outputs.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
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
00195
00196 if ( !mEOFReached && !mIsPaused )
00197 {
00198 mEOFReached = mNativeStream->ReadData(
00199 &mSelectedChannels[0],
00200 mSelectedChannels.size(),
00201 &mSamplesMatrix[0],
00202 sizeTmp );
00203 }
00204 else
00205 {
00206 if ( mEOFReached )
00207 mCurrentBeginTime = GetHeader().GetLength()/1000;
00208 for (unsigned i = 0; i != mSamplesMatrix.size(); i++)
00209 {
00210 memset ((void *)mSamplesMatrix[i], 0, sizeTmp*sizeof(TData));
00211 }
00212 }
00213
00214
00215
00216 for ( OutRefsVector::iterator i = outRefs.begin();
00217 i != outRefs.end(); i++ )
00218 {
00219 (*i)->SetSampleRate( mAudioFile.GetHeader().GetSampleRate() );
00220 (*i)->SetBeginTime( mCurrentBeginTime );
00221 }
00222
00223 if (!mEOFReached && !mIsPaused)
00224 {
00225 mDeltaTime = TData(sizeTmp)/mAudioFile.GetHeader().GetSampleRate()*1000;
00226 mCurrentBeginTime += mDeltaTime;
00227 }
00228
00229 mTimeOutput.SendControl( mCurrentBeginTime );
00230
00231 for ( OutputVector::iterator i = _outputs.begin();
00232 i!= _outputs.end(); i++ )
00233 {
00234 (*i)->Produce();
00235 }
00236
00237 return !mEOFReached;
00238 }
00239
00240 bool MultiChannelAudioFileReader::ConcreteConfigure( const ProcessingConfig& cfgObj )
00241 {
00242 CopyAsConcreteConfig( mConfig, cfgObj );
00243
00244 if ( !mConfig.HasSourceFile() )
00245 {
00246 AddConfigErrorMessage("No 'source file' was specified in the configuration!");
00247 return false;
00248 }
00249
00250 if ( mConfig.GetSourceFile() == "" )
00251 {
00252 AddConfigErrorMessage("No file selected");
00253 return false;
00254 }
00255
00256 mAudioFile.OpenExisting(mConfig.GetSourceFile());
00257 if ( !mAudioFile.IsReadable() )
00258 {
00259 AddConfigErrorMessage("The audio file '" + mConfig.GetSourceFile() + "' could not be opened!");
00260 return false;
00261 }
00262
00263 if ( !mConfig.HasSelectedChannels() )
00264 {
00265 mSelectedChannels.resize( mAudioFile.GetHeader().GetChannels() );
00266
00267 ResizePorts(mSelectedChannels.size());
00268
00269 for (unsigned i = 0; i < mSelectedChannels.size(); i++ )
00270 {
00271 mSelectedChannels[ i ] = i;
00272 }
00273
00274 mSamplesMatrix.resize( mSelectedChannels.size() );
00275
00276 }
00277 else
00278 {
00279
00280 const Array<TIndex> & selectedChannels = mConfig.GetSelectedChannels();
00281 mSelectedChannels.assign(
00282 selectedChannels.GetPtr(),
00283 selectedChannels.GetPtr()+selectedChannels.Size());
00284
00285 if ( mSelectedChannels.size() != mAudioFile.GetHeader().GetChannels() )
00286 {
00287 return AddConfigErrorMessage(
00288 "The configuration asked for more channels than the audio file has.");
00289 }
00290
00291 int maxChannels = mAudioFile.GetHeader().GetChannels();
00292
00293 for (unsigned i = 0; i < mSelectedChannels.size(); i++ )
00294 if ( mSelectedChannels[i] < 0
00295 || mSelectedChannels[i] >= maxChannels )
00296 {
00297 return AddConfigErrorMessage(
00298 "Invalid channel index in configuration!");
00299 }
00300
00301 ResizePorts(0);
00302
00303 for (unsigned i = 0; i < mSelectedChannels.size(); i++ )
00304 {
00305 std::stringstream sstr;
00306 sstr << mSelectedChannels[i];
00307
00308 _outputs.push_back(
00309 new AudioOutPort( "Channel #" + sstr.str(), this )
00310 );
00311 }
00312
00313 mSamplesMatrix.resize( maxChannels );
00314 }
00315
00316 mNativeStream = mAudioFile.GetStream();
00317
00318 if (not mNativeStream )
00319 {
00320 return AddConfigErrorMessage("Could not get a valid audio file stream!");
00321 }
00322
00323 return true;
00324 }
00325
00326 bool MultiChannelAudioFileReader::ConcreteStart()
00327 {
00328 if (mNativeStream == NULL)
00329 mNativeStream = mAudioFile.GetStream();
00330 mNativeStream->PrepareReading();
00331 mCurrentBeginTime = 0.0;
00332 mEOFReached = false;
00333 mIsPaused = false;
00334
00335 return true;
00336 }
00337
00338 bool MultiChannelAudioFileReader::ConcreteStop()
00339 {
00340 mNativeStream->Dispose();
00341 delete mNativeStream;
00342 mNativeStream = NULL;
00343
00344 return true;
00345 }
00346 void MultiChannelAudioFileReader::ResizePorts(unsigned nPorts)
00347 {
00348 const std::string nameBase = "Channel #";
00349 for (unsigned i=_outputs.size(); i<nPorts; i++)
00350 {
00351 std::ostringstream nameStream;
00352 nameStream << nameBase << i;
00353 AudioOutPort * port = new AudioOutPort( nameStream.str(), this);
00354 _outputs.push_back( port );
00355 }
00356 for (unsigned i=nPorts; i<_outputs.size(); i++)
00357 delete _outputs[i];
00358 _outputs.resize(nPorts);
00359
00360
00361
00362
00363
00364
00365
00366
00367 }
00368
00369 }
00370