CLAM-Development  1.4.0
OfflineNetworkPlayer.cxx
Go to the documentation of this file.
1 
5 #include "AudioSink.hxx"
6 #include "AudioSource.hxx"
7 
8 #include <iostream>
9 #include <sstream>
10 
11 namespace CLAM
12 {
13 
15 {
17  return (_inFileNames.size() != GetNSources())
18  && (_outFileNames.size() != GetNSinks());
19 }
20 
22 {
23  std::stringstream ss;
24  ss << GetNSources() << " inputs and "
25  << GetNSinks() << " outputs needed but just "
26  << _inFileNames.size() << " input files provided"
27  << _outFileNames.size() << " output files provided"
28  << std::ends;
29  return ss.str();
30 }
31 
33 {
34  std::ostringstream result;
35 
36  unsigned inFileIndex = 0;
37  unsigned inChannel = 0;
38  for (unsigned i=0; i<GetNSources(); i++)
39  {
40  ++inChannel;
41  result << " * source:\t" << SourceName(i) << "\t";
42  result << "In:\t" << _inFileNames[inFileIndex] << "\tchannel " << inChannel << "\n";
43 
44  //We have read all the channels of infiles[inFileIndex]
45  if((unsigned)infiles[inFileIndex]->channels() == inChannel)
46  {
47  inFileIndex++;
48  inChannel = 0;
49  }
50  }
51 
52  unsigned outFileIndex = 0;
53  unsigned outChannel = 0;
54  for (unsigned i=0; i<GetNSinks(); i++)
55  {
56  outChannel++;
57  result << " * sink:\t" << SinkName(i) << "\t";
58  result << "Out:\t" << _outFileNames[outFileIndex] << "\tchannel " << outChannel << "\n";
59 
60  //We have read all the channels of outfiles[outFileIndex]
61  if((unsigned)outfiles[outFileIndex]->channels() == outChannel)
62  {
63  outFileIndex++;
64  outChannel = 0;
65  }
66  }
67 
68  return result.str();
69 }
70 
72 {
73  if ( IsPlaying() )
74  return;
75 
76  BePlaying();
77 
79 
80  const int frameSize = 512;
81 
82  //Open the files, get the total number of channels and the sample rate
83  int sampleRate = 0;
84  unsigned inputChannelsCount = 0;
85  SndFileHandles infiles;
86 
87  for(unsigned fileIndex = 0; fileIndex < _inFileNames.size(); fileIndex++)
88  {
89  CLAM_ASSERT(fileIndex < _inFileNames.size(),
90  "Not all the network inputs could be fullfiled. Have you checked the IsWorking() method?");
91  std::ifstream checkfile(_inFileNames[fileIndex].c_str());
92 
93  CLAM_ASSERT(checkfile.is_open(),std::string("Could not open one of the input files: "+_inFileNames[fileIndex]).c_str());
94  SndfileHandle* infile = new SndfileHandle(_inFileNames[fileIndex].c_str(), SFM_READ );
95 
96  CLAM_ASSERT(*infile, "Can not create the infile ");
97  inputChannelsCount += infile->channels();
98 
99  if(fileIndex == 0)
100  sampleRate = infile->samplerate();
101 
102  CLAM_ASSERT(infile->samplerate() == sampleRate,
103  "All the input audio files have to have the same sample rate");
104 
105  infiles.push_back(infile);
106  }
107 
108  // Check that the number of input channels matches the number of ports in the network
109  CLAM_ASSERT(inputChannelsCount == GetNSources(),
110  "The number of input channels is different than the number of sourceports in the provided network.");
111 
112  //Open the files and get the total number of channels
113  unsigned outputChannelsCount=0;
114  SndFileHandles outfiles;
115  for(unsigned fileIndex=0;fileIndex<_outFileNames.size();fileIndex++)
116  {
117  if (fileIndex>=_outFileNames.size())
118  {
119  std::cerr << "Not all the network outputs could be fullfiled.";
120  break;
121  }
122 
123  SndfileHandle* outfile = new SndfileHandle(_outFileNames[fileIndex].c_str(), SFM_WRITE,
124  _format,_outChannelsFiles[fileIndex],sampleRate);
125  CLAM_ASSERT(*outfile, "Can not create the outfile ");
126  outputChannelsCount +=_outChannelsFiles[fileIndex];
127  outfiles.push_back(outfile);
128  }
129 
130  // Check that the number of output channels matches the of ports in the network
131  CLAM_ASSERT(outputChannelsCount == GetNSinks(),
132  "The number of output channels is different than the number of sinkports in the provided network.");
133 
134  std::cout << "Sources and Sinks list:" <<std::endl;
135  std::cout << listOfSourcesSinksAndFiles(infiles,outfiles)<<std::endl;
136 
137  // Prepare the sources
138  //CLAM_ASSERT(_audioSources.size() == infiles.size(),
139  // "The number of sources is greater than the intput files.");
140 
141  std::vector<DataArray> inbuffers(inputChannelsCount);
142  for(unsigned i = 0; i < GetNSources(); ++i)
143  {
144  inbuffers[i].Resize( frameSize );
145  inbuffers[i].SetSize( frameSize );
146  const TData * data = &inbuffers[i][0];
147  SetSourceBuffer(i, data, frameSize);
148  }
149 
150  //Prepare the sinks
151  //CLAM_ASSERT(_audioSinks.size() == outfiles.size(),
152  // "The number of sinks is greater than the output files ");
153 
154  std::vector<DataArray> outbuffers(outputChannelsCount);
155  for( unsigned i = 0; i < GetNSinks(); ++i)
156  {
157  outbuffers[i].Resize( frameSize );
158  outbuffers[i].SetSize( frameSize );
159 
160  TData * data = &outbuffers[i][0];
161  SetSinkBuffer(i, data, frameSize);
162  }
163 
164 
165  long iterationIndex = 0;
166  bool timeLimitedMode = _resultWavsTime > 0.001;
167  int fileIndex = 0;
168  while(true)
169  {
170  std::cout << "." << std::flush;
171  unsigned inAudioIndex =0;
172  bool someInputFinished=false;
173  for(SndFileHandles::iterator it = infiles.begin(); it != infiles.end(); ++it)
174  {
175  SndfileHandle * sndfileHandle = (*it);
176  unsigned int nChannels = sndfileHandle->channels();
177  CLAM_ASSERT(nChannels, "The audio had no channels");
178  int bufferReaderSize = nChannels*frameSize;
179  float * bufferReader = new float[bufferReaderSize];
180  int readSize = sndfileHandle->read(bufferReader,bufferReaderSize);
181 
182  //We have read the last part (not complete) of the buffer file. Fill the buffer with zeros.
183  if(readSize<bufferReaderSize)
184  {
185  for(int i = readSize; i < bufferReaderSize; i++)
186  {
187  bufferReader[i] = 0;
188  }
189  if(_enableLoopInputWavs)
190  sndfileHandle->seek(0,SEEK_SET);
191  someInputFinished = true;
192  }
193  //Save the bufferReader into the sources' buffers.
194  for(int frameIndex=0; frameIndex <frameSize; frameIndex ++)
195  {
196  for(unsigned channel=0; channel < nChannels; channel++)
197  {
198  inbuffers[inAudioIndex+channel][frameIndex] = bufferReader[(frameIndex*nChannels)+channel];
199  }
200  }
201  inAudioIndex += nChannels;
202  fileIndex ++;
203  delete[] bufferReader;
204  }
205 
206  GetNetwork().Do();
207 
208  unsigned outAudioIndex = 0;
209  for(SndFileHandles::iterator it = outfiles.begin(); it != outfiles.end(); ++it)
210  {
211  SndfileHandle * sndfileHandle = (*it);
212  unsigned int nChannels = sndfileHandle->channels();
213  int bufferWriterSize = nChannels*frameSize;
214  float* bufferWriter = new float[bufferWriterSize];
215 
216  //Save the sources' buffers into the bufferWriter.
217  for(int frameIndex = 0; frameIndex < frameSize; frameIndex ++)
218  {
219  for(unsigned channel = 0; channel < nChannels; channel++)
220  {
221  bufferWriter[(frameIndex*nChannels) + channel] =
222  outbuffers[outAudioIndex + channel][frameIndex];
223  }
224  }
225  int writeSize = sndfileHandle->write(bufferWriter, bufferWriterSize);
226  CLAM_ASSERT(writeSize == bufferWriterSize,"The outfile has not been written correctly");
227  outAudioIndex += nChannels;
228  delete[] bufferWriter;
229  }
230 
231  if (timeLimitedMode and float(iterationIndex * frameSize) / sampleRate > _resultWavsTime)
232  {
233  std::cout << "REACHED MAX TIME - finalizing"<< std::endl;
234  break;
235  }
236  iterationIndex++;
237 
238  if (someInputFinished and not _enableLoopInputWavs )
239  break;
240  }
241 
242  //Deleting the sndfiles
243  for(SndFileHandles::iterator it = infiles.begin(); it != infiles.end(); ++it)
244  delete *it;
245 
246  for(SndFileHandles::iterator it = outfiles.begin(); it != outfiles.end(); ++it)
247  delete *it;
248 }
249 
251 {
252  if ( IsStopped() )
253  return;
254  BeStopped();
255 
256  //TODO close files
257 }
258 
260 {
261  GetNetwork().Do();
262 }
263 
264 void OfflineNetworkPlayer::AddInputFile( const std::string& filename )
265 {
266  _inFileNames.push_back(filename);
267 }
268 
269 void OfflineNetworkPlayer::AddOutputFile( const std::string& filename )
270 {
271  _outFileNames.push_back(filename);
272 }
273 
275 {
276  _outChannelsFiles.push_back(channel);
277 }
278 
280 {
281  _format = format;
282 }
283 
284 } //namespace
285