/********************************************************************** Audacity: A Digital Audio Editor InterpolateAudio.cpp Dominic Mazzoni **********************************************************************/ #include "InterpolateAudio.h" #include #include #include #include "Matrix.h" static inline int imin(int x, int y) { return xy? x: y; } // This function is a really dumb, simple way to interpolate audio, // if the more general InterpolateAudio function below doesn't have // enough data to work with. If the bad samples are in the middle, // it's literally linear. If it's on either edge, we add some decay // back to zero. static void LinearInterpolateAudio(float *buffer, int len, int firstBad, int numBad) { int i; float decay = 0.9f; if (firstBad==0) { float delta = buffer[numBad] - buffer[numBad+1]; float value = buffer[numBad]; i = numBad - 1; while (i >= 0) { value += delta; buffer[i] = value; value *= decay; delta *= decay; i--; } } else if (firstBad + numBad == len) { float delta = buffer[firstBad-1] - buffer[firstBad-2]; float value = buffer[firstBad-1]; i = firstBad; while (i < firstBad + numBad) { value += delta; buffer[i] = value; value *= decay; delta *= decay; i++; } } else { float v1 = buffer[firstBad-1]; float v2 = buffer[firstBad+numBad]; float value = v1; float delta = (v2 - v1) / (numBad+1); i = firstBad; while (i < firstBad + numBad) { value += delta; buffer[i] = value; i++; } } } // Here's the main interpolate function, using // Least Squares AutoRegression (LSAR): void InterpolateAudio(float *buffer, const size_t len, size_t firstBad, size_t numBad) { const auto N = len; wxASSERT(len > 0 && firstBad >= 0 && numBad < len && firstBad+numBad <= len); if(numBad >= len) return; //should never have been called! if (firstBad == 0) { // The algorithm below has a weird asymmetry in that it // performs poorly when interpolating to the left. If // we're asked to interpolate the left side of a buffer, // we just reverse the problem and try it that way. Floats buffer2{ len }; for(size_t i=0; i= (int)N) { LinearInterpolateAudio(buffer, len, firstBad, numBad); return; } size_t P(IP); // Add a tiny amount of random noise to the input signal - // this sounds like a bad idea, but the amount we're adding // is only about 1 bit in 16-bit audio, and it's an extremely // effective way to avoid nearly-singular matrices. If users // run it more than once they get slightly different results; // this is sometimes even advantageous. for(size_t i=0; i= (firstBad + numBad)) for(size_t row=0; row