CLAM-Development  1.4.0
MultiChannelAudioFileReader.cxx
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2001-2004 MUSIC TECHNOLOGY GROUP (MTG)
3  * UNIVERSITAT POMPEU FABRA
4  *
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  *
20  */
21 
23 #include "AudioCodecs_Stream.hxx"
24 #include "AudioOutPort.hxx"
25 #include "ProcessingFactory.hxx"
26 
27 
28 namespace CLAM
29 {
30 
31 namespace Hidden
32 {
33  static const char * metadata[] = {
34  "key", "MultiChannelAudioFileReader",
35  "category", "Audio File I/O",
36  "description", "MultiChannelAudioFileReader",
37  0
38  };
39  static FactoryRegistrator<ProcessingFactory, MultiChannelAudioFileReader> reg = metadata;
40 }
41 
42 
44  : mTimeOutput( "Current Time Position", this)
45  , mNativeStream( NULL )
46  {
48  }
49 
51  : mTimeOutput( "Current Time Position", this)
52  , mNativeStream( NULL )
53  {
54  Configure( cfg );
55  }
56 
58  {
59  if ( mNativeStream )
60  delete mNativeStream;
61  ResizePorts(0);
62  }
63 
65  {
66  return "MultiChannelAudioFileReader";
67  }
68 
70  {
71  return true;
72  }
73 
75  {
76  return mConfig;
77  }
78 
79  //TODO remove Do() and Do(vector<Audio>) duplication
80  bool MultiChannelAudioFileReader::Do( std::vector<Audio>& outputs )
81  {
82  typedef std::vector<Audio> OutputVec;
83 
84  if ( !AbleToExecute() )
85  return false;
86 
87  // Check all outputs sizes
88  bool allOutputsSameSize = true;
89 
90  TSize sizeTmp = 0;
91 
92  // MRJ: We have to keep internally references to
93  // the Audio objects yield by Flow Control, since
94  // the GetData operation not just returns a reference
95  // to writable/readable data, but also performs
96  // several checks ( as well as advancing reading/writing
97  // zones, etc. )
98  // TODO: update this code, because GetData doesn't modifies state anymore
99 
100  sizeTmp = outputs[0].GetSize();
101 
102  for( OutputVec::iterator i = outputs.begin();
103  i!= outputs.end(); i++ )
104  {
105  allOutputsSameSize &= ( sizeTmp == i->GetSize() );
106  }
107 
108 
109  CLAM_ASSERT( allOutputsSameSize, "Outputs sizes differ!" );
110 
111  // build the samples matrix
112  int j = 0;
113  for ( OutputVec::iterator i = outputs.begin(); i != outputs.end(); i++ )
114  mSamplesMatrix[ j++ ] = (*i).GetBuffer().GetPtr();
115 
116  // read the data
117  if ( !mEOFReached && !mIsPaused )
118  {
120  &mSelectedChannels[0],
121  mSelectedChannels.size(),
122  &mSamplesMatrix[0],
123  sizeTmp );
124  }
125  else
126  {
127  if ( mEOFReached )
128  mCurrentBeginTime = GetHeader().GetLength()/1000;
129  for (unsigned i = 0; i != mSamplesMatrix.size(); i++ )
130  memset ((void *)mSamplesMatrix[i], 0, sizeTmp*sizeof(TData));
131  }
132  // Audio 'simple meta-data' setup
133  for ( OutputVec::iterator i = outputs.begin();
134  i != outputs.end(); i++ )
135  {
136  (*i).SetSampleRate( mAudioFile.GetHeader().GetSampleRate() );
137  (*i).SetBeginTime( mCurrentBeginTime );
138  }
139 
140 
141  if ( !mEOFReached && !mIsPaused )
142  {
143  mDeltaTime = TData(sizeTmp)/mAudioFile.GetHeader().GetSampleRate()*1000;
145  }
147 
148  return !mEOFReached;
149  }
150  //TODO remove Do() and Do(vector<Audio>) duplication
152  {
153  if ( !AbleToExecute() )
154  return false;
155 
156  // Check all outputs sizes
157  bool allOutputsSameSize = true;
158 
159  TSize sizeTmp = 0;
160 
161  // MRJ: We have to keep internally references to
162  // the Audio objects yield by Flow Control, since
163  // the GetData operation not just returns a reference
164  // to writable/readable data, but also performs
165  // several checks ( as well as advancing reading/writing
166  // zones, etc. )
167  // TODO: update this code, because GetData doesn't modifies state anymore
168  OutRefsVector outRefs;
169 
170  for ( OutputVector::iterator i = _outputs.begin();
171  i!= _outputs.end();
172  i++ )
173  outRefs.push_back( &((*i)->GetAudio()) );
174 
175 
176  sizeTmp = outRefs[0]->GetSize();
177 
178  for( OutRefsVector::iterator i = outRefs.begin();
179  i!= outRefs.end(); i++ )
180  {
181  allOutputsSameSize = ( sizeTmp == (*i)->GetSize() );
182  }
183 
184 
185  CLAM_ASSERT( allOutputsSameSize, "Outputs sizes differ!" );
186 
187  // build the samples matrix
188 
189  int j = 0;
190  for ( OutRefsVector::iterator i = outRefs.begin();
191  i != outRefs.end(); i++ )
192  mSamplesMatrix[ j++ ] = (*i)->GetBuffer().GetPtr();
193 
194  // read the data
195 
196  if ( !mEOFReached && !mIsPaused )
197  {
199  &mSelectedChannels[0],
200  mSelectedChannels.size(),
201  &mSamplesMatrix[0],
202  sizeTmp );
203  }
204  else
205  {
206  if ( mEOFReached )
207  mCurrentBeginTime = GetHeader().GetLength()/1000;
208  for (unsigned i = 0; i != mSamplesMatrix.size(); i++)
209  {
210  memset ((void *)mSamplesMatrix[i], 0, sizeTmp*sizeof(TData));
211  }
212  }
213 
214  // Audio 'simple meta-data' setup
215 
216  for ( OutRefsVector::iterator i = outRefs.begin();
217  i != outRefs.end(); i++ )
218  {
219  (*i)->SetSampleRate( mAudioFile.GetHeader().GetSampleRate() );
220  (*i)->SetBeginTime( mCurrentBeginTime );
221  }
222 
223  if (!mEOFReached && !mIsPaused)
224  {
225  mDeltaTime = TData(sizeTmp)/mAudioFile.GetHeader().GetSampleRate()*1000;
227  }
228 
230 
231  for ( OutputVector::iterator i = _outputs.begin();
232  i!= _outputs.end(); i++ )
233  {
234  (*i)->Produce();
235  }
236 
237  return !mEOFReached;
238  }
239 
241  {
242  CopyAsConcreteConfig( mConfig, cfgObj );
243 
244  if ( !mConfig.HasSourceFile() )
245  {
246  AddConfigErrorMessage("No 'source file' was specified in the configuration!");
247  return false;
248  }
249 
250  if ( mConfig.GetSourceFile() == "" )
251  {
252  AddConfigErrorMessage("No file selected");
253  return false;
254  }
255 
256  mAudioFile.OpenExisting(mConfig.GetSourceFile());
257  if ( !mAudioFile.IsReadable() )
258  {
259  AddConfigErrorMessage("The audio file '" + mConfig.GetSourceFile() + "' could not be opened!");
260  return false;
261  }
262 
263  if ( !mConfig.HasSelectedChannels() )
264  {
265  mSelectedChannels.resize( mAudioFile.GetHeader().GetChannels() );
266 
268 
269  for (unsigned i = 0; i < mSelectedChannels.size(); i++ )
270  {
271  mSelectedChannels[ i ] = i;
272  }
273 
274  mSamplesMatrix.resize( mSelectedChannels.size() );
275 
276  }
277  else
278  {
279  // Checking selected channels validity
280  const Array<TIndex> & selectedChannels = mConfig.GetSelectedChannels();
281  mSelectedChannels.assign(
282  selectedChannels.GetPtr(),
283  selectedChannels.GetPtr()+selectedChannels.Size());
284 
285  if ( mSelectedChannels.size() != mAudioFile.GetHeader().GetChannels() )
286  {
287  return AddConfigErrorMessage(
288  "The configuration asked for more channels than the audio file has.");
289  }
290 
291  int maxChannels = mAudioFile.GetHeader().GetChannels();
292 
293  for (unsigned i = 0; i < mSelectedChannels.size(); i++ )
294  if ( mSelectedChannels[i] < 0
295  || mSelectedChannels[i] >= maxChannels )
296  {
297  return AddConfigErrorMessage(
298  "Invalid channel index in configuration!");
299  }
300 
301  ResizePorts(0);
302 
303  for (unsigned i = 0; i < mSelectedChannels.size(); i++ )
304  {
305  std::stringstream sstr;
306  sstr << mSelectedChannels[i];
307 
308  _outputs.push_back(
309  new AudioOutPort( "Channel #" + sstr.str(), this )
310  );
311  }
312 
313  mSamplesMatrix.resize( maxChannels );
314  }
315 
317 
318  if (not mNativeStream )
319  {
320  return AddConfigErrorMessage("Could not get a valid audio file stream!");
321  }
322 
323  return true;
324  }
325 
327  {
328  if (mNativeStream == NULL)
331  mCurrentBeginTime = 0.0;
332  mEOFReached = false;
333  mIsPaused = false;
334 
335  return true;
336  }
337 
339  {
341  delete mNativeStream;
343 
344  return true;
345  }
347  {
348  const std::string nameBase = "Channel #";
349  for (unsigned i=_outputs.size(); i<nPorts; i++)
350  {
351  std::ostringstream nameStream;
352  nameStream << nameBase << i;
353  AudioOutPort * port = new AudioOutPort( nameStream.str(), this);
354  _outputs.push_back( port );
355  }
356  for (unsigned i=nPorts; i<_outputs.size(); i++)
357  delete _outputs[i];
358  _outputs.resize(nPorts);
359 /*
360  const unsigned portSize = BackendBufferSize();
361  for (unsigned i=0; i<_outputs.size(); i++)
362  {
363  _outputs[i]->SetSize( portSize );
364  _outputs[i]->SetHop( portSize );
365  }
366 */
367  }
368 
369 }
370