diff --git a/gstlal-ugly/gst/lal/Makefile.am b/gstlal-ugly/gst/lal/Makefile.am index ff5f9eb68d7311bf5222edf04588675a20c8e0f0..b846c12c8e903a3f130fd63316e7e549c258ca1e 100644 --- a/gstlal-ugly/gst/lal/Makefile.am +++ b/gstlal-ugly/gst/lal/Makefile.am @@ -5,6 +5,7 @@ plugin_LTLIBRARIES = lib@GSTPLUGINPREFIX@gstlalugly.la lib@GSTPLUGINPREFIX@gstlalugly_la_SOURCES = \ gstlalugly.c \ audioratefaker.h audioratefaker.c \ + gstlal_aggregator.h gstlal_aggregator.c \ gstlal_bitvectorgen.h gstlal_bitvectorgen.c \ gstlaldeglitchfilter.h gstlaldeglitchfilter.c \ gstlal_iirbank.h gstlal_iirbank.c \ diff --git a/gstlal-ugly/gst/lal/gstlal_aggregator.c b/gstlal-ugly/gst/lal/gstlal_aggregator.c new file mode 100644 index 0000000000000000000000000000000000000000..66f5fa730bbc4008dc573962756090900b878bcf --- /dev/null +++ b/gstlal-ugly/gst/lal/gstlal_aggregator.c @@ -0,0 +1,605 @@ +/* + * An aggregator element + * + * Copyright (C) 2019 Patrick Godwin, Chad Hanna, Kipp Cannon + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + + +/* + * ======================================================================== + * + * Preamble + * + * ======================================================================== + */ + + +#include <glib.h> +#include <glib/gprintf.h> +#include <gst/gst.h> +#include <gst/base/gstbasetransform.h> +#include <gst/base/gstadapter.h> +#include <math.h> +#include <string.h> +#include <gsl/gsl_statistics.h> +#include <gsl/gsl_vector.h> + +/* + * our own stuff + */ + +#include <gstlal/gstlal.h> +#include <gstlal/gstlal_debug.h> +#include <gstlal/gstaudioadapter.h> +#include <gstlal_aggregator.h> + +#define GST_CAT_DEFAULT gstlal_aggregator_debug +GST_DEBUG_CATEGORY_STATIC(GST_CAT_DEFAULT); + +G_DEFINE_TYPE_WITH_CODE( + GSTLALAggregator, + gstlal_aggregator, + GST_TYPE_BASE_TRANSFORM, + GST_DEBUG_CATEGORY_INIT(GST_CAT_DEFAULT, "lal_aggregator", 0, "lal_aggregator element") +); + + +static void aggregate32(float *output, float *input, guint factor, guint channels, guint blockstrideout, gboolean nongap) { + + if (!nongap) { + memset(output, 0, sizeof(*output) * blockstrideout * channels); + return; + } + + guint output_offset, input_offset; + for (guint samp = 0; samp < blockstrideout; samp++) { + output_offset = samp * channels; + input_offset = samp * channels * factor; + + gsl_vector_float_view output_vector = gsl_vector_float_view_array(output + output_offset, channels); + + for (guint i = 0; i < factor; i++) { + gsl_vector_float_view input_vector = gsl_vector_float_view_array_with_stride(input + input_offset + i, channels, factor); + float aggregate = gsl_stats_float_max(input_vector.vector.data, channels, factor); + gsl_vector_float_set(&output_vector.vector, i, aggregate); + } + } + + return; +} + + +static void aggregate64(double *output, double *input, guint factor, guint channels, guint blockstrideout, gboolean nongap) { + + if (!nongap) { + memset(output, 0, sizeof(*output) * blockstrideout * channels); + return; + } + + guint output_offset, input_offset; + for (guint samp = 0; samp < blockstrideout; samp++) { + output_offset = samp * channels; + input_offset = samp * channels * factor; + + gsl_vector_view output_vector = gsl_vector_view_array(output + output_offset, channels); + + for (guint i = 0; i < channels; i++) { + gsl_vector_view input_vector = gsl_vector_view_array_with_stride(input + input_offset + i, channels, factor); + double aggregate = gsl_stats_max(input_vector.vector.data, channels, factor); + gsl_vector_set(&output_vector.vector, i, aggregate); + } + } + + return; +} + + +/* + * gstreamer boiler plate + */ + + +/* + * Pads + */ + + +static GstStaticPadTemplate sink_template = + GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("audio/x-raw, " \ + "format = (string) {" GST_AUDIO_NE(F32) ", " GST_AUDIO_NE(F64) "}, " \ + "rate = (int) {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768}, " \ + "channels = " GST_AUDIO_CHANNELS_RANGE ", " \ + "layout = (string) interleaved, " \ + "channel-mask = (bitmask) 0") + ); + + +static GstStaticPadTemplate src_template = + GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("audio/x-raw, " \ + "format = (string) {" GST_AUDIO_NE(F32) ", " GST_AUDIO_NE(F64) "}, " \ + "rate = (int) {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768}, " \ + "channels = " GST_AUDIO_CHANNELS_RANGE ", " \ + "layout = (string) interleaved, " \ + "channel-mask = (bitmask) 0") + + ); + + +/* + * Virtual method protototypes + */ + + +static void finalize(GObject *object); +static gboolean get_unit_size(GstBaseTransform *trans, GstCaps *caps, gsize *size); +static gboolean set_caps (GstBaseTransform * base, GstCaps * incaps, GstCaps * outcaps); +static GstFlowReturn transform(GstBaseTransform *trans, GstBuffer *inbuf, GstBuffer *outbuf); +static GstCaps* transform_caps (GstBaseTransform *trans, GstPadDirection direction, GstCaps *caps, GstCaps *filter); +static gboolean transform_size(GstBaseTransform *trans, GstPadDirection direction, GstCaps *caps, gsize size, GstCaps *othercaps, gsize *othersize); +static gboolean start(GstBaseTransform *trans); +static gboolean stop(GstBaseTransform *trans); + + +/* + * class_init() + */ + + +static void gstlal_aggregator_class_init(GSTLALAggregatorClass *klass) +{ + + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + GstElementClass *element_class = GST_ELEMENT_CLASS(klass); + GstBaseTransformClass *transform_class = GST_BASE_TRANSFORM_CLASS(klass); + + gst_element_class_set_details_simple( + element_class, + "Aggregator", + "Filter/Audio", + "Aggregates audio data", + "Patrick Godwin <patrick.godwin@ligo.org>, Chad Hanna <chad.hanna@ligo.org>, Kipp Cannon <kipp.cannon@ligo.org>"); + + gobject_class->finalize = GST_DEBUG_FUNCPTR(finalize); + transform_class->get_unit_size = GST_DEBUG_FUNCPTR(get_unit_size); + transform_class->set_caps = GST_DEBUG_FUNCPTR(set_caps); + transform_class->transform = GST_DEBUG_FUNCPTR(transform); + transform_class->transform_caps = GST_DEBUG_FUNCPTR(transform_caps); + transform_class->transform_size = GST_DEBUG_FUNCPTR(transform_size); + transform_class->start = GST_DEBUG_FUNCPTR(start); + transform_class->stop = GST_DEBUG_FUNCPTR(stop); + + gst_element_class_add_pad_template(element_class, gst_static_pad_template_get(&src_template)); + gst_element_class_add_pad_template(element_class, gst_static_pad_template_get(&sink_template)); +} + +static void gstlal_aggregator_init(GSTLALAggregator *element) +{ + gst_base_transform_set_gap_aware(GST_BASE_TRANSFORM(element), TRUE); + + /* internal data */ + element->inrate = 0; + element->outrate = 0; + + element->workspace32 = NULL; + element->workspace64 = NULL; + + /* Always initialize with a discont */ + element->need_discont = TRUE; + element->last_gap_state = FALSE; + + element->adapter = g_object_new(GST_TYPE_AUDIOADAPTER, NULL); +} + + +static GstCaps* transform_caps (GstBaseTransform *trans, GstPadDirection direction, GstCaps *caps, GstCaps *filter) { + + /* + * All powers of two rates from 1 to 32768 Hz are allowed. This + * element is designed to be efficient when using power of two rate + * ratios. + */ + + gint channels; + GstAudioInfo info; + char capsstr[256] = {0}; + + if (direction == GST_PAD_SINK && gst_caps_is_fixed(caps)) { + gst_audio_info_from_caps(&info, caps); + channels = GST_AUDIO_INFO_CHANNELS(&info); + sprintf(capsstr, "audio/x-raw, format = (string) %s, rate = (int) {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768}, channels = (int) %d, layout=(string)interleaved, channel-mask=(bitmask)0", GST_AUDIO_INFO_NAME(&info), channels); + + return gst_caps_from_string(capsstr); + } + + return gst_caps_from_string("audio/x-raw, format= (string) {" GST_AUDIO_NE(F32) ", " GST_AUDIO_NE(F64) "}, rate = (int) {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768}, channels = (int) [1, MAX]"); +} + + +static gboolean set_caps (GstBaseTransform * base, GstCaps * incaps, GstCaps * outcaps) { + GSTLALAggregator *element = GSTLAL_AGGREGATOR (base); + GstStructure *instruct, *outstruct; + gint inchannels, inrate, outchannels, outrate; + gboolean success = gst_audio_info_from_caps(&element->audio_info, outcaps); + + instruct = gst_caps_get_structure (incaps, 0); + outstruct = gst_caps_get_structure (outcaps, 0); + + + g_return_val_if_fail(gst_structure_get_int (instruct, "channels", &inchannels), FALSE); + g_return_val_if_fail(gst_structure_get_int (instruct, "rate", &inrate), FALSE); + g_return_val_if_fail(gst_structure_get_int (outstruct, "channels", &outchannels), FALSE); + g_return_val_if_fail(gst_structure_get_int (outstruct, "rate", &outrate), FALSE); + + GST_INFO_OBJECT(element, "in channels %d in rate %d out channels %d out rate %d", inchannels, inrate, outchannels, outrate); + + g_return_val_if_fail(inchannels == outchannels, FALSE); + g_return_val_if_fail(inrate > outrate, FALSE); + + element->inrate = inrate; + element->outrate = outrate; + element->channels = inchannels; + element->width = GST_AUDIO_INFO_WIDTH(&element->audio_info); + + get_unit_size(base, outcaps, &(element->unitsize)); + + /* Timestamp and offset bookeeping */ + element->t0 = GST_CLOCK_TIME_NONE; + element->offset0 = GST_BUFFER_OFFSET_NONE; + element->next_input_offset = GST_BUFFER_OFFSET_NONE; + element->next_output_offset = GST_BUFFER_OFFSET_NONE; + element->need_discont = TRUE; + + /* + * Keep blockstride small to prevent GAPS from growing to be large + * FIXME probably this should be decoupled + */ + + element->blockstrideout = element->outrate; + // Downsampling requires the ratio of rates (in/out) of input to produce a given output + element->blockstridein = element->blockstrideout * element->inrate / element->outrate; + element->blocksampsin = element->blockstridein; + element->blocksampsout = element->blocksampsin * element->outrate / element->inrate; + GST_INFO_OBJECT(element, "blocksampsin %d, blocksampsout %d, blockstridein %d, blockstrideout %d unit size %d width %d", element->blocksampsin, element->blocksampsout, element->blockstridein, element->blockstrideout, (int) element->unitsize, element->width); + + if (element->workspace32) + gsl_matrix_float_free(element->workspace32); + element->workspace32 = gsl_matrix_float_calloc (element->blocksampsin, element->channels); + if (element->workspace64) + gsl_matrix_free(element->workspace64); + element->workspace64 = gsl_matrix_calloc (element->blocksampsin, element->channels); + + g_object_set(element->adapter, "unit-size", element->unitsize, NULL); + + return success; +} + + +/* + * ============================================================================ + * + * GstBaseTransform Method Overrides + * + * ============================================================================ + */ + + +/* + * get_unit_size() + */ + + +static gboolean get_unit_size(GstBaseTransform *trans, GstCaps *caps, gsize *size) +{ + GstAudioInfo info; + gboolean success = gst_audio_info_from_caps(&info, caps); + + + if(success) { + *size = GST_AUDIO_INFO_BPF(&info); + } + else + GST_WARNING_OBJECT(trans, "unable to parse channels from %" GST_PTR_FORMAT, caps); + + return success; +} + + +static guint64 get_available_samples(GSTLALAggregator *element) +{ + guint size; + g_object_get(element->adapter, "size", &size, NULL); + return size; +} + + +static guint minimum_input_length(GSTLALAggregator *element, guint samps) { + return (guint) ceil( (float) samps * element->outrate / element->inrate); +} + + +static guint minimum_input_size(GSTLALAggregator *element, guint size) { + return minimum_input_length(element, size / element->unitsize) * element->unitsize; +} + + +static guint get_output_length(GSTLALAggregator *element, guint samps) { + + /* + * The output length is either a multiple of the blockstride or 0 if + * there is not enough data. + * + */ + + guint numinsamps = get_available_samples(element) + samps; + if (numinsamps < element->blocksampsin) + return 0; + + // Note this could be zero + guint numoutsamps = numinsamps * element->outrate / element->inrate; + guint numblocks = numoutsamps / element->blockstrideout; + + /* NOTE could be zero */ + return numblocks * element->blockstrideout; +} + + +static guint get_output_size(GSTLALAggregator *element, guint size) { + return get_output_length(element, size / element->unitsize) * element->unitsize; +} + + +static gboolean transform_size(GstBaseTransform *trans, GstPadDirection direction, GstCaps *caps, gsize size, GstCaps *othercaps, gsize *othersize) +{ + GSTLALAggregator *element = GSTLAL_AGGREGATOR(trans); + gsize unit_size; + gsize other_unit_size; + gboolean success = TRUE; + + if(!get_unit_size(trans, caps, &unit_size)) + return FALSE; + if(size % unit_size) { + GST_ERROR_OBJECT(element, "size not a multiple of %" G_GSIZE_FORMAT, unit_size); + return FALSE; + } + if(!get_unit_size(trans, othercaps, &other_unit_size)) + return FALSE; + + switch(direction) { + case GST_PAD_SRC: + + /* + * number of input bytes required to produce an output + * buffer of (at least) the requested size + */ + + *othersize = minimum_input_size(element, size); + GST_INFO_OBJECT(element, "producing %" G_GSIZE_FORMAT " (bytes) buffer for request on SRC pad", *othersize); + break; + + case GST_PAD_SINK: + + /* + * number of output bytes to be generated by the receipt of + * an input buffer of the given size. + */ + + *othersize = get_output_size(element, size); + GST_INFO_OBJECT(element, "SINK pad buffer of size %" G_GSIZE_FORMAT " (bytes) %" G_GSIZE_FORMAT " (samples) provided. Transforming to size %" G_GSIZE_FORMAT " (bytes) %" G_GSIZE_FORMAT " (samples).", size, size / element->unitsize, *othersize, *othersize / element->unitsize); + break; + + case GST_PAD_UNKNOWN: + GST_ELEMENT_ERROR(trans, CORE, NEGOTIATION, (NULL), ("invalid direction GST_PAD_UNKNOWN")); + success = FALSE; + break; + } + + return success; +} + + +static gboolean start(GstBaseTransform *trans) +{ + GSTLALAggregator *element = GSTLAL_AGGREGATOR(trans); + element->t0 = GST_CLOCK_TIME_NONE; + element->offset0 = GST_BUFFER_OFFSET_NONE; + element->next_input_offset = GST_BUFFER_OFFSET_NONE; + element->next_output_offset = GST_BUFFER_OFFSET_NONE; + element->need_discont = TRUE; + /* FIXME properly handle segments */ + return TRUE; +} + + +static gboolean stop(GstBaseTransform *trans) +{ + GSTLALAggregator *element = GSTLAL_AGGREGATOR(trans); + g_object_unref(element->adapter); + element->adapter = NULL; + return TRUE; +} + + +static void flush_history(GSTLALAggregator *element) { + GST_INFO_OBJECT(element, "flushing adapter contents"); + gst_audioadapter_clear(element->adapter); +} + + +static void set_metadata(GSTLALAggregator *element, GstBuffer *buf, guint64 outsamples, gboolean gap) +{ + GST_BUFFER_OFFSET(buf) = element->next_output_offset; + element->next_output_offset += outsamples; + GST_BUFFER_OFFSET_END(buf) = element->next_output_offset; + GST_BUFFER_PTS(buf) = element->t0 + gst_util_uint64_scale_int_round(GST_BUFFER_OFFSET(buf) - element->offset0, GST_SECOND, element->outrate); + GST_BUFFER_DURATION(buf) = element->t0 + gst_util_uint64_scale_int_round(GST_BUFFER_OFFSET_END(buf) - element->offset0, GST_SECOND, GST_AUDIO_INFO_RATE(&(element->audio_info))) - GST_BUFFER_PTS(buf); + if(G_UNLIKELY(element->need_discont)) { + GST_BUFFER_FLAG_SET(buf, GST_BUFFER_FLAG_DISCONT); + element->need_discont = FALSE; + } + if(gap) { + GST_BUFFER_FLAG_SET(buf, GST_BUFFER_FLAG_GAP); + element->last_gap_state = TRUE; + } + else { + GST_BUFFER_FLAG_UNSET(buf, GST_BUFFER_FLAG_GAP); + element->last_gap_state = FALSE; + } + GST_INFO_OBJECT(element, "%s%s output_buffer %p spans %" GST_BUFFER_BOUNDARIES_FORMAT, gap ? "gap" : "nongap", GST_BUFFER_FLAG_IS_SET(buf, GST_BUFFER_FLAG_DISCONT) ? "+discont" : "", buf, GST_BUFFER_BOUNDARIES_ARGS(buf)); +} + + +static GstFlowReturn transform(GstBaseTransform *trans, GstBuffer *inbuf, GstBuffer *outbuf) +{ + GSTLALAggregator *element = GSTLAL_AGGREGATOR(trans); + guint output_length; + GstFlowReturn result = GST_FLOW_OK; + gboolean copied_nongap; + GstMapInfo mapinfo; + + g_assert(GST_BUFFER_PTS_IS_VALID(inbuf)); + g_assert(GST_BUFFER_DURATION_IS_VALID(inbuf)); + g_assert(GST_BUFFER_OFFSET_IS_VALID(inbuf)); + g_assert(GST_BUFFER_OFFSET_END_IS_VALID(inbuf)); + + if(G_UNLIKELY(GST_BUFFER_IS_DISCONT(inbuf) || GST_BUFFER_OFFSET(inbuf) != element->next_input_offset || !GST_CLOCK_TIME_IS_VALID(element->t0))) { + + /* + * flush any previous history and clear the adapter + */ + + flush_history(element); + + /* + * (re)sync timestamp and offset book-keeping + */ + + element->t0 = GST_BUFFER_PTS(inbuf); + element->offset0 = GST_BUFFER_OFFSET(inbuf); + element->next_output_offset = element->offset0; + + /* + * be sure to flag the next output buffer as a discontinuity + */ + + element->need_discont = TRUE; + /* FIXME-- clean up this debug statement */ + /* GST_INFO_OBJECT(element, "A discontinuity was detected. The offset has been reset to %" G_GUINT64_FORMAT " and the timestamp has been reset to %" GST_TIME_SECONDS_FORMAT, element->offset0, element->t0); */ + + } + + element->next_input_offset = GST_BUFFER_OFFSET_END(inbuf); + + GST_INFO_OBJECT(element, "%s input_buffer %p spans %" GST_BUFFER_BOUNDARIES_FORMAT, GST_BUFFER_FLAG_IS_SET(inbuf, GST_BUFFER_FLAG_DISCONT) ? "+discont" : "", inbuf, GST_BUFFER_BOUNDARIES_ARGS(inbuf)); + + /* FIXME- clean up this debug statement */ + GST_INFO_OBJECT(element, "pushing %d (bytes) %d (samples) sample buffer into adapter with size %d (samples) offset %d offset end %d: unitsize %d adapter->unit-size %d", (int) gst_buffer_get_size(inbuf), (int) gst_buffer_get_size(inbuf) / (int) element->unitsize, (int) get_available_samples(element), (int) GST_BUFFER_OFFSET(inbuf), (int) GST_BUFFER_OFFSET_END(inbuf), (int) element->unitsize, (int) element->adapter->unit_size); + + gst_buffer_ref(inbuf); /* don't let calling code free buffer */ + gst_audioadapter_push(element->adapter, inbuf); + GST_INFO_OBJECT(element, "adapter_size %u (samples)", (guint) get_available_samples(element)); + + /* + * Handle the different possiblilities + */ + + output_length = gst_buffer_get_size(outbuf) / element->unitsize; + + if (gst_buffer_get_size(outbuf) == 0) + set_metadata(element, outbuf, 0, element->last_gap_state); + else { + + if (element->width == 32) { + guint processed = 0; + gst_buffer_map(outbuf, &mapinfo, GST_MAP_WRITE); + float *output = (float *) mapinfo.data; + memset(mapinfo.data, 0, mapinfo.size); + /* FIXME- clean up this print statement (format) */ + /* GST_INFO_OBJECT(element, "Processing a %d sample output buffer from %d input", output_length); */ + + while (processed < output_length) { + + gst_audioadapter_copy_samples(element->adapter, element->workspace32->data, element->blocksampsin, NULL, &copied_nongap); + + aggregate32(output, element->workspace32->data, element->inrate / element->outrate, element->channels, element->blockstrideout, copied_nongap); + + GST_INFO_OBJECT(element, "Flushing %d samples : processed %d samples : output length %d samples", element->blockstridein, processed, output_length); + gst_audioadapter_flush_samples(element->adapter, element->blockstridein); + + output += element->blockstrideout * element->channels; + processed += element->blockstrideout; + } + GST_INFO_OBJECT(element, "Processed %d samples", processed); + set_metadata(element, outbuf, output_length, !copied_nongap); + gst_buffer_unmap(outbuf, &mapinfo); + } + if (element->width == 64) { + guint processed = 0; + gst_buffer_map(outbuf, &mapinfo, GST_MAP_WRITE); + double *output = (double *) mapinfo.data; + memset(mapinfo.data, 0, mapinfo.size); + /* FIXME- clean up this print statement (format) */ + /* GST_INFO_OBJECT(element, "Processing a %d sample output buffer from %d input", output_length); */ + + while (processed < output_length) { + + + /* Special case to handle discontinuities: effectively + * zero pad. FIXME make this more elegant + */ + + gst_audioadapter_copy_samples(element->adapter, element->workspace64->data, element->blocksampsin, NULL, &copied_nongap); + + aggregate64(output, element->workspace64->data, element->inrate / element->outrate, element->channels, element->blockstrideout, copied_nongap); + + GST_INFO_OBJECT(element, "Flushing %d samples : processed %d samples : output length %d samples", element->blockstridein, processed, output_length); + gst_audioadapter_flush_samples(element->adapter, element->blockstridein); + + output += element->blockstrideout * element->channels; + processed += element->blockstrideout; + } + GST_INFO_OBJECT(element, "Processed %d samples", processed); + set_metadata(element, outbuf, output_length, !copied_nongap); + gst_buffer_unmap(outbuf, &mapinfo); + } + } + return result; +} + + +static void finalize(GObject *object) +{ + GSTLALAggregator *element = GSTLAL_AGGREGATOR(object); + + /* + * free resources + */ + + gsl_matrix_float_free(element->workspace32); + gsl_matrix_free(element->workspace64); + + /* + * chain to parent class' finalize() method + */ + + G_OBJECT_CLASS(gstlal_aggregator_parent_class)->finalize(object); +} diff --git a/gstlal-ugly/gst/lal/gstlal_aggregator.h b/gstlal-ugly/gst/lal/gstlal_aggregator.h new file mode 100644 index 0000000000000000000000000000000000000000..495242d36bb1fe8f89c177ee940f46106dc080bd --- /dev/null +++ b/gstlal-ugly/gst/lal/gstlal_aggregator.h @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2019 Patrick Godwin, Chad Hanna + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __GSTLAL_AGGREGATOR_H__ +#define __GSTLAL_AGGREGATOR_H__ + + +#include <glib.h> +#include <gst/gst.h> +#include <gst/base/gstadapter.h> +#include <gst/base/gstbasetransform.h> +#include <gsl/gsl_statistics.h> +#include <gsl/gsl_vector.h> + +#include <gstlal/gstlal.h> +#include <gstlal/gstaudioadapter.h> + +G_BEGIN_DECLS + + +#define GSTLAL_AGGREGATOR_TYPE \ + (gstlal_aggregator_get_type()) + +#define GSTLAL_AGGREGATOR(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), GSTLAL_AGGREGATOR_TYPE, GSTLALAggregator)) + +#define GSTLAL_AGGREGATOR_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), GSTLAL_AGGREGATOR_TYPE, GSTLALAggregatorClass)) + +#define GST_IS_GSTLAL_AGGREGATOR(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), GSTLAL_AGGREGATOR_TYPE)) + +#define GST_IS_GSTLAL_AGGREGATOR_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), GSTLAL_AGGREGATOR_TYPE)) + + +typedef struct _GSTLALAggregator GSTLALAggregator; +typedef struct _GSTLALAggregatorClass GSTLALAggregatorClass; + + +/** + * GSTLALAggregator: + */ + + +struct _GSTLALAggregator { + GstBaseTransform element; + + GstAudioInfo audio_info; + GstAudioAdapter *adapter; + + gint inrate; + gint outrate; + guint channels; + gint width; + + /* Timestamp and offset bookeeping */ + guint64 t0; + guint64 offset0; + guint64 next_input_offset; + GstClockTime next_input_timestamp; + guint64 next_output_offset; + GstClockTime next_output_timestamp; + gboolean need_discont; + gboolean need_pretend; + gboolean last_gap_state; + + /* Variables to control the size of transforms */ + gsize unitsize; + guint blocksampsin; + guint blocksampsout; + guint blockstridein; + guint blockstrideout; + gsl_matrix_float *workspace32; + gsl_matrix *workspace64; +}; + + +/** + * GSTLALAggregatorClass: + * @parent_class: the parent class + */ + + +struct _GSTLALAggregatorClass { + GstBaseTransformClass parent_class; +}; + + +GType gstlal_aggregator_get_type(void); + + +G_END_DECLS + + +#endif /* __GSTLAL_AGGREGATOR_H__ */ diff --git a/gstlal-ugly/gst/lal/gstlalugly.c b/gstlal-ugly/gst/lal/gstlalugly.c index 225a73a33faedacd280e1d0558c13849ba99f92e..d12da7182b2bc241c1ccd3f27a94f39a6f1a9cde 100644 --- a/gstlal-ugly/gst/lal/gstlalugly.c +++ b/gstlal-ugly/gst/lal/gstlalugly.c @@ -50,6 +50,7 @@ #include <gstlal/gstlal_tags.h> +#include <gstlal_aggregator.h> #include <gstlal_iirbank.h> #include <gstlal_interpolator.h> #include <gstlal_tdwhiten.h> @@ -77,6 +78,7 @@ static gboolean plugin_init(GstPlugin *plugin) const gchar *name; GType type; } *element, elements[] = { + {"lal_aggregator", GSTLAL_AGGREGATOR_TYPE}, {"lal_iirbank", GSTLAL_IIRBANK_TYPE}, {"lal_interpolator", GSTLAL_INTERPOLATOR_TYPE}, {"lal_tdwhiten", GSTLAL_TDWHITEN_TYPE},