1 
2 /*
3  *  Diverse Bristol audio routines.
4  *  Copyright (c) by Nick Copeland <nickycopeland@hotmail.com> 1996,2012
5  *
6  *
7  *   This program is free software; you can redistribute it and/or modify
8  *   it under the terms of the GNU General Public License as published by
9  *   the Free Software Foundation; either version 3 of the License, or
10  *   (at your option) any later version.
11  *
12  *   This program is distributed in the hope that it will be useful,
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *   GNU General Public License for more details.
16  *
17  *   You should have received a copy of the GNU General Public License
18  *   along with this program; if not, see <http://www.gnu.org/licenses/>.
19  *
20  */
21 
22 /*#define DEBUG */
23 
24 #include <math.h>
25 
26 #include "bristol.h"
27 #include "vibrachorus.h"
28 
29 #define SPEED		0
30 #define DEPTH		1
31 #define SCAN		2
32 #define GAIN		3
33 
34 #define OPNAME "Dimension"
35 #define OPDESCRIPTION "Vibrato Chorus"
36 #define PCOUNT 3
37 #define IOCOUNT 3
38 
39 #define VCHORUS_IN_IND 0
40 #define VCHORUS_LOUT_IND 1
41 #define VCHORUS_ROUT_IND 2
42 
43 /*
44  * Reset any local memory information.
45  */
destroy(bristolOP * operator)46 static int destroy(bristolOP *operator)
47 {
48 #ifdef BRISTOL_DBG
49 	printf("destroy(%x)\n", operator);
50 #endif
51 
52 	bristolfree(operator->specs);
53 
54 	cleanup(operator);
55 	return(0);
56 }
57 
58 /*
59  * This is called by the frontend when a parameter is changed.
60 static int param(param, value)
61  */
param(bristolOP * operator,bristolOPParams * param,unsigned char index,float value)62 static int param(bristolOP *operator, bristolOPParams *param,
63 	unsigned char index, float value)
64 {
65 	bristolVCHORUS *specs;
66 
67 	specs = (bristolVCHORUS *) operator->specs;
68 
69 #ifdef DEBUG
70 	printf("checkParams(%f)\n", value);
71 #endif
72 
73 	switch (index) {
74 		case 0:
75 			/*
76 			 * We want to go from 0.1Hz up to perhaps 20Hz. That means we need
77 			 * to step through the 1024 sinewave table at that rate.
78 			 *
79 			 * specs->samplerate
80 			 */
81 			param->param[index].float_val =
82 				(0.1 + value * 20) * 1024 / specs->samplerate;
83 			return(0);
84 		case 1:
85 			if ((param->param[index].int_val = value * 256) <= 0)
86 				param->param[index].int_val = 1;
87 			break;
88 		case 2:
89 			if (value == 0)
90 				param->param[index].int_val = 0;
91 			else
92 				param->param[index].int_val = 1;
93 			break;
94 	}
95 	param->param[index].float_val = value;
96 	return(0);
97 }
98 
99 static float sinewave[1024];
100 
101 /*
102  * Reset any local memory information.
103  */
reset(bristolOP * operator,bristolOPParams * param)104 static int reset(bristolOP *operator, bristolOPParams *param)
105 {
106 	int i;
107 
108 #ifdef BRISTOL_DBG
109 	printf("reset(%x)\n", operator);
110 #endif
111 
112 	if (param->param[0].mem)
113 		bristolfree(param->param[0].mem);
114 
115 	param->param[0].mem = bristolmalloc0(sizeof(float) * HISTSIZE);
116 
117 	param->param[0].int_val = 10;
118 	param->param[1].int_val = 10;
119 	param->param[2].int_val = 0;
120 
121 	// Get a normalised sinewave.
122 	for (i = 0; i < 1024; i++)
123 		sinewave[i] = sinf(M_PI * ((float) i) * 2.0 / 1024.0f) + 1.0;
124 
125 	return(0);
126 }
127 
128 static float table[TABSIZE];
129 
130 /*
131  * Stereo chorus. Create a vibrato effect at given speed from mono input signal
132  * and mix it in varying amount back into the left and right channels. The
133  * left and right should be given a copy of the input data as pass through.
134  *
135  * We need a parameter for depth that controls how far into the history we are
136  * going to scan, the rate at which we scan, the depth of the returned signal
137  * that defines the amount of 'flanging', and perhaps a second rate parameter
138  * that alters the stereo panning of the signals. Having this separate from
139  * the scan speed should improve the helicopter effect. All parameters will
140  * have to be float to ensure we can have subsample scan rates, previous
141  * versions have been a bit limited with single sample steps. We should also
142  * make this a resampling chorus.
143  *
144  * Extra parameters could be used to adjust the gain of both the original and
145  * the vibrato signal, and we could consider different scaning waveforms. The
146  * only one at the moment is a triangular which is close enough to sine, but a
147  * front or back loaded tri wave would introduce some interesting leading and
148  * trailing pumping effects, something that could be done by a factor that
149  * justs affects the ramp rate, applied +ve when ramping up and -ve when down.
150  */
operate(bristolOP * operator,bristolVoice * voice,bristolOPParams * param,void * lcl)151 static int operate(bristolOP *operator,
152 	bristolVoice *voice,
153 	bristolOPParams *param,
154 	void *lcl)
155 {
156 	bristolVCHORUS *specs;
157 	bristolVCHORUSlocal *local = (bristolVCHORUSlocal *) lcl;
158 	register float *source, *ldest, *rdest;
159 	register int count;
160 	register float *history, depth, speed, scan, fdir;
161 	register float histout, value, scanp, gain, cg, dir, scanr;
162 	register int histin, i;
163 
164 	specs = (bristolVCHORUS *) operator->specs;
165 
166 	count = specs->spec.io[VCHORUS_LOUT_IND].samplecount;
167 	source = specs->spec.io[VCHORUS_IN_IND].buf;
168 	ldest = specs->spec.io[VCHORUS_LOUT_IND].buf;
169 	rdest = specs->spec.io[VCHORUS_ROUT_IND].buf;
170 
171 	/*
172 	 * operational parameters. Speed should be a function of depth, ie, if
173 	 * depth changes, speed should be adjusted to maintain scan rate.
174 	 *
175 	 * Let speed be 10 seconds require to reach the given depth. That can be
176 	 * calculated as 441000 samples, so we divide speed by depth * 44100;
177 	 */
178 	depth = param->param[DEPTH].float_val * 1024;
179 	speed = param->param[SPEED].float_val;
180 
181 	/*
182 	 * Let scan be ten seconds to reach gain
183 	 */
184 	gain = param->param[GAIN].float_val * 1.5;
185 	scan = param->param[SCAN].float_val * 0.0005 * gain;
186 
187 	history = param->param[0].mem;
188 
189 #ifdef DEBUG
190 	printf("dimensionD()\n");
191 #endif
192 
193 	histin = local->Histin;
194 	histout = local->Histout;
195 	scanr = local->scanr;
196 	scanp = local->scanp;
197 	cg = local->cg;
198 	dir = local->dir;
199 	fdir = local->fdir;
200 
201 	for (i = 0; i < count; i++) {
202 		/*
203 		 * Save our current signal into the history buffer.
204 		 */
205 		history[histin] = *source;
206 
207 		/*
208 		 * Take our sample. Resample the two nearest for the position of our
209 		 * current scan through the history.
210 		 *
211 		 * Resampling is to take the current sample, plus the difference of the
212 		 * distance between this and the next sample.
213 		 value = history[histout]
214 		 	+ (history[histout + 1] - history[histout])
215 				* histout - (int) histout)
216 		 */
217 		if ((histout + 1) >= HISTSIZE)
218 		{
219 			value = history[(int) histout] +
220 				(history[0] - history[(int) histout])
221 					* (histout - ((float) ((int) histout)));
222 		} else {
223 			value = history[(int) histout] +
224 				(history[(int) histout + 1] - history[(int) histout])
225 					* (histout - ((float) ((int) histout)));
226 		}
227 
228 		/*
229 		 * This is wrong. We take our sample and add to one channel and then
230 		 * subtract from the other. Correct operation is to take the sample
231 		 * in value, and then also alter the add/subtract value. We actually
232 		 * need three parameters, the speed at which we scan through the data
233 		 * history, the depth to which we scan, and the gain to apply the
234 		 * phasing effect. FIXED.
235 		 */
236 		if (dir == 0)
237 		{
238 			if ((cg += scan) > gain)
239 				dir = 1;
240 		} else {
241 			if ((cg -= scan) < 0.0)
242 				dir = 0;
243 		}
244 
245 		if (scan == 0)
246 		{
247 			*rdest++ = (*source * (1.5 - gain)) + value * gain;
248 			*ldest++ = (*source * (1.5 - gain)) + value * gain;
249 		} else {
250 			*rdest++ = (*source * (1.5 - gain)) + value * (gain - cg);
251 			*ldest++ = (*source * (1.5 - gain)) + value * cg;
252 		}
253 
254 		history[histin] += value * gain * 0.5;
255 		source++;
256 
257 		if (++histin >= HISTSIZE) histin = 0;
258 
259 		if ((histout = ((float) histin) - scanp) < 0)
260 			while (histout < 0)
261 				histout += HISTSIZE;
262 
263 		while (histout >= HISTSIZE)
264 			histout -= HISTSIZE;
265 
266 		/*
267 		 * Adjust the scan rate through memory. Initially out is zero, and we
268 		 * tend it towards depth by adding the speed increments. When we reach
269 		 * depth we change the direction.
270 		if (fdir == 0)
271 		{
272 			if ((scanp += speed) > depth)
273 				fdir = 1;
274 		} else {
275 			if ((scanp -= speed) < speed)
276 				fdir = 0;
277 		}
278 		 */
279 		if ((scanr += speed) >= 1024)
280 			scanr -= 1024;
281 		scanp = sinewave[(int) scanr] * depth;
282 	}
283 
284 	local->Histin = histin;
285 	local->Histout = histout;
286 	local->scanr = scanr;
287 	local->scanp = scanp;
288 	local->cg = cg;
289 	local->dir = dir;
290 	local->fdir = fdir;
291 	return(0);
292 }
293 
294 static void
buildSineTable(float * table)295 buildSineTable(float *table)
296 {
297 	int i;
298 
299 	for (i = 260; i < (TABSIZE + 260); i++)
300 		table[i - 260] = (float) sin(2 * M_PI * ((double) i) / TABSIZE);
301 }
302 
303 /*
304  * Setup any variables in our OP structure, in our IO structures, and malloc
305  * any memory we need.
306  */
307 bristolOP *
chorusinit(bristolOP ** operator,int index,int samplerate,int samplecount)308 chorusinit(bristolOP **operator, int index, int samplerate, int samplecount)
309 {
310 	bristolVCHORUS *specs;
311 
312 	*operator = bristolOPinit(operator, index, samplecount);
313 
314 #ifdef BRISTOL_DBG
315 	printf("chorusinit(%x(%x), %i, %i, %i)\n",
316 		operator, *operator, index, samplerate, samplecount);
317 #endif
318 
319 	/*
320 	 * Then the local parameters specific to this operator. These will be
321 	 * the same for each operator, but must be inited in the local code.
322 	 */
323 	(*operator)->operate = operate;
324 	(*operator)->destroy = destroy;
325 	(*operator)->reset = reset;
326 	(*operator)->param= param;
327 
328 	specs = (bristolVCHORUS *) bristolmalloc0(sizeof(bristolVCHORUS));
329 	specs->samplerate = samplerate;
330 	(*operator)->specs = (bristolOPSpec *) specs;
331 	(*operator)->size = sizeof(bristolVCHORUS);
332 
333 	/*
334 	 * These are specific to this operator, and will need to be altered for
335 	 * each operator.
336 	 */
337 	specs->spec.opname = OPNAME;
338 	specs->spec.description = OPDESCRIPTION;
339 	specs->spec.pcount = PCOUNT;
340 	specs->spec.iocount = IOCOUNT;
341 	specs->spec.localsize = sizeof(bristolVCHORUSlocal);
342 
343 	/*
344 	 * Now fill in the specs for this operator.
345 	 */
346 	specs->spec.param[0].pname = "speed";
347 	specs->spec.param[0].description= "rotation speed";
348 	specs->spec.param[0].type = BRISTOL_FLOAT;
349 	specs->spec.param[0].low = 0;
350 	specs->spec.param[0].high = 1;
351 	specs->spec.param[0].flags = BRISTOL_ROTARY|BRISTOL_SLIDER;
352 
353 	specs->spec.param[1].pname = "depth";
354 	specs->spec.param[1].description = "depth of rotation";
355 	specs->spec.param[1].type = BRISTOL_FLOAT;
356 	specs->spec.param[1].low = 0;
357 	specs->spec.param[1].high = 1;
358 	specs->spec.param[1].flags = BRISTOL_ROTARY|BRISTOL_SLIDER;
359 
360 	specs->spec.param[2].pname = "crunch";
361 	specs->spec.param[2].description = "gain of return signal";
362 	specs->spec.param[2].type = BRISTOL_FLOAT;
363 	specs->spec.param[2].low = 0;
364 	specs->spec.param[2].high = 1;
365 	specs->spec.param[2].flags = BRISTOL_ROTARY|BRISTOL_SLIDER;
366 
367 	specs->spec.param[3].pname = "scan";
368 	specs->spec.param[3].description = "stereo pan rate";
369 	specs->spec.param[3].type = BRISTOL_FLOAT;
370 	specs->spec.param[3].low = 0;
371 	specs->spec.param[3].high = 1;
372 	specs->spec.param[3].flags = BRISTOL_ROTARY|BRISTOL_SLIDER;
373 
374 
375 	/*
376 	 * Now fill in the IO specs.
377 	 */
378 	specs->spec.io[0].ioname = "input";
379 	specs->spec.io[0].description = "Input signal";
380 	specs->spec.io[0].samplerate = samplerate;
381 	specs->spec.io[0].samplecount = samplecount;
382 	specs->spec.io[0].flags = BRISTOL_AC|BRISTOL_INPUT;
383 
384 	specs->spec.io[1].ioname = "left output";
385 	specs->spec.io[1].description = "output signal";
386 	specs->spec.io[1].samplerate = samplerate;
387 	specs->spec.io[1].samplecount = samplecount;
388 	specs->spec.io[1].flags = BRISTOL_AC|BRISTOL_OUTPUT;
389 
390 	specs->spec.io[2].ioname = "right output";
391 	specs->spec.io[2].description = "output signal";
392 	specs->spec.io[2].samplerate = samplerate;
393 	specs->spec.io[2].samplecount = samplecount;
394 	specs->spec.io[2].flags = BRISTOL_AC|BRISTOL_OUTPUT;
395 
396 	buildSineTable(table);
397 
398 	return(*operator);
399 }
400 
401