Enforce no-null-args to FFTs; avoid corresponding potential crash in formant preservation code
This commit is contained in:
@@ -930,7 +930,8 @@ RubberBandStretcher::Impl::formantShiftChunk(size_t channel)
|
|||||||
|
|
||||||
v_scale(dblbuf, factor, cutoff);
|
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_exp(envelope, hs + 1);
|
||||||
v_divide(mag, envelope, hs + 1);
|
v_divide(mag, envelope, hs + 1);
|
||||||
|
|||||||
@@ -3187,99 +3187,154 @@ FFT::~FFT()
|
|||||||
delete d;
|
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
|
void
|
||||||
FFT::forward(const double *R__ realIn, double *R__ realOut, double *R__ imagOut)
|
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);
|
d->forward(realIn, realOut, imagOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
FFT::forwardInterleaved(const double *R__ realIn, double *R__ complexOut)
|
FFT::forwardInterleaved(const double *R__ realIn, double *R__ complexOut)
|
||||||
{
|
{
|
||||||
|
CHECK_NOT_NULL(realIn);
|
||||||
|
CHECK_NOT_NULL(complexOut);
|
||||||
d->forwardInterleaved(realIn, complexOut);
|
d->forwardInterleaved(realIn, complexOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
FFT::forwardPolar(const double *R__ realIn, double *R__ magOut, double *R__ phaseOut)
|
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);
|
d->forwardPolar(realIn, magOut, phaseOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
FFT::forwardMagnitude(const double *R__ realIn, double *R__ magOut)
|
FFT::forwardMagnitude(const double *R__ realIn, double *R__ magOut)
|
||||||
{
|
{
|
||||||
|
CHECK_NOT_NULL(realIn);
|
||||||
|
CHECK_NOT_NULL(magOut);
|
||||||
d->forwardMagnitude(realIn, magOut);
|
d->forwardMagnitude(realIn, magOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
FFT::forward(const float *R__ realIn, float *R__ realOut, float *R__ imagOut)
|
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);
|
d->forward(realIn, realOut, imagOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
FFT::forwardInterleaved(const float *R__ realIn, float *R__ complexOut)
|
FFT::forwardInterleaved(const float *R__ realIn, float *R__ complexOut)
|
||||||
{
|
{
|
||||||
|
CHECK_NOT_NULL(realIn);
|
||||||
|
CHECK_NOT_NULL(complexOut);
|
||||||
d->forwardInterleaved(realIn, complexOut);
|
d->forwardInterleaved(realIn, complexOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
FFT::forwardPolar(const float *R__ realIn, float *R__ magOut, float *R__ phaseOut)
|
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);
|
d->forwardPolar(realIn, magOut, phaseOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
FFT::forwardMagnitude(const float *R__ realIn, float *R__ magOut)
|
FFT::forwardMagnitude(const float *R__ realIn, float *R__ magOut)
|
||||||
{
|
{
|
||||||
|
CHECK_NOT_NULL(realIn);
|
||||||
|
CHECK_NOT_NULL(magOut);
|
||||||
d->forwardMagnitude(realIn, magOut);
|
d->forwardMagnitude(realIn, magOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
FFT::inverse(const double *R__ realIn, const double *R__ imagIn, double *R__ realOut)
|
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);
|
d->inverse(realIn, imagIn, realOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
FFT::inverseInterleaved(const double *R__ complexIn, double *R__ realOut)
|
FFT::inverseInterleaved(const double *R__ complexIn, double *R__ realOut)
|
||||||
{
|
{
|
||||||
|
CHECK_NOT_NULL(complexIn);
|
||||||
|
CHECK_NOT_NULL(realOut);
|
||||||
d->inverseInterleaved(complexIn, realOut);
|
d->inverseInterleaved(complexIn, realOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
FFT::inversePolar(const double *R__ magIn, const double *R__ phaseIn, double *R__ realOut)
|
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);
|
d->inversePolar(magIn, phaseIn, realOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
FFT::inverseCepstral(const double *R__ magIn, double *R__ cepOut)
|
FFT::inverseCepstral(const double *R__ magIn, double *R__ cepOut)
|
||||||
{
|
{
|
||||||
|
CHECK_NOT_NULL(magIn);
|
||||||
|
CHECK_NOT_NULL(cepOut);
|
||||||
d->inverseCepstral(magIn, cepOut);
|
d->inverseCepstral(magIn, cepOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
FFT::inverse(const float *R__ realIn, const float *R__ imagIn, float *R__ realOut)
|
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);
|
d->inverse(realIn, imagIn, realOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
FFT::inverseInterleaved(const float *R__ complexIn, float *R__ realOut)
|
FFT::inverseInterleaved(const float *R__ complexIn, float *R__ realOut)
|
||||||
{
|
{
|
||||||
|
CHECK_NOT_NULL(complexIn);
|
||||||
|
CHECK_NOT_NULL(realOut);
|
||||||
d->inverseInterleaved(complexIn, realOut);
|
d->inverseInterleaved(complexIn, realOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
FFT::inversePolar(const float *R__ magIn, const float *R__ phaseIn, float *R__ realOut)
|
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);
|
d->inversePolar(magIn, phaseIn, realOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
FFT::inverseCepstral(const float *R__ magIn, float *R__ cepOut)
|
FFT::inverseCepstral(const float *R__ magIn, float *R__ cepOut)
|
||||||
{
|
{
|
||||||
|
CHECK_NOT_NULL(magIn);
|
||||||
|
CHECK_NOT_NULL(cepOut);
|
||||||
d->inverseCepstral(magIn, cepOut);
|
d->inverseCepstral(magIn, cepOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -45,17 +45,21 @@ class FFTImpl;
|
|||||||
* The "interleaved" functions use the format sometimes called CCS --
|
* The "interleaved" functions use the format sometimes called CCS --
|
||||||
* size/2+1 real+imaginary pairs. So, the array elements at indices 1
|
* 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).
|
* 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.
|
* Neither forward nor inverse transform is scaled.
|
||||||
*
|
*
|
||||||
* This class is reentrant but not thread safe: use a separate
|
* This class is reentrant but not thread safe: use a separate
|
||||||
* instance per thread, or use a mutex.
|
* instance per thread, or use a mutex.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class FFT
|
class FFT
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum Exception { InvalidSize, InvalidImplementation, InternalError };
|
enum Exception {
|
||||||
|
NullArgument, InvalidSize, InvalidImplementation, InternalError
|
||||||
|
};
|
||||||
|
|
||||||
FFT(int size, int debugLevel = 0); // may throw InvalidSize
|
FFT(int size, int debugLevel = 0); // may throw InvalidSize
|
||||||
~FFT();
|
~FFT();
|
||||||
|
|||||||
Reference in New Issue
Block a user