/[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 866 - (show annotations) (download) (as text)
Thu May 25 14:39:45 2006 UTC (17 years, 10 months ago) by persson
File MIME type: text/x-c++hdr
File size: 15368 byte(s)
* gcc 4.1 compilation fix

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

  ViewVC Help
Powered by ViewVC