libpsynth 0.2.1
/home/raskolnikov/dev/psynth/trunk/src/psynth/synth/multi_point_envelope.hpp
Go to the documentation of this file.
00001 
00017 /*
00018  *  Copyright (C) 2008, 2009 Juan Pedro BolĂ­var Puente
00019  *
00020  *  This file is part of Psychosynth.
00021  *   
00022  *  Psychosynth is free software: you can redistribute it and/or modify
00023  *  it under the terms of the GNU General Public License as published by
00024  *  the Free Software Foundation, either version 3 of the License, or
00025  *  (at your option) any later version.
00026  *
00027  *  Psychosynth is distributed in the hope that it will be useful,
00028  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00029  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00030  *  GNU General Public License for more details.
00031  *
00032  *  You should have received a copy of the GNU General Public License
00033  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00034  *
00035  */
00036 
00037 #ifndef PSYNTH_SYNTH_MULTI_POINT_ENVELOPE_H
00038 #define PSYNTH_SYNTH_MULTI_POINT_ENVELOPE_H
00039 
00040 #include <vector>
00041 #include <psynth/sound/forwards.hpp>
00042 #include <psynth/sound/algorithm.hpp>
00043 #include <psynth/synth/envelope.hpp>
00044 
00045 namespace psynth
00046 {
00047 namespace synth
00048 {
00049 
00050 template <class Sample>
00051 struct envelope_point
00052 {
00053     float  dt;
00054     Sample val;
00055 };
00056 
00063 template <class Sample>
00064 class envelope_values
00065 {
00066     template <class R, class Vp>
00067     friend class multi_point_envelope;
00068 
00069 public:
00070     typedef envelope_point<Sample> point;
00071     
00072     envelope_values ()
00073         : _sustain (1)
00074         , _factor (1.0f)
00075         {}
00076     
00077     void set_asr (point a, point s, point r);
00078     void set_adsr (point a, point d, point s, point r);
00079 
00080     void set_factor (float factor)
00081     { _factor = factor; }
00082 
00083     float factor () const
00084     { return _factor; }
00085     
00086     void set_sustain (std::size_t sustain)
00087     { _sustain = sustain; }
00088     
00089     void set (const std::vector<point>& p, std::size_t sustain)
00090     {
00091         _points  = p;
00092         _sustain = sustain;
00093     }
00094     
00095     point& get (std::size_t index)
00096     { return _points [index]; }
00097 
00098     const point& get (std::size_t index) const
00099     { return _points [index]; }
00100 
00101     point& operator [] (int index)
00102     { return _points [index]; }
00103 
00104     const point& operator[] (int index) const
00105     { return _points [index]; }
00106 
00107     std::size_t size () const
00108     { return _points.size (); }
00109 
00110     void resize (std::size_t size)
00111     { _points.resize (size); }
00112 
00113 private:
00114     std::vector<point> _points;
00115     std::size_t        _sustain;
00116     float              _factor;
00117 };
00118 
00119 template <class Range,
00120           typename ValuesPtr =
00121           envelope_values<typename sound::sample_type<Range>::type>* >
00122 class multi_point_envelope : public envelope<Range>
00123 {
00124 public:
00125     typedef Range                      range;
00126     typedef typename Range::value_type value_type;
00127     typedef ValuesPtr                  values_ptr;
00128     
00129     multi_point_envelope (values_ptr val)
00130         : _val (val)
00131         , _cur_point (0)
00132         , _time (0.0f)
00133         , _pressed (false)
00134         {}
00135 
00136     void set_values (values_ptr vals)
00137     { _val = vals; }
00138 
00139     values_ptr get_values ()
00140     { return _val; }
00141 
00142     float time () const
00143     { return _time; }
00144 
00145     void set_time (float time)
00146     { _time = time; }
00147 
00148     void restart ()
00149     {
00150         _time = 0;
00151         _cur_point = 0;
00152     }
00153     
00154     void press ()
00155     {
00156         if (multi_point_envelope::finished ())
00157             multi_point_envelope::restart ();
00158         _pressed = true;
00159     }
00160 
00161     void release ()
00162     { _pressed = false; }
00163 
00164     PSYNTH_FORCEINLINE value_type update ()
00165     { return multi_point_envelope::update (1); }
00166     
00167     value_type update (std::size_t sample);
00168 
00169     void update (const range& samples)
00170     {
00171         generate_frames (samples, [&] () -> value_type {
00172                 return this->multi_point_envelope::update ();
00173             });
00174     }
00175 
00176     bool finished ()
00177     { return _cur_point >= _val->size() - 1; }
00178 
00179 private:
00180     values_ptr    _val;
00181     std::size_t   _cur_point;
00182     float         _time;
00183     bool          _pressed;
00184 };
00185 
00186 } /* namespace synth */
00187 } /* namespace psynth */
00188 
00189 #include <psynth/synth/multi_point_envelope.tpp>
00190 
00191 #endif /* PSYNTH_SYNTH_MULTI_POINT_ENVELOPE_H */