static gboolean gst_iir_equalizer_setup (GstAudioFilter * audio, const GstAudioInfo * info) { GstIirEqualizer *equ = GST_IIR_EQUALIZER (audio); switch (GST_AUDIO_INFO_FORMAT (info)) { case GST_AUDIO_FORMAT_S16: equ->history_size = history_size_gint16; equ->process = gst_iir_equ_process_gint16; break; case GST_AUDIO_FORMAT_F32: equ->history_size = history_size_gfloat; equ->process = gst_iir_equ_process_gfloat; break; case GST_AUDIO_FORMAT_F64: equ->history_size = history_size_gdouble; equ->process = gst_iir_equ_process_gdouble; break; default: return FALSE; } alloc_history (equ, info); return TRUE; }
static void gst_iir_equalizer_nbands_init (GstIirEqualizerNBands * equ_n) { GstIirEqualizer *equ = GST_IIR_EQUALIZER (equ_n); gst_iir_equalizer_compute_frequencies (equ, 10); }
static GstFlowReturn gst_iir_equalizer_transform_ip (GstBaseTransform * btrans, GstBuffer * buf) { GstAudioFilter *filter = GST_AUDIO_FILTER (btrans); GstIirEqualizer *equ = GST_IIR_EQUALIZER (btrans); GstClockTime timestamp; if (G_UNLIKELY (filter->format.channels < 1 || equ->process == NULL)) return GST_FLOW_NOT_NEGOTIATED; if (equ->need_new_coefficients) { update_coefficients (equ); set_passthrough (equ); } if (gst_base_transform_is_passthrough (btrans)) return GST_FLOW_OK; timestamp = GST_BUFFER_TIMESTAMP (buf); timestamp = gst_segment_to_stream_time (&btrans->segment, GST_FORMAT_TIME, timestamp); if (GST_CLOCK_TIME_IS_VALID (timestamp)) gst_object_sync_values (G_OBJECT (equ), timestamp); equ->process (equ, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf), filter->format.channels); return GST_FLOW_OK; }
static void gst_iir_equalizer_3bands_init (GstIirEqualizer3Bands * equ_n, GstIirEqualizer3BandsClass * g_class) { GstIirEqualizer *equ = GST_IIR_EQUALIZER (equ_n); gst_iir_equalizer_compute_frequencies (equ, 3); }
static guint gst_iir_equalizer_child_proxy_get_children_count (GstChildProxy * child_proxy) { GstIirEqualizer *equ = GST_IIR_EQUALIZER (child_proxy); GST_LOG ("we have %d children", equ->freq_band_count); return equ->freq_band_count; }
/* child proxy iface */ static GstObject * gst_iir_equalizer_child_proxy_get_child_by_index (GstChildProxy * child_proxy, guint index) { GstIirEqualizer *equ = GST_IIR_EQUALIZER (child_proxy); g_return_val_if_fail (index < equ->freq_band_count, NULL); GST_LOG ("return child[%d] '%s'", index, GST_OBJECT_NAME (equ->bands[index])); return (gst_object_ref (equ->bands[index])); }
static GstFlowReturn gst_iir_equalizer_transform_ip (GstBaseTransform * btrans, GstBuffer * buf) { GstAudioFilter *filter = GST_AUDIO_FILTER (btrans); GstIirEqualizer *equ = GST_IIR_EQUALIZER (btrans); GstClockTime timestamp; GstMapInfo map; gint channels = GST_AUDIO_FILTER_CHANNELS (filter); gboolean need_new_coefficients; if (G_UNLIKELY (channels < 1 || equ->process == NULL)) return GST_FLOW_NOT_NEGOTIATED; BANDS_LOCK (equ); need_new_coefficients = equ->need_new_coefficients; BANDS_UNLOCK (equ); if (!need_new_coefficients && gst_base_transform_is_passthrough (btrans)) return GST_FLOW_OK; timestamp = GST_BUFFER_TIMESTAMP (buf); timestamp = gst_segment_to_stream_time (&btrans->segment, GST_FORMAT_TIME, timestamp); if (GST_CLOCK_TIME_IS_VALID (timestamp)) { GstIirEqualizerBand **filters = equ->bands; guint f, nf = equ->freq_band_count; gst_object_sync_values (GST_OBJECT (equ), timestamp); /* sync values for bands too */ /* FIXME: iterating equ->bands is not thread-safe here */ for (f = 0; f < nf; f++) { gst_object_sync_values (GST_OBJECT (filters[f]), timestamp); } } BANDS_LOCK (equ); if (need_new_coefficients) { update_coefficients (equ); set_passthrough (equ); } BANDS_UNLOCK (equ); gst_buffer_map (buf, &map, GST_MAP_READWRITE); equ->process (equ, map.data, map.size, channels); gst_buffer_unmap (buf, &map); return GST_FLOW_OK; }
static void gst_iir_equalizer_nbands_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { GstIirEqualizer *equ = GST_IIR_EQUALIZER (object); switch (prop_id) { case PROP_NUM_BANDS: g_value_set_uint (value, equ->freq_band_count); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } }
/* child proxy iface */ static GstObject * gst_iir_equalizer_child_proxy_get_child_by_index (GstChildProxy * child_proxy, guint index) { GstIirEqualizer *equ = GST_IIR_EQUALIZER (child_proxy); GstObject *ret; BANDS_LOCK (equ); if (G_UNLIKELY (index >= equ->freq_band_count)) { BANDS_UNLOCK (equ); g_return_val_if_fail (index < equ->freq_band_count, NULL); } ret = gst_object_ref (equ->bands[index]); BANDS_UNLOCK (equ); GST_LOG_OBJECT (equ, "return child[%d] %" GST_PTR_FORMAT, index, ret); return ret; }
static void gst_iir_equalizer_finalize (GObject * object) { GstIirEqualizer *equ = GST_IIR_EQUALIZER (object); gint i; for (i = 0; i < equ->freq_band_count; i++) { if (equ->bands[i]) gst_object_unparent (GST_OBJECT (equ->bands[i])); equ->bands[i] = NULL; } equ->freq_band_count = 0; g_free (equ->bands); g_free (equ->history); G_OBJECT_CLASS (parent_class)->finalize (object); }
static void gst_iir_equalizer_3bands_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { GstIirEqualizer *equ = GST_IIR_EQUALIZER (object); switch (prop_id) { case ARG_BAND0: gst_child_proxy_get_property (GST_OBJECT (equ), "band0::gain", value); break; case ARG_BAND1: gst_child_proxy_get_property (GST_OBJECT (equ), "band1::gain", value); break; case ARG_BAND2: gst_child_proxy_get_property (GST_OBJECT (equ), "band2::gain", value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } }
static gboolean gst_iir_equalizer_setup (GstAudioFilter * audio, GstRingBufferSpec * fmt) { GstIirEqualizer *equ = GST_IIR_EQUALIZER (audio); switch (fmt->type) { case GST_BUFTYPE_LINEAR: switch (fmt->width) { case 16: equ->history_size = history_size_gint16; equ->process = gst_iir_equ_process_gint16; break; default: return FALSE; } break; case GST_BUFTYPE_FLOAT: switch (fmt->width) { case 32: equ->history_size = history_size_gfloat; equ->process = gst_iir_equ_process_gfloat; break; case 64: equ->history_size = history_size_gdouble; equ->process = gst_iir_equ_process_gdouble; break; default: return FALSE; } break; default: return FALSE; } alloc_history (equ); return TRUE; }
static void gst_iir_equalizer_band_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { GstIirEqualizerBand *band = GST_IIR_EQUALIZER_BAND (object); GstIirEqualizer *equ = GST_IIR_EQUALIZER (gst_object_get_parent (GST_OBJECT (band))); switch (prop_id) { case PROP_GAIN:{ gdouble gain; gain = g_value_get_double (value); GST_DEBUG_OBJECT (band, "gain = %lf -> %lf", band->gain, gain); if (gain != band->gain) { BANDS_LOCK (equ); equ->need_new_coefficients = TRUE; band->gain = gain; BANDS_UNLOCK (equ); GST_DEBUG_OBJECT (band, "changed gain = %lf ", band->gain); } break; } case PROP_FREQ:{ gdouble freq; freq = g_value_get_double (value); GST_DEBUG_OBJECT (band, "freq = %lf -> %lf", band->freq, freq); if (freq != band->freq) { BANDS_LOCK (equ); equ->need_new_coefficients = TRUE; band->freq = freq; BANDS_UNLOCK (equ); GST_DEBUG_OBJECT (band, "changed freq = %lf ", band->freq); } break; } case PROP_BANDWIDTH:{ gdouble width; width = g_value_get_double (value); GST_DEBUG_OBJECT (band, "width = %lf -> %lf", band->width, width); if (width != band->width) { BANDS_LOCK (equ); equ->need_new_coefficients = TRUE; band->width = width; BANDS_UNLOCK (equ); GST_DEBUG_OBJECT (band, "changed width = %lf ", band->width); } break; } case PROP_TYPE:{ GstIirEqualizerBandType type; type = g_value_get_enum (value); GST_DEBUG_OBJECT (band, "type = %d -> %d", band->type, type); if (type != band->type) { BANDS_LOCK (equ); equ->need_new_coefficients = TRUE; band->type = type; BANDS_UNLOCK (equ); GST_DEBUG_OBJECT (band, "changed type = %d ", band->type); } break; } default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } gst_object_unref (equ); }
static void gst_iir_equalizer_band_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { GstIirEqualizerBand *band = GST_IIR_EQUALIZER_BAND (object); GstIirEqualizer *equ = GST_IIR_EQUALIZER (gst_object_get_parent (GST_OBJECT (band))); switch (prop_id) { case PROP_GAIN:{ gdouble gain; gain = g_value_get_double (value); GST_DEBUG_OBJECT (band, "gain = %lf -> %lf", band->gain, gain); if (gain != band->gain) { BANDS_LOCK (equ); equ->need_new_coefficients = TRUE; band->gain = gain; set_passthrough (equ); BANDS_UNLOCK (equ); GST_DEBUG_OBJECT (band, "changed gain = %lf ", band->gain); } break; } case PROP_FREQ:{ gdouble freq; freq = g_value_get_double (value); GST_DEBUG_OBJECT (band, "freq = %lf -> %lf", band->freq, freq); if (freq != band->freq) { BANDS_LOCK (equ); equ->need_new_coefficients = TRUE; band->freq = freq; BANDS_UNLOCK (equ); GST_DEBUG_OBJECT (band, "changed freq = %lf ", band->freq); } break; } case PROP_BANDWIDTH:{ gdouble width; width = g_value_get_double (value); GST_DEBUG_OBJECT (band, "width = %lf -> %lf", band->width, width); if (width != band->width) { BANDS_LOCK (equ); equ->need_new_coefficients = TRUE; band->width = width; BANDS_UNLOCK (equ); GST_DEBUG_OBJECT (band, "changed width = %lf ", band->width); } break; } case PROP_TYPE:{ GstIirEqualizerBandType type; type = g_value_get_enum (value); GST_DEBUG_OBJECT (band, "type = %d -> %d", band->type, type); if (type != band->type) { BANDS_LOCK (equ); equ->need_new_coefficients = TRUE; band->type = type; BANDS_UNLOCK (equ); GST_DEBUG_OBJECT (band, "changed type = %d ", band->type); } break; } default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } #ifdef GSTREAMER_LITE // We need to update coefficients and disable passthrough // if needed, otherwise after we disable passthrough equalizer will not // get re-enabled. // BANDS_LOCK (equ); // if (equ->need_new_coefficients) { // update_coefficients (equ); // set_passthrough (equ); // } // BANDS_UNLOCK (equ); #endif // GSTREAMER_LITE gst_object_unref (equ); }