Skip to content
Snippets Groups Projects
Commit 5fb2c45e authored by Aaron Viets's avatar Aaron Viets
Browse files

gstlal-calibration: lal_demodulate: New element

- Multiplies incoming real float stream by exp(i*2*pi*line_frequency*t), where line_frequency is a property to set to a calibration line frequency. This allows for the extraction of the calibration factors, "kappa's".
parent 626eb7da
No related branches found
No related tags found
No related merge requests found
......@@ -7,7 +7,8 @@ libgstlalcalibration_la_SOURCES = \
gstlal_wings.c gstlal_wings.h \
gstlal_smoothcalibfactors.c gstlal_smoothcalibfactors.h \
gstlal_constantupsample.c gstlal_constantupsample.h \
gstlal_logicalundersample.c gstlal_logicalundersample.h
gstlal_logicalundersample.c gstlal_logicalundersample.h \
gstlal_demodulate.c gstlal_demodulate.h
libgstlalcalibration_la_CPPFLAGS = $(AM_CPPFLAGS) $(PYTHON_CPPFLAGS)
libgstlalcalibration_la_CFLAGS = $(AM_CFLAGS) $(LAL_CFLAGS) $(GSTLAL_CFLAGS) $(gstreamer_CFLAGS) $(gstreamer_audio_CFLAGS)
libgstlalcalibration_la_LDFLAGS = $(AM_LDFLAGS) $(LAL_LIBS) $(GSTLAL_LIBS) $(PYTHON_LDFLAGS) $(gstreamer_LIBS) $(gstreamer_audio_LIBS) $(GSTLAL_PLUGIN_LDFLAGS)
/*
* Copyright (C) 2016 Aaron Viets <aaron.viets@ligo.org>
*
* 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
*
* ============================================================================
*/
/*
* stuff from the C library
*/
#include <string.h>
#include <complex.h>
#include <math.h>
/*
* stuff from gobject/gstreamer
*/
#include <glib.h>
#include <gst/gst.h>
#include <gst/audio/audio.h>
#include <gst/base/gstbasetransform.h>
#include <gst/audio/audio.h>
/*
* our own stuff
*/
#include <gstlal_demodulate.h>
/*
* ============================================================================
*
* Utilities
*
* ============================================================================
*/
static void demodulate_float(const float *src, gsize src_size, float complex *dst, guint64 t, gint rate, const double frequency)
{
const float *src_end;
for(src_end = src + src_size; src < src_end; src++, dst++) {
*dst = *src * cexpf(2. * M_PI * I * frequency * t / 1000000000);
t += 1000000000 / rate;
}
}
static void demodulate_double(const double *src, gsize src_size, double complex *dst, guint64 t, gint rate, const double frequency)
{
const double *src_end;
for(src_end = src + src_size; src < src_end; src++, dst++) {
*dst = *src * cexp(2. * M_PI * I * frequency * t / 1000000000);
t += 1000000000 / rate;
}
}
static void demodulate(const void *src, gsize src_size, void *dst, gsize dst_size, guint64 t, gint rate, gint unit_size, const double frequency)
{
g_assert_cmpuint(src_size % unit_size, ==, 0);
g_assert_cmpuint(dst_size % unit_size, ==, 0);
g_assert_cmpuint(2 * src_size, ==, dst_size);
dst_size /= unit_size;
src_size /= unit_size;
switch(unit_size) {
case 4:
demodulate_float(src, src_size, dst, t, rate, frequency);
break;
case 8:
demodulate_double(src, src_size, dst, t, rate, frequency);
break;
default:
g_assert_not_reached();
}
}
/*
* set the metadata on an output buffer
*/
static void set_metadata(GSTLALDemodulate *element, GstBuffer *buf, guint64 outsamples, gboolean gap)
{
GST_BUFFER_OFFSET(buf) = element->next_out_offset;
element->next_out_offset += outsamples;
GST_BUFFER_OFFSET_END(buf) = element->next_out_offset;
GST_BUFFER_TIMESTAMP(buf) = element->t0 + gst_util_uint64_scale_int_round(GST_BUFFER_OFFSET(buf) - element->offset0, GST_SECOND, element->rate);
GST_BUFFER_DURATION(buf) = element->t0 + gst_util_uint64_scale_int_round(GST_BUFFER_OFFSET_END(buf) - element->offset0, GST_SECOND, element->rate) - GST_BUFFER_TIMESTAMP(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);
else
GST_BUFFER_FLAG_UNSET(buf, GST_BUFFER_FLAG_GAP);
}
/*
* ============================================================================
*
* GStreamer Boiler Plate
*
* ============================================================================
*/
#define INCAPS \
"audio/x-raw, " \
"format = (string) {"GST_AUDIO_NE(F32)", "GST_AUDIO_NE(F64)"}, " \
"rate = " GST_AUDIO_RATE_RANGE ", " \
"channels = (int) [1, MAX], " \
"layout = (string) interleaved, " \
"channel-mask = (bitmask) 0"
#define OUTCAPS \
"audio/x-raw, " \
"format = (string) {"GST_AUDIO_NE(Z64)", "GST_AUDIO_NE(Z128)"}, " \
"rate = " GST_AUDIO_RATE_RANGE ", " \
"channels = (int) [1, MAX], " \
"layout = (string) interleaved, " \
"channel-mask = (bitmask) 0"
static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE(
GST_BASE_TRANSFORM_SINK_NAME,
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_STATIC_CAPS(INCAPS)
);
static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE(
GST_BASE_TRANSFORM_SRC_NAME,
GST_PAD_SRC,
GST_PAD_ALWAYS,
GST_STATIC_CAPS(OUTCAPS)
);
G_DEFINE_TYPE(
GSTLALDemodulate,
gstlal_demodulate,
GST_TYPE_BASE_TRANSFORM
);
/*
* ============================================================================
*
* 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 caps %" GST_PTR_FORMAT, caps);
return success;
}
/*
* transform_caps()
*/
static GstCaps *transform_caps(GstBaseTransform *trans, GstPadDirection direction, GstCaps *caps, GstCaps *filter)
{
guint n;
caps = gst_caps_normalize(gst_caps_copy(caps));
switch(direction) {
case GST_PAD_SRC:
for(n = 0; n < gst_caps_get_size(caps); n++) {
GstStructure *str = gst_caps_get_structure(caps, n);
const gchar *format = gst_structure_get_string(str, "format");
if(!format) {
GST_DEBUG_OBJECT(trans, "unrecognized caps %" GST_PTR_FORMAT, caps);
goto error;
} else if(!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(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, caps);
goto error;
}
}
break;
case GST_PAD_SINK:
for(n = 0; n < gst_caps_get_size(caps); n++) {
GstStructure *str = gst_caps_get_structure(caps, n);
const gchar *format = gst_structure_get_string(str, "format");
if(!format) {
GST_DEBUG_OBJECT(trans, "unrecognized caps %" GST_PTR_FORMAT, caps);
goto error;
} else if(!strcmp(format, GST_AUDIO_NE(F32)))
gst_structure_set(str, "format", G_TYPE_STRING, GST_AUDIO_NE(Z64), NULL);
else if(!strcmp(format, GST_AUDIO_NE(F64)))
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, caps);
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(caps, filter);
gst_caps_unref(caps);
caps = intersection;
}
return gst_caps_simplify(caps);
error:
gst_caps_unref(caps);
return GST_CAPS_NONE;
}
/*
* set_caps()
*/
static gboolean set_caps(GstBaseTransform *trans, GstCaps *incaps, GstCaps *outcaps)
{
GSTLALDemodulate *element = GSTLAL_DEMODULATE(trans);
gint rate_in, rate_out;
gsize unit_size;
/*
* parse the caps
*/
if(!get_unit_size(trans, incaps, &unit_size)) {
GST_DEBUG_OBJECT(element, "function 'get_unit_size' failed");
return FALSE;
}
if(!gst_structure_get_int(gst_caps_get_structure(incaps, 0), "rate", &rate_in)) {
GST_DEBUG_OBJECT(element, "unable to parse rate from %" GST_PTR_FORMAT, incaps);
return FALSE;
}
if(!gst_structure_get_int(gst_caps_get_structure(outcaps, 0), "rate", &rate_out)) {
GST_DEBUG_OBJECT(element, "unable to parse rate from %" GST_PTR_FORMAT, outcaps);
return FALSE;
}
/*
* require the output rate to be equal to the input rate
*/
if(rate_out != rate_in) {
GST_ERROR_OBJECT(element, "output rate is not equal to input rate. input caps = %" GST_PTR_FORMAT " output caps = %" GST_PTR_FORMAT, incaps, outcaps);
return FALSE;
}
/*
* record stream parameters
*/
element->rate = rate_in;
element->unit_size = unit_size;
return TRUE;
}
/*
* transform_size()
*/
static gboolean transform_size(GstBaseTransform *trans, GstPadDirection direction, GstCaps *caps, gsize size, GstCaps *othercaps, gsize *othersize)
{
GSTLALDemodulate *element = GSTLAL_DEMODULATE(trans);
gsize unit_size;
switch(direction) {
case GST_PAD_SRC:
/*
* We have the size of the output buffer, and we set the size of the input buffer,
* which is half as large in bytes.
*/
if(!get_unit_size(trans, caps, &unit_size)) {
GST_DEBUG_OBJECT(element, "function 'get_unit_size' failed");
return FALSE;
}
/* buffer size in bytes should be a multiple of unit_size in bytes */
if(G_UNLIKELY(size % unit_size)) {
GST_DEBUG_OBJECT(element, "buffer size %" G_GSIZE_FORMAT " is not a multiple of %" G_GSIZE_FORMAT, size, unit_size);
return FALSE;
}
*othersize = size / 2;
break;
case GST_PAD_SINK:
/*
* We have the size of the input buffer, and we set the size of the output buffer,
* which is twice as large in bytes.
*/
if(!get_unit_size(trans, caps, &unit_size)) {
GST_DEBUG_OBJECT(element, "function 'get_unit_size' failed");
return FALSE;
}
/* buffer size in bytes should be a multiple of unit_size in bytes */
if(G_UNLIKELY(size % unit_size)) {
GST_DEBUG_OBJECT(element, "buffer size %" G_GSIZE_FORMAT " is not a multiple of %" G_GSIZE_FORMAT, size, unit_size);
return FALSE;
}
*othersize = 2 * size;
break;
case GST_PAD_UNKNOWN:
GST_ELEMENT_ERROR(trans, CORE, NEGOTIATION, (NULL), ("invalid direction GST_PAD_UNKNOWN"));
return FALSE;
}
return TRUE;
}
/*
* start()
*/
static gboolean start(GstBaseTransform *trans)
{
GSTLALDemodulate *element = GSTLAL_DEMODULATE(trans);
element->t0 = GST_CLOCK_TIME_NONE;
element->offset0 = GST_BUFFER_OFFSET_NONE;
element->next_in_offset = GST_BUFFER_OFFSET_NONE;
element->next_out_offset = GST_BUFFER_OFFSET_NONE;
element->need_discont = TRUE;
return TRUE;
}
/*
* transform()
*/
static GstFlowReturn transform(GstBaseTransform *trans, GstBuffer *inbuf, GstBuffer *outbuf)
{
GSTLALDemodulate *element = GSTLAL_DEMODULATE(trans);
GstMapInfo inmap, outmap;
GstFlowReturn result = GST_FLOW_OK;
/*
* check for discontinuity
*/
if(G_UNLIKELY(GST_BUFFER_IS_DISCONT(inbuf) || GST_BUFFER_OFFSET(inbuf) != element->next_in_offset || !GST_CLOCK_TIME_IS_VALID(element->t0))) {
element->t0 = GST_BUFFER_TIMESTAMP(inbuf);
element->offset0 = element->next_out_offset = GST_BUFFER_OFFSET(inbuf);
element->need_discont = TRUE;
}
element->next_in_offset = GST_BUFFER_OFFSET_END(inbuf);
/*
* process buffer
*/
if(!GST_BUFFER_FLAG_IS_SET(inbuf, GST_BUFFER_FLAG_GAP)) {
/*
* input is not gap.
*/
gst_buffer_map(inbuf, &inmap, GST_MAP_READ);
gst_buffer_map(outbuf, &outmap, GST_MAP_WRITE);
guint64 t0 = GST_BUFFER_TIMESTAMP(inbuf);
demodulate(inmap.data, inmap.size, outmap.data, outmap.size, t0, element->rate, element->unit_size, element->line_frequency);
set_metadata(element, outbuf, outmap.size / (2 * element->unit_size), FALSE);
gst_buffer_unmap(outbuf, &outmap);
gst_buffer_unmap(inbuf, &inmap);
} else {
/*
* input is gap.
*/
GST_BUFFER_FLAG_SET(outbuf, GST_BUFFER_FLAG_GAP);
gst_buffer_map(outbuf, &outmap, GST_MAP_WRITE);
memset(outmap.data, 0, outmap.size);
set_metadata(element, outbuf, outmap.size / (2 * element->unit_size), TRUE);
gst_buffer_unmap(outbuf, &outmap);
}
/*
* done
*/
return result;
}
/*
* ============================================================================
*
* GObject Method Overrides
*
* ============================================================================
*/
/*
* properties
*/
enum property {
ARG_LINE_FREQUENCY = 1,
};
static void set_property(GObject *object, enum property prop_id, const GValue *value, GParamSpec *pspec)
{
GSTLALDemodulate *element = GSTLAL_DEMODULATE(object);
GST_OBJECT_LOCK(element);
switch (prop_id) {
case ARG_LINE_FREQUENCY:
element->line_frequency = g_value_get_double(value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
}
GST_OBJECT_UNLOCK(element);
}
static void get_property(GObject *object, enum property prop_id, GValue *value, GParamSpec *pspec)
{
GSTLALDemodulate *element = GSTLAL_DEMODULATE(object);
GST_OBJECT_LOCK(element);
switch (prop_id) {
case ARG_LINE_FREQUENCY:
g_value_set_double(value, element->line_frequency);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
}
GST_OBJECT_UNLOCK(element);
}
/*
* class_init()
*/
static void gstlal_demodulate_class_init(GSTLALDemodulateClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
GstElementClass *element_class = GST_ELEMENT_CLASS(klass);
GstBaseTransformClass *transform_class = GST_BASE_TRANSFORM_CLASS(klass);
gobject_class->set_property = GST_DEBUG_FUNCPTR(set_property);
gobject_class->get_property = GST_DEBUG_FUNCPTR(get_property);
transform_class->transform_caps = GST_DEBUG_FUNCPTR(transform_caps);
transform_class->get_unit_size = GST_DEBUG_FUNCPTR(get_unit_size);
transform_class->set_caps = GST_DEBUG_FUNCPTR(set_caps);
transform_class->transform_size = GST_DEBUG_FUNCPTR(transform_size);
transform_class->start = GST_DEBUG_FUNCPTR(start);
transform_class->transform = GST_DEBUG_FUNCPTR(transform);
gst_element_class_set_details_simple(element_class,
"Demodulate",
"Filter/Audio",
"Multiplies incoming float stream by exp(i * 2 * pi * line_frequency * t)",
"Aaron Viets <aaron.viets@ligo.org>"
);
gst_element_class_add_pad_template(element_class, gst_static_pad_template_get(&src_factory));
gst_element_class_add_pad_template(element_class, gst_static_pad_template_get(&sink_factory));
g_object_class_install_property(
gobject_class,
ARG_LINE_FREQUENCY,
g_param_spec_double(
"line-frequency",
"Calibration line frequency",
"The frequency of the calibration line corresponding to the calibration factor 'kappa' we wish to extract from incoming stream",
0, G_MAXDOUBLE, 300.,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT
)
);
}
/*
* init()
*/
static void gstlal_demodulate_init(GSTLALDemodulate *element)
{
element->rate = 0;
element->unit_size = 0;
gst_base_transform_set_qos_enabled(GST_BASE_TRANSFORM(element), TRUE);
gst_base_transform_set_gap_aware(GST_BASE_TRANSFORM(element), TRUE);
}
/*
* Copyright (C) 2016 Aaron Viets <aaron.viets@ligo.org>
*
* 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 __GST_LAL_DEMODULATE_H__
#define __GST_LAL_DEMODULATE_H__
#include <glib.h>
#include <gst/gst.h>
#include <gst/base/gstbasetransform.h>
G_BEGIN_DECLS
#define GSTLAL_DEMODULATE_TYPE \
(gstlal_demodulate_get_type())
#define GSTLAL_DEMODULATE(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj), GSTLAL_DEMODULATE_TYPE, GSTLALDemodulate))
#define GSTLAL_DEMODULATE_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass), GSTLAL_DEMODULATE_TYPE, GSTLALDemodulateClass))
#define GST_IS_GSTLAL_DEMODULATE(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj), GSTLAL_DEMODULATE_TYPE))
#define GST_IS_GSTLAL_DEMODULATE_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE((klass), GSTLAL_DEMODULATE_TYPE))
typedef struct _GSTLALDemodulate GSTLALDemodulate;
typedef struct _GSTLALDemodulateClass GSTLALDemodulateClass;
/*
* GSTLALDemodulate:
*/
struct _GSTLALDemodulate {
GstBaseTransform element;
/* stream info */
gint unit_size;
gint rate;
/* timestamp book-keeping */
GstClockTime t0;
guint64 offset0;
guint64 next_in_offset;
guint64 next_out_offset;
gboolean need_discont;
/* properties */
double line_frequency;
};
/*
* GSTLALDemodulateClass:
* @parent_class: the parent class
*/
struct _GSTLALDemodulateClass {
GstBaseTransformClass parent_class;
};
GType gstlal_demodulate_get_type(void);
G_END_DECLS
#endif /* __GST_LAL_DEMODULATE_H__ */
......@@ -56,6 +56,7 @@
#include <gstlal_smoothcalibfactors.h>
#include <gstlal_constantupsample.h>
#include <gstlal_logicalundersample.h>
#include <gstlal_demodulate.h>
/*
......@@ -79,6 +80,7 @@ static gboolean plugin_init(GstPlugin *plugin)
{"lal_smoothcalibfactors", GSTLAL_SMOOTHCALIBFACTORS_TYPE},
{"lal_constantupsample", GSTLAL_CONSTANTUPSAMPLE_TYPE},
{"lal_logicalundersample", GSTLAL_LOGICALUNDERSAMPLE_TYPE},
{"lal_demodulate", GSTLAL_DEMODULATE_TYPE},
{NULL, 0},
};
......
#!/usr/bin/env python
# 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.
#
# =============================================================================
#
# Preamble
#
# =============================================================================
#
import numpy
import sys
from gstlal import pipeparts
import test_common
#
# =============================================================================
#
# Pipelines
#
# =============================================================================
#
def lal_demodulate_01(pipeline, name):
#
# This test is to check that the inputs are multiplied by exp(2*pi*i*f*t) using the correct timestamps
#
rate = 1000 # Hz
buffer_length = 1.0 # seconds
test_duration = 10.0 # seconds
#
# build pipeline
#
src = test_common.test_src(pipeline, buffer_length = buffer_length, rate = rate, test_duration = test_duration, width = 32)
capsfilter1 = pipeparts.mkcapsfilter(pipeline, src, "audio/x-raw, format=F32LE, rate=%d" % int(rate))
tee1 = pipeparts.mktee(pipeline, capsfilter1)
pipeparts.mknxydumpsink(pipeline, pipeparts.mkqueue(pipeline, tee1), "%s_in.dump" % name)
demodulate = pipeparts.mkgeneric(pipeline, tee1, "lal_demodulate", line_frequency=100)
capsfilter2 = pipeparts.mkcapsfilter(pipeline, demodulate, "audio/x-raw, format=Z64LE, rate=%d" % int(rate))
togglecomplex = pipeparts.mktogglecomplex(pipeline, capsfilter2)
capsfilter3 = pipeparts.mkcapsfilter(pipeline, togglecomplex, "audio/x-raw, format=F32LE, rate=%d" % int(rate))
pipeparts.mknxydumpsink(pipeline, pipeparts.mkqueue(pipeline, capsfilter3), "%s_out.dump" % name)
#
# done
#
return pipeline
def lal_demodulate_02(pipeline, name):
#
# This is similar to the above test, and makes sure the element treats gaps correctly
#
rate = 1000 # Hz
buffer_length = 1.0 # seconds
test_duration = 10.0 # seconds
gap_frequency = 0.1 # Hz
gap_threshold = 0.2 # Hz
control_dump_filename = "control_demodulate_02.dump"
src = test_common.gapped_test_src(pipeline, buffer_length = buffer_length, rate = rate, width=64, test_duration = test_duration, gap_frequency = gap_frequency, gap_threshold = gap_threshold, control_dump_filename = control_dump_filename)
capsfilter1 = pipeparts.mkcapsfilter(pipeline, src, "audio/x-raw, format=F64LE, rate=%d" % int(rate))
tee1 = pipeparts.mktee(pipeline, capsfilter1)
pipeparts.mknxydumpsink(pipeline, pipeparts.mkqueue(pipeline, tee1), "%s_in.dump" % name)
demodulate = pipeparts.mkgeneric(pipeline, tee1, "lal_demodulate")
capsfilter2 = pipeparts.mkcapsfilter(pipeline, demodulate, "audio/x-raw, format=Z128LE, rate=%d" % int(rate))
togglecomplex = pipeparts.mktogglecomplex(pipeline, capsfilter2)
capsfilter3 = pipeparts.mkcapsfilter(pipeline, togglecomplex, "audio/x-raw, format=F64LE, rate=%d" %int(rate))
pipeparts.mknxydumpsink(pipeline, pipeparts.mkqueue(pipeline, capsfilter3), "%s_out.dump" % name)
#
# done
#
return pipeline
#
# =============================================================================
#
# Main
#
# =============================================================================
#
test_common.build_and_run(lal_demodulate_01, "lal_demodulate_01")
#test_common.build_and_run(lal_demodulate_02, "lal_demodulate_02")
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment