Index: bse/bsecompat.c
===================================================================
--- bse/bsecompat.c	(revision 4336)
+++ bse/bsecompat.c	(working copy)
@@ -37,6 +37,7 @@ bse_compat_rewrite_type_name (BseStorage
     { 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++)
Index: bse/bsecxxmodule.cc
===================================================================
--- bse/bsecxxmodule.cc	(revision 4336)
+++ bse/bsecxxmodule.cc	(working copy)
@@ -429,6 +429,13 @@ Effect::max_block_size() const
   return BSE_STREAM_MAX_VALUES;
 }
 
+BseMusicalTuningType
+Effect::current_musical_tuning() const
+{
+  BseSource *source = cast (const_cast <Effect*> (this));
+  return bse_item_current_musical_tuning (BSE_ITEM (source));
+}
+
 void
 Effect::class_init (CxxBaseClass *klass)
 {
Index: bse/ChangeLog
===================================================================
--- bse/ChangeLog	(revision 4336)
+++ bse/ChangeLog	(working copy)
@@ -1,3 +1,13 @@
+Tue Apr 24 18:25:54 2007  Stefan Westerfeld  <stefan@space.twc.de>
+
+	* bsecompat.c: Added DavOrgan -> BseDavOrgan compatibility rewrite
+	typename rule for files <= 0.7.0, since the DavOrgan module is now
+	implemented in C++, and thus properly namespaced.
+
+	* bsecxxmodule.hh:
+	* bsecxxmodule.cc: Introduced Effect::current_musical_tuning(), which
+	can be used to make C++ plugins tuning aware.
+
 Wed Apr 11 15:46:31 2007  Stefan Westerfeld  <stefan@space.twc.de>
 
 	* bsedatahandle-fir.cc: Fix a bug in seek() spotted by Tim: invalidate
Index: bse/bsecxxmodule.hh
===================================================================
--- bse/bsecxxmodule.hh	(revision 4336)
+++ bse/bsecxxmodule.hh	(working copy)
@@ -159,6 +159,8 @@ protected:
                                                         BseTrans        *trans);
   unsigned int              block_size                 () const;
   unsigned int              max_block_size             () const;
+public: /* FIXME: make this protected as soon as the modules have their own current_musical_tuning() accessor */
+  BseMusicalTuningType      current_musical_tuning     () const;
 };
 /* implement Bse::Effect and Bse::SynthesisModule methods */
 #define BSE_EFFECT_INTEGRATE_MODULE(ObjectType,ModuleType,ParamType)            \
Index: plugins/ChangeLog
===================================================================
--- plugins/ChangeLog	(revision 4336)
+++ plugins/ChangeLog	(working copy)
@@ -1,3 +1,13 @@
+Tue Apr 24 18:28:27 2007  Stefan Westerfeld  <stefan@space.twc.de>
+
+	* Makefile.am:
+	* Makefile.plugins: Switch from the C implementation of DavOrgan to
+	the C++ implementation of DavOrgan.
+
+	* davorgan.cc: Ported C code from DavOrgan to C++.
+	
+	* davorgan.idl: Wrote a proper IDL file for the DavOrgan module.
+
 Mon Feb  5 22:16:01 2007  Stefan Westerfeld  <stefan@space.twc.de>
 
 	* bsenoise.cc: Nullify noise_table pointer after deleting it, so that
Index: plugins/Makefile.plugins
===================================================================
--- plugins/Makefile.plugins	(revision 4336)
+++ plugins/Makefile.plugins	(working copy)
@@ -107,6 +107,11 @@ $(srcdir)/davchorus.cc: davchorus.genidl
 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    = $(bseseq
 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
Index: plugins/Makefile.am
===================================================================
--- plugins/Makefile.am	(revision 4336)
+++ plugins/Makefile.am	(working copy)
@@ -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]	\
--- /dev/null	2007-04-26 18:54:25.724281800 +0200
+++ plugins/davorgan.cc	2007-04-26 18:59:27.000000000 +0200
@@ -0,0 +1,312 @@
+/* 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_factor (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];
+    }
+    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 = dtoi32 (BSE_FREQ_FROM_VALUE (ifreq[0]) * m_transpose_factor * m_fine_tune_factor * 256);
+      else
+	freq_256 = dtoi32 (m_cfreq * m_transpose_factor * m_fine_tune_factor * 256);
+
+      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
--- /dev/null	2007-04-26 18:54:25.724281800 +0200
+++ plugins/davorgan.idl	2007-04-26 19:10:55.000000000 +0200
@@ -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
