Cary Sandvig 25 年 前
コミット
a0a940046a
3 ファイル変更523 行追加0 行削除
  1. 266 0
      panda/src/mpg123/audio.c
  2. 89 0
      panda/src/mpg123/audio.h
  3. 168 0
      panda/src/mpg123/dct64.c

+ 266 - 0
panda/src/mpg123/audio.c

@@ -0,0 +1,266 @@
+
+#include "mpg123.h"
+
+void audio_info_struct_init(struct audio_info_struct *ai)
+{
+#ifdef AUDIO_USES_FD
+  ai->fn = -1;
+#endif
+#ifdef SGI
+#if 0
+  ALconfig config;
+  ALport port;
+#endif
+#endif
+  ai->rate = -1;
+  ai->gain = -1;
+  ai->output = -1;
+#ifdef ALSA
+  ai->handle = NULL;
+  ai->alsa_format.format = -1;
+  ai->alsa_format.rate = -1;
+  ai->alsa_format.channels = -1;
+#endif
+  ai->device = NULL;
+  ai->channels = -1;
+  ai->format = -1;
+}
+
+#define NUM_CHANNELS 2
+#define NUM_ENCODINGS 6
+#define NUM_RATES 10
+
+struct audio_name audio_val2name[NUM_ENCODINGS+1] = {
+ { AUDIO_FORMAT_SIGNED_16  , "signed 16 bit" , "s16 " } ,
+ { AUDIO_FORMAT_UNSIGNED_16, "unsigned 16 bit" , "u16 " } ,  
+ { AUDIO_FORMAT_UNSIGNED_8 , "unsigned 8 bit" , "u8  " } ,
+ { AUDIO_FORMAT_SIGNED_8   , "signed 8 bit" , "s8  " } ,
+ { AUDIO_FORMAT_ULAW_8     , "mu-law (8 bit)" , "ulaw " } ,
+ { AUDIO_FORMAT_ALAW_8     , "a-law (8 bit)" , "alaw " } ,
+ { -1 , NULL }
+};
+
+#if 0
+static char *channel_name[NUM_CHANNELS] = 
+ { "mono" , "stereo" };
+#endif
+
+static int channels[NUM_CHANNELS] = { 1 , 2 };
+static int rates[NUM_RATES] = { 
+	 8000, 11025, 12000, 
+	16000, 22050, 24000,
+	32000, 44100, 48000,
+	8000	/* 8000 = dummy for user forced */
+
+};
+static int encodings[NUM_ENCODINGS] = {
+ AUDIO_FORMAT_SIGNED_16, 
+ AUDIO_FORMAT_UNSIGNED_16,
+ AUDIO_FORMAT_UNSIGNED_8,
+ AUDIO_FORMAT_SIGNED_8,
+ AUDIO_FORMAT_ULAW_8,
+ AUDIO_FORMAT_ALAW_8
+};
+
+static char capabilities[NUM_CHANNELS][NUM_ENCODINGS][NUM_RATES];
+
+void audio_capabilities(struct audio_info_struct *ai)
+{
+	int fmts;
+	int i,j,k,k1=NUM_RATES-1;
+	struct audio_info_struct ai1 = *ai;
+
+        if (param.outmode != DECODE_AUDIO) {
+		memset(capabilities,1,sizeof(capabilities));
+		return;
+	}
+
+	memset(capabilities,0,sizeof(capabilities));
+	if(param.force_rate) {
+		rates[NUM_RATES-1] = param.force_rate;
+		k1 = NUM_RATES;
+	}
+
+	if(audio_open(&ai1) < 0) {
+		perror("audio");
+		exit(1);
+	}
+
+	for(i=0;i<NUM_CHANNELS;i++) {
+		for(j=0;j<NUM_RATES;j++) {
+			ai1.channels = channels[i];
+			ai1.rate = rates[j];
+			fmts = audio_get_formats(&ai1);
+			if(fmts < 0)
+				continue;
+			for(k=0;k<NUM_ENCODINGS;k++) {
+				if((fmts & encodings[k]) == encodings[k])
+					capabilities[i][k][j] = 1;
+			}
+		}
+	}
+
+	audio_close(&ai1);
+
+	if(param.verbose > 1) {
+		fprintf(stderr,"\nAudio capabilities:\n        |");
+		for(j=0;j<NUM_ENCODINGS;j++) {
+			fprintf(stderr," %5s |",audio_val2name[j].sname);
+		}
+		fprintf(stderr,"\n --------------------------------------------------------\n");
+		for(k=0;k<k1;k++) {
+			fprintf(stderr," %5d  |",rates[k]);
+			for(j=0;j<NUM_ENCODINGS;j++) {
+				if(capabilities[0][j][k]) {
+					if(capabilities[1][j][k])
+						fprintf(stderr,"  M/S  |");
+					else
+						fprintf(stderr,"   M   |");
+				}
+				else if(capabilities[1][j][k])
+					fprintf(stderr,"   S   |");
+				else
+					fprintf(stderr,"       |");
+			}
+			fprintf(stderr,"\n");
+		}
+		fprintf(stderr,"\n");
+	}
+}
+
+static int rate2num(int r)
+{
+	int i;
+	for(i=0;i<NUM_RATES;i++) 
+		if(rates[i] == r)
+			return i;
+	return -1;
+}
+
+
+static int audio_fit_cap_helper(struct audio_info_struct *ai,int rn,int f0,int f2,int c)
+{
+	int i;
+
+        if(rn >= 0) {
+                for(i=f0;i<f2;i++) {
+                        if(capabilities[c][i][rn]) {
+                                ai->rate = rates[rn];
+                                ai->format = encodings[i];
+                                ai->channels = channels[c];
+				return 1;
+                        }
+                }
+        }
+	return 0;
+
+}
+
+/*
+ * c=num of channels of stream
+ * r=rate of stream
+ */
+void audio_fit_capabilities(struct audio_info_struct *ai,int c,int r)
+{
+	int rn;
+	int f0=0;
+	
+	if(param.force_8bit) {
+		f0 = 2;
+	}
+
+	c--; /* stereo=1 ,mono=0 */
+
+	if(param.force_mono >= 0)
+		c = 0;
+	if(param.force_stereo)
+		c = 1;
+
+	if(param.force_rate) {
+		rn = rate2num(param.force_rate);
+		if(audio_fit_cap_helper(ai,rn,f0,2,c))
+			return;
+		if(audio_fit_cap_helper(ai,rn,2,NUM_ENCODINGS,c))
+			return;
+
+		if(c == 1 && !param.force_stereo)
+			c = 0;
+		else if(c == 0 && !param.force_mono)
+			c = 1;
+
+		if(audio_fit_cap_helper(ai,rn,f0,2,c))
+			return;
+		if(audio_fit_cap_helper(ai,rn,2,NUM_ENCODINGS,c))
+			return;
+
+		fprintf(stderr,"No supported rate found!\n");
+		exit(1);
+	}
+
+	rn = rate2num(r>>0);
+	if(audio_fit_cap_helper(ai,rn,f0,2,c))
+		return;
+	rn = rate2num(r>>1);
+	if(audio_fit_cap_helper(ai,rn,f0,2,c))
+		return;
+	rn = rate2num(r>>2);
+	if(audio_fit_cap_helper(ai,rn,f0,2,c))
+		return;
+
+	rn = rate2num(r>>0);
+	if(audio_fit_cap_helper(ai,rn,2,NUM_ENCODINGS,c))
+		return;
+	rn = rate2num(r>>1);
+	if(audio_fit_cap_helper(ai,rn,2,NUM_ENCODINGS,c))
+		return;
+	rn = rate2num(r>>2);
+	if(audio_fit_cap_helper(ai,rn,2,NUM_ENCODINGS,c))
+		return;
+
+
+        if(c == 1 && !param.force_stereo)
+		c = 0;
+        else if(c == 0 && !param.force_mono)
+                c = 1;
+
+        rn = rate2num(r>>0);
+        if(audio_fit_cap_helper(ai,rn,f0,2,c))
+                return;
+        rn = rate2num(r>>1);
+        if(audio_fit_cap_helper(ai,rn,f0,2,c))
+                return;
+        rn = rate2num(r>>2);
+        if(audio_fit_cap_helper(ai,rn,f0,2,c))
+                return;
+
+        rn = rate2num(r>>0);
+        if(audio_fit_cap_helper(ai,rn,2,NUM_ENCODINGS,c))
+                return;
+        rn = rate2num(r>>1);
+        if(audio_fit_cap_helper(ai,rn,2,NUM_ENCODINGS,c))
+                return;
+        rn = rate2num(r>>2);
+        if(audio_fit_cap_helper(ai,rn,2,NUM_ENCODINGS,c))
+                return;
+
+	fprintf(stderr,"No supported rate found!\n");
+	exit(1);
+}
+
+char *audio_encoding_name(int format)
+{
+	int i;
+
+	for(i=0;i<NUM_ENCODINGS;i++) {
+		if(audio_val2name[i].val == format)
+			return audio_val2name[i].name;
+	}
+	return "Unknown";
+}
+
+#if !defined(SOLARIS) && !defined(__NetBSD__) || defined(NAS)
+void audio_queueflush(struct audio_info_struct *ai)
+{
+}
+#endif
+

+ 89 - 0
panda/src/mpg123/audio.h

@@ -0,0 +1,89 @@
+/* 
+ * Audio 'LIB' defines
+ */
+
+#define AUDIO_OUT_HEADPHONES       0x01
+#define AUDIO_OUT_INTERNAL_SPEAKER 0x02
+#define AUDIO_OUT_LINE_OUT         0x04
+
+enum { DECODE_TEST, DECODE_AUDIO, DECODE_FILE, DECODE_BUFFER, DECODE_WAV,
+	DECODE_AU,DECODE_CDR,DECODE_AUDIOFILE };
+
+#define AUDIO_FORMAT_MASK	  0x100
+#define AUDIO_FORMAT_16		  0x100
+#define AUDIO_FORMAT_8		  0x000
+
+#define AUDIO_FORMAT_SIGNED_16    0x110
+#define AUDIO_FORMAT_UNSIGNED_16  0x120
+#define AUDIO_FORMAT_UNSIGNED_8   0x1
+#define AUDIO_FORMAT_SIGNED_8     0x2
+#define AUDIO_FORMAT_ULAW_8       0x4
+#define AUDIO_FORMAT_ALAW_8       0x8
+
+/* 3% rate tolerance */
+#define AUDIO_RATE_TOLERANCE	  3
+
+#if 0
+#if defined(HPUX) || defined(SUNOS) || defined(SOLARIS) || defined(OSS) || defined(__NetBSD__) || defined(SPARCLINUX) || defined(__FreeBSD__)
+#endif
+#endif
+
+#define AUDIO_USES_FD
+
+#ifdef SGI
+/* #include <audio.h> */
+#include <dmedia/audio.h>
+#endif
+
+
+#ifdef ALSA
+#include <sys/asoundlib.h>
+#endif
+
+struct audio_info_struct
+{
+#ifdef AUDIO_USES_FD
+  int fn; /* filenumber */
+#endif
+#ifdef SGI
+  ALconfig config;
+  ALport port;
+#endif
+  long rate;
+  long gain;
+  int output;
+#ifdef ALSA
+  snd_pcm_t *handle;
+  snd_pcm_format_t alsa_format;
+#endif
+  char *device;
+  int channels;
+  int format;
+  int private1;
+  void *private2;
+};
+
+struct audio_name {
+  int  val;
+  char *name;
+  char *sname;
+};
+
+extern void audio_capabilities(struct audio_info_struct *);
+extern void audio_fit_capabilities(struct audio_info_struct *ai,int c,int r);
+
+extern char *audio_encoding_name(int format);
+
+extern int audio_play_samples(struct audio_info_struct *,unsigned char *,int);
+extern int audio_open(struct audio_info_struct *);
+extern int audio_reset_parameters(struct audio_info_struct *);
+extern int audio_rate_best_match(struct audio_info_struct *ai);
+extern int audio_set_rate(struct audio_info_struct *);
+extern int audio_set_format(struct audio_info_struct *);
+extern int audio_get_formats(struct audio_info_struct *);
+extern int audio_set_channels(struct audio_info_struct *);
+extern int audio_write_sample(struct audio_info_struct *,short *,int);
+extern int audio_close(struct audio_info_struct *);
+extern void audio_info_struct_init(struct audio_info_struct *);
+extern void audio_queueflush(struct audio_info_struct *ai);
+

+ 168 - 0
panda/src/mpg123/dct64.c

@@ -0,0 +1,168 @@
+
+/*
+ * Discrete Cosine Tansform (DCT) for subband synthesis
+ *
+ * -funroll-loops (for gcc) will remove the loops for better performance
+ * using loops in the source-code enhances readabillity
+ */
+
+/*
+ * TODO: write an optimized version for the down-sampling modes
+ *       (in these modes the bands 16-31 (2:1) or 8-31 (4:1) are zero 
+ */
+
+#include "mpg123.h"
+
+void dct64(real *out0,real *out1,real *samples)
+{
+  real bufs[64];
+
+ {
+  register int i,j;
+  register real *b1,*b2,*bs,*costab;
+
+  b1 = samples;
+  bs = bufs;
+  costab = pnts[0]+16;
+  b2 = b1 + 32;
+
+  for(i=15;i>=0;i--)
+    *bs++ = (*b1++ + *--b2); 
+  for(i=15;i>=0;i--)
+    *bs++ = (*--b2 - *b1++) * *--costab;
+
+  b1 = bufs;
+  costab = pnts[1]+8;
+  b2 = b1 + 16;
+
+  {
+    for(i=7;i>=0;i--)
+      *bs++ = (*b1++ + *--b2); 
+    for(i=7;i>=0;i--)
+      *bs++ = (*--b2 - *b1++) * *--costab; 
+    b2 += 32;
+    costab += 8;
+    for(i=7;i>=0;i--)
+      *bs++ = (*b1++ + *--b2); 
+    for(i=7;i>=0;i--)
+      *bs++ = (*b1++ - *--b2) * *--costab; 
+    b2 += 32;
+  }
+
+  bs = bufs;
+  costab = pnts[2];
+  b2 = b1 + 8;
+
+  for(j=2;j;j--)
+  {
+    for(i=3;i>=0;i--)
+      *bs++ = (*b1++ + *--b2); 
+    for(i=3;i>=0;i--)
+      *bs++ = (*--b2 - *b1++) * costab[i]; 
+    b2 += 16;
+    for(i=3;i>=0;i--)
+      *bs++ = (*b1++ + *--b2); 
+    for(i=3;i>=0;i--)
+      *bs++ = (*b1++ - *--b2) * costab[i]; 
+    b2 += 16;
+  }
+
+  b1 = bufs;
+  costab = pnts[3];
+  b2 = b1 + 4;
+
+  for(j=4;j;j--)
+  {
+    *bs++ = (*b1++ + *--b2); 
+    *bs++ = (*b1++ + *--b2);
+    *bs++ = (*--b2 - *b1++) * costab[1]; 
+    *bs++ = (*--b2 - *b1++) * costab[0];
+    b2 += 8;
+    *bs++ = (*b1++ + *--b2); 
+    *bs++ = (*b1++ + *--b2);
+    *bs++ = (*b1++ - *--b2) * costab[1]; 
+    *bs++ = (*b1++ - *--b2) * costab[0];
+    b2 += 8;
+  }
+  bs = bufs;
+  costab = pnts[4];
+
+  for(j=8;j;j--)
+  {
+    real v0,v1;
+    v0=*b1++; v1 = *b1++;
+    *bs++ = (v0 + v1);
+    *bs++ = (v0 - v1) * (*costab);
+    v0=*b1++; v1 = *b1++;
+    *bs++ = (v0 + v1);
+    *bs++ = (v1 - v0) * (*costab);
+  }
+
+ }
+
+
+ {
+  register real *b1;
+  register int i;
+
+  for(b1=bufs,i=8;i;i--,b1+=4)
+    b1[2] += b1[3];
+
+  for(b1=bufs,i=4;i;i--,b1+=8)
+  {
+    b1[4] += b1[6];
+    b1[6] += b1[5];
+    b1[5] += b1[7];
+  }
+
+  for(b1=bufs,i=2;i;i--,b1+=16)
+  {
+    b1[8]  += b1[12];
+    b1[12] += b1[10];
+    b1[10] += b1[14];
+    b1[14] += b1[9];
+    b1[9]  += b1[13];
+    b1[13] += b1[11];
+    b1[11] += b1[15];
+  }
+ }
+
+
+  out0[0x10*16] = bufs[0];
+  out0[0x10*15] = bufs[16+0]  + bufs[16+8];
+  out0[0x10*14] = bufs[8];
+  out0[0x10*13] = bufs[16+8]  + bufs[16+4];
+  out0[0x10*12] = bufs[4];
+  out0[0x10*11] = bufs[16+4]  + bufs[16+12];
+  out0[0x10*10] = bufs[12];
+  out0[0x10* 9] = bufs[16+12] + bufs[16+2];
+  out0[0x10* 8] = bufs[2];
+  out0[0x10* 7] = bufs[16+2]  + bufs[16+10];
+  out0[0x10* 6] = bufs[10];
+  out0[0x10* 5] = bufs[16+10] + bufs[16+6];
+  out0[0x10* 4] = bufs[6];
+  out0[0x10* 3] = bufs[16+6]  + bufs[16+14];
+  out0[0x10* 2] = bufs[14];
+  out0[0x10* 1] = bufs[16+14] + bufs[16+1];
+  out0[0x10* 0] = bufs[1];
+
+  out1[0x10* 0] = bufs[1];
+  out1[0x10* 1] = bufs[16+1]  + bufs[16+9];
+  out1[0x10* 2] = bufs[9];
+  out1[0x10* 3] = bufs[16+9]  + bufs[16+5];
+  out1[0x10* 4] = bufs[5];
+  out1[0x10* 5] = bufs[16+5]  + bufs[16+13];
+  out1[0x10* 6] = bufs[13];
+  out1[0x10* 7] = bufs[16+13] + bufs[16+3];
+  out1[0x10* 8] = bufs[3];
+  out1[0x10* 9] = bufs[16+3]  + bufs[16+11];
+  out1[0x10*10] = bufs[11];
+  out1[0x10*11] = bufs[16+11] + bufs[16+7];
+  out1[0x10*12] = bufs[7];
+  out1[0x10*13] = bufs[16+7]  + bufs[16+15];
+  out1[0x10*14] = bufs[15];
+  out1[0x10*15] = bufs[16+15];
+
+}
+
+