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