/[svn]/linuxsampler/trunk/src/engines/gig/Synthesizer.h
ViewVC logotype

Contents of /linuxsampler/trunk/src/engines/gig/Synthesizer.h

Parent Directory Parent Directory | Revision Log Revision Log


Revision 877 - (show annotations) (download) (as text)
Sun Jun 25 13:54:17 2006 UTC (17 years, 10 months ago) by persson
File MIME type: text/x-c++hdr
File size: 15332 byte(s)
* new filter implementation, which is more accurate and supports all
  filter types including bandreject and lowpass turbo

1 /***************************************************************************
2 * *
3 * LinuxSampler - modular, streaming capable sampler *
4 * *
5 * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 * Copyright (C) 2005 Christian Schoenebeck *
7 * *
8 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (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 *
16 * GNU General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program; if not, write to the Free Software *
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
21 * MA 02111-1307 USA *
22 ***************************************************************************/
23
24 #ifndef __LS_GIG_SYNTHESIZER_H__
25 #define __LS_GIG_SYNTHESIZER_H__
26
27 #include "../../common/global.h"
28 #include "../../common/RTMath.h"
29 #include "../common/Resampler.h"
30 #include "Filter.h"
31 #include "SynthesisParam.h"
32
33 #define SYNTHESIS_MODE_SET_INTERPOLATE(iMode,bVal) if (bVal) iMode |= 0x01; else iMode &= ~0x01 /* (un)set mode bit 0 */
34 #define SYNTHESIS_MODE_SET_FILTER(iMode,bVal) if (bVal) iMode |= 0x02; else iMode &= ~0x02 /* (un)set mode bit 1 */
35 #define SYNTHESIS_MODE_SET_LOOP(iMode,bVal) if (bVal) iMode |= 0x04; else iMode &= ~0x04 /* (un)set mode bit 2 */
36 #define SYNTHESIS_MODE_SET_CHANNELS(iMode,bVal) if (bVal) iMode |= 0x08; else iMode &= ~0x08 /* (un)set mode bit 3 */
37 #define SYNTHESIS_MODE_SET_IMPLEMENTATION(iMode,bVal) if (bVal) iMode |= 0x10; else iMode &= ~0x10 /* (un)set mode bit 4 */
38 #define SYNTHESIS_MODE_SET_PROFILING(iMode,bVal) if (bVal) iMode |= 0x20; else iMode &= ~0x20 /* (un)set mode bit 5 */
39
40 #define SYNTHESIS_MODE_GET_INTERPOLATE(iMode) iMode & 0x01
41 #define SYNTHESIS_MODE_GET_FILTER(iMode) iMode & 0x02
42 #define SYNTHESIS_MODE_GET_LOOP(iMode) iMode & 0x04
43 #define SYNTHESIS_MODE_GET_CHANNELS(iMode) iMode & 0x08
44 #define SYNTHESIS_MODE_GET_IMPLEMENTATION(iMode) iMode & 0x10
45
46 namespace LinuxSampler { namespace gig {
47
48 typedef void SynthesizeFragment_Fn(SynthesisParam* pFinalParam, Loop* pLoop);
49
50 void* GetSynthesisFunction(const int SynthesisMode);
51 void RunSynthesisFunction(const int SynthesisMode, SynthesisParam* pFinalParam, Loop* pLoop);
52
53 enum channels_t {
54 MONO,
55 STEREO
56 };
57
58 /** @brief Main Synthesis algorithms for the gig::Engine
59 *
60 * Implementation of the main synthesis algorithms of the Gigasampler
61 * format capable sampler engine. This means resampling / interpolation
62 * for pitching the audio signal, looping, filter and amplification.
63 */
64 template<channels_t CHANNELS, bool DOLOOP, bool USEFILTER, bool INTERPOLATE>
65 class Synthesizer : public __RTMath<CPP>, public LinuxSampler::Resampler<INTERPOLATE> {
66
67 // declarations of derived functions (see "Name lookup,
68 // templates, and accessing members of base classes" in
69 // the gcc manual for an explanation of why this is
70 // needed).
71 //using LinuxSampler::Resampler<INTERPOLATE>::GetNextSampleMonoCPP;
72 //using LinuxSampler::Resampler<INTERPOLATE>::GetNextSampleStereoCPP;
73 using LinuxSampler::Resampler<INTERPOLATE>::Interpolate1StepMonoCPP;
74 using LinuxSampler::Resampler<INTERPOLATE>::Interpolate1StepStereoCPP;
75
76 public:
77 //protected:
78
79 static void SynthesizeSubFragment(SynthesisParam* pFinalParam, Loop* pLoop) {
80 if (DOLOOP) {
81 const float fLoopEnd = Float(pLoop->uiEnd);
82 const float fLoopStart = Float(pLoop->uiStart);
83 const float fLoopSize = Float(pLoop->uiSize);
84 if (pLoop->uiTotalCycles) {
85 // render loop (loop count limited)
86 for (; pFinalParam->uiToGo > 0 && pLoop->uiCyclesLeft; pLoop->uiCyclesLeft -= WrapLoop(fLoopStart, fLoopSize, fLoopEnd, &pFinalParam->dPos)) {
87 const uint uiToGo = Min(pFinalParam->uiToGo, DiffToLoopEnd(fLoopEnd, &pFinalParam->dPos, pFinalParam->fFinalPitch) + 1); //TODO: instead of +1 we could also round up
88 SynthesizeSubSubFragment(pFinalParam, uiToGo);
89 }
90 // render on without loop
91 SynthesizeSubSubFragment(pFinalParam, pFinalParam->uiToGo);
92 } else { // render loop (endless loop)
93 for (; pFinalParam->uiToGo > 0; WrapLoop(fLoopStart, fLoopSize, fLoopEnd, &pFinalParam->dPos)) {
94 const uint uiToGo = Min(pFinalParam->uiToGo, DiffToLoopEnd(fLoopEnd, &pFinalParam->dPos, pFinalParam->fFinalPitch) + 1); //TODO: instead of +1 we could also round up
95 SynthesizeSubSubFragment(pFinalParam, uiToGo);
96 }
97 }
98 } else { // no looping
99 SynthesizeSubSubFragment(pFinalParam, pFinalParam->uiToGo);
100 }
101 }
102
103 /**
104 * Returns the difference to the sample's loop end.
105 */
106 inline static int DiffToLoopEnd(const float& LoopEnd, const void* Pos, const float& Pitch) {
107 return uint((LoopEnd - *((double *)Pos)) / Pitch);
108 }
109
110 #if 0
111 //TODO: this method is not in use yet, it's intended to be used for pitch=x.0f where we could use integer instead of float as playback position variable
112 inline static int WrapLoop(const int& LoopStart, const int& LoopSize, const int& LoopEnd, int& Pos) {
113 //TODO: we can easily eliminate the branch here
114 if (Pos < LoopEnd) return 0;
115 Pos = (Pos - LoopEnd) % LoopSize + LoopStart;
116 return 1;
117 }
118 #endif
119
120 /**
121 * This method handles looping of the RAM playback part of the
122 * sample, thus repositioning the playback position once the
123 * loop limit was reached. Note: looping of the disk streaming
124 * part is handled by libgig (ReadAndLoop() method which will
125 * be called by the DiskThread).
126 */
127 inline static int WrapLoop(const float& LoopStart, const float& LoopSize, const float& LoopEnd, void* vPos) {
128 double * Pos = (double *)vPos;
129 if (*Pos < LoopEnd) return 0;
130 *Pos = fmod(*Pos - LoopEnd, LoopSize) + LoopStart;
131 return 1;
132 }
133
134 static void SynthesizeSubSubFragment(SynthesisParam* pFinalParam, uint uiToGo) {
135 float fVolumeL = pFinalParam->fFinalVolumeLeft;
136 float fVolumeR = pFinalParam->fFinalVolumeRight;
137 sample_t* pSrc = pFinalParam->pSrc;
138 float* pOutL = pFinalParam->pOutLeft;
139 float* pOutR = pFinalParam->pOutRight;
140 #ifdef CONFIG_INTERPOLATE_VOLUME
141 float fDeltaL = pFinalParam->fFinalVolumeDeltaLeft;
142 float fDeltaR = pFinalParam->fFinalVolumeDeltaRight;
143 #endif
144 switch (CHANNELS) {
145 case MONO: {
146 float samplePoint;
147 if (INTERPOLATE) {
148 double dPos = pFinalParam->dPos;
149 float fPitch = pFinalParam->fFinalPitch;
150 if (USEFILTER) {
151 Filter filterL = pFinalParam->filterLeft;
152 for (int i = 0; i < uiToGo; ++i) {
153 samplePoint = Interpolate1StepMonoCPP(pSrc, &dPos, fPitch);
154 samplePoint = filterL.Apply(samplePoint);
155 #ifdef CONFIG_INTERPOLATE_VOLUME
156 fVolumeL += fDeltaL;
157 fVolumeR += fDeltaR;
158 #endif
159 pOutL[i] += samplePoint * fVolumeL;
160 pOutR[i] += samplePoint * fVolumeR;
161 }
162 } else { // no filter needed
163 for (int i = 0; i < uiToGo; ++i) {
164 samplePoint = Interpolate1StepMonoCPP(pSrc, &dPos, fPitch);
165 #ifdef CONFIG_INTERPOLATE_VOLUME
166 fVolumeL += fDeltaL;
167 fVolumeR += fDeltaR;
168 #endif
169 pOutL[i] += samplePoint * fVolumeL;
170 pOutR[i] += samplePoint * fVolumeR;
171 }
172 }
173 pFinalParam->dPos = dPos;
174 } else { // no interpolation
175 int pos_offset = (int) pFinalParam->dPos;
176 if (USEFILTER) {
177 Filter filterL = pFinalParam->filterLeft;
178 for (int i = 0; i < uiToGo; ++i) {
179 samplePoint = pSrc[i + pos_offset];
180 samplePoint = filterL.Apply(samplePoint);
181 #ifdef CONFIG_INTERPOLATE_VOLUME
182 fVolumeL += fDeltaL;
183 fVolumeR += fDeltaR;
184 #endif
185 pOutL[i] += samplePoint * fVolumeL;
186 pOutR[i] += samplePoint * fVolumeR;
187 }
188 } else { // no filter needed
189 for (int i = 0; i < uiToGo; ++i) {
190 samplePoint = pSrc[i + pos_offset];
191 #ifdef CONFIG_INTERPOLATE_VOLUME
192 fVolumeL += fDeltaL;
193 fVolumeR += fDeltaR;
194 #endif
195 pOutL[i] += samplePoint * fVolumeL;
196 pOutR[i] += samplePoint * fVolumeR;
197 }
198 }
199 pFinalParam->dPos += uiToGo;
200 }
201 break;
202 }
203 case STEREO: {
204 stereo_sample_t samplePoint;
205 if (INTERPOLATE) {
206 double dPos = pFinalParam->dPos;
207 float fPitch = pFinalParam->fFinalPitch;
208 if (USEFILTER) {
209 Filter filterL = pFinalParam->filterLeft;
210 Filter filterR = pFinalParam->filterRight;
211 for (int i = 0; i < uiToGo; ++i) {
212 samplePoint = Interpolate1StepStereoCPP(pSrc, &dPos, fPitch);
213 samplePoint.left = filterL.Apply(samplePoint.left);
214 samplePoint.right = filterR.Apply(samplePoint.right);
215 #ifdef CONFIG_INTERPOLATE_VOLUME
216 fVolumeL += fDeltaL;
217 fVolumeR += fDeltaR;
218 #endif
219 pOutL[i] += samplePoint.left * fVolumeL;
220 pOutR[i] += samplePoint.right * fVolumeR;
221 }
222 } else { // no filter needed
223 for (int i = 0; i < uiToGo; ++i) {
224 samplePoint = Interpolate1StepStereoCPP(pSrc, &dPos, fPitch);
225 #ifdef CONFIG_INTERPOLATE_VOLUME
226 fVolumeL += fDeltaL;
227 fVolumeR += fDeltaR;
228 #endif
229 pOutL[i] += samplePoint.left * fVolumeL;
230 pOutR[i] += samplePoint.right * fVolumeR;
231 }
232 }
233 pFinalParam->dPos = dPos;
234 } else { // no interpolation
235 int pos_offset = ((int) pFinalParam->dPos) << 1;
236 if (USEFILTER) {
237 Filter filterL = pFinalParam->filterLeft;
238 Filter filterR = pFinalParam->filterRight;
239 for (int i = 0, ii = 0; i < uiToGo; ++i, ii+=2) {
240 samplePoint.left = pSrc[ii + pos_offset];
241 samplePoint.right = pSrc[ii + pos_offset + 1];
242 samplePoint.left = filterL.Apply(samplePoint.left);
243 samplePoint.right = filterR.Apply(samplePoint.right);
244 #ifdef CONFIG_INTERPOLATE_VOLUME
245 fVolumeL += fDeltaL;
246 fVolumeR += fDeltaR;
247 #endif
248 pOutL[i] += samplePoint.left * fVolumeL;
249 pOutR[i] += samplePoint.right * fVolumeR;
250 }
251 } else { // no filter needed
252 for (int i = 0, ii = 0; i < uiToGo; ++i, ii+=2) {
253 samplePoint.left = pSrc[ii + pos_offset];
254 samplePoint.right = pSrc[ii + pos_offset + 1];
255 #ifdef CONFIG_INTERPOLATE_VOLUME
256 fVolumeL += fDeltaL;
257 fVolumeR += fDeltaR;
258 #endif
259 pOutL[i] += samplePoint.left * fVolumeL;
260 pOutR[i] += samplePoint.right * fVolumeR;
261 }
262 }
263 pFinalParam->dPos += uiToGo;
264 }
265 break;
266 }
267 }
268 pFinalParam->fFinalVolumeLeft = fVolumeL;
269 pFinalParam->fFinalVolumeRight = fVolumeR;
270 pFinalParam->pOutRight += uiToGo;
271 pFinalParam->pOutLeft += uiToGo;
272 pFinalParam->uiToGo -= uiToGo;
273 }
274 };
275
276 }} // namespace LinuxSampler::gig
277
278 #endif // __LS_GIG_SYNTHESIZER_H__

  ViewVC Help
Powered by ViewVC