Enforce no-null-args to FFTs; avoid corresponding potential crash in formant preservation code

This commit is contained in:
Chris Cannam
2012-10-28 10:23:42 +00:00
parent 39a311b383
commit 82d1f570da
3 changed files with 63 additions and 3 deletions

View File

@@ -930,7 +930,8 @@ RubberBandStretcher::Impl::formantShiftChunk(size_t channel)
v_scale(dblbuf, factor, cutoff);
cd.fft->forward(dblbuf, envelope, 0);
double *spare = (double *)alloca((hs + 1) * sizeof(double));
cd.fft->forward(dblbuf, envelope, spare);
v_exp(envelope, hs + 1);
v_divide(mag, envelope, hs + 1);

View File

@@ -3187,99 +3187,154 @@ FFT::~FFT()
delete d;
}
#ifndef NO_EXCEPTIONS
#define CHECK_NOT_NULL(x) \
if (!(x)) { \
std::cerr << "FFT: ERROR: Null argument " #x << std::endl; \
throw NullArgument; \
}
#else
#define CHECK_NOT_NULL(x) \
if (!(x)) { \
std::cerr << "FFT: ERROR: Null argument " #x << std::endl; \
std::cerr << "FFT: Would be throwing NullArgument here, if exceptions were not disabled" << std::endl; \
return; \
}
#endif
void
FFT::forward(const double *R__ realIn, double *R__ realOut, double *R__ imagOut)
{
CHECK_NOT_NULL(realIn);
CHECK_NOT_NULL(realOut);
CHECK_NOT_NULL(imagOut);
d->forward(realIn, realOut, imagOut);
}
void
FFT::forwardInterleaved(const double *R__ realIn, double *R__ complexOut)
{
CHECK_NOT_NULL(realIn);
CHECK_NOT_NULL(complexOut);
d->forwardInterleaved(realIn, complexOut);
}
void
FFT::forwardPolar(const double *R__ realIn, double *R__ magOut, double *R__ phaseOut)
{
CHECK_NOT_NULL(realIn);
CHECK_NOT_NULL(magOut);
CHECK_NOT_NULL(phaseOut);
d->forwardPolar(realIn, magOut, phaseOut);
}
void
FFT::forwardMagnitude(const double *R__ realIn, double *R__ magOut)
{
CHECK_NOT_NULL(realIn);
CHECK_NOT_NULL(magOut);
d->forwardMagnitude(realIn, magOut);
}
void
FFT::forward(const float *R__ realIn, float *R__ realOut, float *R__ imagOut)
{
CHECK_NOT_NULL(realIn);
CHECK_NOT_NULL(realOut);
CHECK_NOT_NULL(imagOut);
d->forward(realIn, realOut, imagOut);
}
void
FFT::forwardInterleaved(const float *R__ realIn, float *R__ complexOut)
{
CHECK_NOT_NULL(realIn);
CHECK_NOT_NULL(complexOut);
d->forwardInterleaved(realIn, complexOut);
}
void
FFT::forwardPolar(const float *R__ realIn, float *R__ magOut, float *R__ phaseOut)
{
CHECK_NOT_NULL(realIn);
CHECK_NOT_NULL(magOut);
CHECK_NOT_NULL(phaseOut);
d->forwardPolar(realIn, magOut, phaseOut);
}
void
FFT::forwardMagnitude(const float *R__ realIn, float *R__ magOut)
{
CHECK_NOT_NULL(realIn);
CHECK_NOT_NULL(magOut);
d->forwardMagnitude(realIn, magOut);
}
void
FFT::inverse(const double *R__ realIn, const double *R__ imagIn, double *R__ realOut)
{
CHECK_NOT_NULL(realIn);
CHECK_NOT_NULL(imagIn);
CHECK_NOT_NULL(realOut);
d->inverse(realIn, imagIn, realOut);
}
void
FFT::inverseInterleaved(const double *R__ complexIn, double *R__ realOut)
{
CHECK_NOT_NULL(complexIn);
CHECK_NOT_NULL(realOut);
d->inverseInterleaved(complexIn, realOut);
}
void
FFT::inversePolar(const double *R__ magIn, const double *R__ phaseIn, double *R__ realOut)
{
CHECK_NOT_NULL(magIn);
CHECK_NOT_NULL(phaseIn);
CHECK_NOT_NULL(realOut);
d->inversePolar(magIn, phaseIn, realOut);
}
void
FFT::inverseCepstral(const double *R__ magIn, double *R__ cepOut)
{
CHECK_NOT_NULL(magIn);
CHECK_NOT_NULL(cepOut);
d->inverseCepstral(magIn, cepOut);
}
void
FFT::inverse(const float *R__ realIn, const float *R__ imagIn, float *R__ realOut)
{
CHECK_NOT_NULL(realIn);
CHECK_NOT_NULL(imagIn);
CHECK_NOT_NULL(realOut);
d->inverse(realIn, imagIn, realOut);
}
void
FFT::inverseInterleaved(const float *R__ complexIn, float *R__ realOut)
{
CHECK_NOT_NULL(complexIn);
CHECK_NOT_NULL(realOut);
d->inverseInterleaved(complexIn, realOut);
}
void
FFT::inversePolar(const float *R__ magIn, const float *R__ phaseIn, float *R__ realOut)
{
CHECK_NOT_NULL(magIn);
CHECK_NOT_NULL(phaseIn);
CHECK_NOT_NULL(realOut);
d->inversePolar(magIn, phaseIn, realOut);
}
void
FFT::inverseCepstral(const float *R__ magIn, float *R__ cepOut)
{
CHECK_NOT_NULL(magIn);
CHECK_NOT_NULL(cepOut);
d->inverseCepstral(magIn, cepOut);
}

View File

@@ -45,17 +45,21 @@ class FFTImpl;
* The "interleaved" functions use the format sometimes called CCS --
* size/2+1 real+imaginary pairs. So, the array elements at indices 1
* and size+1 will always be zero (since the signal is real).
*
* All pointer arguments must point to valid data. A NullArgument
* exception is thrown if any argument is NULL.
*
* Neither forward nor inverse transform is scaled.
*
* This class is reentrant but not thread safe: use a separate
* instance per thread, or use a mutex.
*/
class FFT
{
public:
enum Exception { InvalidSize, InvalidImplementation, InternalError };
enum Exception {
NullArgument, InvalidSize, InvalidImplementation, InternalError
};
FFT(int size, int debugLevel = 0); // may throw InvalidSize
~FFT();