BEAST/BSE - Better Audio System and Sound Engine
0.8.2
|
00001 // Licensed GNU LGPL v2.1 or later: http://www.gnu.org/licenses/lgpl.html 00002 #ifndef __BSE_CXX_MODULE_H__ 00003 #define __BSE_CXX_MODULE_H__ 00004 00005 #include <bse/bsecxxbase.hh> 00006 #include <bse/bseieee754.hh> 00007 00008 namespace Bse { 00009 00010 /* enums/structures mirrored from bseengine.hh */ 00011 enum ProcessCost { 00012 NORMAL, 00013 CHEAP, 00014 EXPENSIVE 00015 }; 00016 struct JStream { 00017 const float **values; 00018 uint n_connections; 00019 /* private: */ 00020 uint jcount; /* reserved */ 00021 }; 00022 struct IStream { 00023 const float *values; 00024 gboolean connected; 00025 }; 00026 struct OStream { 00027 float *values; 00028 gboolean connected; 00029 }; 00030 00031 class Effect; 00032 00033 class SynthesisModule { 00034 template<class T, typename P> class ClosureP1; /* 1-argument member function closure */ 00035 BseModule *intern_module; 00036 public: 00037 explicit SynthesisModule (); 00038 virtual ~SynthesisModule () = 0; 00039 virtual void reset () = 0; 00040 virtual void process (uint n_values) = 0; 00041 virtual const ProcessCost cost (); 00042 inline const IStream& istream (uint istream_index) const; 00043 inline const JStream& jstream (uint jstream_index) const; 00044 inline const OStream& ostream (uint ostream_index) const; 00045 void ostream_set (uint ostream_index, 00046 const float *values); 00047 const float* const_values (float value); 00048 inline const uint mix_freq () const; 00049 inline const uint block_size () const; 00050 inline guint64 tick_stamp (); 00051 inline BseModule* engine_module (); 00052 static inline int dtoi (double d) { return bse_dtoi (d); } 00053 static inline int ftoi (float f) { return bse_ftoi (f); } 00054 /* member functions and closures */ 00055 struct Closure { 00056 virtual void operator() (SynthesisModule*) = 0; 00057 virtual ~Closure () {} 00058 }; 00059 /* create a 1-argument member function closure, where C must be derived from SynthesisModule */ 00060 template<class D, class C> 00061 static Closure* make_closure (void (C::*method) (D*), 00062 const D &data); 00063 /* internal */ 00064 void set_module (BseModule *module); 00065 /* auto_update() trampoline */ 00066 public: 00067 typedef void (*AutoUpdate) (BseModule*, gpointer); 00068 struct AutoUpdateData { 00069 guint prop_id; 00070 double prop_value; 00071 /* required by back propagation */ 00072 guint64 tick_stamp; 00073 GParamSpec *pspec; 00074 Effect *effect; 00075 }; 00076 struct NeedAutoUpdateTag {}; 00077 protected: 00078 template<class M, class P, class C> struct Trampoline { 00079 static void auto_update_accessor (BseModule*, gpointer); 00080 }; 00081 /* partial trampoline specializations */ 00082 template<class M, class P> struct Trampoline<M,P,NeedAutoUpdateTag> { 00083 static void auto_update_accessor (BseModule*, gpointer); 00084 }; 00085 template<class M, class P> struct Trampoline<M,P,void> { 00086 static void auto_update_accessor (BseModule*, gpointer); 00087 }; 00088 }; 00089 00090 #define BSE_TYPE_EFFECT (BSE_CXX_TYPE_GET_REGISTERED (Bse, Effect)) 00091 class EffectBase : public CxxBase {}; 00092 class Effect : public EffectBase { 00093 private: 00094 guint64 last_module_update; 00095 public: 00096 /* BseObject functionality */ 00097 explicit Effect (); 00098 void set_property (guint prop_id, 00099 const Value &value, 00100 GParamSpec *pspec); 00101 void get_property (guint prop_id, 00102 Value &value, 00103 GParamSpec *pspec); 00104 /* BseSource accessors */ 00105 bool is_prepared() const { return BSE_SOURCE_PREPARED (gobject()); } 00106 guint n_ichannels() const { return BSE_SOURCE_N_ICHANNELS (gobject()); } 00107 guint n_joint_ichannels() const { return BSE_SOURCE_N_JOINT_ICHANNELS (gobject()); } 00108 guint n_ochannels() const { return BSE_SOURCE_N_OCHANNELS (gobject()); } 00109 bool is_joint_ichannel (guint i) const { return BSE_SOURCE_IS_JOINT_ICHANNEL (gobject(), i); } 00110 guint ichannels_istream (guint i) const { return BSE_SOURCE_ICHANNEL_ISTREAM (gobject(), i); } 00111 guint ichannels_jstream (guint i) const { return BSE_SOURCE_ICHANNEL_JSTREAM (gobject(), i); } 00112 guint ochannels_ostream (guint i) const { return BSE_SOURCE_OCHANNEL_OSTREAM (gobject(), i); } 00113 const gchar* ichannel_ident (guint i) const { return BSE_SOURCE_ICHANNEL_IDENT (gobject(), i); } 00114 const gchar* ichannel_label (guint i) const { return BSE_SOURCE_ICHANNEL_LABEL (gobject(), i); } 00115 const gchar* ichannel_blurb (guint i) const { return BSE_SOURCE_ICHANNEL_BLURB (gobject(), i); } 00116 const gchar* ochannel_ident (guint i) const { return BSE_SOURCE_OCHANNEL_IDENT (gobject(), i); } 00117 const gchar* ochannel_label (guint i) const { return BSE_SOURCE_OCHANNEL_LABEL (gobject(), i); } 00118 const gchar* ochannel_blurb (guint i) const { return BSE_SOURCE_OCHANNEL_BLURB (gobject(), i); } 00119 virtual SynthesisModule* create_module (uint context_handle, 00120 BseTrans *trans) = 0; 00121 virtual SynthesisModule:: 00122 Closure* make_module_config_closure () = 0; 00123 virtual SynthesisModule:: 00124 AutoUpdate get_module_auto_update () = 0; 00125 void update_modules (BseTrans *trans = NULL); 00126 guint64 module_update_tick_stamp () { return last_module_update; } 00127 /* prepare & dismiss pre and post invocation hooks */ 00128 virtual void prepare1() { /* override this to do something before parent class prepare */ } 00129 virtual void prepare2() { /* override this to do something after parent class prepare */ } 00130 virtual void reset1() { /* override this to do something before parent class dismiss */ } 00131 virtual void reset2() { /* override this to do something after parent class dismiss */ } 00132 00133 static void class_init (CxxBaseClass *klass); 00134 protected: 00135 const BseModuleClass* create_engine_class (SynthesisModule *sample_module, 00136 int cost = -1, 00137 int n_istreams = -1, 00138 int n_jstreams = -1, 00139 int n_ostreams = -1); 00140 virtual BseModule* integrate_engine_module (uint context_handle, 00141 BseTrans *trans); 00142 virtual void dismiss_engine_module (BseModule *engine_module, 00143 guint context_handle, 00144 BseTrans *trans); 00145 uint block_size () const; 00146 uint max_block_size () const; 00147 public: /* FIXME: make this protected as soon as the modules have their own current_musical_tuning() accessor */ 00148 BseMusicalTuningType current_musical_tuning () const; 00149 }; 00150 /* implement Bse::Effect and Bse::SynthesisModule methods */ 00151 #define BSE_EFFECT_INTEGRATE_MODULE(ObjectType,ModuleType,ParamType) \ 00152 Bse::SynthesisModule* \ 00153 create_module (uint context_handle, \ 00154 BseTrans *trans) \ 00155 { \ 00156 /* check that 'this' is a ObjectType* */ \ 00157 (void) const_cast<ObjectType*> (this); \ 00158 /* create a synthesis module */ \ 00159 return new ModuleType(); \ 00160 } \ 00161 Bse::SynthesisModule::Closure* \ 00162 make_module_config_closure() \ 00163 { \ 00164 return SynthesisModule::make_closure (&ModuleType::config, ParamType (this)); \ 00165 } \ 00166 Bse::SynthesisModule::AutoUpdate \ 00167 get_module_auto_update() \ 00168 { \ 00169 return SynthesisModule::Trampoline<ModuleType,ParamType, \ 00170 ObjectType::AutoUpdateCategory>::auto_update_accessor; \ 00171 } 00172 template<class M, class P> 00173 void 00174 SynthesisModule::Trampoline<M,P,SynthesisModule::NeedAutoUpdateTag>:: 00175 auto_update_accessor (BseModule *bmodule, /* Engine Thread */ 00176 gpointer data) 00177 { 00178 M *m = static_cast<M*> (BSE_MODULE_GET_USER_DATA (bmodule)); 00179 AutoUpdateData *au = static_cast<AutoUpdateData*> (data); 00180 typename P::IDType prop_id = static_cast<typename P::IDType> (au->prop_id); 00181 if (0) // check M::auto_update() member and prototype 00182 (void) static_cast<void (M::*) (typename P::IDType, double)> (&M::auto_update); 00183 m->auto_update (prop_id, au->prop_value); 00184 } 00185 template<class M, class P> 00186 void 00187 SynthesisModule::Trampoline<M,P,void>:: 00188 auto_update_accessor (BseModule *bmodule, 00189 gpointer data) 00190 { 00191 } 00192 00193 00194 /* --- implementation details --- */ 00195 namespace externC { extern "C" { 00196 extern guint bse_engine_exvar_sample_freq; 00197 extern guint bse_engine_exvar_block_size; 00198 extern guint64 bse_module_tick_stamp (BseModule*); 00199 } } 00200 inline BseModule* 00201 SynthesisModule::engine_module () 00202 { 00203 return intern_module; 00204 } 00205 inline const uint 00206 SynthesisModule::mix_freq () const 00207 { 00208 return externC::bse_engine_exvar_sample_freq; 00209 } 00210 inline const uint 00211 SynthesisModule::block_size () const 00212 { 00213 return externC::bse_engine_exvar_block_size; 00214 } 00215 inline guint64 00216 SynthesisModule::tick_stamp () 00217 { 00218 return externC::bse_module_tick_stamp (engine_module()); 00219 } 00220 inline const IStream& 00221 SynthesisModule::istream (uint istream_index) const 00222 { 00223 void *istreams = BSE_MODULE_GET_ISTREAMSP (intern_module); 00224 return reinterpret_cast<IStream*> (istreams)[istream_index]; 00225 } 00226 inline const JStream& 00227 SynthesisModule::jstream (uint jstream_index) const 00228 { 00229 void *jstreams = BSE_MODULE_GET_JSTREAMSP (intern_module); 00230 return reinterpret_cast<JStream*> (jstreams)[jstream_index]; 00231 } 00232 inline const OStream& 00233 SynthesisModule::ostream (uint ostream_index) const 00234 { 00235 void *ostreams = BSE_MODULE_GET_OSTREAMSP (intern_module); 00236 return reinterpret_cast<OStream*> (ostreams)[ostream_index]; 00237 } 00238 template<class T, typename P> 00239 class SynthesisModule::ClosureP1 : public SynthesisModule::Closure { 00240 typedef void (T::*Member) (P*); 00241 Member func; 00242 P *data; 00243 public: 00244 ClosureP1 (void (T::*f) (P*), P *p) 00245 : func (f), data (p) 00246 { 00247 assert_derived_from<T,SynthesisModule>(); 00248 } 00249 void operator() (SynthesisModule *p) 00250 { 00251 T *t = static_cast<T*> (p); 00252 (t->*func) (data); 00253 } 00254 ~ClosureP1 () 00255 { 00256 delete data; 00257 } 00258 }; 00259 template<class D, class C> SynthesisModule::Closure* 00260 SynthesisModule::make_closure (void (C::*method) (D*), 00261 const D &data) 00262 { 00263 D *d = new D (data); 00264 ClosureP1<C,D> *ac = new ClosureP1<C,D> (method, d); 00265 return ac; 00266 } 00267 00268 } // Bse 00269 00270 #endif /* __BSE_CXX_MODULE_H__ */