1 /* 2 * Oscillator.h - declaration of class Oscillator 3 * 4 * Copyright (c) 2004-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net> 5 * 6 * This file is part of LMMS - https://lmms.io 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public 10 * License as published by the Free Software Foundation; either 11 * version 2 of the License, or (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public 19 * License along with this program (see COPYING); if not, write to the 20 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 21 * Boston, MA 02110-1301 USA. 22 * 23 */ 24 25 #ifndef OSCILLATOR_H 26 #define OSCILLATOR_H 27 28 #include "lmmsconfig.h" 29 30 #include <math.h> 31 32 #ifdef LMMS_HAVE_STDLIB_H 33 #include <stdlib.h> 34 #endif 35 36 #include "SampleBuffer.h" 37 #include "lmms_constants.h" 38 39 class IntModel; 40 41 42 class EXPORT Oscillator 43 { 44 MM_OPERATORS 45 public: 46 enum WaveShapes 47 { 48 SineWave, 49 TriangleWave, 50 SawWave, 51 SquareWave, 52 MoogSawWave, 53 ExponentialWave, 54 WhiteNoise, 55 UserDefinedWave, 56 NumWaveShapes 57 } ; 58 59 enum ModulationAlgos 60 { 61 PhaseModulation, 62 AmplitudeModulation, 63 SignalMix, 64 SynchronizedBySubOsc, 65 FrequencyModulation, 66 NumModulationAlgos 67 } ; 68 69 70 Oscillator( const IntModel * _wave_shape_model, 71 const IntModel * _mod_algo_model, 72 const float & _freq, 73 const float & _detuning, 74 const float & _phase_offset, 75 const float & _volume, 76 Oscillator * _m_subOsc = NULL ); ~Oscillator()77 virtual ~Oscillator() 78 { 79 delete m_subOsc; 80 } 81 82 setUserWave(const SampleBuffer * _wave)83 inline void setUserWave( const SampleBuffer * _wave ) 84 { 85 m_userWave = _wave; 86 } 87 88 void update( sampleFrame * _ab, const fpp_t _frames, 89 const ch_cnt_t _chnl ); 90 91 // now follow the wave-shape-routines... 92 sinSample(const float _sample)93 static inline sample_t sinSample( const float _sample ) 94 { 95 return sinf( _sample * F_2PI ); 96 } 97 triangleSample(const float _sample)98 static inline sample_t triangleSample( const float _sample ) 99 { 100 const float ph = fraction( _sample ); 101 if( ph <= 0.25f ) 102 { 103 return ph * 4.0f; 104 } 105 else if( ph <= 0.75f ) 106 { 107 return 2.0f - ph * 4.0f; 108 } 109 return ph * 4.0f - 4.0f; 110 } 111 sawSample(const float _sample)112 static inline sample_t sawSample( const float _sample ) 113 { 114 return -1.0f + fraction( _sample ) * 2.0f; 115 } 116 squareSample(const float _sample)117 static inline sample_t squareSample( const float _sample ) 118 { 119 return ( fraction( _sample ) > 0.5f ) ? -1.0f : 1.0f; 120 } 121 moogSawSample(const float _sample)122 static inline sample_t moogSawSample( const float _sample ) 123 { 124 const float ph = fraction( _sample ); 125 if( ph < 0.5f ) 126 { 127 return -1.0f + ph * 4.0f; 128 } 129 return 1.0f - 2.0f * ph; 130 } 131 expSample(const float _sample)132 static inline sample_t expSample( const float _sample ) 133 { 134 float ph = fraction( _sample ); 135 if( ph > 0.5f ) 136 { 137 ph = 1.0f - ph; 138 } 139 return -1.0f + 8.0f * ph * ph; 140 } 141 noiseSample(const float)142 static inline sample_t noiseSample( const float ) 143 { 144 // Precise implementation 145 // return 1.0f - rand() * 2.0f / RAND_MAX; 146 147 // Fast implementation 148 return 1.0f - fast_rand() * 2.0f / FAST_RAND_MAX; 149 } 150 userWaveSample(const float _sample)151 inline sample_t userWaveSample( const float _sample ) const 152 { 153 return m_userWave->userWaveSample( _sample ); 154 } 155 156 157 private: 158 const IntModel * m_waveShapeModel; 159 const IntModel * m_modulationAlgoModel; 160 const float & m_freq; 161 const float & m_detuning; 162 const float & m_volume; 163 const float & m_ext_phaseOffset; 164 Oscillator * m_subOsc; 165 float m_phaseOffset; 166 float m_phase; 167 const SampleBuffer * m_userWave; 168 169 170 void updateNoSub( sampleFrame * _ab, const fpp_t _frames, 171 const ch_cnt_t _chnl ); 172 void updatePM( sampleFrame * _ab, const fpp_t _frames, 173 const ch_cnt_t _chnl ); 174 void updateAM( sampleFrame * _ab, const fpp_t _frames, 175 const ch_cnt_t _chnl ); 176 void updateMix( sampleFrame * _ab, const fpp_t _frames, 177 const ch_cnt_t _chnl ); 178 void updateSync( sampleFrame * _ab, const fpp_t _frames, 179 const ch_cnt_t _chnl ); 180 void updateFM( sampleFrame * _ab, const fpp_t _frames, 181 const ch_cnt_t _chnl ); 182 183 float syncInit( sampleFrame * _ab, const fpp_t _frames, 184 const ch_cnt_t _chnl ); 185 inline bool syncOk( float _osc_coeff ); 186 187 template<WaveShapes W> 188 void updateNoSub( sampleFrame * _ab, const fpp_t _frames, 189 const ch_cnt_t _chnl ); 190 template<WaveShapes W> 191 void updatePM( sampleFrame * _ab, const fpp_t _frames, 192 const ch_cnt_t _chnl ); 193 template<WaveShapes W> 194 void updateAM( sampleFrame * _ab, const fpp_t _frames, 195 const ch_cnt_t _chnl ); 196 template<WaveShapes W> 197 void updateMix( sampleFrame * _ab, const fpp_t _frames, 198 const ch_cnt_t _chnl ); 199 template<WaveShapes W> 200 void updateSync( sampleFrame * _ab, const fpp_t _frames, 201 const ch_cnt_t _chnl ); 202 template<WaveShapes W> 203 void updateFM( sampleFrame * _ab, const fpp_t _frames, 204 const ch_cnt_t _chnl ); 205 206 template<WaveShapes W> 207 inline sample_t getSample( const float _sample ); 208 209 inline void recalcPhase(); 210 211 } ; 212 213 214 #endif 215