1 /*
2  * liquidsfz - sfz sampler
3  *
4  * Copyright (C) 2019  Stefan Westerfeld
5  *
6  * This library is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU Lesser General Public License as published by the
8  * Free Software Foundation; either version 2.1 of the License, or (at your
9  * option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
14  * for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this library; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19  */
20 
21 #ifndef LIQUIDSFZ_VOICE_HH
22 #define LIQUIDSFZ_VOICE_HH
23 
24 #include "envelope.hh"
25 #include "filter.hh"
26 #include "lfogen.hh"
27 
28 namespace LiquidSFZInternal
29 {
30 
31 class Voice
32 {
33   LinearSmooth left_gain_;
34   LinearSmooth right_gain_;
35 
36   struct FImpl {
37     Filter              filter;
38     LinearSmooth        cutoff_smooth;
39     LinearSmooth        resonance_smooth;
40     const FilterParams *params;
41   } fimpl_, fimpl2_;
42 
43   Envelope filter_envelope_;
44   float    filter_envelope_depth_ = 0;
45 
46   LFOGen lfo_gen_;
47 
48   float volume_gain_ = 0;
49   float amplitude_gain_ = 0;
50   float velocity_gain_ = 0;
51   float rt_decay_gain_ = 0;
52   float pan_left_gain_ = 0;
53   float pan_right_gain_ = 0;
54 
55   float amp_random_gain_ = 0;
56   float pitch_random_cent_ = 0;
57   uint  delay_samples_ = 0;
58 
59   void update_volume_gain();
60   void update_amplitude_gain();
61   void update_pan_gain();
62   void update_lr_gain (bool now);
63 
64   float amp_value (float vnorm, const EGParam& amp_param);
65 
66   void  start_filter (FImpl& fi, const FilterParams *params);
67   void  update_cutoff (FImpl& fi, bool now);
68   void  update_resonance (FImpl& fi, bool now);
69 
70   LinearSmooth replay_speed_;
71   float        pitch_bend_value_ = 0; // [-1:1]
72 
73   void set_pitch_bend (int value);
74   void update_replay_speed (bool now);
75 public:
76   Synth *synth_;
77   int sample_rate_ = 44100;
78   int channel_ = 0;
79   int key_ = 0;
80   int velocity_ = 0;
81   bool loop_enabled_ = false;
82 
83   enum State {
84     ACTIVE,
85     SUSTAIN,
86     RELEASED,
87     IDLE
88   };
89   State state_ = IDLE;
90 
91   double ppos_ = 0;
92   uint64_t start_frame_count_ = 0;
93   Trigger trigger_ = Trigger::ATTACK;
94   Envelope envelope_;
95 
96   const Region *region_ = nullptr;
97 
Voice(Synth * synth,const Limits & limits)98   Voice (Synth *synth,
99          const Limits& limits) :
100     lfo_gen_ (synth, limits),
101     synth_ (synth)
102   {
103   }
104   double pan_stereo_factor (double region_pan, int ch);
105   double velocity_track_factor (const Region& r, int midi_velocity);
106 
107   void start (const Region& region, int channel, int key, int velocity, double time_since_note_on, uint64_t global_frame_count, uint sample_rate);
108   void stop (OffMode off_mode);
109   void kill();
110   void process (float **outputs, uint n_frames);
111   void process_filter (FImpl& fi, bool envelope, float *left, float *right, uint n_frames, const float *lfo_cutoff_factor);
112   uint off_by();
113   void update_cc (int controller);
114   void update_gain();
115 
116   void update_pitch_bend (int bend);
117 
118   float xfin_gain (int value, int lo, int hi, XFCurve curve);
119   float xfout_gain (int value, int lo, int hi, XFCurve curve);
120   float apply_xfcurve (float f, XFCurve curve);
121 };
122 
123 }
124 
125 #endif /* LIQUIDSFZ_VOICE_HH */
126