Commit edb4a505 authored by Sebastian Dröge's avatar Sebastian Dröge
Browse files

Remove the magnitude and phase calculation functions as these have very...

Remove the magnitude and phase calculation functions as these have very special use cases and can't even be used for ...

Original commit message from CVS:
* docs/libs/gst-plugins-base-libs-sections.txt:
* gst-libs/gst/fft/gstfftf32.c:
* gst-libs/gst/fft/gstfftf32.h:
* gst-libs/gst/fft/gstfftf64.c:
* gst-libs/gst/fft/gstfftf64.h:
* gst-libs/gst/fft/gstffts16.c:
* gst-libs/gst/fft/gstffts16.h:
* gst-libs/gst/fft/gstffts32.c:
* gst-libs/gst/fft/gstffts32.h:
* tests/check/libs/fft.c: (GST_START_TEST):
Remove the magnitude and phase calculation functions as these have
very special use cases and can't even be used for the spectrum
element. Also adjust the docs to mention some properties of the used
FFT implemention, i.e. how the values are scaled. Fixes #492098.
parent 750a7248
2007-11-06 Sebastian Dröge <slomo@circular-chaos.org>
* docs/libs/gst-plugins-base-libs-sections.txt:
* gst-libs/gst/fft/gstfftf32.c:
* gst-libs/gst/fft/gstfftf32.h:
* gst-libs/gst/fft/gstfftf64.c:
* gst-libs/gst/fft/gstfftf64.h:
* gst-libs/gst/fft/gstffts16.c:
* gst-libs/gst/fft/gstffts16.h:
* gst-libs/gst/fft/gstffts32.c:
* gst-libs/gst/fft/gstffts32.h:
* tests/check/libs/fft.c: (GST_START_TEST):
Remove the magnitude and phase calculation functions as these have
very special use cases and can't even be used for the spectrum
element. Also adjust the docs to mention some properties of the used
FFT implemention, i.e. how the values are scaled. Fixes #492098.
2007-11-06 Tim-Philipp Müller <tim at centricular dot net>
 
* gst/playback/gstplaybasebin.c: (queue_threshold_reached),
......@@ -242,10 +242,8 @@ GstFFTS16Complex
gst_fft_s16_new
gst_fft_s16_fft
gst_fft_s16_inverse_fft
gst_fft_s16_free
gst_fft_s16_magnitude
gst_fft_s16_phase
gst_fft_s16_window
gst_fft_s16_free
</SECTION>
<SECTION>
......@@ -256,10 +254,8 @@ GstFFTS32Complex
gst_fft_s32_new
gst_fft_s32_fft
gst_fft_s32_inverse_fft
gst_fft_s32_free
gst_fft_s32_magnitude
gst_fft_s32_phase
gst_fft_s32_window
gst_fft_s32_free
</SECTION>
<SECTION>
......@@ -270,10 +266,8 @@ GstFFTF32Complex
gst_fft_f32_new
gst_fft_f32_fft
gst_fft_f32_inverse_fft
gst_fft_f32_free
gst_fft_f32_magnitude
gst_fft_f32_phase
gst_fft_f32_window
gst_fft_f32_free
</SECTION>
<SECTION>
......@@ -284,10 +278,8 @@ GstFFTF64Complex
gst_fft_f64_new
gst_fft_f64_fft
gst_fft_f64_inverse_fft
gst_fft_f64_free
gst_fft_f64_magnitude
gst_fft_f64_phase
gst_fft_f64_window
gst_fft_f64_free
</SECTION>
# floatcast
......
......@@ -48,10 +48,11 @@
* to apply a window function to it. For this gst_fft_f32_window() can comfortably
* be used.
*
* For calculating the magnitude or phase of frequency data the functions
* gst_fft_f32_magnitude() and gst_fft_f32_phase() exist, if you want to calculate
* the magnitude yourself note that the magnitude of the frequency data is
* a value between 0 and 1 and is to be scaled by the length of the FFT.
* Be aware, that you can't simply run gst_fft_f32_inverse_fft() on the
* resulting frequency data of gst_fft_f32_fft() to get the original data back.
* The relation between them is iFFT (FFT (x)) = x * nfft where nfft is the
* length of the FFT. This also has to be taken into account when calculation
* the magnitude of the frequency data.
*
*/
......@@ -200,71 +201,3 @@ gst_fft_f32_window (GstFFTF32 * self, gfloat * timedata, GstFFTWindow window)
break;
}
}
/**
* gst_fft_f32_magnitude:
* @self: #GstFFTF32 instance for this call
* @freqdata: Frequency domain samples
* @magnitude: Target buffer for the magnitude
* @decibel: %TRUE if the magnitude should be in decibel, %FALSE if it should be an amplitude
*
* This calculates the magnitude of @freqdata in @magnitude. Depending on the value
* of @decibel the magnitude can be calculated in decibel or as amplitude between 0.0
* and 1.0.
*
* @magnitude must be large enough to hold @len/2 + 1 values.
*
*/
void
gst_fft_f32_magnitude (GstFFTF32 * self, GstFFTF32Complex * freqdata,
gdouble * magnitude, gboolean decibel)
{
gint i, len, nfft;
gdouble val;
g_return_if_fail (self);
g_return_if_fail (freqdata);
g_return_if_fail (magnitude);
len = self->len / 2 + 1;
nfft = self->len;
for (i = 0; i < len; i++) {
val = (gdouble) freqdata[i].r * (gdouble) freqdata[i].r
+ (gdouble) freqdata[i].i * (gdouble) freqdata[i].i;
val = sqrt (val) / nfft;
if (decibel)
val = 20.0 * log10 (val);
magnitude[i] = val;
}
}
/**
* gst_fft_f32_phase:
* @self: #GstFFTF32 instance for this call
* @freqdata: Frequency domain samples
* @phase: Target buffer for the phase
*
* This calculates the phases of @freqdata in @phase. The returned
* phases will be values between -pi and pi.
*
* @phase must be large enough to hold @len/2 + 1 values.
*
*/
void
gst_fft_f32_phase (GstFFTF32 * self, GstFFTF32Complex * freqdata,
gdouble * phase)
{
gint i, len;
g_return_if_fail (self);
g_return_if_fail (freqdata);
g_return_if_fail (phase);
len = self->len / 2 + 1;
for (i = 0; i < len; i++)
phase[i] = atan2 (freqdata[i].i, freqdata[i].r);
}
......@@ -69,9 +69,4 @@ void gst_fft_f32_free (GstFFTF32 *self);
void gst_fft_f32_window (GstFFTF32 *self, gfloat *timedata, GstFFTWindow window);
void gst_fft_f32_magnitude (GstFFTF32 *self, GstFFTF32Complex *freqdata,
gdouble *magnitude, gboolean decibel);
void gst_fft_f32_phase (GstFFTF32 *self, GstFFTF32Complex *freqdata,
gdouble *phase);
#endif /* __GST_FFT_F32_H__ */
......@@ -48,10 +48,11 @@
* to apply a window function to it. For this gst_fft_f64_window() can comfortably
* be used.
*
* For calculating the magnitude or phase of frequency data the functions
* gst_fft_f64_magnitude() and gst_fft_f64_phase() exist, if you want to calculate
* the magnitude yourself note that the magnitude of the frequency data is
* a value between 0 and 1 and is to be scaled by the length of the FFT.
* Be aware, that you can't simply run gst_fft_f32_inverse_fft() on the
* resulting frequency data of gst_fft_f32_fft() to get the original data back.
* The relation between them is iFFT (FFT (x)) = x * nfft where nfft is the
* length of the FFT. This also has to be taken into account when calculation
* the magnitude of the frequency data.
*
*/
......@@ -200,71 +201,3 @@ gst_fft_f64_window (GstFFTF64 * self, gdouble * timedata, GstFFTWindow window)
break;
}
}
/**
* gst_fft_f64_magnitude:
* @self: #GstFFTF64 instance for this call
* @freqdata: Frequency domain samples
* @magnitude: Target buffer for the magnitude
* @decibel: %TRUE if the magnitude should be in decibel, %FALSE if it should be an amplitude
*
* This calculates the magnitude of @freqdata in @magnitude. Depending on the value
* of @decibel the magnitude can be calculated in decibel or as amplitude between 0.0
* and 1.0.
*
* @magnitude must be large enough to hold @len/2 + 1 values.
*
*/
void
gst_fft_f64_magnitude (GstFFTF64 * self, GstFFTF64Complex * freqdata,
gdouble * magnitude, gboolean decibel)
{
gint i, len, nfft;
gdouble val;
g_return_if_fail (self);
g_return_if_fail (freqdata);
g_return_if_fail (magnitude);
len = self->len / 2 + 1;
nfft = self->len;
for (i = 0; i < len; i++) {
val = (gdouble) freqdata[i].r * (gdouble) freqdata[i].r
+ (gdouble) freqdata[i].i * (gdouble) freqdata[i].i;
val = sqrt (val) / nfft;
if (decibel)
val = 20.0 * log10 (val);
magnitude[i] = val;
}
}
/**
* gst_fft_f64_phase:
* @self: #GstFFTF64 instance for this call
* @freqdata: Frequency domain samples
* @phase: Target buffer for the phase
*
* This calculates the phases of @freqdata in @phase. The returned
* phases will be values between -pi and pi.
*
* @phase must be large enough to hold @len/2 + 1 values.
*
*/
void
gst_fft_f64_phase (GstFFTF64 * self, GstFFTF64Complex * freqdata,
gdouble * phase)
{
gint i, len;
g_return_if_fail (self);
g_return_if_fail (freqdata);
g_return_if_fail (phase);
len = self->len / 2 + 1;
for (i = 0; i < len; i++)
phase[i] = atan2 (freqdata[i].i, freqdata[i].r);
}
......@@ -69,9 +69,4 @@ void gst_fft_f64_free (GstFFTF64 *self);
void gst_fft_f64_window (GstFFTF64 *self, gdouble *timedata, GstFFTWindow window);
void gst_fft_f64_magnitude (GstFFTF64 *self, GstFFTF64Complex *freqdata,
gdouble *magnitude, gboolean decibel);
void gst_fft_f64_phase (GstFFTF64 *self, GstFFTF64Complex *freqdata,
gdouble *phase);
#endif /* __GST_FFT_F64_H__ */
......@@ -48,11 +48,12 @@
* to apply a window function to it. For this gst_fft_s16_window() can comfortably
* be used.
*
* For calculating the magnitude or phase of frequency data the functions
* gst_fft_s16_magnitude() and gst_fft_s16_phase() exist, if you want to calculate
* the magnitude yourself note that the magnitude of the frequency data is
* a value between 0 and 32767 and is not to be scaled by the length of the FFT.
*
* Be aware, that you can't simply run gst_fft_s16_inverse_fft() on the
* resulting frequency data of gst_fft_s16_fft() to get the original data back.
* The relation between them is iFFT (FFT (x)) = x / nfft where nfft is the
* length of the FFT. This also has to be taken into account when calculation
* the magnitude of the frequency data.
*
*/
/**
......@@ -200,70 +201,3 @@ gst_fft_s16_window (GstFFTS16 * self, gint16 * timedata, GstFFTWindow window)
break;
}
}
/**
* gst_fft_s16_magnitude:
* @self: #GstFFTS16 instance for this call
* @freqdata: Frequency domain samples
* @magnitude: Target buffer for the magnitude
* @decibel: %TRUE if the magnitude should be in decibel, %FALSE if it should be an amplitude
*
* This calculates the magnitude of @freqdata in @magnitude. Depending on the value
* of @decibel the magnitude can be calculated in decibel or as amplitude between 0.0
* and 1.0.
*
* @magnitude must be large enough to hold @len/2 + 1 values.
*
*/
void
gst_fft_s16_magnitude (GstFFTS16 * self, GstFFTS16Complex * freqdata,
gdouble * magnitude, gboolean decibel)
{
gint i, len;
gdouble val;
g_return_if_fail (self);
g_return_if_fail (freqdata);
g_return_if_fail (magnitude);
len = self->len / 2 + 1;
for (i = 0; i < len; i++) {
val = (gdouble) freqdata[i].r * (gdouble) freqdata[i].r
+ (gdouble) freqdata[i].i * (gdouble) freqdata[i].i;
val = sqrt (val) / 32767.0;
if (decibel)
val = 20.0 * log10 (val);
magnitude[i] = val;
}
}
/**
* gst_fft_s16_phase:
* @self: #GstFFTS16 instance for this call
* @freqdata: Frequency domain samples
* @phase: Target buffer for the phase
*
* This calculates the phases of @freqdata in @phase. The returned
* phases will be values between -pi and pi.
*
* @phase must be large enough to hold @len/2 + 1 values.
*
*/
void
gst_fft_s16_phase (GstFFTS16 * self, GstFFTS16Complex * freqdata,
gdouble * phase)
{
gint i, len;
g_return_if_fail (self);
g_return_if_fail (freqdata);
g_return_if_fail (phase);
len = self->len / 2 + 1;
for (i = 0; i < len; i++)
phase[i] = atan2 (freqdata[i].i, freqdata[i].r);
}
......@@ -68,10 +68,4 @@ void gst_fft_s16_inverse_fft (GstFFTS16 *self, const GstFFTS16Complex *freqdata,
void gst_fft_s16_free (GstFFTS16 *self);
void gst_fft_s16_window (GstFFTS16 *self, gint16 *timedata, GstFFTWindow window);
void gst_fft_s16_magnitude (GstFFTS16 *self, GstFFTS16Complex *freqdata,
gdouble *magnitude, gboolean decibel);
void gst_fft_s16_phase (GstFFTS16 *self, GstFFTS16Complex *freqdata,
gdouble *phase);
#endif /* __GST_FFT_S16_H__ */
......@@ -48,11 +48,11 @@
* to apply a window function to it. For this gst_fft_s32_window() can comfortably
* be used.
*
* For calculating the magnitude or phase of frequency data the functions
* gst_fft_s32_magnitude() and gst_fft_s32_phase() exist, if you want to calculate
* the magnitude yourself note that the magnitude of the frequency data is
* a value between 0 and 2147483647 and is not to be scaled by the length of the FFT.
*
* Be aware, that you can't simply run gst_fft_s32_inverse_fft() on the
* resulting frequency data of gst_fft_s32_fft() to get the original data back.
* The relation between them is iFFT (FFT (x)) = x / nfft where nfft is the
* length of the FFT. This also has to be taken into account when calculation
* the magnitude of the frequency data.
*/
/**
......@@ -200,70 +200,3 @@ gst_fft_s32_window (GstFFTS32 * self, gint32 * timedata, GstFFTWindow window)
break;
}
}
/**
* gst_fft_s32_magnitude:
* @self: #GstFFTS32 instance for this call
* @freqdata: Frequency domain samples
* @magnitude: Target buffer for the magnitude
* @decibel: %TRUE if the magnitude should be in decibel, %FALSE if it should be an amplitude
*
* This calculates the magnitude of @freqdata in @magnitude. Depending on the value
* of @decibel the magnitude can be calculated in decibel or as amplitude between 0.0
* and 1.0.
*
* @magnitude must be large enough to hold @len/2 + 1 values.
*
*/
void
gst_fft_s32_magnitude (GstFFTS32 * self, GstFFTS32Complex * freqdata,
gdouble * magnitude, gboolean decibel)
{
gint i, len;
gdouble val;
g_return_if_fail (self);
g_return_if_fail (freqdata);
g_return_if_fail (magnitude);
len = self->len / 2 + 1;
for (i = 0; i < len; i++) {
val = (gdouble) freqdata[i].r * (gdouble) freqdata[i].r
+ (gdouble) freqdata[i].i * (gdouble) freqdata[i].i;
val = sqrt (val) / 2147483647.0;
if (decibel)
val = 20.0 * log10 (val);
magnitude[i] = val;
}
}
/**
* gst_fft_s32_phase:
* @self: #GstFFTS32 instance for this call
* @freqdata: Frequency domain samples
* @phase: Target buffer for the phase
*
* This calculates the phases of @freqdata in @phase. The returned
* phases will be values between -pi and pi.
*
* @phase must be large enough to hold @len/2 + 1 values.
*
*/
void
gst_fft_s32_phase (GstFFTS32 * self, GstFFTS32Complex * freqdata,
gdouble * phase)
{
gint i, len;
g_return_if_fail (self);
g_return_if_fail (freqdata);
g_return_if_fail (phase);
len = self->len / 2 + 1;
for (i = 0; i < len; i++)
phase[i] = atan2 (freqdata[i].i, freqdata[i].r);
}
......@@ -69,9 +69,4 @@ void gst_fft_s32_free (GstFFTS32 *self);
void gst_fft_s32_window (GstFFTS32 *self, gint32 *timedata, GstFFTWindow window);
void gst_fft_s32_magnitude (GstFFTS32 *self, GstFFTS32Complex *freqdata,
gdouble *magnitude, gboolean decibel);
void gst_fft_s32_phase (GstFFTS32 *self, GstFFTS32Complex *freqdata,
gdouble *phase);
#endif /* __GST_FFT_S32_H__ */
......@@ -47,12 +47,10 @@ GST_START_TEST (test_s16_0hz)
gint i;
gint16 *in;
GstFFTS16Complex *out;
gdouble *mag;
GstFFTS16 *ctx;
in = g_new (gint16, 2048);
out = g_new (GstFFTS16Complex, 1025);
mag = g_new (gdouble, 1025);
ctx = gst_fft_s16_new (2048, FALSE);
for (i = 0; i < 2048; i++)
......@@ -60,17 +58,24 @@ GST_START_TEST (test_s16_0hz)
gst_fft_s16_window (ctx, in, GST_FFT_WINDOW_HAMMING);
gst_fft_s16_fft (ctx, in, out);
gst_fft_s16_magnitude (ctx, out, mag, TRUE);
for (i = 0; i < 1025; i++) {
fail_if (i < 2 && mag[i] < -15.0);
fail_if (i >= 2 && mag[i] > -60.0);
gdouble mag;
mag = (gdouble) out[i].r * (gdouble) out[i].r;
mag += (gdouble) out[i].i * (gdouble) out[i].i;
mag *= 2048.0;
mag /= 32767.0 * 32767.0;
mag = 10.0 * log10 (mag);
if (i < 2)
fail_unless (mag > -15.0);
else
fail_unless (mag < -55.0);
}
gst_fft_s16_free (ctx);
g_free (in);
g_free (out);
g_free (mag);
}
GST_END_TEST;
......@@ -80,12 +85,10 @@ GST_START_TEST (test_s16_11025hz)
gint i;
gint16 *in;
GstFFTS16Complex *out;
gdouble *mag;
GstFFTS16 *ctx;
in = g_new (gint16, 2048);
out = g_new (GstFFTS16Complex, 1025);
mag = g_new (gdouble, 1025);
ctx = gst_fft_s16_new (2048, FALSE);
for (i = 0; i < 2048; i += 4) {
......@@ -97,17 +100,25 @@ GST_START_TEST (test_s16_11025hz)
gst_fft_s16_window (ctx, in, GST_FFT_WINDOW_HAMMING);
gst_fft_s16_fft (ctx, in, out);
gst_fft_s16_magnitude (ctx, out, mag, TRUE);
for (i = 0; i < 1025; i++) {
fail_if (abs (512 - i) < 2 && mag[i] < -20.0);
fail_if (abs (512 - i) >= 2 && mag[i] > -60.0);
gdouble mag;
mag = (gdouble) out[i].r * (gdouble) out[i].r;
mag += (gdouble) out[i].i * (gdouble) out[i].i;
mag *= 2048.0;
mag /= 32767.0 * 32767.0;
mag = 10.0 * log10 (mag);
if (abs (512 - i) < 2)
fail_unless (mag > -15.0);
else
fail_unless (mag < -55.0);
}
gst_fft_s16_free (ctx);
g_free (in);
g_free (out);
g_free (mag);
}
GST_END_TEST;
......@@ -117,12 +128,10 @@ GST_START_TEST (test_s16_22050hz)
gint i;
gint16 *in;
GstFFTS16Complex *out;
gdouble *mag;
GstFFTS16 *ctx;
in = g_new (gint16, 2048);
out = g_new (GstFFTS16Complex, 1025);
mag = g_new (gdouble, 1025);
ctx = gst_fft_s16_new (2048, FALSE);
for (i = 0; i < 2048; i += 2) {
......@@ -132,17 +141,25 @@ GST_START_TEST (test_s16_22050hz)
gst_fft_s16_window (ctx, in, GST_FFT_WINDOW_HAMMING);
gst_fft_s16_fft (ctx, in, out);
gst_fft_s16_magnitude (ctx, out, mag, TRUE);
for (i = 0; i < 1025; i++) {
fail_if (i > 1022 && mag[i] < -20.0);
fail_if (i <= 1022 && mag[i] > -60.0);
gdouble mag;
mag = (gdouble) out[i].r * (gdouble) out[i].r;
mag += (gdouble) out[i].i * (gdouble) out[i].i;
mag *= 2048.0;
mag /= 32767.0 * 32767.0;
mag = 10.0 * log10 (mag);
if (i > 1022)
fail_unless (mag > -15.0);
else
fail_unless (mag < -55.0);
}
gst_fft_s16_free (ctx);
g_free (in);
g_free (out);
g_free (mag);
}
GST_END_TEST;
......@@ -152,12 +169,10 @@ GST_START_TEST (test_s32_0hz)
gint i;
gint32 *in;
GstFFTS32Complex *out;
gdouble *mag;
GstFFTS32 *ctx;
in = g_new (gint32, 2048);
out = g_new (GstFFTS32Complex, 1025);
mag = g_new (gdouble, 1025);
ctx = gst_fft_s32_new (2048, FALSE);
for (i = 0; i < 2048; i++)
......@@ -165,17 +180,25 @@ GST_START_TEST (test_s32_0hz)
gst_fft_s32_window (ctx, in, GST_FFT_WINDOW_HAMMING);
gst_fft_s32_fft (ctx, in, out);
gst_fft_s32_magnitude (ctx, out, mag, TRUE);
for (i = 0; i < 1025; i++) {
fail_if (i < 2 && mag[i] < -15.0);
fail_if (i >= 2 && mag[i] > -60.0);
gdouble mag;
mag = (gdouble) out[i].r * (gdouble) out[i].r;
mag += (gdouble) out[i].i * (gdouble) out[i].i;
mag *= 2048.0;
mag /= 2147483647.0 * 2147483647.0;
mag = 10.0 * log10 (mag);
if (i < 2)
fail_unless (mag > -15.0);
else
fail_unless (mag < -60.0);
}
gst_fft_s32_free (ctx);
g_free (in);
g_free (out);