changeset 128:f6ceb8f4ad5c trunk

[svn] Optimized decoders, and custom resampler. We don't use these yet.
author nenolod
date Wed, 09 Nov 2005 16:42:39 -0800
parents 05d824e30afd
children ce9d4aa5889a
files Plugins/Input/mpg123/decode_i486.c Plugins/Input/mpg123/decode_ntom.c
diffstat 2 files changed, 532 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/mpg123/decode_i486.c	Wed Nov 09 16:42:39 2005 -0800
@@ -0,0 +1,250 @@
+/* 
+ * Subband Synthesis for MPEG Audio. 
+ *
+ * Version optimized for 80486 by using integer arithmetic,
+ * multiplications by shift and add, and by increasing locality in
+ * order to fit the 8KB L1 cache. This code should be compiled with gcc
+ * 2.7.2 or higher.
+ *
+ * Note: this version does not guaranty a good accuracy. The filter
+ * coefficients are quantified on 14 bits.
+ *
+ * (c) 1998 Fabrice Bellard 
+ *
+ * GPL clean
+ */
+
+#include <stdlib.h>
+
+#include "mpg123.h"
+
+#define FIR_SIZE 16
+
+#define FIR16_1(pos,c0,c1,c2,c3,c4,c5,c6,c7,c8,c9,c10,c11,c12,c13,c14,c15) \
+{\
+  int sum;\
+  sum=(c0)*b0[0]+(c1)*b0[1]+(c2)*b0[2]+(c3)*b0[3]+\
+  (c4)*b0[4]+(c5)*b0[5]+(c6)*b0[6]+(c7)*b0[7]+\
+  (c8)*b0[8]+(c9)*b0[9]+(c10)*b0[10]+(c11)*b0[11]+\
+  (c12)*b0[12]+(c13)*b0[13]+(c14)*b0[14]+(c15)*b0[15];\
+  sum=(sum+(1 << 13))>>14;\
+  if (sum<-32768) sum=-32768;\
+  else if (sum>32767) sum=32767;\
+  samples[2*(pos)]=sum;\
+  b0+=FIR_BUFFER_SIZE;\
+}
+
+#define FIR16_2(pos1,c0,c1,c2,c3,c4,c5,c6,c7,c8,c9,c10,c11,c12,c13,c14,c15,\
+              pos2,d0,d1,d2,d3,d4,d5,d6,d7,d8,d9,d10,d11,d12,d13,d14,d15) \
+{\
+  int sum1,sum2,v;\
+\
+  v=b0[0];\
+  sum1=(c0)*v;\
+  sum2=(d0)*v;\
+  v=b0[1];\
+  sum1+=(c1)*v;\
+  sum2+=(d1)*v;\
+  v=b0[2];\
+  sum1+=(c2)*v;\
+  sum2+=(d2)*v;\
+  v=b0[3];\
+  sum1+=(c3)*v;\
+  sum2+=(d3)*v;\
+  v=b0[4];\
+  sum1+=(c4)*v;\
+  sum2+=(d4)*v;\
+  v=b0[5];\
+  sum1+=(c5)*v;\
+  sum2+=(d5)*v;\
+  v=b0[6];\
+  sum1+=(c6)*v;\
+  sum2+=(d6)*v;\
+  v=b0[7];\
+  sum1+=(c7)*v;\
+  sum2+=(d7)*v;\
+  v=b0[8];\
+  sum1+=(c8)*v;\
+  sum2+=(d8)*v;\
+  v=b0[9];\
+  sum1+=(c9)*v;\
+  sum2+=(d9)*v;\
+  v=b0[10];\
+  sum1+=(c10)*v;\
+  sum2+=(d10)*v;\
+  v=b0[11];\
+  sum1+=(c11)*v;\
+  sum2+=(d11)*v;\
+  v=b0[12];\
+  sum1+=(c12)*v;\
+  sum2+=(d12)*v;\
+  v=b0[13];\
+  sum1+=(c13)*v;\
+  sum2+=(d13)*v;\
+  v=b0[14];\
+  sum1+=(c14)*v;\
+  sum2+=(d14)*v;\
+  v=b0[15];\
+  sum1+=(c15)*v;\
+  sum2+=(d15)*v;\
+\
+  sum1=(sum1+(1<<13))>>14;\
+  sum2=(sum2+(1<<13))>>14;\
+\
+  if (sum1<-32768) sum1=-32768;\
+  else if (sum1>32767) sum1=32767;\
+  samples[(pos1)*2]=sum1;\
+\
+  if (sum2<-32768) sum2=-32768;\
+  else if (sum2>32767) sum2=32767;\
+  samples[(pos2)*2]=sum2;\
+  b0+=FIR_BUFFER_SIZE;\
+}
+
+int synth_1to1_486(real *bandPtr,int channel,unsigned char *out,int nb_blocks)
+{
+  static int buffs[2][2][17*FIR_BUFFER_SIZE];
+  static int bo[2] = { FIR_SIZE-1, FIR_SIZE-1 };
+  short *samples = (short *) out;
+  int *b0,(*buf)[17*FIR_BUFFER_SIZE];
+  int clip = 0; 
+  int block,b,bo_start;
+
+  /* samples address */
+  samples+=channel;
+
+  bo_start=bo[channel];
+  buf = buffs[channel];
+
+  b=bo_start;
+  for(block=0;block<nb_blocks;block++) {
+
+    /* FIR offset */
+    b++;
+    if (b >= FIR_BUFFER_SIZE) {
+      int *p,*q;
+      int c,i,j;
+      
+      /* we shift the buffers */
+      for(c=0;c<2;c++) {
+        p=&buf[c][0]+1;
+        q=p+(FIR_BUFFER_SIZE-FIR_SIZE);
+        for(i=0;i<17;i++) {
+          for(j=0;j<FIR_SIZE-1;j++) p[j]=q[j];
+          p+=FIR_BUFFER_SIZE;
+          q+=FIR_BUFFER_SIZE;
+        }
+      }
+      /* we update 'bo' accordingly */
+      b=bo[channel]=FIR_SIZE;
+    }
+    
+    if(b & 1) {
+      dct64_486(buf[1]+b,buf[0]+b,bandPtr);
+    } else {
+      dct64_486(buf[0]+b,buf[1]+b,bandPtr);
+    }
+    bandPtr+=32;
+  }
+  bo[channel]=b;
+
+  /* filter bank: part 1 */
+  b=bo_start;
+  for(block=0;block<nb_blocks;block++) {
+    b++;
+    if (b >= FIR_BUFFER_SIZE) b=FIR_SIZE;
+    if(b & 1) {
+      b0 = buf[0] + b - (FIR_SIZE-1);
+    } else {
+      b0 = buf[1] + b - (FIR_SIZE-1);
+    }
+
+ FIR16_1(0,-7,53,-114,509,-1288,1643,-9372,18759,9372,1643,1288,509,114,53,7,0);
+ FIR16_2(1,-6,52,-100,515,-1197,1783,-8910,18748,9834,1489,1379,500,129,54,7,0,
+ 31,0,-7,54,-129,500,-1379,1489,-9834,18748,8910,1783,1197,515,100,52,6);
+ FIR16_2(2,-6,50,-86,520,-1106,1910,-8447,18714,10294,1322,1469,488,145,55,8,0,
+ 30,0,-8,55,-145,488,-1469,1322,-10294,18714,8447,1910,1106,520,86,50,6);
+ FIR16_2(3,-5,49,-73,521,-1015,2023,-7986,18657,10751,1140,1559,473,161,56,9,0,
+ 29,0,-9,56,-161,473,-1559,1140,-10751,18657,7986,2023,1015,521,73,49,5);              
+    samples+=64;
+  }
+  samples-=64*nb_blocks;
+  
+  /* filter bank: part 2 */
+
+  b=bo_start;
+  for(block=0;block<nb_blocks;block++) {
+    b++;
+    if (b >= FIR_BUFFER_SIZE) b=FIR_SIZE;
+    if(b & 1) {
+      b0 = buf[0] + b - (FIR_SIZE-1) + 4*FIR_BUFFER_SIZE;
+    } else {
+      b0 = buf[1] + b - (FIR_SIZE-1) + 4*FIR_BUFFER_SIZE;
+    }
+
+ FIR16_2(4,-4,47,-61,521,-926,2123,-7528,18578,11205,944,1647,455,177,56,10,0,
+ 28,0,-10,56,-177,455,-1647,944,-11205,18578,7528,2123,926,521,61,47,4);
+ FIR16_2(5,-4,45,-49,518,-837,2210,-7072,18477,11654,733,1733,434,194,57,11,0,
+ 27,0,-11,57,-194,434,-1733,733,-11654,18477,7072,2210,837,518,49,45,4);
+ FIR16_2(6,-4,44,-38,514,-751,2284,-6620,18353,12097,509,1817,411,212,57,12,0,
+ 26,0,-12,57,-212,411,-1817,509,-12097,18353,6620,2284,751,514,38,44,4);
+ FIR16_2(7,-3,42,-27,508,-665,2347,-6173,18208,12534,270,1899,383,229,56,13,0,
+ 25,0,-13,56,-229,383,-1899,270,-12534,18208,6173,2347,665,508,27,42,3);             
+
+    samples+=64;
+  }
+  samples-=64*nb_blocks;
+
+  /* filter bank: part 3 */
+
+  b=bo_start;
+  for(block=0;block<nb_blocks;block++) {
+    b++;
+    if (b >= FIR_BUFFER_SIZE) b=FIR_SIZE;
+    if(b & 1) {
+      b0 = buf[0] + b - (FIR_SIZE-1) + 8*FIR_BUFFER_SIZE;
+    } else {
+      b0 = buf[1] + b - (FIR_SIZE-1) + 8*FIR_BUFFER_SIZE;
+    }
+
+ FIR16_2(8,-3,40,-18,500,-582,2398,-5732,18042,12963,17,1977,353,247,56,14,0,
+ 24,0,-14,56,-247,353,-1977,17,-12963,18042,5732,2398,582,500,18,40,3);
+ FIR16_2(9,-2,38,-9,490,-501,2437,-5297,17855,13383,-249,2052,320,266,55,15,0,
+ 23,0,-15,55,-266,320,-2052,-249,-13383,17855,5297,2437,501,490,9,38,2);
+ FIR16_2(10,-2,36,0,479,-423,2465,-4869,17647,13794,-530,2122,282,284,53,17,0,
+ 22,0,-17,53,-284,282,-2122,-530,-13794,17647,4869,2465,423,479,0,36,2);
+ FIR16_2(11,-2,34,7,467,-347,2483,-4449,17419,14194,-825,2188,242,302,52,18,0,
+ 21,0,-18,52,-302,242,-2188,-825,-14194,17419,4449,2483,347,467,-7,34,2);          
+
+    samples+=64;
+  }
+  samples-=64*nb_blocks;
+
+  /* filter bank: part 4 */
+
+  b=bo_start;
+  for(block=0;block<nb_blocks;block++) {
+    b++;
+    if (b >= FIR_BUFFER_SIZE) b=FIR_SIZE;
+    if(b & 1) {
+      b0 = buf[0] + b - (FIR_SIZE-1) + 12*FIR_BUFFER_SIZE;
+    } else {
+      b0 = buf[1] + b - (FIR_SIZE-1) + 12*FIR_BUFFER_SIZE;
+    }
+
+ FIR16_2(12,-2,33,14,454,-273,2491,-4038,17173,14583,-1133,2249,198,320,50,19,0,
+ 20,0,-19,50,-320,198,-2249,-1133,-14583,17173,4038,2491,273,454,-14,33,2);
+ FIR16_2(13,-1,31,20,439,-203,2489,-3637,16907,14959,-1454,2304,151,339,47,21,-1,
+ 19,-1,-21,47,-339,151,-2304,-1454,-14959,16907,3637,2489,203,439,-20,31,1);
+ FIR16_2(14,-1,29,26,424,-136,2479,-3245,16623,15322,-1788,2354,100,357,44,22,-1,
+ 18,-1,-22,44,-357,100,-2354,-1788,-15322,16623,3245,2479,136,424,-26,29,1);
+ FIR16_2(15,-1,27,31,408,-72,2459,-2863,16322,15671,-2135,2396,46,374,40,24,-1,
+ 17,-1,-24,40,-374,46,-2396,-2135,-15671,16322,2863,2459,72,408,-31,27,1);
+ FIR16_1(16,-1,0,36,0,-11,0,-2493,0,16004,0,2431,0,391,0,26,0);      
+
+    samples+=64;
+  }
+
+  return clip;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Input/mpg123/decode_ntom.c	Wed Nov 09 16:42:39 2005 -0800
@@ -0,0 +1,282 @@
+/* 
+ * Mpeg Layer-1,2,3 audio decoder 
+ * ------------------------------
+ * copyright (c) 1995,1996,1997 by Michael Hipp, All rights reserved.
+ * See also 'README'
+ *
+ * N->M down/up sampling. Not optimized for speed.
+ */
+
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+
+#include "mpg123.h"
+
+#define WRITE_SAMPLE(samples,sum,clip) \
+  if( (sum) > 32767.0) { *(samples) = 0x7fff; (clip)++; } \
+  else if( (sum) < -32768.0) { *(samples) = -0x8000; (clip)++; } \
+  else { *(samples) = sum; }
+
+#define NTOM_MUL (32768)
+static unsigned long ntom_val[2] = { NTOM_MUL>>1,NTOM_MUL>>1 };
+static unsigned long ntom_step = NTOM_MUL;
+
+
+void mpg123_synth_ntom_set_step(long m,long n)
+{
+	if(n >= 96000 || m >= 96000 || m == 0 || n == 0) {
+		fprintf(stderr,"NtoM converter: illegal rates\n");
+		exit(1);
+	}
+
+	n *= NTOM_MUL;
+	ntom_step = n / m;
+
+	if(ntom_step > 8*NTOM_MUL) {
+		fprintf(stderr,"max. 1:8 conversion allowed!\n");
+		exit(1);
+	}
+
+	ntom_val[0] = ntom_val[1] = NTOM_MUL>>1;
+}
+
+int mpg123_synth_ntom_8bit(real *bandPtr,int channel,unsigned char *samples,int *pnt)
+{
+  short samples_tmp[8*64];
+  short *tmp1 = samples_tmp + channel;
+  int i,ret;
+  int pnt1 = 0;
+
+  ret = mpg123_synth_ntom(bandPtr,channel,(unsigned char *) samples_tmp,&pnt1);
+  samples += channel + *pnt;
+
+  for(i=0;i<(pnt1>>2);i++) {
+    *samples = mpg123_conv16to8[*tmp1>>AUSHIFT];
+    samples += 2;
+    tmp1 += 2;
+  }
+  *pnt += pnt1>>1;
+
+  return ret;
+}
+
+int mpg123_synth_ntom_8bit_mono(real *bandPtr,unsigned char *samples,int *pnt)
+{
+  short samples_tmp[8*64];
+  short *tmp1 = samples_tmp;
+  int i,ret;
+  int pnt1 = 0;
+
+  ret = mpg123_synth_ntom(bandPtr,0,(unsigned char *) samples_tmp,&pnt1);
+  samples += *pnt;
+
+  for(i=0;i<(pnt1>>2);i++) {
+    *samples++ = mpg123_conv16to8[*tmp1>>AUSHIFT];
+    tmp1 += 2;
+  }
+  *pnt += pnt1 >> 2;
+  
+  return ret;
+}
+
+int mpg123_synth_ntom_8bit_mono2stereo(real *bandPtr,unsigned char *samples,int *pnt)
+{
+  short samples_tmp[8*64];
+  short *tmp1 = samples_tmp;
+  int i,ret;
+  int pnt1 = 0;
+
+  ret = mpg123_synth_ntom(bandPtr,0,(unsigned char *) samples_tmp,&pnt1);
+  samples += *pnt;
+
+  for(i=0;i<(pnt1>>2);i++) {
+    *samples++ = mpg123_conv16to8[*tmp1>>AUSHIFT];
+    *samples++ = mpg123_conv16to8[*tmp1>>AUSHIFT];
+    tmp1 += 2;
+  }
+  *pnt += pnt1 >> 1;
+
+  return ret;
+}
+
+int mpg123_synth_ntom_mono(real *bandPtr,unsigned char *samples,int *pnt)
+{
+  short samples_tmp[8*64];
+  short *tmp1 = samples_tmp;
+  int i,ret;
+  int pnt1 = 0;
+
+  ret = mpg123_synth_ntom(bandPtr,0,(unsigned char *) samples_tmp,&pnt1);
+  samples += *pnt;
+
+  for(i=0;i<(pnt1>>2);i++) {
+    *( (short *)samples) = *tmp1;
+    samples += 2;
+    tmp1 += 2;
+  }
+  *pnt += pnt1 >> 1;
+
+  return ret;
+}
+
+
+int mpg123_synth_ntom_mono2stereo(real *bandPtr,unsigned char *samples,int *pnt)
+{
+  int i,ret;
+  int pnt1 = *pnt;
+
+  ret = mpg123_synth_ntom(bandPtr,0,samples,pnt);
+  samples += pnt1;
+  
+  for(i=0;i<((*pnt-pnt1)>>2);i++) {
+    ((short *)samples)[1] = ((short *)samples)[0];
+    samples+=4;
+  }
+
+  return ret;
+}
+
+
+int mpg123_synth_ntom(real *bandPtr,int channel,unsigned char *out,int *pnt)
+{
+  static real buffs[2][2][0x110];
+  static const int step = 2;
+  static int bo = 1;
+  short *samples = (short *) (out + *pnt);
+
+  real *b0,(*buf)[0x110];
+  int clip = 0; 
+  int bo1;
+  int ntom;
+
+  if(!channel) {
+    bo--;
+    bo &= 0xf;
+    buf = buffs[0];
+    ntom = ntom_val[1] = ntom_val[0];
+  }
+  else {
+    samples++;
+    out += 2; /* to compute the right *pnt value */
+    buf = buffs[1];
+    ntom = ntom_val[1];
+  }
+
+  if(bo & 0x1) {
+    b0 = buf[0];
+    bo1 = bo;
+    mpg123_dct64(buf[1]+((bo+1)&0xf),buf[0]+bo,bandPtr);
+  }
+  else {
+    b0 = buf[1];
+    bo1 = bo+1;
+    mpg123_dct64(buf[0]+bo,buf[1]+bo+1,bandPtr);
+  }
+
+
+  {
+    register int j;
+    real *window = decwin + 16 - bo1;
+ 
+    for (j=16;j;j--,window+=0x10)
+    {
+      real sum;
+
+      ntom += ntom_step;
+      if(ntom < NTOM_MUL) {
+        window += 16;
+        b0 += 16;
+        continue;
+      }
+
+      sum  = *window++ * *b0++;
+      sum -= *window++ * *b0++;
+      sum += *window++ * *b0++;
+      sum -= *window++ * *b0++;
+      sum += *window++ * *b0++;
+      sum -= *window++ * *b0++;
+      sum += *window++ * *b0++;
+      sum -= *window++ * *b0++;
+      sum += *window++ * *b0++;
+      sum -= *window++ * *b0++;
+      sum += *window++ * *b0++;
+      sum -= *window++ * *b0++;
+      sum += *window++ * *b0++;
+      sum -= *window++ * *b0++;
+      sum += *window++ * *b0++;
+      sum -= *window++ * *b0++;
+
+      while(ntom >= NTOM_MUL) {
+        WRITE_SAMPLE(samples,sum,clip);
+        samples += step;
+        ntom -= NTOM_MUL;
+      }
+    }
+
+    ntom += ntom_step;
+    if(ntom >= NTOM_MUL)
+    {
+      real sum;
+      sum  = window[0x0] * b0[0x0];
+      sum += window[0x2] * b0[0x2];
+      sum += window[0x4] * b0[0x4];
+      sum += window[0x6] * b0[0x6];
+      sum += window[0x8] * b0[0x8];
+      sum += window[0xA] * b0[0xA];
+      sum += window[0xC] * b0[0xC];
+      sum += window[0xE] * b0[0xE];
+
+      while(ntom >= NTOM_MUL) {
+        WRITE_SAMPLE(samples,sum,clip);
+        samples += step;
+        ntom -= NTOM_MUL;
+      }
+    }
+
+    b0-=0x10,window-=0x20;
+    window += bo1<<1;
+
+    for (j=15;j;j--,b0-=0x20,window-=0x10)
+    {
+      real sum;
+
+      ntom += ntom_step;
+      if(ntom < NTOM_MUL) {
+        window -= 16;
+        b0 += 16;
+        continue;
+      }
+
+      sum = -*(--window) * *b0++;
+      sum -= *(--window) * *b0++;
+      sum -= *(--window) * *b0++;
+      sum -= *(--window) * *b0++;
+      sum -= *(--window) * *b0++;
+      sum -= *(--window) * *b0++;
+      sum -= *(--window) * *b0++;
+      sum -= *(--window) * *b0++;
+      sum -= *(--window) * *b0++;
+      sum -= *(--window) * *b0++;
+      sum -= *(--window) * *b0++;
+      sum -= *(--window) * *b0++;
+      sum -= *(--window) * *b0++;
+      sum -= *(--window) * *b0++;
+      sum -= *(--window) * *b0++;
+      sum -= *(--window) * *b0++;
+
+      while(ntom >= NTOM_MUL) {
+        WRITE_SAMPLE(samples,sum,clip);
+        samples += step;
+        ntom -= NTOM_MUL;
+      }
+    }
+  }
+
+  ntom_val[channel] = ntom;
+  *pnt = ((unsigned char *) samples - out);
+
+  return clip;
+}
+
+