r4111 - in trunk/bse: . tests
- From: stw svn gnome org
- To: svn-commits-list gnome org
- Subject: r4111 - in trunk/bse: . tests
- Date: Mon, 27 Nov 2006 16:39:49 -0500 (EST)
Author: stw
Date: 2006-11-27 16:39:30 -0500 (Mon, 27 Nov 2006)
New Revision: 4111
Modified:
trunk/bse/ChangeLog
trunk/bse/bsedatahandle-fir.cc
trunk/bse/gsldatahandle.h
trunk/bse/tests/firhandle.cc
Log:
Mon Nov 27 22:32:24 2006 Stefan Westerfeld <stefan space twc de>
* bsedatahandle-fir.cc:
* gsldatahandle.h:
* tests/firhandle.cc: Move highpass handle from gsl to bse namespace.
* bsedatahandle-fir.cc: Implement a "real" data handle. It is not yet
performance optimized, though.
Modified: trunk/bse/ChangeLog
===================================================================
--- trunk/bse/ChangeLog 2006-11-27 19:51:35 UTC (rev 4110)
+++ trunk/bse/ChangeLog 2006-11-27 21:39:30 UTC (rev 4111)
@@ -1,3 +1,12 @@
+Mon Nov 27 22:32:24 2006 Stefan Westerfeld <stefan space twc de>
+
+ * bsedatahandle-fir.cc:
+ * gsldatahandle.h:
+ * tests/firhandle.cc: Move highpass handle from gsl to bse namespace.
+
+ * bsedatahandle-fir.cc: Implement a "real" data handle. It is not yet
+ performance optimized, though.
+
Mon Nov 27 20:29:53 2006 Stefan Westerfeld <stefan space twc de>
* gsldatahandle.[hc]: Added new gsl_data_handle_get_state_length
Modified: trunk/bse/bsedatahandle-fir.cc
===================================================================
--- trunk/bse/bsedatahandle-fir.cc 2006-11-27 19:51:35 UTC (rev 4110)
+++ trunk/bse/bsedatahandle-fir.cc 2006-11-27 21:39:30 UTC (rev 4111)
@@ -20,52 +20,248 @@
#include "gsldatautils.h"
#include "gslfilter.h"
#include <complex>
+#include <vector>
#include <string.h>
#include <stdio.h>
#include <math.h>
-/*
- * 0db ---------- __________
- * /
- * /
- * /
- * f1_level (dB) - _____/
- *
- * | |
- * f1 f2
- *
- * @f1: high pass start frequency [0:PI] (SR = 2*PI)
- * @f2: high pass end frequency [0:PI] (SR = 2*PI)
- */
+namespace Bse {
-static void
-fir_hp (const gfloat *src,
- const guint n_samples,
- gfloat *dest,
- gdouble cutoff_freq,
- guint iorder)
+using std::vector;
+
+class DataHandleFir;
+
+struct CDataHandleFir : public GslDataHandle
{
- double a[iorder + 1];
+ // back pointer to get casting right, even in presence of C++ vtable:
+ DataHandleFir* cxx_dh;
+};
- //const guint transfer_func_length = 64;
- const guint transfer_func_length = 4;
- double transfer_func_freqs[transfer_func_length];
- double transfer_func_values[transfer_func_length];
+class DataHandleFir {
+protected:
+ CDataHandleFir m_dhandle;
+ GslDataHandle *m_src_handle;
+ vector<double> m_a; /* FIR coefficients: [0..order] */
+ bool m_init_ok;
- transfer_func_freqs[0] = 0;
- transfer_func_values[0] = 0;
+public:
+ DataHandleFir (GslDataHandle *src_handle,
+ guint order) :
+ m_src_handle (src_handle),
+ m_a (order),
+ m_init_ok (false)
+ {
+ g_return_if_fail (src_handle != NULL);
- transfer_func_freqs[1] = cutoff_freq;
- transfer_func_values[1] = 0;
+ memset (&m_dhandle, 0, sizeof (m_dhandle));
+ m_init_ok = gsl_data_handle_common_init (&m_dhandle, NULL);
+ if (m_init_ok)
+ gsl_data_handle_ref (m_src_handle);
+ }
- transfer_func_freqs[2] = cutoff_freq;
- transfer_func_values[2] = 1.0; // 0 dB
+ /* protected destructor: (use reference counting instead) */
+ virtual
+ ~DataHandleFir()
+ {
+ if (m_init_ok)
+ {
+ gsl_data_handle_unref (m_src_handle);
+ gsl_data_handle_common_free (&m_dhandle);
+ }
+ }
- transfer_func_freqs[3] = PI;
- transfer_func_values[3] = 1.0; // 0 dB
+ BseErrorType
+ open (GslDataHandleSetup *setup)
+ {
+ BseErrorType error = gsl_data_handle_open (m_src_handle);
+ if (error != BSE_ERROR_NONE)
+ return error;
- gsl_filter_fir_approx (iorder, a, transfer_func_length, transfer_func_freqs, transfer_func_values, false);
+ /* !not! m_dhandle.setup; the framework magically ensures that *m_dhandle.setup
+ * is initialized by whatever we write into *setup if open is successful
+ */
+ *setup = m_src_handle->setup; /* copies setup.xinfos by pointer */
+ setup->bit_depth = 32; /* possibly increased by filtering */
+ design_filter_coefficients (gsl_data_handle_mix_freq (m_src_handle));
+
+ return BSE_ERROR_NONE;
+ }
+
+ virtual void
+ design_filter_coefficients (double mix_freq) = 0;
+
+ void
+ close()
+ {
+ m_dhandle.setup.xinfos = NULL; /* cleanup pointer reference */
+ gsl_data_handle_close (m_src_handle);
+ }
+
+ void
+ fir_apply (const gfloat *src,
+ const guint n_samples,
+ gfloat *dest)
+ {
+ /* tiny FIR evaluation: not optimized for speed */
+ guint i, j;
+ const guint iorder = m_a.size();
+ for (i = 0; i < n_samples; i++)
+ {
+ gdouble accu = 0;
+ for (j = 0; j <= iorder; j++)
+ {
+ GslLong p = i + j;
+ p -= iorder / 2;
+
+ if (p >= 0 && p < n_samples)
+ accu += m_a[j] * src[p];
+ }
+ dest[i] = accu;
+ }
+ }
+
+ int64
+ read (int64 voffset,
+ int64 n_values,
+ float *values)
+ {
+ GslLong src_handle_n_values = gsl_data_handle_n_values (m_src_handle);
+ GslDataPeekBuffer pbuf = { +1, };
+ vector<float> src_data;
+ int64 history = m_a.size() / 2 + 1;
+ for (int64 i = -history; i < n_values + history; i++)
+ {
+ int64 offset = voffset + i;
+ float v = 0.0;
+ if (offset >= 0 && offset < src_handle_n_values)
+ v = gsl_data_handle_peek_value (m_src_handle, offset, &pbuf);
+ src_data.push_back (v);
+ /* FIXME: use gsl_data_handle_read() */
+ }
+ // return gsl_data_handle_read (m_src_handle, voffset, n_values, values);
+ vector<float> dest_data (src_data.size());
+ fir_apply (&src_data[0], src_data.size(), &dest_data[0]);
+ std::copy (&dest_data[history], &dest_data[history + n_values], values);
+ return n_values;
+ }
+
+ int64
+ get_state_length() const
+ {
+ int64 source_state_length = gsl_data_handle_get_state_length (m_src_handle);
+ // m_src_handle must be opened and have valid state size
+ g_return_val_if_fail (source_state_length >= 0, 0);
+
+ int64 per_channel_state = 0;
+ return source_state_length + per_channel_state * m_dhandle.setup.n_channels;
+ }
+
+ static GslDataHandle*
+ dh_create (DataHandleFir *cxx_dh)
+ {
+ static GslDataHandleFuncs dh_vtable =
+ {
+ dh_open,
+ dh_read,
+ dh_close,
+ NULL,
+ dh_get_state_length,
+ dh_destroy,
+ };
+
+ if (cxx_dh->m_init_ok)
+ {
+ cxx_dh->m_dhandle.vtable = &dh_vtable;
+ cxx_dh->m_dhandle.cxx_dh = cxx_dh; /* make casts work, later on */
+ return &cxx_dh->m_dhandle;
+ }
+ else
+ {
+ delete cxx_dh;
+ return NULL;
+ }
+ }
+private:
+/* for the "C" API (vtable) */
+ static DataHandleFir*
+ dh_cast (GslDataHandle *dhandle)
+ {
+ return static_cast<CDataHandleFir *> (dhandle)->cxx_dh;
+ }
+ static BseErrorType
+ dh_open (GslDataHandle *dhandle, GslDataHandleSetup *setup)
+ {
+ return dh_cast (dhandle)->open (setup);
+ }
+ static void
+ dh_close (GslDataHandle *dhandle)
+ {
+ dh_cast (dhandle)->close();
+ }
+ static void
+ dh_destroy (GslDataHandle *dhandle)
+ {
+ delete dh_cast (dhandle);
+ }
+ static int64
+ dh_read (GslDataHandle *dhandle,
+ int64 voffset,
+ int64 n_values,
+ gfloat *values)
+ {
+ return dh_cast (dhandle)->read (voffset, n_values, values);
+ }
+ static int64
+ dh_get_state_length (GslDataHandle *dhandle)
+ {
+ return dh_cast (dhandle)->get_state_length();
+ }
+};
+
+class DataHandleFirHighpass : public DataHandleFir
+{
+protected:
+ gdouble m_cutoff_freq;
+
+public:
+ DataHandleFirHighpass (GslDataHandle *src_handle,
+ gdouble cutoff_freq,
+ guint order) :
+ DataHandleFir (src_handle, order),
+ m_cutoff_freq (cutoff_freq)
+ {
+ if (m_init_ok)
+ m_dhandle.name = g_strconcat (m_src_handle->name, "// #highpass /", NULL);
+ }
+
+ virtual void
+ design_filter_coefficients (double mix_freq)
+ {
+ const guint transfer_func_length = 4;
+ double transfer_func_freqs[transfer_func_length];
+ double transfer_func_values[transfer_func_length];
+
+ transfer_func_freqs[0] = 0;
+ transfer_func_values[0] = 0;
+
+ transfer_func_freqs[1] = m_cutoff_freq / mix_freq * 2 * M_PI;
+ transfer_func_values[1] = 0;
+
+ transfer_func_freqs[2] = m_cutoff_freq / mix_freq * 2 * M_PI;
+ transfer_func_values[2] = 1.0; // 0 dB
+
+ transfer_func_freqs[3] = PI;
+ transfer_func_values[3] = 1.0; // 0 dB
+
+ gsl_filter_fir_approx (m_a.size(), &m_a[0],
+ transfer_func_length, transfer_func_freqs, transfer_func_values,
+ false); // interpolate dB
+ }
+};
+
+}
+
#if 0 // debugging
gfloat freq;
for (freq = 0; freq < PI; freq += 0.01)
@@ -81,34 +277,10 @@
}
printf ("%f %f\n", freq, cabs (r));
}
-
- /* normalize */
- gdouble norm = 0;
- guint k;
- for (k = 0; k <= iorder; k++)
- norm += fabs (a[k]);
-
- printf ("# norm = %f\n", norm);
- for (k = 0; k <= iorder; k++)
- a[k] /= norm;
#endif
- /* tiny FIR evaluation: not optimized for speed */
- guint i, j;
- for (i = 0; i < n_samples; i++)
- {
- gdouble accu = 0;
- for (j = 0; j <= iorder; j++)
- {
- GslLong p = i + j;
- p -= iorder / 2;
- if (p >= 0 && p < n_samples)
- accu += a[j] * src[p];
- }
- dest[i] = accu;
- }
-}
+using namespace Bse;
/*
* __________
@@ -123,43 +295,10 @@
* @order: number of filter coefficients
*/
extern "C" GslDataHandle*
-gsl_data_handle_new_fir_highpass (GslDataHandle *src_handle,
+bse_data_handle_new_fir_highpass (GslDataHandle *src_handle,
gdouble cutoff_freq,
guint order)
{
- g_return_val_if_fail (src_handle != NULL, NULL);
-
- /* check out data handle */
- if (gsl_data_handle_open (src_handle) != BSE_ERROR_NONE)
- return NULL;
-
- GslLong src_handle_n_values = gsl_data_handle_n_values (src_handle);
- GslLong src_handle_n_channels = gsl_data_handle_n_channels (src_handle);
- GslLong src_handle_mix_freq = gsl_data_handle_mix_freq (src_handle);
- GslLong src_handle_osc_freq = gsl_data_handle_osc_freq (src_handle);
-
- /* read input */
- gfloat *src_values = g_new (gfloat, src_handle_n_values);
- GslLong i;
- GslDataPeekBuffer pbuf = { +1, };
- for (i = 0; i < src_handle_n_values; i++) /* FIXME: use gsl_data_handle_read() */
- src_values[i] = gsl_data_handle_peek_value (src_handle, i, &pbuf);
-
- /* apply fir filter to new memory buffer */
- gfloat *dest_values = g_new (gfloat, src_handle_n_values);
- fir_hp (src_values, src_handle_n_values, dest_values, cutoff_freq * 2 * M_PI / src_handle_mix_freq, order);
- g_free (src_values);
-
- /* create a mem handle with filtered data */
- GslDataHandle *mhandle = gsl_data_handle_new_mem (src_handle_n_channels,
- 32, // bit_depth: possibly increased by filtering
- src_handle_mix_freq,
- src_handle_osc_freq,
- src_handle_n_values,
- dest_values,
- g_free);
- GslDataHandle *dhandle = gsl_data_handle_new_add_xinfos (mhandle, src_handle->setup.xinfos);
- gsl_data_handle_close (src_handle);
- gsl_data_handle_unref (mhandle);
- return dhandle;
+ DataHandleFir *cxx_dh = new DataHandleFirHighpass (src_handle, cutoff_freq, order);
+ return DataHandleFir::dh_create (cxx_dh);
}
Modified: trunk/bse/gsldatahandle.h
===================================================================
--- trunk/bse/gsldatahandle.h 2006-11-27 19:51:35 UTC (rev 4110)
+++ trunk/bse/gsldatahandle.h 2006-11-27 21:39:30 UTC (rev 4111)
@@ -120,9 +120,9 @@
GslDataHandle* bse_data_handle_new_downsample2 (GslDataHandle *src_handle,
int precision_bits); // implemented in bsedatahandle-resample.cc
-GslDataHandle* gsl_data_handle_new_fir_highpass (GslDataHandle *src_handle, // implemented in bsedatahandle-fir.cc
- gdouble cutoff_freq,
- guint order);
+GslDataHandle* bse_data_handle_new_fir_highpass (GslDataHandle *src_handle, // implemented in bsedatahandle-fir.cc
+ gdouble cutoff_freq,
+ guint order);
/* --- xinfo handling --- */
Modified: trunk/bse/tests/firhandle.cc
===================================================================
--- trunk/bse/tests/firhandle.cc 2006-11-27 19:51:35 UTC (rev 4110)
+++ trunk/bse/tests/firhandle.cc 2006-11-27 21:39:30 UTC (rev 4111)
@@ -77,8 +77,8 @@
GslDataHandle *ihandle_cos = gsl_data_handle_new_mem (1, 32, mix_freq, 440, sweep_cos.size(), &sweep_cos[0], NULL);
const int order = 64;
- GslDataHandle *fir_handle_sin = gsl_data_handle_new_fir_highpass (ihandle_sin, 9000.0, order);
- GslDataHandle *fir_handle_cos = gsl_data_handle_new_fir_highpass (ihandle_cos, 9000.0, order);
+ GslDataHandle *fir_handle_sin = bse_data_handle_new_fir_highpass (ihandle_sin, 9000.0, order);
+ GslDataHandle *fir_handle_cos = bse_data_handle_new_fir_highpass (ihandle_cos, 9000.0, order);
BseErrorType error;
error = gsl_data_handle_open (fir_handle_sin);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]