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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3034 - (hide annotations) (download) (as text)
Mon Oct 31 00:05:00 2016 UTC (7 years, 5 months ago) by schoenebeck
File MIME type: text/x-c++hdr
File size: 16607 byte(s)
* Fixed a bunch of minor issues (mostly compiler warnings).
* Bumped version (2.0.0.svn31).

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

  ViewVC Help
Powered by ViewVC