/[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 497 by persson, Sun Apr 10 11:55:44 2005 UTC revision 685 by persson, Tue Jul 5 19:30:37 2005 UTC
# Line 65  namespace LinuxSampler { namespace gig { Line 65  namespace LinuxSampler { namespace gig {
65          STEREO          STEREO
66      };      };
67    
68        /** @brief Main Synthesis algorithms for the gig::Engine
69         *
70         * Implementation of the main synthesis algorithms of the Gigasampler
71         * format capable sampler engine. This means resampling / interpolation
72         * for pitching the audio signal, looping, filter and amplification.
73         */
74      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>
75      class Synthesizer : public __RTMath<IMPLEMENTATION>, public LinuxSampler::Resampler<INTERPOLATE> {      class Synthesizer : public __RTMath<IMPLEMENTATION>, public LinuxSampler::Resampler<INTERPOLATE> {
76    
# Line 76  namespace LinuxSampler { namespace gig { Line 82  namespace LinuxSampler { namespace gig {
82              using __RTMath<IMPLEMENTATION>::Float;              using __RTMath<IMPLEMENTATION>::Float;
83              using LinuxSampler::Resampler<INTERPOLATE>::GetNextSampleMonoCPP;              using LinuxSampler::Resampler<INTERPOLATE>::GetNextSampleMonoCPP;
84              using LinuxSampler::Resampler<INTERPOLATE>::GetNextSampleStereoCPP;              using LinuxSampler::Resampler<INTERPOLATE>::GetNextSampleStereoCPP;
85  #if ARCH_X86  #if CONFIG_ASM && ARCH_X86
86              using LinuxSampler::Resampler<INTERPOLATE>::GetNext4SamplesMonoMMXSSE;              using LinuxSampler::Resampler<INTERPOLATE>::GetNext4SamplesMonoMMXSSE;
87              using LinuxSampler::Resampler<INTERPOLATE>::GetNext4SamplesStereoMMXSSE;              using LinuxSampler::Resampler<INTERPOLATE>::GetNext4SamplesStereoMMXSSE;
88  #endif  #endif
89    
90          public:          public:
91                /**
92                 * Render audio for the current fragment for the given voice.
93                 * This is the toplevel method of this class.
94                 */            
95              template<typename VOICE_T>              template<typename VOICE_T>
96              inline static void SynthesizeFragment(VOICE_T& Voice, uint Samples, sample_t* pSrc, uint i) {              inline static void SynthesizeFragment(VOICE_T& Voice, uint Samples, sample_t* pSrc, uint i) {
97                  const float panLeft  = Mul(Voice.PanLeft,  Voice.pEngineChannel->GlobalPanLeft);                  const float panLeft  = Mul(Voice.PanLeft,  Voice.pEngineChannel->GlobalPanLeft);
# Line 97  namespace LinuxSampler { namespace gig { Line 107  namespace LinuxSampler { namespace gig {
107                                         Voice.PitchBase,                                         Voice.PitchBase,
108                                         Voice.PitchBend,                                         Voice.PitchBend,
109                                         &panLeft, &panRight);                                         &panLeft, &panRight);
110                      #if  ARCH_X86                      #if CONFIG_ASM && ARCH_X86
111                      if (INTERPOLATE) EMMS;                      if (INTERPOLATE) EMMS;
112                      #endif                      #endif
113                      Voice.Pos = (double) fPos;                      Voice.Pos = (double) fPos;
# Line 116  namespace LinuxSampler { namespace gig { Line 126  namespace LinuxSampler { namespace gig {
126    
127          //protected:          //protected:
128    
129                /**
130                 * Render audio for the current fragment for the given voice.
131                 * Will be called by the toplevel SynthesizeFragment() method.
132                 */  
133              template<typename VOICE_T>              template<typename VOICE_T>
134              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) {              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) {
135                  const float loopEnd = Float(LoopEnd);                  const float loopEnd = Float(LoopEnd);
# Line 152  namespace LinuxSampler { namespace gig { Line 166  namespace LinuxSampler { namespace gig {
166                  }                  }
167              }              }
168    
169                /**
170                 * Atomicly render a piece for the voice. For the C++
171                 * implementation this means rendering exactly one sample
172                 * point, whereas for the MMX/SSE implementation this means
173                 * rendering 4 sample points.
174                 */
175              template<typename VOICE_T>              template<typename VOICE_T>
176              inline static void Synthesize(VOICE_T& Voice, void* Pos, sample_t* pSrc, uint& i, const float* PanLeft, const float* PanRight) {              inline static void Synthesize(VOICE_T& Voice, void* Pos, sample_t* pSrc, uint& i, const float* PanLeft, const float* PanRight) {
177                  Synthesize(pSrc, Pos,                  Synthesize(pSrc, Pos,
# Line 168  namespace LinuxSampler { namespace gig { Line 188  namespace LinuxSampler { namespace gig {
188                             Voice.pEngine->pMainFilterParameters[i]);                             Voice.pEngine->pMainFilterParameters[i]);
189              }              }
190    
191                /**
192                 * Returns the difference to the sample's loop end.
193                 */
194              inline static int DiffToLoopEnd(const float& LoopEnd, const void* Pos, const float& Pitch) {              inline static int DiffToLoopEnd(const float& LoopEnd, const void* Pos, const float& Pitch) {
195                  switch (IMPLEMENTATION) {                  switch (IMPLEMENTATION) {
196                      // pure C++ implementation (thus platform independent)                      #if CONFIG_ASM && ARCH_X86
                     case CPP: {  
                         return uint((LoopEnd - *((double *)Pos)) / Pitch);  
                     }  
                     #if ARCH_X86  
197                      case ASM_X86_MMX_SSE: {                      case ASM_X86_MMX_SSE: {
198                          int result;                          int result;
199                          __asm__ __volatile__ (                          __asm__ __volatile__ (
# Line 189  namespace LinuxSampler { namespace gig { Line 208  namespace LinuxSampler { namespace gig {
208                          );                          );
209                          return result;                          return result;
210                      }                      }
211                      #endif // ARCH_X86                      #endif // CONFIG_ASM && ARCH_X86
212                        // pure C++ implementation (thus platform independent)
213                        default: {
214                            return uint((LoopEnd - *((double *)Pos)) / Pitch);
215                        }
216                  }                  }
217              }              }
218    
219                /**
220                 * This method handles looping of the RAM playback part of the
221                 * sample, thus repositioning the playback position once the
222                 * loop limit was reached. Note: looping of the disk streaming
223                 * part is handled by libgig (ReadAndLoop() method which will
224                 * be called by the DiskThread).
225                 */
226              inline static int WrapLoop(const float& LoopStart, const float& LoopSize, const float& LoopEnd, void* vPos) {              inline static int WrapLoop(const float& LoopStart, const float& LoopSize, const float& LoopEnd, void* vPos) {
227                  switch (IMPLEMENTATION) {                  switch (IMPLEMENTATION) {
228                      // pure C++ implementation (thus platform independent)                      #if CONFIG_ASM && ARCH_X86
                     case CPP: {  
                         double * Pos = (double *)vPos;  
                         if (*Pos < LoopEnd) return 0;  
                         *Pos = fmod(*Pos - LoopEnd, LoopSize) + LoopStart;  
                         return 1;  
                     }  
                     #if ARCH_X86  
229                      case ASM_X86_MMX_SSE: {                      case ASM_X86_MMX_SSE: {
230                          int result = 0;                          int result = 0;
231                          __asm__ __volatile__ (                          __asm__ __volatile__ (
# Line 215  namespace LinuxSampler { namespace gig { Line 238  namespace LinuxSampler { namespace gig {
238                              //now the fmodf                              //now the fmodf
239                              "movss    %%xmm1, %%xmm3    # xmm3 = (Pos - LoopEnd)\n\t"                              "movss    %%xmm1, %%xmm3    # xmm3 = (Pos - LoopEnd)\n\t"
240                              "divss    %%xmm2, %%xmm1    # (Pos - LoopEnd) / LoopSize\n\t"                              "divss    %%xmm2, %%xmm1    # (Pos - LoopEnd) / LoopSize\n\t"
241                              "cvttss2si %%xmm1, %%eax    # convert to int\n\t"                              "cvttss2si %%xmm1, %2    # convert to int\n\t"
242                              "cvtsi2ss  %%eax, %%xmm1    # convert back to float\n\t"                              "cvtsi2ss  %2, %%xmm1    # convert back to float\n\t"
243                              "movss    (%4), %%xmm0      # load LoopStart\n\t"                              "movss    (%4), %%xmm0      # load LoopStart\n\t"
244                              "mulss    %%xmm2, %%xmm1    # LoopSize * int((Pos-LoopEnd)/LoopSize)\n\t"                              "mulss    %%xmm2, %%xmm1    # LoopSize * int((Pos-LoopEnd)/LoopSize)\n\t"
245                              "subss    %%xmm1, %%xmm3    # xmm2 = fmodf(Pos - LoopEnd, LoopSize)\n\t"                              "subss    %%xmm1, %%xmm3    # xmm2 = fmodf(Pos - LoopEnd, LoopSize)\n\t"
# Line 234  namespace LinuxSampler { namespace gig { Line 257  namespace LinuxSampler { namespace gig {
257                          );                          );
258                          return result;                          return result;
259                      }                      }
260                      #endif // ARCH_X86                      #endif // CONFIG_ASM && ARCH_X86
261                        // pure C++ implementation (thus platform independent)
262                        default: {
263                            double * Pos = (double *)vPos;
264                            if (*Pos < LoopEnd) return 0;
265                            *Pos = fmod(*Pos - LoopEnd, LoopSize) + LoopStart;
266                            return 1;
267                        }
268                  }                  }
269              }              }
270    
271                /**
272                 * Atomicly render a piece for the voice. For the C++
273                 * implementation this means rendering exactly one sample
274                 * point, whereas for the MMX/SSE implementation this means
275                 * rendering 4 sample points.
276                 */
277              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) {              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) {
278                  switch (IMPLEMENTATION) {                  switch (IMPLEMENTATION) {
279                      // pure C++ implementation (thus platform independent)                      // pure C++ implementation (thus platform independent)
# Line 265  namespace LinuxSampler { namespace gig { Line 301  namespace LinuxSampler { namespace gig {
301                          }                          }
302                          break;                          break;
303                      }                      }
304                      #if ARCH_X86                      #if CONFIG_ASM && ARCH_X86
305                      // 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)
306                      case ASM_X86_MMX_SSE: {                      case ASM_X86_MMX_SSE: {
307                          const int ii = i & 0xfffffffc;                          const int ii = i & 0xfffffffc;
# Line 351  namespace LinuxSampler { namespace gig { Line 387  namespace LinuxSampler { namespace gig {
387                                "r" (&pOutR[ii])  /* %1 - must be 16 byte aligned ! */                                "r" (&pOutR[ii])  /* %1 - must be 16 byte aligned ! */
388                          );                          );
389                      }                      }
390                      #endif // ARCH_X86                      #endif // CONFIG_ASM && ARCH_X86
391                  }                  }
392              }              }
393      };      };

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

  ViewVC Help
Powered by ViewVC