diff --git a/gstlal-calibration/gst/cmath/Makefile.am b/gstlal-calibration/gst/cmath/Makefile.am index a2b6c7acb6104621340319de8e2de28ca60205f5..04afb595237381729239478627f3bba26a7c53ec 100644 --- a/gstlal-calibration/gst/cmath/Makefile.am +++ b/gstlal-calibration/gst/cmath/Makefile.am @@ -5,6 +5,8 @@ libgstcmath_la_SOURCES = \ cmath.c \ cmath_base.h cmath_base.c \ cmath_cabs.c \ + cmath_creal.c \ + cmath_cimag.c \ cmath_cexp.c \ cmath_cln.c \ cmath_clog.c \ diff --git a/gstlal-calibration/gst/cmath/cmath.c b/gstlal-calibration/gst/cmath/cmath.c index 6bbf425bdec5fb056393429b12546ccc1b42ed95..8975c0eb6d7ab3f9959ec47a041fcf4b78ee1e13 100644 --- a/gstlal-calibration/gst/cmath/cmath.c +++ b/gstlal-calibration/gst/cmath/cmath.c @@ -53,6 +53,8 @@ GType cmath_cabs_get_type (void); +GType cmath_creal_get_type (void); +GType cmath_cimag_get_type (void); GType cmath_cexp_get_type (void); GType cmath_cln_get_type (void); GType cmath_clog_get_type (void); @@ -71,6 +73,8 @@ plugin_init (GstPlugin *plugin) { "cmath_base", CMATH_BASE_TYPE}, { "cabs", cmath_cabs_get_type ()}, { + "creal", cmath_creal_get_type ()}, { + "cimag", cmath_cimag_get_type ()}, { "cexp", cmath_cexp_get_type ()}, { "cln", cmath_cln_get_type ()}, { "clog", cmath_clog_get_type ()}, { diff --git a/gstlal-calibration/gst/cmath/cmath_base.c b/gstlal-calibration/gst/cmath/cmath_base.c index e943569923aeb2165a52ab9b606cb5b3ed2516c9..4b4cc867198cf3419c2c7a93423cd810113e8aee 100644 --- a/gstlal-calibration/gst/cmath/cmath_base.c +++ b/gstlal-calibration/gst/cmath/cmath_base.c @@ -22,6 +22,8 @@ * https://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer-libs/html/GstBaseTransform.html#GstBaseTransform-struct */ + +#include <gst/audio/audio.h> #include <cmath_base.h> @@ -36,7 +38,7 @@ #define CAPS \ "audio/x-raw, " \ - "format = (string) { F32LE, F32BE, F64LE, F64BE, Z64LE, Z64BE, Z128LE, Z128BE }, " \ + "format = (string) {"GST_AUDIO_NE(F32)", "GST_AUDIO_NE(F64)", "GST_AUDIO_NE(Z64)", "GST_AUDIO_NE(Z128)"}, " \ "rate = (int) [1, MAX], " \ "channels = (int) [1, MAX], " \ "layout = (string) {interleaved, non-interleaved}, " \ @@ -111,7 +113,7 @@ gboolean set_caps(GstBaseTransform *trans, GstCaps *incaps, GstCaps *outcaps) { gboolean success = TRUE; - static char *formats[] = {"Z128LE", "Z64LE", "F64LE", "F32LE"}; + static char *formats[] = {GST_AUDIO_NE(Z128), GST_AUDIO_NE(Z64), GST_AUDIO_NE(F64), GST_AUDIO_NE(F32)}; static int is_complex[] = {1, 1, 0, 0}; static int bits[] = {128, 64, 64, 32}; const gchar *format; diff --git a/gstlal-calibration/gst/cmath/cmath_cabs.c b/gstlal-calibration/gst/cmath/cmath_cabs.c index 689a4ea18029c37838bd037db0702baca030ae4d..6eaff1801b61ea9612d81e00ce5500716f9fc536 100644 --- a/gstlal-calibration/gst/cmath/cmath_cabs.c +++ b/gstlal-calibration/gst/cmath/cmath_cabs.c @@ -18,6 +18,7 @@ */ +#include <gst/audio/audio.h> #include <cmath_base.h> #define TYPE_CMATH_CABS \ @@ -56,72 +57,175 @@ struct _CMathCAbsClass * ============================================================================ */ -/* An in-place transform really does the same thing as the chain function */ +static GstCaps *transform_caps(GstBaseTransform *trans, GstPadDirection direction, GstCaps *caps, GstCaps *filter) +{ + guint n; + + caps = gst_caps_normalize(gst_caps_copy(caps)); + GstCaps *othercaps = gst_caps_new_empty(); + + switch(direction) { + case GST_PAD_SRC: + /* There are two possible sink pad formats for each src pad format, so the sink pad caps has twice as many structures */ + for(n = 0; n < gst_caps_get_size(caps); n++) { + gst_caps_append(othercaps, gst_caps_copy_nth(caps, n)); + gst_caps_append(othercaps, gst_caps_copy_nth(caps, n)); + + GstStructure *str = gst_caps_get_structure(othercaps, 2 * n); + const gchar *format = gst_structure_get_string(str, "format"); + + if(!format) { + GST_DEBUG_OBJECT(trans, "unrecognized caps %" GST_PTR_FORMAT, othercaps); + goto error; + } else if(!strcmp(format, GST_AUDIO_NE(F32)) || !strcmp(format, GST_AUDIO_NE(Z64))) + gst_structure_set(str, "format", G_TYPE_STRING, GST_AUDIO_NE(Z64), NULL); + else if(!strcmp(format, GST_AUDIO_NE(F64)) || !strcmp(format, GST_AUDIO_NE(Z128))) + gst_structure_set(str, "format", G_TYPE_STRING, GST_AUDIO_NE(Z128), NULL); + else { + GST_DEBUG_OBJECT(trans, "unrecognized format %s in %" GST_PTR_FORMAT, format, othercaps); + goto error; + } + } + break; + + case GST_PAD_SINK: + for(n = 0; n < gst_caps_get_size(caps); n++) { + gst_caps_append(othercaps, gst_caps_copy_nth(caps, n)); + GstStructure *str = gst_caps_get_structure(othercaps, n); + const gchar *format = gst_structure_get_string(str, "format"); + + if(!format) { + GST_DEBUG_OBJECT(trans, "unrecognized caps %" GST_PTR_FORMAT, othercaps); + goto error; + } else if(!strcmp(format, GST_AUDIO_NE(F32)) || !strcmp(format, GST_AUDIO_NE(Z64))) + gst_structure_set(str, "format", G_TYPE_STRING, GST_AUDIO_NE(F32), NULL); + else if(!strcmp(format, GST_AUDIO_NE(F64)) || !strcmp(format, GST_AUDIO_NE(Z128))) + gst_structure_set(str, "format", G_TYPE_STRING, GST_AUDIO_NE(F64), NULL); + else { + GST_DEBUG_OBJECT(trans, "unrecognized format %s in %" GST_PTR_FORMAT, format, othercaps); + goto error; + } + } + break; + + case GST_PAD_UNKNOWN: + GST_ELEMENT_ERROR(trans, CORE, NEGOTIATION, (NULL), ("invalid direction GST_PAD_UNKNOWN")); + goto error; + } + + if(filter) { + GstCaps *intersection = gst_caps_intersect(othercaps, filter); + gst_caps_unref(othercaps); + othercaps = intersection; + } + gst_caps_unref(caps); + return gst_caps_simplify(othercaps); + +error: + gst_caps_unref(caps); + gst_caps_unref(othercaps); + return GST_CAPS_NONE; +} + +static gboolean transform_size(GstBaseTransform *trans, GstPadDirection direction, GstCaps *caps, gsize size, GstCaps *othercaps, gsize *othersize) +{ + CMathCAbs* element = CMATH_CABS(trans); + + int is_complex = element->cmath_base.is_complex; -static GstFlowReturn -transform_ip(GstBaseTransform *trans, GstBuffer *buf) + switch(direction) { + case GST_PAD_SRC: + /* + * We have the size of the output buffer, and we set the size of the input buffer, + * which depends on the sink pad caps. + */ + + if(is_complex) { + /* input buffer is twice as large as output buffer since it is complex */ + *othersize = 2 * size; + } else { + /* input and output buffers are the same size */ + *othersize = size; + } + break; + + case GST_PAD_SINK: + /* + * We have the size of the input buffer, and we set the size of the output buffer, + * which depends on the sink pad caps.. + */ + + if(is_complex) { + /* output buffer is half as large as input buffer since it is complex */ + *othersize = size / 2; + } else { + /* input and output buffers are the same size */ + *othersize = size; + } + break; + + case GST_PAD_UNKNOWN: + GST_ELEMENT_ERROR(trans, CORE, NEGOTIATION, (NULL), ("invalid direction GST_PAD_UNKNOWN")); + return FALSE; + } + + return TRUE; + +} + +/* A transform really does the same thing as the chain function */ + +static GstFlowReturn transform(GstBaseTransform *trans, GstBuffer *inbuf, GstBuffer *outbuf) { CMathCAbs* element = CMATH_CABS(trans); int bits = element -> cmath_base.bits; int is_complex = element -> cmath_base.is_complex; - /* - * Debugging - * - * GstObject* element_gstobj = GST_OBJECT(trans); - * int channels = element -> cmath_base.channels; - * int rate = element -> cmath_base.rate; - * g_print("[%s]: passing GstBuffer: ", element_gstobj->name); - * g_print("%d channels, ", channels); - * g_print("%d bits, ", bits); - * g_print("rate: %d, ", rate); - */ - - GstMapInfo info; - if(!gst_buffer_map(buf, &info, GST_MAP_READWRITE)) { - GST_ERROR_OBJECT(trans, "gst_buffer_map failed\n"); - } - gpointer data = info.data; - gpointer data_end = data + info.size; + GstMapInfo inmap, outmap; + gst_buffer_map(inbuf, &inmap, GST_MAP_READ); + gst_buffer_map(outbuf, &outmap, GST_MAP_WRITE); + + gpointer indata = inmap.data; + gpointer outdata = outmap.data; + gpointer indata_end = indata + inmap.size; if(is_complex == 1) { if(bits == 128) { - /* g_print("COMPLEX FLOAT128\n"); */ - double complex *ptr, *end = data_end; - for(ptr = data; ptr < end; ptr++) { - *ptr = cabs(*ptr); - } + double complex *ptr, *end = indata_end; + double *outptr = outdata; + for(ptr = indata; ptr < end; ptr++, outptr++) + *outptr = cabs(*ptr); } else if(bits == 64) { - /* g_print("COMPLEX FLOAT64\n"); */ - float complex *ptr, *end = data_end; - for(ptr = data; ptr < end; ptr++) { - *ptr = cabsf(*ptr); - } + float complex *ptr, *end = indata_end; + float *outptr = outdata; + for(ptr = indata; ptr < end; ptr++, outptr++) + *outptr = cabsf(*ptr); } else { g_assert_not_reached(); } } else if(is_complex == 0) { if(bits == 64) { - /* g_print("REAL FLOAT64\n"); */ - double *ptr, *end = data_end; - for(ptr = data; ptr < end; ptr++) { - *ptr = fabs(*ptr); - } + double *ptr, *end = indata_end; + double *outptr = outdata; + for(ptr = indata; ptr < end; ptr++, outptr++) + *outptr = fabs(*ptr); } else if(bits == 32) { - /* g_print("REAL FLOAT32\n"); */ - float *ptr, *end = data_end; - for(ptr = data; ptr < end; ptr++) { - *ptr = fabsf(*ptr); - } + float *ptr, *end = indata_end; + float *outptr = outdata; + for(ptr = indata; ptr < end; ptr++, outptr++) + *outptr = fabsf(*ptr); } else { g_assert_not_reached(); } } else { g_assert_not_reached(); } - gst_buffer_unmap(buf, &info); + + gst_buffer_unmap(inbuf, &inmap); + gst_buffer_unmap(outbuf, &outmap); + return GST_FLOW_OK; } @@ -146,8 +250,10 @@ cmath_cabs_class_init(gpointer klass, gpointer klass_data) "Calculate absolute value, y = |x|", "Aaron Viets <aaron.viets@ligo.org>, Leo Singer <leo.singer@ligo.org>"); - basetransform_class -> transform_ip = GST_DEBUG_FUNCPTR(transform_ip); + basetransform_class -> transform = GST_DEBUG_FUNCPTR(transform); basetransform_class -> set_caps = GST_DEBUG_FUNCPTR(set_caps); + basetransform_class -> transform_caps = GST_DEBUG_FUNCPTR(transform_caps); + basetransform_class -> transform_size = GST_DEBUG_FUNCPTR(transform_size); } GType diff --git a/gstlal-calibration/gst/cmath/cmath_cimag.c b/gstlal-calibration/gst/cmath/cmath_cimag.c new file mode 100644 index 0000000000000000000000000000000000000000..adc2600e88b81102fbc362c088b076bd42493506 --- /dev/null +++ b/gstlal-calibration/gst/cmath/cmath_cimag.c @@ -0,0 +1,274 @@ +/* + * Copyright (C) 2010 Leo Singer + * Copyright (C) 2016 Aaron Viets + * + * 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. + */ + + +#include <gst/audio/audio.h> +#include <cmath_base.h> + +#define TYPE_CMATH_CIMAG \ + (cmath_cimag_get_type()) +#define CMATH_CIMAG(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),TYPE_CMATH_CIMAG,CMathCImag)) +#define CMATH_CIMAG_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),TYPE_CMATH_CIMAG,CMathCImagClass)) +#define IS_PLUGIN_TEMPLATE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),TYPE_CMATH_CIMAG)) +#define IS_PLUGIN_TEMPLATE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),TYPE_CMATH_CIMAG)) + +typedef struct _CMathCImag CMathCImag; +typedef struct _CMathCImagClass CMathCImagClass; + +GType +cmath_cimag_get_type(void); + +struct _CMathCImag +{ + CMathBase cmath_base; +}; + +struct _CMathCImagClass +{ + CMathBaseClass parent_class; +}; + + +/* + * ============================================================================ + * + * GstBaseTransform vmethod Implementations + * + * ============================================================================ + */ + +static GstCaps *transform_caps(GstBaseTransform *trans, GstPadDirection direction, GstCaps *caps, GstCaps *filter) +{ + guint n; + + caps = gst_caps_normalize(gst_caps_copy(caps)); + GstCaps *othercaps = gst_caps_new_empty(); + + switch(direction) { + case GST_PAD_SRC: + /* There are two possible sink pad formats for each src pad format, so the sink pad caps has twice as many structures */ + for(n = 0; n < gst_caps_get_size(caps); n++) { + gst_caps_append(othercaps, gst_caps_copy_nth(caps, n)); + gst_caps_append(othercaps, gst_caps_copy_nth(caps, n)); + + GstStructure *str = gst_caps_get_structure(othercaps, 2 * n); + const gchar *format = gst_structure_get_string(str, "format"); + + if(!format) { + GST_DEBUG_OBJECT(trans, "unrecognized caps %" GST_PTR_FORMAT, othercaps); + goto error; + } else if(!strcmp(format, GST_AUDIO_NE(F32)) || !strcmp(format, GST_AUDIO_NE(Z64))) + gst_structure_set(str, "format", G_TYPE_STRING, GST_AUDIO_NE(Z64), NULL); + else if(!strcmp(format, GST_AUDIO_NE(F64)) || !strcmp(format, GST_AUDIO_NE(Z128))) + gst_structure_set(str, "format", G_TYPE_STRING, GST_AUDIO_NE(Z128), NULL); + else { + GST_DEBUG_OBJECT(trans, "unrecognized format %s in %" GST_PTR_FORMAT, format, othercaps); + goto error; + } + } + break; + + case GST_PAD_SINK: + for(n = 0; n < gst_caps_get_size(caps); n++) { + gst_caps_append(othercaps, gst_caps_copy_nth(caps, n)); + GstStructure *str = gst_caps_get_structure(othercaps, n); + const gchar *format = gst_structure_get_string(str, "format"); + + if(!format) { + GST_DEBUG_OBJECT(trans, "unrecognized caps %" GST_PTR_FORMAT, othercaps); + goto error; + } else if(!strcmp(format, GST_AUDIO_NE(F32)) || !strcmp(format, GST_AUDIO_NE(Z64))) + gst_structure_set(str, "format", G_TYPE_STRING, GST_AUDIO_NE(F32), NULL); + else if(!strcmp(format, GST_AUDIO_NE(F64)) || !strcmp(format, GST_AUDIO_NE(Z128))) + gst_structure_set(str, "format", G_TYPE_STRING, GST_AUDIO_NE(F64), NULL); + else { + GST_DEBUG_OBJECT(trans, "unrecognized format %s in %" GST_PTR_FORMAT, format, othercaps); + goto error; + } + } + break; + + case GST_PAD_UNKNOWN: + GST_ELEMENT_ERROR(trans, CORE, NEGOTIATION, (NULL), ("invalid direction GST_PAD_UNKNOWN")); + goto error; + } + + if(filter) { + GstCaps *intersection = gst_caps_intersect(othercaps, filter); + gst_caps_unref(othercaps); + othercaps = intersection; + } + gst_caps_unref(caps); + return gst_caps_simplify(othercaps); + +error: + gst_caps_unref(caps); + gst_caps_unref(othercaps); + return GST_CAPS_NONE; +} + +static gboolean transform_size(GstBaseTransform *trans, GstPadDirection direction, GstCaps *caps, gsize size, GstCaps *othercaps, gsize *othersize) +{ + CMathCImag* element = CMATH_CIMAG(trans); + + int is_complex = element->cmath_base.is_complex; + + switch(direction) { + case GST_PAD_SRC: + /* + * We have the size of the output buffer, and we set the size of the input buffer, + * which depends on the sink pad caps. + */ + + if(is_complex) { + /* input buffer is twice as large as output buffer since it is complex */ + *othersize = 2 * size; + } else { + /* input and output buffers are the same size */ + *othersize = size; + } + break; + + case GST_PAD_SINK: + /* + * We have the size of the input buffer, and we set the size of the output buffer, + * which depends on the sink pad caps.. + */ + + if(is_complex) { + /* output buffer is half as large as input buffer since it is complex */ + *othersize = size / 2; + } else { + /* input and output buffers are the same size */ + *othersize = size; + } + break; + + case GST_PAD_UNKNOWN: + GST_ELEMENT_ERROR(trans, CORE, NEGOTIATION, (NULL), ("invalid direction GST_PAD_UNKNOWN")); + return FALSE; + } + + return TRUE; + +} + +/* A transform really does the same thing as the chain function */ + +static GstFlowReturn transform(GstBaseTransform *trans, GstBuffer *inbuf, GstBuffer *outbuf) +{ + CMathCImag* element = CMATH_CIMAG(trans); + int bits = element -> cmath_base.bits; + int is_complex = element -> cmath_base.is_complex; + + GstMapInfo inmap, outmap; + gst_buffer_map(inbuf, &inmap, GST_MAP_READ); + gst_buffer_map(outbuf, &outmap, GST_MAP_WRITE); + + gpointer indata = inmap.data; + gpointer outdata = outmap.data; + gpointer indata_end = indata + inmap.size; + + if(is_complex == 1) { + + if(bits == 128) { + double complex *ptr, *end = indata_end; + double *outptr = outdata; + for(ptr = indata; ptr < end; ptr++, outptr++) + *outptr = cimag(*ptr); + } else if(bits == 64) { + float complex *ptr, *end = indata_end; + float *outptr = outdata; + for(ptr = indata; ptr < end; ptr++, outptr++) + *outptr = cimagf(*ptr); + } else { + g_assert_not_reached(); + } + } else if(is_complex == 0) { + + if(bits == 64) { + double *ptr, *end = indata_end; + double *outptr = outdata; + for(ptr = indata; ptr < end; ptr++, outptr++) + *outptr = 0; + } else if(bits == 32) { + float *ptr, *end = indata_end; + float *outptr = outdata; + for(ptr = indata; ptr < end; ptr++, outptr++) + *outptr = 0; + } else { + g_assert_not_reached(); + } + } else { + g_assert_not_reached(); + } + + gst_buffer_unmap(inbuf, &inmap); + gst_buffer_unmap(outbuf, &outmap); + + return GST_FLOW_OK; +} + + +/* + * ============================================================================ + * + * Type Support + * + * ============================================================================ + */ + +/* Initialize the plugin's class */ +static void +cmath_cimag_class_init(gpointer klass, gpointer klass_data) +{ + GstBaseTransformClass *basetransform_class = GST_BASE_TRANSFORM_CLASS(klass); + + gst_element_class_set_details_simple(GST_ELEMENT_CLASS(klass), + "Imaginary", + "Filter/Audio", + "Calculate imanginary part of a complex number, y = Im(x)", + "Aaron Viets <aaron.viets@ligo.org>"); + + basetransform_class -> transform = GST_DEBUG_FUNCPTR(transform); + basetransform_class -> set_caps = GST_DEBUG_FUNCPTR(set_caps); + basetransform_class -> transform_caps = GST_DEBUG_FUNCPTR(transform_caps); + basetransform_class -> transform_size = GST_DEBUG_FUNCPTR(transform_size); +} + +GType +cmath_cimag_get_type(void) +{ + static GType type = 0; + + if(!type) { + static const GTypeInfo info = { + .class_size = sizeof(CMathBaseClass), + .class_init = cmath_cimag_class_init, + .instance_size = sizeof(CMathBase), + }; + type = g_type_register_static(CMATH_BASE_TYPE, "CMathCImag", &info, 0); + } + + return type; +} diff --git a/gstlal-calibration/gst/cmath/cmath_creal.c b/gstlal-calibration/gst/cmath/cmath_creal.c new file mode 100644 index 0000000000000000000000000000000000000000..cd41db49c6950ab1ff7d8f33c4a87d84f360c033 --- /dev/null +++ b/gstlal-calibration/gst/cmath/cmath_creal.c @@ -0,0 +1,274 @@ +/* + * Copyright (C) 2010 Leo Singer + * Copyright (C) 2016 Aaron Viets + * + * 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. + */ + + +#include <gst/audio/audio.h> +#include <cmath_base.h> + +#define TYPE_CMATH_CREAL \ + (cmath_creal_get_type()) +#define CMATH_CREAL(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),TYPE_CMATH_CREAL,CMathCReal)) +#define CMATH_CREAL_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),TYPE_CMATH_CREAL,CMathCRealClass)) +#define IS_PLUGIN_TEMPLATE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),TYPE_CMATH_CREAL)) +#define IS_PLUGIN_TEMPLATE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),TYPE_CMATH_CREAL)) + +typedef struct _CMathCReal CMathCReal; +typedef struct _CMathCRealClass CMathCRealClass; + +GType +cmath_creal_get_type(void); + +struct _CMathCReal +{ + CMathBase cmath_base; +}; + +struct _CMathCRealClass +{ + CMathBaseClass parent_class; +}; + + +/* + * ============================================================================ + * + * GstBaseTransform vmethod Implementations + * + * ============================================================================ + */ + +static GstCaps *transform_caps(GstBaseTransform *trans, GstPadDirection direction, GstCaps *caps, GstCaps *filter) +{ + guint n; + + caps = gst_caps_normalize(gst_caps_copy(caps)); + GstCaps *othercaps = gst_caps_new_empty(); + + switch(direction) { + case GST_PAD_SRC: + /* There are two possible sink pad formats for each src pad format, so the sink pad caps has twice as many structures */ + for(n = 0; n < gst_caps_get_size(caps); n++) { + gst_caps_append(othercaps, gst_caps_copy_nth(caps, n)); + gst_caps_append(othercaps, gst_caps_copy_nth(caps, n)); + + GstStructure *str = gst_caps_get_structure(othercaps, 2 * n); + const gchar *format = gst_structure_get_string(str, "format"); + + if(!format) { + GST_DEBUG_OBJECT(trans, "unrecognized caps %" GST_PTR_FORMAT, othercaps); + goto error; + } else if(!strcmp(format, GST_AUDIO_NE(F32)) || !strcmp(format, GST_AUDIO_NE(Z64))) + gst_structure_set(str, "format", G_TYPE_STRING, GST_AUDIO_NE(Z64), NULL); + else if(!strcmp(format, GST_AUDIO_NE(F64)) || !strcmp(format, GST_AUDIO_NE(Z128))) + gst_structure_set(str, "format", G_TYPE_STRING, GST_AUDIO_NE(Z128), NULL); + else { + GST_DEBUG_OBJECT(trans, "unrecognized format %s in %" GST_PTR_FORMAT, format, othercaps); + goto error; + } + } + break; + + case GST_PAD_SINK: + for(n = 0; n < gst_caps_get_size(caps); n++) { + gst_caps_append(othercaps, gst_caps_copy_nth(caps, n)); + GstStructure *str = gst_caps_get_structure(othercaps, n); + const gchar *format = gst_structure_get_string(str, "format"); + + if(!format) { + GST_DEBUG_OBJECT(trans, "unrecognized caps %" GST_PTR_FORMAT, othercaps); + goto error; + } else if(!strcmp(format, GST_AUDIO_NE(F32)) || !strcmp(format, GST_AUDIO_NE(Z64))) + gst_structure_set(str, "format", G_TYPE_STRING, GST_AUDIO_NE(F32), NULL); + else if(!strcmp(format, GST_AUDIO_NE(F64)) || !strcmp(format, GST_AUDIO_NE(Z128))) + gst_structure_set(str, "format", G_TYPE_STRING, GST_AUDIO_NE(F64), NULL); + else { + GST_DEBUG_OBJECT(trans, "unrecognized format %s in %" GST_PTR_FORMAT, format, othercaps); + goto error; + } + } + break; + + case GST_PAD_UNKNOWN: + GST_ELEMENT_ERROR(trans, CORE, NEGOTIATION, (NULL), ("invalid direction GST_PAD_UNKNOWN")); + goto error; + } + + if(filter) { + GstCaps *intersection = gst_caps_intersect(othercaps, filter); + gst_caps_unref(othercaps); + othercaps = intersection; + } + gst_caps_unref(caps); + return gst_caps_simplify(othercaps); + +error: + gst_caps_unref(caps); + gst_caps_unref(othercaps); + return GST_CAPS_NONE; +} + +static gboolean transform_size(GstBaseTransform *trans, GstPadDirection direction, GstCaps *caps, gsize size, GstCaps *othercaps, gsize *othersize) +{ + CMathCReal* element = CMATH_CREAL(trans); + + int is_complex = element->cmath_base.is_complex; + + switch(direction) { + case GST_PAD_SRC: + /* + * We have the size of the output buffer, and we set the size of the input buffer, + * which depends on the sink pad caps. + */ + + if(is_complex) { + /* input buffer is twice as large as output buffer since it is complex */ + *othersize = 2 * size; + } else { + /* input and output buffers are the same size */ + *othersize = size; + } + break; + + case GST_PAD_SINK: + /* + * We have the size of the input buffer, and we set the size of the output buffer, + * which depends on the sink pad caps.. + */ + + if(is_complex) { + /* output buffer is half as large as input buffer since it is complex */ + *othersize = size / 2; + } else { + /* input and output buffers are the same size */ + *othersize = size; + } + break; + + case GST_PAD_UNKNOWN: + GST_ELEMENT_ERROR(trans, CORE, NEGOTIATION, (NULL), ("invalid direction GST_PAD_UNKNOWN")); + return FALSE; + } + + return TRUE; + +} + +/* A transform really does the same thing as the chain function */ + +static GstFlowReturn transform(GstBaseTransform *trans, GstBuffer *inbuf, GstBuffer *outbuf) +{ + CMathCReal* element = CMATH_CREAL(trans); + int bits = element -> cmath_base.bits; + int is_complex = element -> cmath_base.is_complex; + + GstMapInfo inmap, outmap; + gst_buffer_map(inbuf, &inmap, GST_MAP_READ); + gst_buffer_map(outbuf, &outmap, GST_MAP_WRITE); + + gpointer indata = inmap.data; + gpointer outdata = outmap.data; + gpointer indata_end = indata + inmap.size; + + if(is_complex == 1) { + + if(bits == 128) { + double complex *ptr, *end = indata_end; + double *outptr = outdata; + for(ptr = indata; ptr < end; ptr++, outptr++) + *outptr = creal(*ptr); + } else if(bits == 64) { + float complex *ptr, *end = indata_end; + float *outptr = outdata; + for(ptr = indata; ptr < end; ptr++, outptr++) + *outptr = crealf(*ptr); + } else { + g_assert_not_reached(); + } + } else if(is_complex == 0) { + + if(bits == 64) { + double *ptr, *end = indata_end; + double *outptr = outdata; + for(ptr = indata; ptr < end; ptr++, outptr++) + *outptr = *ptr; + } else if(bits == 32) { + float *ptr, *end = indata_end; + float *outptr = outdata; + for(ptr = indata; ptr < end; ptr++, outptr++) + *outptr = *ptr; + } else { + g_assert_not_reached(); + } + } else { + g_assert_not_reached(); + } + + gst_buffer_unmap(inbuf, &inmap); + gst_buffer_unmap(outbuf, &outmap); + + return GST_FLOW_OK; +} + + +/* + * ============================================================================ + * + * Type Support + * + * ============================================================================ + */ + +/* Initialize the plugin's class */ +static void +cmath_creal_class_init(gpointer klass, gpointer klass_data) +{ + GstBaseTransformClass *basetransform_class = GST_BASE_TRANSFORM_CLASS(klass); + + gst_element_class_set_details_simple(GST_ELEMENT_CLASS(klass), + "Real", + "Filter/Audio", + "Calculate real part of a complex number, y = Re(x)", + "Aaron Viets <aaron.viets@ligo.org>"); + + basetransform_class -> transform = GST_DEBUG_FUNCPTR(transform); + basetransform_class -> set_caps = GST_DEBUG_FUNCPTR(set_caps); + basetransform_class -> transform_caps = GST_DEBUG_FUNCPTR(transform_caps); + basetransform_class -> transform_size = GST_DEBUG_FUNCPTR(transform_size); +} + +GType +cmath_creal_get_type(void) +{ + static GType type = 0; + + if(!type) { + static const GTypeInfo info = { + .class_size = sizeof(CMathBaseClass), + .class_init = cmath_creal_class_init, + .instance_size = sizeof(CMathBase), + }; + type = g_type_register_static(CMATH_BASE_TYPE, "CMathCReal", &info, 0); + } + + return type; +} diff --git a/gstlal-calibration/gst/lal/gstlal_demodulate.c b/gstlal-calibration/gst/lal/gstlal_demodulate.c index 6320d5eb621f1aaeca588a9c2b44e5ae28b98862..ee0b5474c3fbcc04e9b78395b34d4cbb9c14db45 100644 --- a/gstlal-calibration/gst/lal/gstlal_demodulate.c +++ b/gstlal-calibration/gst/lal/gstlal_demodulate.c @@ -47,7 +47,6 @@ #include <gst/gst.h> #include <gst/audio/audio.h> #include <gst/base/gstbasetransform.h> -#include <gst/audio/audio.h> /*