LoopingSDIFFileReader.cxx

Go to the documentation of this file.
00001 #include "LoopingSDIFFileReader.hxx"
00002 #include "DataUtil.hxx"
00003 #include <time.h>
00004 #include <vector>
00005 
00006 namespace CLAM
00007 {
00008         
00009 LoopingSDIFFileReader::LoopingSDIFFileReader(const SDIFInConfig& argSDIFInConfig)
00010 :       BufferedSDIFFileReader(argSDIFInConfig), 
00011         numberOfCrossfadeFrames(DEFAULT_NUMBER_OF_CROSSFADE_FRAMES),
00012         indexOfCurrentLoop(0)
00013 {
00014         outgoingFrame = new Frame();
00015         outgoingFrame->AddSpectralPeakArray();
00016         outgoingFrame->AddResidualSpec();
00017         outgoingFrame->AddFundamental();
00018         outgoingFrame->AddSynthAudioFrame();
00019         outgoingFrame->UpdateData();
00020         
00021         Configure(argSDIFInConfig);
00022 }
00023 
00024 LoopingSDIFFileReader::~LoopingSDIFFileReader()
00025 {
00026         delete outgoingFrame;
00027 }
00028 
00029 bool LoopingSDIFFileReader::Configure(const SDIFInConfig& c)
00030 {
00031         /* initialize random seed: */
00032         srand ( time(NULL) );
00033         
00034         return true;
00035 }
00036 
00037 bool LoopingSDIFFileReader::isLooping()
00038 {
00039         return listOfLoops.size() != 0;
00040 }
00041 
00042 void LoopingSDIFFileReader::AddLoop(SimpleLoopMetadata& aSimpleLoop)
00043 {
00044         listOfLoops.push_back(aSimpleLoop);
00045 }
00046 
00047 void LoopingSDIFFileReader::ClearLoops()
00048 {
00049         listOfLoops.clear();
00050 }
00051 
00052 std::vector<SimpleLoopMetadata>& LoopingSDIFFileReader::GetListOfLoops()
00053 {
00054         return listOfLoops;
00055 }
00056 
00057 void LoopingSDIFFileReader::SetListOfLoops(std::vector<SimpleLoopMetadata>& argListOfLoops)
00058 {
00059         listOfLoops.clear();
00060         std::vector<SimpleLoopMetadata>::iterator theIterator;
00061         for( theIterator = argListOfLoops.begin(); theIterator != argListOfLoops.end(); theIterator++)
00062         {
00063                 SimpleLoopMetadata& aSimpleLoop = *theIterator;
00064                 listOfLoops.push_back(aSimpleLoop);
00065                 
00066                 //std::cout << "LoopingSDIFFileReader: received loop point <" << aSimpleLoop.GetStart();
00067                 //std::cout << ">, <" << aSimpleLoop.GetEnd() << ">" << std::endl;
00068         }
00069 }
00070 
00071 Frame* LoopingSDIFFileReader::ReadFrame()
00072 {
00073         int lFrameBufferPosition = BufferedSDIFFileReader::GetFrameBufferPosition();
00074         SimpleLoopMetadata& simpleLoop = listOfLoops.at(indexOfCurrentLoop);
00075         
00076         // check to see whether we are at the loop point. if so, push the framePosition
00077         // back to the start of the loop
00078         if (lFrameBufferPosition == simpleLoop.GetEnd())
00079         {
00080                 lFrameBufferPosition = simpleLoop.GetStart();
00081                 BufferedSDIFFileReader::SetFrameBufferPosition(lFrameBufferPosition);
00082                 indexOfCurrentLoop = ChooseLoopRandomly(lFrameBufferPosition, indexOfCurrentLoop);
00083                 
00084                 //SimpleLoopMetadata& tempSimpleLoop = listOfLoops.at(indexOfCurrentLoop);
00085                 //std::cout << "LoopingSDIFFIleREader: switching to loop with start: " << tempSimpleLoop.GetStart();
00086                 //std::cout << " and end: " << tempSimpleLoop.GetEnd() << std::endl;
00087         }
00088 
00089         // get the current frame from the BufferedSDIFFileReader
00090         Frame* nextFrame = BufferedSDIFFileReader::ReadFrame();
00091 
00092         // we will later modify the frame, but we don't want the frame object
00093         // being cached by the BufferedSDIFFIleReader to be modified
00094         // so let's copy it.
00095         DataUtil::CopyFrameMembers(*nextFrame, *outgoingFrame);
00096 
00097         // Check to see whether we are near the loop point. If so, we'll have
00098         // to crossfade this frame with the frame at the other end of the loop.
00099         if ( (lFrameBufferPosition + numberOfCrossfadeFrames) >= simpleLoop.GetEnd() )
00100         {
00101                 Frame* startLoopFrame = BufferedSDIFFileReader::GetFrame( simpleLoop.GetStart() );
00102                 Frame* frameNearEndLoopFrame = nextFrame;
00103                 
00104                 // if we are crossfading 10 frames and we are currently on frame 3, the 
00105                 // crossfade factor is 3/10
00106                 float crossfadeFactor = ( (lFrameBufferPosition + numberOfCrossfadeFrames) 
00107                                                                 - simpleLoop.GetEnd() * 1.0 ) /
00108                                                                 numberOfCrossfadeFrames;
00109                                                                 
00110                 CrossfadeSpectralPeakArrays(frameNearEndLoopFrame->GetSpectralPeakArray(), 
00111                                                                         startLoopFrame->GetSpectralPeakArray(),
00112                                                                         outgoingFrame->GetSpectralPeakArray(),
00113                                                                         crossfadeFactor);
00114                 
00115                 CrossfadeResidualSpectrum(frameNearEndLoopFrame->GetResidualSpec(), 
00116                                                                         startLoopFrame->GetResidualSpec(),
00117                                                                         outgoingFrame->GetResidualSpec(),
00118                                                                         crossfadeFactor);
00119         }
00120         
00121         return outgoingFrame;
00122 }
00123 
00124 int LoopingSDIFFileReader::ChooseLoopRandomly(int argFrameBufferPosition, int argIndexOfCurrentLoop)
00125 {
00126         // suppose that the current frame number is 1413. If we have a list of possible
00127         // loops whose start and end points are (580, 1163), (850, 2100), and (982, 2310)
00128         // we can only choose the second two loops, because the end point of the first
00129         // is before the current frame position.
00130         // but if we've only loaded 2200 frames into memory, then actually only the middle
00131         // loop is valid.
00132         // so here we look for valid loops that pass these two tests.
00133         std::deque<int> validLoopPositions;
00134         std::deque<int>::iterator currentLoopIterator = validLoopPositions.end();
00135         for (unsigned int counter = 0; counter < listOfLoops.size(); counter++)
00136         {
00137                 SimpleLoopMetadata& simpleLoop = listOfLoops.at(indexOfCurrentLoop);
00138                 
00139                 if ( argFrameBufferPosition < simpleLoop.GetEnd() 
00140                         && BufferedSDIFFileReader::GetNumberOfFramesLoaded() >= simpleLoop.GetEnd() )
00141                 {
00142                         validLoopPositions.push_back(counter);
00143                         if (counter == argIndexOfCurrentLoop)
00144                         {
00145                                 currentLoopIterator = validLoopPositions.end();
00146                                 currentLoopIterator--;
00147                         }
00148                 }
00149         }
00150         
00151         // if we have a couple of loops to choose from, don't allow the algorithm to
00152         // choose the loop we are already in. 
00153         if (validLoopPositions.size() > 1 && currentLoopIterator != validLoopPositions.end())
00154         {
00155                 validLoopPositions.erase(currentLoopIterator);
00156         }
00157         
00158         double randomNumber0To1 = (rand()*1.0) / RAND_MAX;
00159         int randomIndex = floor( randomNumber0To1 * validLoopPositions.size() );
00160         
00161         return validLoopPositions.at(randomIndex);
00162 }
00163 
00164 void LoopingSDIFFileReader::CrossfadeSpectralPeakArrays(SpectralPeakArray& sourceSpectralPeaks1,
00165                                                                                                                 SpectralPeakArray& sourceSpectralPeaks2,
00166                                                                                                                 SpectralPeakArray& targetSpectralPeaks,
00167                                                                                                                 float crossfadeFactor)
00168 {
00169         // todo why does this sound bad?
00170         //sourceSpectralPeaks1.TodB();
00171         //sourceSpectralPeaks2.TodB();
00172         //targetSpectralPeaks.SetScale(EScale::eLog);
00173         
00174         DataArray& srcFreqBuffer1 = sourceSpectralPeaks1.GetFreqBuffer();
00175         DataArray& srcMagBuffer1 = sourceSpectralPeaks1.GetMagBuffer();
00176 
00177         DataArray& srcFreqBuffer2 = sourceSpectralPeaks2.GetFreqBuffer();
00178         DataArray& srcMagBuffer2 = sourceSpectralPeaks2.GetMagBuffer();
00179 
00180         DataArray& targetFreqBuffer = targetSpectralPeaks.GetFreqBuffer();
00181         DataArray& targetMagBuffer = targetSpectralPeaks.GetMagBuffer();
00182 
00183         float flippedCrossfadeFactor = 1.0 - crossfadeFactor;
00184         int numberOfPeaks1 = sourceSpectralPeaks1.GetnPeaks();
00185         int numberOfPeaks2 = sourceSpectralPeaks2.GetnPeaks();
00186         int srcCounter1 = 0;
00187         int srcCounter2 = 0;
00188         int targetCounter = 0;
00189         float semitoneDown = 0.944;
00190         float semitoneUp = 1.059;
00191         while ( srcCounter1 < numberOfPeaks1 || srcCounter2 < numberOfPeaks2 )
00192         {
00193                 float peakDifference = srcFreqBuffer1[srcCounter1] / srcFreqBuffer2[srcCounter2];
00194                 
00195                 // if the peaks are less than a semitone apart, everything is fine. crossfade them.
00196                 if ( peakDifference > semitoneDown && peakDifference < semitoneUp )
00197                 {
00198                         // get frequency , mag and phase
00199                         targetFreqBuffer[targetCounter] = (srcFreqBuffer1[srcCounter1] * flippedCrossfadeFactor)
00200                                                                         + (srcFreqBuffer2[srcCounter2] * crossfadeFactor);
00201                         targetMagBuffer[targetCounter] = (srcMagBuffer1[srcCounter1] * flippedCrossfadeFactor)
00202                                                                         + (srcMagBuffer2[srcCounter2] * crossfadeFactor);
00203                         /*
00204                         if (targetCounter == 0)
00205                         {
00206                                 printf("mag 1: %f, mag 2: %f, result: %f \n", srcMagBuffer1[srcCounter1], srcMagBuffer2[srcCounter2], targetMagBuffer[targetCounter]);
00207                                 printf("scale is linear? %i \n", (sourceSpectralPeaks1.GetScale()==EScale::eLinear));
00208                         }
00209                         */
00210                         targetCounter++;
00211                         if (srcCounter1 < numberOfPeaks1)
00212                                 srcCounter1++;
00213                         if (srcCounter2 < numberOfPeaks2)
00214                                 srcCounter2++;
00215                 }
00216                 // the first frequency is a over a semitone below the second. let's fade the
00217                 // first freqency out and skip on to the next frequency
00218                 else if (peakDifference < semitoneDown)
00219                 {
00220                         if (srcCounter1 < numberOfPeaks1)
00221                                 srcCounter1++;
00222 
00223                         targetFreqBuffer[targetCounter] = (srcFreqBuffer1[srcCounter1] * flippedCrossfadeFactor);
00224                         targetMagBuffer[targetCounter] = (srcMagBuffer1[srcCounter1] * flippedCrossfadeFactor);
00225                 }
00226                 // the first frequency is a over a semitone above the second. let's fade 
00227                 // the second frequency in and skip on to the second frequency
00228                 else
00229                 {
00230                         if (srcCounter2 < numberOfPeaks2)
00231                                 srcCounter2++;
00232 
00233                         targetFreqBuffer[targetCounter] = (srcFreqBuffer2[srcCounter2] * crossfadeFactor);
00234                         targetMagBuffer[targetCounter] = (srcMagBuffer2[srcCounter2] * crossfadeFactor);
00235                 }
00236         }
00237 
00238         //targetSpectralPeaks.ToLinear();
00239 }
00240 
00241 
00242 void LoopingSDIFFileReader::CrossfadeResidualSpectrum(Spectrum& sourceSpectrum1,
00243                                                                 Spectrum& sourceSpectrum2,
00244                                                                 Spectrum& targetSpectrum,
00245                                                                 float crossfadeFactor)
00246 {
00247         int size = sourceSpectrum1.GetSize();
00248         targetSpectrum.SetSize( size );
00249 
00250         Array<Complex>& srcComplexBuffer1 = sourceSpectrum1.GetComplexArray();
00251         Array<Complex>& srcComplexBuffer2 = sourceSpectrum2.GetComplexArray();
00252         Array<Complex>& targetComplexBuffer = targetSpectrum.GetComplexArray();
00253 
00254         float flippedCrossfadeFactor = 1.0 - crossfadeFactor;
00255         for (int r=0; r < size; r++)
00256         {
00257                 // TODO figure out how to implement this using complex numbers
00258                 targetComplexBuffer[r] = (srcComplexBuffer1[r] * flippedCrossfadeFactor)
00259                                                                         + (srcComplexBuffer2[r] * crossfadeFactor);
00260         }
00261 }
00262 
00263 void LoopingSDIFFileReader::Reset()
00264 {
00265         BufferedSDIFFileReader::SetFrameBufferPosition( 0 );
00266 }
00267 
00268 } // end namespace CLAM
00269 
Generated by  doxygen 1.6.3