[beast] PLUGINS: ported DavOrgan plugin from C to C++. See also bug #433311.
- From: Tim Janik <timj src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [beast] PLUGINS: ported DavOrgan plugin from C to C++. See also bug #433311.
- Date: Sun, 8 May 2011 17:23:08 +0000 (UTC)
commit abb66c7c2d1fe8279cc9fcd9047539e038ef4354
Author: Stefan Westerfeld <stefan space twc de>
Date: Mon Jun 14 11:01:02 2010 +0200
PLUGINS: ported DavOrgan plugin from C to C++. See also bug #433311.
bse/bsecompat.c | 1 +
plugins/Makefile.am | 2 +-
plugins/Makefile.plugins | 20 +--
plugins/davorgan.c | 533 ----------------------------------------------
plugins/davorgan.cc | 328 ++++++++++++++++++++++++++++
plugins/davorgan.idl | 57 +++++
6 files changed, 392 insertions(+), 549 deletions(-)
---
diff --git a/bse/bsecompat.c b/bse/bsecompat.c
index 7adc1e3..cfddc0a 100644
--- a/bse/bsecompat.c
+++ b/bse/bsecompat.c
@@ -37,6 +37,7 @@ bse_compat_rewrite_type_name (BseStorage *storage,
{ 0, 6, 2, "ArtsStereoCompressor", "BseArtsCompressor" },
{ 0, 6, 2, "DavBassFilter", "BseDavBassFilter" },
{ 0, 6, 2, "DavChorus", "BseDavChorus" },
+ { 0, 7, 1, "DavOrgan", "BseDavOrgan" },
};
guint i;
for (i = 0; i < G_N_ELEMENTS (type_changes); i++)
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index b155bd9..18066db 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -27,6 +27,7 @@ idl_plugins = $(strip \
+++davplugins \
davbassfilter.idl \
davchorus.idl \
+ davorgan.idl \
)
EXTRA_HEADERS += $(filter-out +++%, $(idl_plugins))
# setup generation of C++ plugins from idl files
@@ -48,7 +49,6 @@ cglob_plugins = $(strip \
bsemixer.[hc] \
bsemult.[hc] \
bsesequencer.[hc] \
- davorgan.[hc] \
davxtalstrings.[hc] \
davsyndrum.[hc] \
davcanyondelay.[hc] \
diff --git a/plugins/Makefile.plugins b/plugins/Makefile.plugins
index d484cf4..e448d86 100644
--- a/plugins/Makefile.plugins
+++ b/plugins/Makefile.plugins
@@ -107,6 +107,11 @@ $(srcdir)/davchorus.cc: davchorus.genidl.hh # davplugins
plugins_built_sources += davchorus.genidl.hh
davplugins_FPU_la_SOURCES += davchorus.cc
+## C++ Plugin davorgan
+$(srcdir)/davorgan.cc: davorgan.genidl.hh # davplugins
+plugins_built_sources += davorgan.genidl.hh
+davplugins_FPU_la_SOURCES += davorgan.cc
+
## C Plugin bsesimpleadsr
EXTRA_HEADERS += bsesimpleadsr.h
@@ -213,21 +218,6 @@ bsesequencer_SSE_la_LIBADD = $(bsesequencer_FPU_la_LIBADD)
bsesequencer_SSE_la_CFLAGS = $(SSE_PLUGIN_CFLAGS)
-## C Plugin davorgan
-EXTRA_HEADERS += davorgan.h
-$(srcdir)/davorgan.c: davorgan.h
-plugin_FPU_ltlibs += davorgan.FPU.la
-davorgan_FPU_la_SOURCES = davorgan.c
-davorgan_FPU_la_LDFLAGS = -module $(plugins_ldflags)
-davorgan_FPU_la_LIBADD = $(plugins_libs)
-davorgan_FPU_la_CFLAGS = $(FPU_PLUGIN_CFLAGS)
-plugin_SSE_ltlibs += davorgan.SSE.la
-davorgan_SSE_la_SOURCES = $(davorgan_FPU_la_SOURCES)
-davorgan_SSE_la_LDFLAGS = $(davorgan_FPU_la_LDFLAGS)
-davorgan_SSE_la_LIBADD = $(davorgan_FPU_la_LIBADD)
-davorgan_SSE_la_CFLAGS = $(SSE_PLUGIN_CFLAGS)
-
-
## C Plugin davxtalstrings
EXTRA_HEADERS += davxtalstrings.h
$(srcdir)/davxtalstrings.c: davxtalstrings.h
diff --git a/plugins/davorgan.cc b/plugins/davorgan.cc
new file mode 100644
index 0000000..9ff33f0
--- /dev/null
+++ b/plugins/davorgan.cc
@@ -0,0 +1,328 @@
+/* DavOrgan - DAV Additive Organ Synthesizer
+ * Copyright (c) 1999, 2000, 2002 David A. Bartold and Tim Janik
+ * Copyright (c) 2006-2007 Stefan Westerfeld
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * A copy of the GNU Lesser General Public License should ship along
+ * with this library; if not, see http://www.gnu.org/copyleft/.
+ */
+#include "davorgan.genidl.hh"
+#include <bse/bsemathsignal.h>
+#include <bse/bsemain.h>
+#include <vector>
+
+namespace Bse { namespace Dav {
+
+using namespace std;
+using namespace Birnet; // FIXME: move to Bse namespace
+using Birnet::uint32; // FIXME: move to Bse header
+
+class Organ : public OrganBase {
+ /* per mix_freq() tables */
+ class Tables
+ {
+ uint m_ref_count;
+ uint m_rate;
+
+ vector<float> m_sine_table;
+ vector<float> m_triangle_table;
+ vector<float> m_pulse_table;
+
+ Tables (uint urate) :
+ m_ref_count (1),
+ m_rate (urate),
+ m_sine_table (urate),
+ m_triangle_table (urate),
+ m_pulse_table (urate)
+ {
+ double rate = urate;
+ double half = rate / 2;
+ double slope = rate / 10;
+ int i;
+
+ /* Initialize sine table. */
+ for (i = 0; i < rate; i++)
+ m_sine_table[i] = sin ((i / rate) * 2.0 * PI) / 6.0;
+
+ /* Initialize triangle table. */
+ for (i = 0; i < rate / 2; i++)
+ m_triangle_table[i] = (4 / rate * i - 1.0) / 6.0;
+ for (; i < rate; i++)
+ m_triangle_table[i] = (4 / rate * (rate - i) - 1.0) / 6.0;
+
+ /* Initialize pulse table. */
+ for (i = 0; i < slope; i++)
+ m_pulse_table[i] = (-i / slope) / 6.0;
+ for (; i < half - slope; i++)
+ m_pulse_table[i] = -1.0 / 6.0;
+ for (; i < half + slope; i++)
+ m_pulse_table[i] = ((i - half) / slope) / 6.0;
+ for (; i < rate - slope; i++)
+ m_pulse_table[i] = 1.0 / 6.0;
+ for (; i < rate; i++)
+ m_pulse_table[i] = ((rate - i) * 1.0 / slope) / 6.0;
+ }
+ ~Tables()
+ {
+ // private destructor; use ref_counting
+ }
+
+ static map<uint, Tables*> table_map; /* rate -> rate specific tables */
+ static Mutex table_mutex;
+
+ public:
+ static Tables*
+ ref (uint rate)
+ {
+ AutoLocker locker (table_mutex);
+
+ if (table_map[rate])
+ table_map[rate]->m_ref_count++;
+ else
+ table_map[rate] = new Tables (rate);
+
+ return table_map[rate];
+ }
+ void
+ unref()
+ {
+ AutoLocker locker (table_mutex);
+
+ if (--m_ref_count == 0)
+ {
+ table_map[m_rate] = 0;
+ delete this;
+ }
+ }
+ const float*
+ sine_table() const
+ {
+ return &m_sine_table[0];
+ }
+ const float*
+ triangle_table() const
+ {
+ return &m_triangle_table[0];
+ }
+ const float*
+ pulse_table() const
+ {
+ return &m_pulse_table[0];
+ }
+ };
+
+ /* FIXME: get rid of this as soon as the modules have their own current_musical_tuning() accessor */
+ struct Properties : public OrganProperties {
+ BseMusicalTuningType current_musical_tuning;
+
+ Properties (Organ *organ) :
+ OrganProperties (organ),
+ current_musical_tuning (organ->current_musical_tuning())
+ {
+ }
+ };
+ class Module : public SynthesisModule {
+ public:
+ /* frequency */
+ double m_transpose_factor;
+ double m_fine_tune_factor;
+ double m_cfreq;
+
+ /* instrument flavour */
+ bool m_flute;
+ bool m_reed;
+ bool m_brass;
+
+ /* harmonics */
+ double m_harm0;
+ double m_harm1;
+ double m_harm2;
+ double m_harm3;
+ double m_harm4;
+ double m_harm5;
+
+ /* phase accumulators */
+ uint32 m_harm0_paccu;
+ uint32 m_harm1_paccu;
+ uint32 m_harm2_paccu;
+ uint32 m_harm3_paccu;
+ uint32 m_harm4_paccu;
+ uint32 m_harm5_paccu;
+
+ /* mix_freq() specific tables */
+ Tables *m_tables;
+
+ Module() :
+ m_tables (Tables::ref (mix_freq()))
+ {
+ }
+ ~Module()
+ {
+ m_tables->unref();
+ m_tables = 0;
+ }
+ void
+ config (Properties *properties)
+ {
+ m_cfreq = properties->base_freq;
+ m_transpose_factor = bse_transpose_factor (properties->current_musical_tuning, properties->transpose);
+ m_fine_tune_factor = bse_cent_tune_fast (properties->fine_tune);
+
+ // percent -> factor conversions
+ m_harm0 = properties->harm0 / 100.0;
+ m_harm1 = properties->harm1 / 100.0;
+ m_harm2 = properties->harm2 / 100.0;
+ m_harm3 = properties->harm3 / 100.0;
+ m_harm4 = properties->harm4 / 100.0;
+ m_harm5 = properties->harm5 / 100.0;
+
+ m_flute = properties->flute;
+ m_reed = properties->reed;
+ m_brass = properties->brass;
+ }
+ void
+ reset()
+ {
+ uint32 rfactor = bse_main_args->allow_randomization ? 1 : 0;
+ uint32 mix_freq_256 = mix_freq() * 256;
+
+ /* to make all notes sound a bit different, randomize the initial phase of
+ * each harmonic (except if the user requested deterministic behaviour)
+ */
+ m_harm0_paccu = rfactor * g_random_int_range (0, mix_freq_256);
+ m_harm1_paccu = rfactor * g_random_int_range (0, mix_freq_256);
+ m_harm2_paccu = rfactor * g_random_int_range (0, mix_freq_256);
+ m_harm3_paccu = rfactor * g_random_int_range (0, mix_freq_256);
+ m_harm4_paccu = rfactor * g_random_int_range (0, mix_freq_256);
+ m_harm5_paccu = rfactor * g_random_int_range (0, mix_freq_256);
+ }
+ static inline float
+ table_pos (const float *table,
+ uint freq_256,
+ uint mix_freq_256,
+ uint32 *paccu)
+ {
+ *paccu += freq_256;
+ while (*paccu >= mix_freq_256)
+ *paccu -= mix_freq_256;
+
+ return table[*paccu >> 8];
+ }
+ inline uint
+ dfreq_to_freq_256 (double dfreq)
+ {
+ dfreq *= m_transpose_factor * m_fine_tune_factor;
+
+ /* Make sure that the actual sound generation code will only see
+ * frequencies in the range [0, mix_freq/2]. We map negative frequencies
+ * (like -440 Hz) to their positive equivalents (+440 Hz).
+ */
+ dfreq = min (fabs (dfreq), mix_freq() * 0.5);
+
+ /* round frequency with dtoi during conversion from floating point to our
+ * fixed point representation, in order to minimize the conversion error
+ */
+ return dtoi (dfreq * 256);
+ }
+ void
+ process (unsigned int n_values)
+ {
+ const float *sine_table = m_tables->sine_table();
+ const float *flute_table = m_flute ? m_tables->triangle_table() : sine_table;
+ const float *reed_table = m_reed ? m_tables->pulse_table() : sine_table;
+ const float *ifreq = istream (ICHANNEL_FREQ_IN).values;
+ float *ovalues = ostream (OCHANNEL_AUDIO_OUT).values;
+ uint freq_256;
+
+ if (istream (ICHANNEL_FREQ_IN).connected)
+ freq_256 = dfreq_to_freq_256 (BSE_FREQ_FROM_VALUE (ifreq[0]));
+ else
+ freq_256 = dfreq_to_freq_256 (m_cfreq);
+
+ uint mix_freq_256 = mix_freq() * 256;
+ uint freq_256_harm0 = freq_256 / 2;
+ uint freq_256_harm1 = freq_256;
+
+ if (m_brass)
+ {
+ uint freq_256_harm2 = freq_256 * 2;
+ uint freq_256_harm3 = freq_256_harm2 * 2;
+ uint freq_256_harm4 = freq_256_harm3 * 2;
+ uint freq_256_harm5 = freq_256_harm4 * 2;
+
+ for (uint i = 0; i < n_values; i++)
+ {
+ float vaccu;
+
+ vaccu = table_pos (sine_table, freq_256_harm0, mix_freq_256, &m_harm0_paccu) * m_harm0;
+ vaccu += table_pos (sine_table, freq_256_harm1, mix_freq_256, &m_harm1_paccu) * m_harm1;
+ vaccu += table_pos (reed_table, freq_256_harm2, mix_freq_256, &m_harm2_paccu) * m_harm2;
+ vaccu += table_pos (sine_table, freq_256_harm3, mix_freq_256, &m_harm3_paccu) * m_harm3;
+ vaccu += table_pos (flute_table, freq_256_harm4, mix_freq_256, &m_harm4_paccu) * m_harm4;
+ vaccu += table_pos (flute_table, freq_256_harm5, mix_freq_256, &m_harm5_paccu) * m_harm5;
+ ovalues[i] = vaccu;
+ }
+ }
+ else
+ {
+ uint freq_256_harm2 = freq_256 * 3 / 2;
+ uint freq_256_harm3 = freq_256 * 2;
+ uint freq_256_harm4 = freq_256 * 3;
+ uint freq_256_harm5 = freq_256_harm3 * 2;
+
+ for (uint i = 0; i < n_values; i++)
+ {
+ float vaccu;
+
+ vaccu = table_pos (sine_table, freq_256_harm0, mix_freq_256, &m_harm0_paccu) * m_harm0;
+ vaccu += table_pos (sine_table, freq_256_harm1, mix_freq_256, &m_harm1_paccu) * m_harm1;
+ vaccu += table_pos (sine_table, freq_256_harm2, mix_freq_256, &m_harm2_paccu) * m_harm2;
+ vaccu += table_pos (reed_table, freq_256_harm3, mix_freq_256, &m_harm3_paccu) * m_harm3;
+ vaccu += table_pos (sine_table, freq_256_harm4, mix_freq_256, &m_harm4_paccu) * m_harm4;
+ vaccu += table_pos (flute_table, freq_256_harm5, mix_freq_256, &m_harm5_paccu) * m_harm5;
+ ovalues[i] = vaccu;
+ }
+ }
+ }
+ };
+public:
+ bool
+ property_changed (OrganPropertyID prop_id)
+ {
+ switch (prop_id)
+ {
+ /* implement special handling of GUI properties */
+ case PROP_BASE_FREQ:
+ base_note = bse_note_from_freq (current_musical_tuning(), base_freq);
+ notify ("base_note");
+ break;
+ case PROP_BASE_NOTE:
+ base_freq = bse_note_to_freq (current_musical_tuning(), base_note);
+ notify ("base_freq");
+ break;
+ default: ;
+ }
+ return false;
+ }
+
+ /* implement creation and config methods for synthesis Module */
+ BSE_EFFECT_INTEGRATE_MODULE (Organ, Module, Properties);
+};
+
+map<uint, Organ::Tables*> Organ::Tables::table_map;
+Mutex Organ::Tables::table_mutex;
+
+BSE_CXX_DEFINE_EXPORTS();
+BSE_CXX_REGISTER_EFFECT (Organ);
+
+} // Dav
+} // Bse
diff --git a/plugins/davorgan.idl b/plugins/davorgan.idl
new file mode 100644
index 0000000..69ea2ee
--- /dev/null
+++ b/plugins/davorgan.idl
@@ -0,0 +1,57 @@
+/* DavOrgan - DAV Additive Organ Synthesizer -*-mode: c++;-*-
+ * Copyright (c) 1999, 2000, 2002 David A. Bartold and Tim Janik
+ * Copyright (c) 2006-2007 Stefan Westerfeld
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * A copy of the GNU Lesser General Public License should ship along
+ * with this library; if not, see http://www.gnu.org/copyleft/.
+ */
+#include <bse/bse.idl>
+
+namespace Bse {
+namespace Dav {
+
+class Organ : Effect {
+ Info icon = "icons/organ.png";
+ Info authors = "David A. Bartold";
+ Info license = _("GNU Lesser General Public License");
+ Info category = _("/Audio Sources/Organ");
+ Info blurb = _("DavOrgan is a modifiable additive organ synthesizer");
+ IStream freq_in = (_("Freq In"), _("Frequency Input"));
+ OStream audio_out = (_("Audio Out"), _("Organ output"));
+ group _("Base Frequency") {
+ Real base_freq = Freq (_("Frequency"), _("Organ frequency in Hertz, i.e. the pitch of the base tone"),
+ BSE_KAMMER_FREQUENCY, STANDARD ":dial");
+ Int base_note = Note (_("Note"), _("Organ frequency as note, converted to Hertz according to the current musical tuning"),
+ BSE_KAMMER_NOTE, GUI);
+ Int transpose = (_("Transpose"), _("Transposition of the frequency in semitones"),
+ 0, BSE_MIN_TRANSPOSE, BSE_MAX_TRANSPOSE, 12, STANDARD ":f:dial:skip-default");
+ Int fine_tune = FineTune (_("Fine Tune"), _("Amount of detuning in cent (hundredth part of a semitone)"),
+ STANDARD ":f:dial:skip-default");
+ };
+ group _("Harmonics") {
+ Real harm0 = Perc (_("16th"), _("16th Harmonic"), 100.0, STANDARD ":scale");
+ Real harm1 = Perc (_("8th"), _("8th Harmonic"), 100. * 36. / 127., STANDARD ":scale");
+ Real harm2 = Perc (_("5 1/3rd"), _("5 1/3rd Harmonic"), 100. * 100. / 127., STANDARD ":scale");
+ Real harm3 = Perc (_("4th"), _("4th Harmonic"), 100. * 32. / 127., STANDARD ":scale");
+ Real harm4 = Perc (_("2 2/3rd"), _("2 2/3rd Harmonic"), 100. * 91. / 127., STANDARD ":scale");
+ Real harm5 = Perc (_("2nd"), _("2nd Harmonic"), 100. * 55. / 127., STANDARD ":scale");
+ };
+ group _("Instrument flavour") {
+ Bool brass = (_("Brass Sounds"), _("Changes the organ to sound more brassy"), FALSE, STANDARD);
+ Bool reed = (_("Reed Sounds"), _("Adds reeds sound"), FALSE, STANDARD);
+ Bool flute = (_("Flute Sounds"), _("Adds flute sounds"), FALSE, STANDARD);
+ };
+};
+
+} // Dav
+} // Bse
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]