mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-29 19:50:40 +00:00
spectrum: factor out the code that accumulated samples into the ring-buffer
Use a separate function to read a sample frame into a ringbuffer slot. In the future we can use format-specific function pointer to avoid the reoccuring format checks.
This commit is contained in:
parent
5b9028c52c
commit
65f4c4b3e6
1 changed files with 52 additions and 45 deletions
|
@ -518,6 +518,55 @@ gst_spectrum_message_new (GstSpectrum * spectrum, GstClockTime timestamp,
|
||||||
return gst_message_new_element (GST_OBJECT (spectrum), s);
|
return gst_message_new_element (GST_OBJECT (spectrum), s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* FIXME: have dedicated read function pointers for each format */
|
||||||
|
static gfloat
|
||||||
|
gst_spectrum_input_data_mixed (const guint8 * data, gfloat is_float,
|
||||||
|
guint width, guint channels, gfloat max_value)
|
||||||
|
{
|
||||||
|
guint i;
|
||||||
|
gfloat v = 0.0;
|
||||||
|
|
||||||
|
if (is_float) {
|
||||||
|
if (width == 4) {
|
||||||
|
gfloat *in = (gfloat *) data;
|
||||||
|
for (i = 0; i < channels; i++)
|
||||||
|
v += in[i];
|
||||||
|
} else if (width == 8) {
|
||||||
|
gdouble *in = (gdouble *) data;
|
||||||
|
for (i = 0; i < channels; i++)
|
||||||
|
v += in[i];
|
||||||
|
} else {
|
||||||
|
g_assert_not_reached ();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (width == 4) {
|
||||||
|
gint32 *in = (gint32 *) data;
|
||||||
|
/* max_value will be 0 when depth is 1,
|
||||||
|
* interpret -1 and 0 as -1 and +1 if that's the case. */
|
||||||
|
for (i = 0; i < channels; i++)
|
||||||
|
v += max_value ? in[i] / max_value : in[i] * 2 + 1;
|
||||||
|
} else if (width == 3) {
|
||||||
|
for (i = 0; i < channels; i++) {
|
||||||
|
#if G_BYTE_ORDER == G_BIG_ENDIAN
|
||||||
|
gint32 value = GST_READ_UINT24_BE (data);
|
||||||
|
#else
|
||||||
|
gint32 value = GST_READ_UINT24_LE (data);
|
||||||
|
#endif
|
||||||
|
if (value & 0x00800000)
|
||||||
|
value |= 0xff000000;
|
||||||
|
v += max_value ? value / max_value : value * 2 + 1;
|
||||||
|
}
|
||||||
|
} else if (width == 2) {
|
||||||
|
gint16 *in = (gint16 *) data;
|
||||||
|
for (i = 0; i < channels; i++)
|
||||||
|
v += max_value ? in[i] / max_value : in[i] * 2 + 1;
|
||||||
|
} else {
|
||||||
|
g_assert_not_reached ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return v / channels;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_spectrum_run_fft (GstSpectrum * spectrum, GstSpectrumChannel * cd,
|
gst_spectrum_run_fft (GstSpectrum * spectrum, GstSpectrumChannel * cd,
|
||||||
guint input_pos)
|
guint input_pos)
|
||||||
|
@ -595,7 +644,6 @@ static GstFlowReturn
|
||||||
gst_spectrum_transform_ip (GstBaseTransform * trans, GstBuffer * buffer)
|
gst_spectrum_transform_ip (GstBaseTransform * trans, GstBuffer * buffer)
|
||||||
{
|
{
|
||||||
GstSpectrum *spectrum = GST_SPECTRUM (trans);
|
GstSpectrum *spectrum = GST_SPECTRUM (trans);
|
||||||
guint i;
|
|
||||||
GstRingBufferSpec *format = &GST_AUDIO_FILTER (spectrum)->format;
|
GstRingBufferSpec *format = &GST_AUDIO_FILTER (spectrum)->format;
|
||||||
guint rate = format->rate;
|
guint rate = format->rate;
|
||||||
guint channels = format->channels;
|
guint channels = format->channels;
|
||||||
|
@ -646,50 +694,9 @@ gst_spectrum_transform_ip (GstBaseTransform * trans, GstBuffer * buffer)
|
||||||
input = cd->input;
|
input = cd->input;
|
||||||
|
|
||||||
while (size >= width * channels) {
|
while (size >= width * channels) {
|
||||||
/* Move the current frame into our ringbuffer and
|
/* Move the mixdown of current frame into our ringbuffer */
|
||||||
* take the average of all channels
|
input[input_pos] = gst_spectrum_input_data_mixed (data, is_float, width,
|
||||||
*/
|
channels, max_value);
|
||||||
input[input_pos] = 0.0;
|
|
||||||
if (is_float) {
|
|
||||||
if (width == 4) {
|
|
||||||
gfloat *in = (gfloat *) data;
|
|
||||||
for (i = 0; i < channels; i++)
|
|
||||||
input[input_pos] += in[i];
|
|
||||||
} else if (width == 8) {
|
|
||||||
gdouble *in = (gdouble *) data;
|
|
||||||
for (i = 0; i < channels; i++)
|
|
||||||
input[input_pos] += in[i];
|
|
||||||
} else {
|
|
||||||
g_assert_not_reached ();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (width == 4) {
|
|
||||||
gint32 *in = (gint32 *) data;
|
|
||||||
for (i = 0; i < channels; i++)
|
|
||||||
/* max_value will be 0 when depth is 1, interpret -1 and 0
|
|
||||||
* as -1 and +1 if that's the case.
|
|
||||||
*/
|
|
||||||
input[input_pos] += max_value ? in[i] / max_value : in[i] * 2 + 1;
|
|
||||||
} else if (width == 3) {
|
|
||||||
for (i = 0; i < channels; i++) {
|
|
||||||
#if G_BYTE_ORDER == G_BIG_ENDIAN
|
|
||||||
gint32 value = GST_READ_UINT24_BE (data);
|
|
||||||
#else
|
|
||||||
gint32 value = GST_READ_UINT24_LE (data);
|
|
||||||
#endif
|
|
||||||
if (value & 0x00800000)
|
|
||||||
value |= 0xff000000;
|
|
||||||
input[input_pos] += max_value ? value / max_value : value * 2 + 1;
|
|
||||||
}
|
|
||||||
} else if (width == 2) {
|
|
||||||
gint16 *in = (gint16 *) data;
|
|
||||||
for (i = 0; i < channels; i++)
|
|
||||||
input[input_pos] += max_value ? in[i] / max_value : in[i] * 2 + 1;
|
|
||||||
} else {
|
|
||||||
g_assert_not_reached ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
input[input_pos] /= channels;
|
|
||||||
|
|
||||||
data += width * channels;
|
data += width * channels;
|
||||||
size -= width * channels;
|
size -= width * channels;
|
||||||
|
|
Loading…
Reference in a new issue