1 /*
2  * Copyright (C) 2002 - David W. Durham
3  *
4  * This file is part of ReZound, an audio editing application.
5  *
6  * ReZound is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published
8  * by the Free Software Foundation; either version 2 of the License,
9  * or (at your option) any later version.
10  *
11  * ReZound is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
19  */
20 
21 #ifndef __DSP_DelayEffect_H__
22 #define __DSP_DelayEffect_H__
23 
24 #include "../../config/common.h"
25 
26 #include "../CSound_defs.h"
27 
28 #include "Delay.h"
29 
30 
31 /* --- CDSPDelayEffect ----------------------------
32  *
33  * - This DSP block is used to create a delay effect or echoes.  It is different
34  *   than the CDSPDelay block in that this one is a full fledged effect more than
35  *   just a DSP component block.
36  *
37  * - The constructor is given the number of taps, tap times, tap gains, and tap feed backs
38  * - To use this DSP block, simply construct it with the parameters and call processSample()
39  *   to given and get each successive sample.
40  * - The following is a diagram showing how this block works
41 	Based somewhat from http://www.harmony-central.com/Effects/Articles/Delay/
42 
43                              ---             ---             ---
44               --------------| + |<----------| + |<----------| + |<-- ... <------------
45              |               ---             ---             ---                      |
46              |                ^               ^               ^                       |
47              |         tap 1  |        tap 2  |        tap 3  |                tap N  |
48              |       feedback/_\     feedback/_\     feedback/_\             feedback/_\
49              v                |               |               |                       |
50   input     ---     -------   |     -------   |     -------   |             -------   |
51     ------>| + |-->| Delay |--+--->| Delay |--+--->| Delay |--+----> ... ->| Delay |--+
52        |    ---     -------   |     -------   |     -------   |             -------   |
53        |                     _|_             _|_             _|_                     _|_
54        |                tap 1\_/        tap 2\_/        tap 3\_/     ...        tap N\_/
55        |                 gain |          gain |          gain |                  gain |
56        |                      v               v               v                       v
57        |                     ---             ---             ---                     ---     output
58         ------------------->| + |---------->| + |---------->| + |--> ... ---------->| + |------>
59                              ---             ---             ---                     ---
60 
61  *
62  */
63 class CDSPDelayEffect
64 {
65 public:
66 		// ??? convert these to vectors of floats and also change the way action parameters are passed
67 		// actually convert tapTimes to a vector of unsigned
CDSPDelayEffect(size_t _tapCount,float * _tapTimes,float * _tapGains,float * _tapFeedbacks)68 	CDSPDelayEffect(size_t _tapCount,float *_tapTimes,float *_tapGains,float *_tapFeedbacks) :
69 		tapCount(_tapCount),
70 
71 		tapTimes(_tapTimes),
72 		tapGains(_tapGains),
73 		tapFeedbacks(_tapFeedbacks),
74 
75 		delays(new TDSPDelay<mix_sample_t>[_tapCount])
76 	{
77 		// perhaps fill with data from the past not zero for initial delay time number of samples
78 		for(size_t t=0;t<tapCount;t++)
79 			delays[t].setDelayTime((unsigned)tapTimes[t]);
80 	}
81 
~CDSPDelayEffect()82 	virtual ~CDSPDelayEffect()
83 	{
84 		delete [] delays;
85 	}
86 
processSample(const mix_sample_t inputSample)87 	const mix_sample_t processSample(const mix_sample_t inputSample)
88 	{
89 		mix_sample_t fedbackSample=inputSample;
90 		mix_sample_t outputSample=inputSample;
91 
92 		int k=tapCount-1;
93 
94 		// start at the last tap and propogate backwards (in the diagram)
95 		const mix_sample_t s=delays[k].getSample();
96 		outputSample+=(mix_sample_t)(s*tapGains[k]);
97 		fedbackSample+=(mix_sample_t)(s*tapFeedbacks[k]);
98 		k--;
99 
100 		for(;k>=0;k--)
101 		{
102 			const mix_sample_t s=delays[k].getSample();
103 			outputSample+=(mix_sample_t)(s*tapGains[k]);
104 			fedbackSample+=(mix_sample_t)(s*tapFeedbacks[k]);
105 			delays[k+1].putSample(s);
106 		}
107 
108 		// write to delay
109 		delays[0].putSample(fedbackSample);
110 
111 		return(outputSample);
112 	}
113 
114 private:
115 	const size_t tapCount;
116 
117 	const float *tapTimes; // in samples
118 	const float *tapGains; // ??? change to unsigned
119 	const float *tapFeedbacks;
120 
121 	TDSPDelay<mix_sample_t> *delays;
122 };
123 
124 #endif
125