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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 320 by schoenebeck, Mon Dec 13 00:53:16 2004 UTC revision 497 by persson, Sun Apr 10 11:55:44 2005 UTC
# Line 3  Line 3 
3   *   LinuxSampler - modular, streaming capable sampler                     *   *   LinuxSampler - modular, streaming capable sampler                     *
4   *                                                                         *   *                                                                         *
5   *   Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck   *   *   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  *   *   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  *   *   it under the terms of the GNU General Public License as published by  *
# Line 23  Line 24 
24  #ifndef __LS_GIG_SYNTHESIZER_H__  #ifndef __LS_GIG_SYNTHESIZER_H__
25  #define __LS_GIG_SYNTHESIZER_H__  #define __LS_GIG_SYNTHESIZER_H__
26    
27    #include "../../common/global.h"
28  #include "../../common/RTMath.h"  #include "../../common/RTMath.h"
29  #include "../common/Resampler.h"  #include "../common/Resampler.h"
30  #include "../common/BiquadFilter.h"  #include "../common/BiquadFilter.h"
31  #include "Filter.h"  #include "Filter.h"
32  #include "Voice.h"  #include "Voice.h"
33    
34  #define SYNTHESIS_MODE_SET_CONSTPITCH(iMode,bVal)       if (bVal) iMode |= 0x01; else iMode &= 0xfe   /* (un)set mode bit 0 */  #define SYNTHESIS_MODE_SET_CONSTPITCH(iMode,bVal)       if (bVal) iMode |= 0x01; else iMode &= ~0x01   /* (un)set mode bit 0 */
35  #define SYNTHESIS_MODE_SET_LOOP(iMode,bVal)             if (bVal) iMode |= 0x02; else iMode &= 0xfd   /* (un)set mode bit 1 */  #define SYNTHESIS_MODE_SET_LOOP(iMode,bVal)             if (bVal) iMode |= 0x02; else iMode &= ~0x02   /* (un)set mode bit 1 */
36  #define SYNTHESIS_MODE_SET_INTERPOLATE(iMode,bVal)      if (bVal) iMode |= 0x04; else iMode &= 0xfb   /* (un)set mode bit 2 */  #define SYNTHESIS_MODE_SET_INTERPOLATE(iMode,bVal)      if (bVal) iMode |= 0x04; else iMode &= ~0x04   /* (un)set mode bit 2 */
37  #define SYNTHESIS_MODE_SET_FILTER(iMode,bVal)           if (bVal) iMode |= 0x08; else iMode &= 0xf7   /* (un)set mode bit 3 */  #define SYNTHESIS_MODE_SET_FILTER(iMode,bVal)           if (bVal) iMode |= 0x08; else iMode &= ~0x08   /* (un)set mode bit 3 */
38  #define SYNTHESIS_MODE_SET_CHANNELS(iMode,bVal)         if (bVal) iMode |= 0x10; else iMode &= 0xef   /* (un)set mode bit 4 */  #define SYNTHESIS_MODE_SET_CHANNELS(iMode,bVal)         if (bVal) iMode |= 0x10; else iMode &= ~0x10   /* (un)set mode bit 4 */
39  #define SYNTHESIS_MODE_SET_IMPLEMENTATION(iMode,bVal)   if (bVal) iMode |= 0x20; else iMode &= 0xdf   /* (un)set mode bit 5 */  #define SYNTHESIS_MODE_SET_IMPLEMENTATION(iMode,bVal)   if (bVal) iMode |= 0x20; else iMode &= ~0x20   /* (un)set mode bit 5 */
40    #define SYNTHESIS_MODE_SET_PROFILING(iMode,bVal)        if (bVal) iMode |= 0x40; else iMode &= ~0x40   /* (un)set mode bit 6 */
41    
42  #define SYNTHESIS_MODE_GET_CONSTPITCH(iMode)            iMode & 0x01  #define SYNTHESIS_MODE_GET_CONSTPITCH(iMode)            iMode & 0x01
43  #define SYNTHESIS_MODE_GET_LOOP(iMode)                  iMode & 0x02  #define SYNTHESIS_MODE_GET_LOOP(iMode)                  iMode & 0x02
# Line 52  Line 55 
55    
56  namespace LinuxSampler { namespace gig {  namespace LinuxSampler { namespace gig {
57    
58      typedef void SynthesizeFragment_Fn(VOICE&, uint, sample_t*, int);      typedef void SynthesizeFragment_Fn(VOICE&, uint, sample_t*, uint);
59    
60      void* GetSynthesisFunction(const int SynthesisMode);      void* GetSynthesisFunction(const int SynthesisMode);
61        void RunSynthesisFunction(const int SynthesisMode, VOICE& voice, uint Samples, sample_t* pSrc, uint Skip);
62    
63      enum channels_t {      enum channels_t {
64          MONO,          MONO,
# Line 63  namespace LinuxSampler { namespace gig { Line 67  namespace LinuxSampler { namespace gig {
67    
68      template<implementation_t IMPLEMENTATION, channels_t CHANNELS, bool USEFILTER, bool INTERPOLATE, bool DOLOOP, bool CONSTPITCH>      template<implementation_t IMPLEMENTATION, channels_t CHANNELS, bool USEFILTER, bool INTERPOLATE, bool DOLOOP, bool CONSTPITCH>
69      class Synthesizer : public __RTMath<IMPLEMENTATION>, public LinuxSampler::Resampler<INTERPOLATE> {      class Synthesizer : public __RTMath<IMPLEMENTATION>, public LinuxSampler::Resampler<INTERPOLATE> {
70    
71                // declarations of derived functions (see "Name lookup,
72                // templates, and accessing members of base classes" in
73                // the gcc manual for an explanation of why this is
74                // needed).
75                using __RTMath<IMPLEMENTATION>::Mul;
76                using __RTMath<IMPLEMENTATION>::Float;
77                using LinuxSampler::Resampler<INTERPOLATE>::GetNextSampleMonoCPP;
78                using LinuxSampler::Resampler<INTERPOLATE>::GetNextSampleStereoCPP;
79    #if ARCH_X86
80                using LinuxSampler::Resampler<INTERPOLATE>::GetNext4SamplesMonoMMXSSE;
81                using LinuxSampler::Resampler<INTERPOLATE>::GetNext4SamplesStereoMMXSSE;
82    #endif
83    
84          public:          public:
85              template<typename VOICE_T>              template<typename VOICE_T>
86              inline static void SynthesizeFragment(VOICE_T& Voice, uint Samples, sample_t* pSrc, int& i) {              inline static void SynthesizeFragment(VOICE_T& Voice, uint Samples, sample_t* pSrc, uint i) {
87                    const float panLeft  = Mul(Voice.PanLeft,  Voice.pEngineChannel->GlobalPanLeft);
88                    const float panRight = Mul(Voice.PanRight, Voice.pEngineChannel->GlobalPanRight);
89                  if (IMPLEMENTATION == ASM_X86_MMX_SSE) {                  if (IMPLEMENTATION == ASM_X86_MMX_SSE) {
90                      float fPos = (float) Voice.Pos;                      float fPos = (float) Voice.Pos;
91                      SynthesizeFragment(Voice, Samples, pSrc, i, Voice.pSample->LoopPlayCount,                      SynthesizeFragment(Voice, Samples, pSrc, i, Voice.pSample->LoopPlayCount,
# Line 75  namespace LinuxSampler { namespace gig { Line 95  namespace LinuxSampler { namespace gig {
95                                         Voice.LoopCyclesLeft,                                         Voice.LoopCyclesLeft,
96                                         (void *)&fPos,                                         (void *)&fPos,
97                                         Voice.PitchBase,                                         Voice.PitchBase,
98                                         Voice.PitchBend);                                         Voice.PitchBend,
99                                           &panLeft, &panRight);
100                        #if  ARCH_X86
101                      if (INTERPOLATE) EMMS;                      if (INTERPOLATE) EMMS;
102                        #endif
103                      Voice.Pos = (double) fPos;                      Voice.Pos = (double) fPos;
104                  } else {                  } else {
105                      SynthesizeFragment(Voice, Samples, pSrc, i, Voice.pSample->LoopPlayCount,                      SynthesizeFragment(Voice, Samples, pSrc, i, Voice.pSample->LoopPlayCount,
# Line 86  namespace LinuxSampler { namespace gig { Line 109  namespace LinuxSampler { namespace gig {
109                                         Voice.LoopCyclesLeft,                                         Voice.LoopCyclesLeft,
110                                         (void *)&Voice.Pos,                                         (void *)&Voice.Pos,
111                                         Voice.PitchBase,                                         Voice.PitchBase,
112                                         Voice.PitchBend);                                         Voice.PitchBend,
113                                           &panLeft, &panRight);
114                  }                  }
115              }              }
116    
117          //protected:          //protected:
118    
119              template<typename VOICE_T>              template<typename VOICE_T>
120              inline static void SynthesizeFragment(VOICE_T& Voice, uint Samples, sample_t* pSrc, int& i, uint& LoopPlayCount, uint LoopStart, uint LoopEnd, uint LoopSize, uint& LoopCyclesLeft, void* Pos, float& PitchBase, float& PitchBend) {              inline static void SynthesizeFragment(VOICE_T& Voice, uint Samples, sample_t* pSrc, uint& i, uint& LoopPlayCount, uint LoopStart, uint LoopEnd, uint LoopSize, uint& LoopCyclesLeft, void* Pos, float& PitchBase, float& PitchBend, const float* PanLeft, const float* PanRight) {
121                  const float loopEnd = Float(LoopEnd);                  const float loopEnd = Float(LoopEnd);
122                  const float PBbyPB = Mul(PitchBase, PitchBend);                  const float PBbyPB = Mul(PitchBase, PitchBend);
123                  const float f_LoopStart = Float(LoopStart);                  const float f_LoopStart = Float(LoopStart);
# Line 103  namespace LinuxSampler { namespace gig { Line 127  namespace LinuxSampler { namespace gig {
127                          // render loop (loop count limited)                          // render loop (loop count limited)
128                          while (i < Samples && LoopCyclesLeft) {                          while (i < Samples && LoopCyclesLeft) {
129                              if (CONSTPITCH) {                              if (CONSTPITCH) {
130                                  const int processEnd = Min(Samples, i + DiffToLoopEnd(loopEnd,Pos, PBbyPB) + 1); //TODO: instead of +1 we could also round up                                  const uint processEnd = Min(Samples, i + DiffToLoopEnd(loopEnd,Pos, PBbyPB) + 1); //TODO: instead of +1 we could also round up
131                                  while (i < processEnd) Synthesize(Voice, Pos, pSrc, i);                                  while (i < processEnd) Synthesize(Voice, Pos, pSrc, i, PanLeft, PanRight);
132                              }                              }
133                              else Synthesize(Voice, Pos, pSrc, i);                              else Synthesize(Voice, Pos, pSrc, i, PanLeft, PanRight);
134                              if (WrapLoop(f_LoopStart, f_LoopSize, loopEnd, Pos)) LoopCyclesLeft--;                              if (WrapLoop(f_LoopStart, f_LoopSize, loopEnd, Pos)) LoopCyclesLeft--;
135                          }                          }
136                          // render on without loop                          // render on without loop
137                          while (i < Samples) Synthesize(Voice, Pos, pSrc, i);                          while (i < Samples) Synthesize(Voice, Pos, pSrc, i, PanLeft, PanRight);
138                      }                      }
139                      else { // render loop (endless loop)                      else { // render loop (endless loop)
140                          while (i < Samples) {                          while (i < Samples) {
141                              if (CONSTPITCH) {                              if (CONSTPITCH) {
142                                  const int processEnd = Min(Samples, i + DiffToLoopEnd(loopEnd, Pos, PBbyPB) + 1); //TODO: instead of +1 we could also round up                                  const uint processEnd = Min(Samples, i + DiffToLoopEnd(loopEnd, Pos, PBbyPB) + 1); //TODO: instead of +1 we could also round up
143                                  while (i < processEnd) Synthesize(Voice, Pos, pSrc, i);                                  while (i < processEnd) Synthesize(Voice, Pos, pSrc, i, PanLeft, PanRight);
144                              }                              }
145                              else Synthesize(Voice, Pos, pSrc, i);                              else Synthesize(Voice, Pos, pSrc, i, PanLeft, PanRight);
146                              WrapLoop(f_LoopStart, f_LoopSize, loopEnd, Pos);                              WrapLoop(f_LoopStart, f_LoopSize, loopEnd, Pos);
147                          }                          }
148                      }                      }
149                  }                  }
150                  else { // no looping                  else { // no looping
151                      while (i < Samples) { Synthesize(Voice, Pos, pSrc, i);}                      while (i < Samples) { Synthesize(Voice, Pos, pSrc, i, PanLeft, PanRight);}
152                  }                  }
153              }              }
154    
155              template<typename VOICE_T>              template<typename VOICE_T>
156              inline static void Synthesize(VOICE_T& Voice, void* Pos, sample_t* pSrc, int& i) {              inline static void Synthesize(VOICE_T& Voice, void* Pos, sample_t* pSrc, uint& i, const float* PanLeft, const float* PanRight) {
157                  Synthesize(pSrc, Pos,                  Synthesize(pSrc, Pos,
158                             Voice.pEngine->pSynthesisParameters[Event::destination_vco][i],                             Voice.pEngine->pSynthesisParameters[Event::destination_vco][i],
159                             Voice.pEngine->pOutputLeft,                             Voice.pEngineChannel->pOutputLeft,
160                             Voice.pEngine->pOutputRight,                             Voice.pEngineChannel->pOutputRight,
161                             i,                             i,
162                             Voice.pEngine->pSynthesisParameters[Event::destination_vca],                             Voice.pEngine->pSynthesisParameters[Event::destination_vca],
163                             &Voice.PanLeft,                             PanLeft,
164                             &Voice.PanRight,                             PanRight,
165                             Voice.FilterLeft,                             Voice.FilterLeft,
166                             Voice.FilterRight,                             Voice.FilterRight,
167                             Voice.pEngine->pBasicFilterParameters[i],                             Voice.pEngine->pBasicFilterParameters[i],
# Line 148  namespace LinuxSampler { namespace gig { Line 172  namespace LinuxSampler { namespace gig {
172                  switch (IMPLEMENTATION) {                  switch (IMPLEMENTATION) {
173                      // pure C++ implementation (thus platform independent)                      // pure C++ implementation (thus platform independent)
174                      case CPP: {                      case CPP: {
175                          return int((LoopEnd - *((double *)Pos)) / Pitch);                          return uint((LoopEnd - *((double *)Pos)) / Pitch);
176                      }                      }
177                        #if ARCH_X86
178                      case ASM_X86_MMX_SSE: {                      case ASM_X86_MMX_SSE: {
179                          int result;                          int result;
180                          __asm__ __volatile__ (                          __asm__ __volatile__ (
# Line 164  namespace LinuxSampler { namespace gig { Line 189  namespace LinuxSampler { namespace gig {
189                          );                          );
190                          return result;                          return result;
191                      }                      }
192                        #endif // ARCH_X86
193                  }                  }
194              }              }
195    
# Line 176  namespace LinuxSampler { namespace gig { Line 202  namespace LinuxSampler { namespace gig {
202                          *Pos = fmod(*Pos - LoopEnd, LoopSize) + LoopStart;                          *Pos = fmod(*Pos - LoopEnd, LoopSize) + LoopStart;
203                          return 1;                          return 1;
204                      }                      }
205                        #if ARCH_X86
206                      case ASM_X86_MMX_SSE: {                      case ASM_X86_MMX_SSE: {
207                          int result;                          int result = 0;
208                          __asm__ __volatile__ (                          __asm__ __volatile__ (
209                              "movss  (%2), %%xmm0          # load LoopEnd\n\t"                              "movss  (%2), %%xmm0          # load LoopEnd\n\t"
210                              "movss  (%1), %%xmm1          # load Pos\n\t"                              "movss  (%1), %%xmm1          # load Pos\n\t"
211                              "comiss %%xmm0, %%xmm1      # LoopEnd <> Pos\n\t"                              "comiss %%xmm0, %%xmm1      # LoopEnd <> Pos\n\t"
                             "movl    $0,%%eax            # result = 0\n\t"  
212                              "jb     1f                  # jump if no work needs to be done\n\t"                              "jb     1f                  # jump if no work needs to be done\n\t"
213                              "movss    (%3), %%xmm2        # load LoopSize\n\t"                              "movss    (%3), %%xmm2        # load LoopSize\n\t"
214                              "subss    %%xmm0, %%xmm1    # Pos - LoopEnd\n\t"                              "subss    %%xmm0, %%xmm1    # Pos - LoopEnd\n\t"
# Line 197  namespace LinuxSampler { namespace gig { Line 223  namespace LinuxSampler { namespace gig {
223                              //done with fmodf                              //done with fmodf
224                              "addss    %%xmm0, %%xmm3      # add LoopStart\n\t"                              "addss    %%xmm0, %%xmm3      # add LoopStart\n\t"
225                              "movss    %%xmm3, (%1)        # update Pos\n\t"                              "movss    %%xmm3, (%1)        # update Pos\n\t"
226                              "movl    $1,%%eax            # result = 1\n\t"                              "movl    $1, (%0)             # result = 1\n\t"
227                              ".balign 16 \n\t"                              ".balign 16 \n\t"
228                              "1:\n\t"                              "1:\n\t"
229                              : "=a" (result)     /* %0 */                              :: "r" (&result),   /* %0 */
230                              : "r"  (vPos),      /* %1 */                                "r"  (vPos),      /* %1 */
231                                "r"  (&LoopEnd),  /* %2 */                                "r"  (&LoopEnd),  /* %2 */
232                                "r"  (&LoopSize), /* %3 */                                "r"  (&LoopSize), /* %3 */
233                                "r"  (&LoopStart) /* %4 */                                "r"  (&LoopStart) /* %4 */
234                          );                          );
235                          return result;                          return result;
236                      }                      }
237                        #endif // ARCH_X86
238                  }                  }
239              }              }
240    
241              inline static void Synthesize(sample_t* pSrc, void* Pos, float& Pitch, float* pOutL, float* pOutR, int& i, float* Volume, float* PanL, float* PanR, Filter& FilterL, Filter& FilterR, biquad_param_t& bqBase, biquad_param_t& bqMain) {              inline static void Synthesize(sample_t* pSrc, void* Pos, float& Pitch, float* pOutL, float* pOutR, uint& i, float* Volume, const float* PanL, const float* PanR, Filter& FilterL, Filter& FilterR, biquad_param_t& bqBase, biquad_param_t& bqMain) {
242                  switch (IMPLEMENTATION) {                  switch (IMPLEMENTATION) {
243                      // pure C++ implementation (thus platform independent)                      // pure C++ implementation (thus platform independent)
244                      case CPP: {                      case CPP: {
# Line 238  namespace LinuxSampler { namespace gig { Line 265  namespace LinuxSampler { namespace gig {
265                          }                          }
266                          break;                          break;
267                      }                      }
268                        #if ARCH_X86
269                      // Assembly optimization using the MMX & SSE(1) instruction set (thus only for x86)                      // Assembly optimization using the MMX & SSE(1) instruction set (thus only for x86)
270                      case ASM_X86_MMX_SSE: {                      case ASM_X86_MMX_SSE: {
271                          const int ii = i & 0xfffffffc;                          const int ii = i & 0xfffffffc;
# Line 323  namespace LinuxSampler { namespace gig { Line 351  namespace LinuxSampler { namespace gig {
351                                "r" (&pOutR[ii])  /* %1 - must be 16 byte aligned ! */                                "r" (&pOutR[ii])  /* %1 - must be 16 byte aligned ! */
352                          );                          );
353                      }                      }
354                        #endif // ARCH_X86
355                  }                  }
356              }              }
357      };      };

Legend:
Removed from v.320  
changed lines
  Added in v.497

  ViewVC Help
Powered by ViewVC