r4115 - in trunk/bse: . tests
- From: stw svn gnome org
- To: svn-commits-list gnome org
- Subject: r4115 - in trunk/bse: . tests
- Date: Sat, 2 Dec 2006 16:12:59 -0500 (EST)
Author: stw
Date: 2006-12-02 16:12:57 -0500 (Sat, 02 Dec 2006)
New Revision: 4115
Modified:
trunk/bse/ChangeLog
trunk/bse/bsedatahandle-fir.cc
trunk/bse/tests/firhandle.cc
Log:
Sat Dec 2 22:03:57 2006 Stefan Westerfeld <stefan space twc de>
* tests/firhandle.cc: Added a highpass test for multichannel signals.
* bsedatahandle-fir.cc: Fixed the code for n_channels != 1. Minor
code cleanups.
Modified: trunk/bse/ChangeLog
===================================================================
--- trunk/bse/ChangeLog 2006-11-29 01:04:38 UTC (rev 4114)
+++ trunk/bse/ChangeLog 2006-12-02 21:12:57 UTC (rev 4115)
@@ -1,3 +1,10 @@
+Sat Dec 2 22:03:57 2006 Stefan Westerfeld <stefan space twc de>
+
+ * tests/firhandle.cc: Added a highpass test for multichannel signals.
+
+ * bsedatahandle-fir.cc: Fixed the code for n_channels != 1. Minor
+ code cleanups.
+
Tue Nov 28 21:05:16 2006 Stefan Westerfeld <stefan space twc de>
* bsedatahandle-fir.cc: Some optimizations, more to come.
Modified: trunk/bse/bsedatahandle-fir.cc
===================================================================
--- trunk/bse/bsedatahandle-fir.cc 2006-11-29 01:04:38 UTC (rev 4114)
+++ trunk/bse/bsedatahandle-fir.cc 2006-12-02 21:12:57 UTC (rev 4115)
@@ -49,6 +49,10 @@
int64 m_history;
bool m_init_ok;
+protected:
+ virtual void
+ design_filter_coefficients (double mix_freq) = 0;
+
public:
DataHandleFir (GslDataHandle *src_handle,
guint order) :
@@ -90,8 +94,8 @@
// since we need overlapping data for consecutive reads we buffer data locally
m_block_size = 1024 * m_src_handle->setup.n_channels;
- m_history = (m_a.size() + 1) / 2;
- m_input_data.resize (m_block_size + (2 * m_history) * m_src_handle->setup.n_channels);
+ m_history = ((m_a.size() + 1) / 2) * m_src_handle->setup.n_channels;
+ m_input_data.resize (m_block_size + 2 * m_history);
m_input_voffset = -2 * m_block_size;
design_filter_coefficients (gsl_data_handle_mix_freq (m_src_handle));
@@ -99,9 +103,6 @@
return BSE_ERROR_NONE;
}
- virtual void
- design_filter_coefficients (double mix_freq) = 0;
-
void
close()
{
@@ -115,16 +116,17 @@
gfloat *dest)
{
/* tiny FIR evaluation: not optimized for speed */
- guint i, j;
+ const guint channels = m_dhandle.setup.n_channels;
const guint iorder = m_a.size();
- for (i = 0; i < n_samples; i++)
+ for (guint i = 0; i < n_samples; i++)
{
gdouble accu = 0;
- for (j = 0; j <= iorder; j++)
+ GslLong p = i;
+ p -= (iorder / 2) * channels;
+ for (guint j = 0; j <= iorder; j++)
{
- GslLong p = i + j;
- p -= iorder / 2;
accu += m_a[j] * src[p];
+ p += channels;
}
dest[i] = accu;
}
@@ -136,9 +138,11 @@
int64 i = 0;
g_return_val_if_fail (voffset % m_block_size == 0, -1);
+ // if this is a consecutive read, the history can be built from the values
+ // we already read last time
if (m_input_voffset == voffset - m_block_size)
{
- int64 overlap_values = 2 * m_history * m_dhandle.setup.n_channels;
+ int64 overlap_values = 2 * m_history;
copy (m_input_data.end() - overlap_values, m_input_data.end(), m_input_data.begin());
i += overlap_values;
}
@@ -150,7 +154,7 @@
{
int64 values_todo = min (static_cast<int64> (m_input_data.size()) - i, m_dhandle.setup.n_values - offset);
int64 l = gsl_data_handle_read (m_src_handle, offset, values_todo, &m_input_data[i]);
- if (l < 0)
+ if (l < 0) // pass on errors
{
// invalidate m_input_data
voffset = -2 * m_block_size;
@@ -176,12 +180,12 @@
float *values)
{
int64 ivoffset = voffset;
- ivoffset = ivoffset - ivoffset % m_block_size;
+ ivoffset -= ivoffset % m_block_size;
if (ivoffset != m_input_voffset)
{
int64 l = seek (ivoffset);
- if (l < 0)
+ if (l < 0) // pass on errors
return l;
}
Modified: trunk/bse/tests/firhandle.cc
===================================================================
--- trunk/bse/tests/firhandle.cc 2006-11-29 01:04:38 UTC (rev 4114)
+++ trunk/bse/tests/firhandle.cc 2006-12-02 21:12:57 UTC (rev 4115)
@@ -50,7 +50,7 @@
void
test_highpass_with_sine_sweep()
{
- TSTART ("Highpass Handle");
+ TSTART ("Highpass Handle (sweep)");
vector<float> sweep_sin (50000);
vector<float> sweep_cos (50000);
vector<double> sweep_freq (50000);
@@ -72,7 +72,6 @@
phase -= 2.0 * M_PI;
}
- /* FIXME: handle n_channels != 1 */
GslDataHandle *ihandle_sin = gsl_data_handle_new_mem (1, 32, mix_freq, 440, sweep_sin.size(), &sweep_sin[0], NULL);
GslDataHandle *ihandle_cos = gsl_data_handle_new_mem (1, 32, mix_freq, 440, sweep_cos.size(), &sweep_cos[0], NULL);
@@ -149,11 +148,85 @@
TDONE();
}
+double
+raised_cosine_fade (int64 pos,
+ int64 length,
+ int64 fade_length)
+{
+ double fade_delta = 1.0 / fade_length;
+ double fade_factor = fade_delta * min (pos, length - pos);
+ if (fade_factor >= 1.0)
+ return 1.0;
+ else
+ return (0.5 - cos (fade_factor * PI) * 0.5);
+}
+
+void
+test_highpass_multi_channel()
+{
+ TSTART ("Highpass Handle (multichannel)");
+ for (int n_channels = 1; n_channels <= 10; n_channels++)
+ {
+ const double mix_freq = 48000;
+ const double cutoff_freq = 7500;
+ const double test_freqs[] = {
+ 50, 100, 234.567, 557, 901, 1350, 1780, 2345, 3745, 4500, // below cutoff
+ 11000, 12000, 13945, 14753, 15934, 16734, 17943, 18930, 19320, 20940 // above cutoff
+ };
+ vector<float> input (2500 * n_channels);
+ vector<double> expected (input.size());
+ vector<double> freq (n_channels);
+ vector<double> phase (n_channels);
+
+ for (int c = 0; c < n_channels; c++)
+ freq[c] = test_freqs [g_random_int_range (0, sizeof (test_freqs) / sizeof (test_freqs[0]))];
+
+ for (size_t i = 0; i < input.size(); i++)
+ {
+ const int c = i % n_channels;
+ const double fade_factor = raised_cosine_fade (i / n_channels, input.size() / n_channels, 500);
+ const double invalue = sin (phase[c]) * fade_factor;
+
+ input[i] = invalue;
+ expected[i] = (freq[c] > cutoff_freq) ? invalue : 0.0;
+
+ phase[c] += freq[c] / mix_freq * 2.0 * M_PI;
+ if (phase[c] > 2.0 * M_PI)
+ phase[c] -= 2.0 * M_PI;
+ }
+
+ GslDataHandle *ihandle = gsl_data_handle_new_mem (n_channels, 32, mix_freq, 440, input.size(), &input[0], NULL);
+ const int order = 116;
+ GslDataHandle *fir_handle = bse_data_handle_new_fir_highpass (ihandle, cutoff_freq, order);
+
+ BseErrorType error;
+ error = gsl_data_handle_open (fir_handle);
+ TASSERT (error == 0);
+
+ for (int repeat = 1; repeat <= 2; repeat++)
+ {
+ GslDataPeekBuffer peek_buffer = { +1 /* incremental direction */, 0, };
+ double worst_diff = 0.0;
+ for (int64 i = 0; i < fir_handle->setup.n_values; i++)
+ {
+ double filtered = gsl_data_handle_peek_value (fir_handle, i, &peek_buffer);
+ worst_diff = max (filtered - expected[i], worst_diff);
+ }
+ double worst_diff_db = bse_db_from_factor (worst_diff, -200);
+ TPRINT ("n_channels = %d: linear(%dst read) read worst_diff = %f (%f dB)\n",
+ n_channels, repeat, worst_diff, worst_diff_db);
+ TASSERT (worst_diff_db < -90);
+ }
+ }
+ TDONE();
+}
+
int
main (int argc,
char **argv)
{
bse_init_test (&argc, &argv, NULL);
test_highpass_with_sine_sweep();
+ test_highpass_multi_channel();
return 0;
}
[Date Prev][
Date Next] [Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]