CLAM-Development  1.4.0
LoopingSDIFFileReader.cxx
Go to the documentation of this file.
2 #include "DataUtil.hxx"
3 #include <time.h>
4 #include <vector>
5 
6 namespace CLAM
7 {
8 
10 : BufferedSDIFFileReader(argSDIFInConfig),
11  numberOfCrossfadeFrames(DEFAULT_NUMBER_OF_CROSSFADE_FRAMES),
12  indexOfCurrentLoop(0)
13 {
14  outgoingFrame = new Frame();
15  outgoingFrame->AddSpectralPeakArray();
16  outgoingFrame->AddResidualSpec();
17  outgoingFrame->AddFundamental();
18  outgoingFrame->AddSynthAudioFrame();
19  outgoingFrame->UpdateData();
20 
21  Configure(argSDIFInConfig);
22 }
23 
25 {
26  delete outgoingFrame;
27 }
28 
30 {
31  /* initialize random seed: */
32  srand ( time(NULL) );
33 
34  return true;
35 }
36 
38 {
39  return listOfLoops.size() != 0;
40 }
41 
43 {
44  listOfLoops.push_back(aSimpleLoop);
45 }
46 
48 {
49  listOfLoops.clear();
50 }
51 
52 std::vector<SimpleLoopMetadata>& LoopingSDIFFileReader::GetListOfLoops()
53 {
54  return listOfLoops;
55 }
56 
57 void LoopingSDIFFileReader::SetListOfLoops(std::vector<SimpleLoopMetadata>& argListOfLoops)
58 {
59  listOfLoops.clear();
60  std::vector<SimpleLoopMetadata>::iterator theIterator;
61  for( theIterator = argListOfLoops.begin(); theIterator != argListOfLoops.end(); theIterator++)
62  {
63  SimpleLoopMetadata& aSimpleLoop = *theIterator;
64  listOfLoops.push_back(aSimpleLoop);
65 
66  //std::cout << "LoopingSDIFFileReader: received loop point <" << aSimpleLoop.GetStart();
67  //std::cout << ">, <" << aSimpleLoop.GetEnd() << ">" << std::endl;
68  }
69 }
70 
72 {
73  int lFrameBufferPosition = BufferedSDIFFileReader::GetFrameBufferPosition();
74  SimpleLoopMetadata& simpleLoop = listOfLoops.at(indexOfCurrentLoop);
75 
76  // check to see whether we are at the loop point. if so, push the framePosition
77  // back to the start of the loop
78  if (lFrameBufferPosition == simpleLoop.GetEnd())
79  {
80  lFrameBufferPosition = simpleLoop.GetStart();
82  indexOfCurrentLoop = ChooseLoopRandomly(lFrameBufferPosition, indexOfCurrentLoop);
83 
84  //SimpleLoopMetadata& tempSimpleLoop = listOfLoops.at(indexOfCurrentLoop);
85  //std::cout << "LoopingSDIFFIleREader: switching to loop with start: " << tempSimpleLoop.GetStart();
86  //std::cout << " and end: " << tempSimpleLoop.GetEnd() << std::endl;
87  }
88 
89  // get the current frame from the BufferedSDIFFileReader
91 
92  // we will later modify the frame, but we don't want the frame object
93  // being cached by the BufferedSDIFFIleReader to be modified
94  // so let's copy it.
95  DataUtil::CopyFrameMembers(*nextFrame, *outgoingFrame);
96 
97  // Check to see whether we are near the loop point. If so, we'll have
98  // to crossfade this frame with the frame at the other end of the loop.
99  if ( (lFrameBufferPosition + numberOfCrossfadeFrames) >= simpleLoop.GetEnd() )
100  {
101  Frame* startLoopFrame = BufferedSDIFFileReader::GetFrame( simpleLoop.GetStart() );
102  Frame* frameNearEndLoopFrame = nextFrame;
103 
104  // if we are crossfading 10 frames and we are currently on frame 3, the
105  // crossfade factor is 3/10
106  float crossfadeFactor = ( (lFrameBufferPosition + numberOfCrossfadeFrames)
107  - simpleLoop.GetEnd() * 1.0 ) /
108  numberOfCrossfadeFrames;
109 
110  CrossfadeSpectralPeakArrays(frameNearEndLoopFrame->GetSpectralPeakArray(),
111  startLoopFrame->GetSpectralPeakArray(),
112  outgoingFrame->GetSpectralPeakArray(),
113  crossfadeFactor);
114 
115  CrossfadeResidualSpectrum(frameNearEndLoopFrame->GetResidualSpec(),
116  startLoopFrame->GetResidualSpec(),
117  outgoingFrame->GetResidualSpec(),
118  crossfadeFactor);
119  }
120 
121  return outgoingFrame;
122 }
123 
124 int LoopingSDIFFileReader::ChooseLoopRandomly(int argFrameBufferPosition, int argIndexOfCurrentLoop)
125 {
126  // suppose that the current frame number is 1413. If we have a list of possible
127  // loops whose start and end points are (580, 1163), (850, 2100), and (982, 2310)
128  // we can only choose the second two loops, because the end point of the first
129  // is before the current frame position.
130  // but if we've only loaded 2200 frames into memory, then actually only the middle
131  // loop is valid.
132  // so here we look for valid loops that pass these two tests.
133  std::deque<int> validLoopPositions;
134  std::deque<int>::iterator currentLoopIterator = validLoopPositions.end();
135  for (unsigned int counter = 0; counter < listOfLoops.size(); counter++)
136  {
137  SimpleLoopMetadata& simpleLoop = listOfLoops.at(indexOfCurrentLoop);
138 
139  if ( argFrameBufferPosition < simpleLoop.GetEnd()
140  && BufferedSDIFFileReader::GetNumberOfFramesLoaded() >= simpleLoop.GetEnd() )
141  {
142  validLoopPositions.push_back(counter);
143  if (counter == argIndexOfCurrentLoop)
144  {
145  currentLoopIterator = validLoopPositions.end();
146  currentLoopIterator--;
147  }
148  }
149  }
150 
151  // if we have a couple of loops to choose from, don't allow the algorithm to
152  // choose the loop we are already in.
153  if (validLoopPositions.size() > 1 && currentLoopIterator != validLoopPositions.end())
154  {
155  validLoopPositions.erase(currentLoopIterator);
156  }
157 
158  double randomNumber0To1 = (rand()*1.0) / RAND_MAX;
159  int randomIndex = floor( randomNumber0To1 * validLoopPositions.size() );
160 
161  return validLoopPositions.at(randomIndex);
162 }
163 
164 void LoopingSDIFFileReader::CrossfadeSpectralPeakArrays(SpectralPeakArray& sourceSpectralPeaks1,
165  SpectralPeakArray& sourceSpectralPeaks2,
166  SpectralPeakArray& targetSpectralPeaks,
167  float crossfadeFactor)
168 {
169  // todo why does this sound bad?
170  //sourceSpectralPeaks1.TodB();
171  //sourceSpectralPeaks2.TodB();
172  //targetSpectralPeaks.SetScale(EScale::eLog);
173 
174  DataArray& srcFreqBuffer1 = sourceSpectralPeaks1.GetFreqBuffer();
175  DataArray& srcMagBuffer1 = sourceSpectralPeaks1.GetMagBuffer();
176 
177  DataArray& srcFreqBuffer2 = sourceSpectralPeaks2.GetFreqBuffer();
178  DataArray& srcMagBuffer2 = sourceSpectralPeaks2.GetMagBuffer();
179 
180  DataArray& targetFreqBuffer = targetSpectralPeaks.GetFreqBuffer();
181  DataArray& targetMagBuffer = targetSpectralPeaks.GetMagBuffer();
182 
183  float flippedCrossfadeFactor = 1.0 - crossfadeFactor;
184  int numberOfPeaks1 = sourceSpectralPeaks1.GetnPeaks();
185  int numberOfPeaks2 = sourceSpectralPeaks2.GetnPeaks();
186  int srcCounter1 = 0;
187  int srcCounter2 = 0;
188  int targetCounter = 0;
189  float semitoneDown = 0.944;
190  float semitoneUp = 1.059;
191  while ( srcCounter1 < numberOfPeaks1 || srcCounter2 < numberOfPeaks2 )
192  {
193  float peakDifference = srcFreqBuffer1[srcCounter1] / srcFreqBuffer2[srcCounter2];
194 
195  // if the peaks are less than a semitone apart, everything is fine. crossfade them.
196  if ( peakDifference > semitoneDown && peakDifference < semitoneUp )
197  {
198  // get frequency , mag and phase
199  targetFreqBuffer[targetCounter] = (srcFreqBuffer1[srcCounter1] * flippedCrossfadeFactor)
200  + (srcFreqBuffer2[srcCounter2] * crossfadeFactor);
201  targetMagBuffer[targetCounter] = (srcMagBuffer1[srcCounter1] * flippedCrossfadeFactor)
202  + (srcMagBuffer2[srcCounter2] * crossfadeFactor);
203  /*
204  if (targetCounter == 0)
205  {
206  printf("mag 1: %f, mag 2: %f, result: %f \n", srcMagBuffer1[srcCounter1], srcMagBuffer2[srcCounter2], targetMagBuffer[targetCounter]);
207  printf("scale is linear? %i \n", (sourceSpectralPeaks1.GetScale()==EScale::eLinear));
208  }
209  */
210  targetCounter++;
211  if (srcCounter1 < numberOfPeaks1)
212  srcCounter1++;
213  if (srcCounter2 < numberOfPeaks2)
214  srcCounter2++;
215  }
216  // the first frequency is a over a semitone below the second. let's fade the
217  // first freqency out and skip on to the next frequency
218  else if (peakDifference < semitoneDown)
219  {
220  if (srcCounter1 < numberOfPeaks1)
221  srcCounter1++;
222 
223  targetFreqBuffer[targetCounter] = (srcFreqBuffer1[srcCounter1] * flippedCrossfadeFactor);
224  targetMagBuffer[targetCounter] = (srcMagBuffer1[srcCounter1] * flippedCrossfadeFactor);
225  }
226  // the first frequency is a over a semitone above the second. let's fade
227  // the second frequency in and skip on to the second frequency
228  else
229  {
230  if (srcCounter2 < numberOfPeaks2)
231  srcCounter2++;
232 
233  targetFreqBuffer[targetCounter] = (srcFreqBuffer2[srcCounter2] * crossfadeFactor);
234  targetMagBuffer[targetCounter] = (srcMagBuffer2[srcCounter2] * crossfadeFactor);
235  }
236  }
237 
238  //targetSpectralPeaks.ToLinear();
239 }
240 
241 
242 void LoopingSDIFFileReader::CrossfadeResidualSpectrum(Spectrum& sourceSpectrum1,
243  Spectrum& sourceSpectrum2,
244  Spectrum& targetSpectrum,
245  float crossfadeFactor)
246 {
247  int size = sourceSpectrum1.GetSize();
248  targetSpectrum.SetSize( size );
249 
250  Array<Complex>& srcComplexBuffer1 = sourceSpectrum1.GetComplexArray();
251  Array<Complex>& srcComplexBuffer2 = sourceSpectrum2.GetComplexArray();
252  Array<Complex>& targetComplexBuffer = targetSpectrum.GetComplexArray();
253 
254  float flippedCrossfadeFactor = 1.0 - crossfadeFactor;
255  for (int r=0; r < size; r++)
256  {
257  // TODO figure out how to implement this using complex numbers
258  targetComplexBuffer[r] = (srcComplexBuffer1[r] * flippedCrossfadeFactor)
259  + (srcComplexBuffer2[r] * crossfadeFactor);
260  }
261 }
262 
264 {
266 }
267 
268 } // end namespace CLAM
269