CLAM-Development
1.1
|
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