shithub: riscv

Download patch

ref: 1a450db960aa3c542c84a5fff0f66c5ce95c853f
parent: 9d60d8262e4ab285da2903192a341ceb81a05eb5
author: cinap_lenrek <[email protected]>
date: Sun Feb 5 22:34:21 EST 2012

oggdec: resample to target frequency

--- a/sys/src/cmd/audio/oggdec/oggdec.c
+++ b/sys/src/cmd/audio/oggdec/oggdec.c
@@ -26,12 +26,83 @@
 #include <math.h>
 #include <vorbis/codec.h>
 
+int rate = 44100;
 
-ogg_int16_t convbuffer[4096]; /* take 8k out of the data segment, not the stack */
-int convsize=4096;
+enum {
+	Max = 32767,
+	Min = -32768,
+};
 
-extern void _VDBG_dump(void);
+typedef unsigned long ulong;
+typedef unsigned char uchar;
+typedef struct Chan Chan;
 
+struct Chan
+{
+	unsigned long	phase;
+	float		last;
+};
+
+static uchar*
+resample(Chan *c, float *src, uchar *dst, int mono, ulong delta, ulong count)
+{
+	float f, last, val;
+	ulong phase, pos;
+	int out;
+	
+	last = c->last;
+	phase = c->phase;
+	pos = phase >> 16;
+	while(pos < count){
+		val = src[pos];
+		if(pos)
+			last = src[pos-1];
+		f = (float)(phase&0xFFFF)/0x10000;
+		out = (last + (val - last) * f) * 32767.f;
+		/* cliping */
+		if(out > Max)
+			out = Max;
+		else if(out < Min)
+			out = Min;
+		*dst++ = out;
+		*dst++ = out >> 8;
+		if(mono){
+			*dst++ = out;
+			*dst++ = out >> 8;
+		} else
+			dst += 2;
+		phase += delta;
+		pos = phase >> 16;
+	}
+	c->last = val;
+	if(delta < 0x10000)
+		c->phase = phase & 0xFFFF;
+	else
+		c->phase = phase - (count << 16);
+	return dst;
+}
+
+static void
+output(float **pcm, int samples, vorbis_info *vi)
+{
+	static uchar *buf;
+	static int nbuf;
+	static Chan c1, c0;
+	ulong n, delta;
+	uchar *p;
+
+	delta = ((ulong)vi->rate << 16) / rate;
+	n = 4 * ((ulong)vi->rate + samples * rate) / (ulong)vi->rate;
+	if(n > nbuf){
+		nbuf = n;
+		buf = realloc(buf, nbuf);
+	}
+	if(vi->channels == 2)
+		resample(&c1, pcm[1], buf+2, 0, delta, samples);
+	p = resample(&c0, pcm[0], buf, vi->channels == 1, delta, samples);
+	fwrite(buf, p-buf, 1, stdout);
+}
+
 int main(){
   ogg_sync_state   oy; /* sync and verify incoming physical bitstream */
   ogg_stream_state os; /* take physical pages, weld into a logical
@@ -167,8 +238,6 @@
       fprintf(stderr,"Encoded by: %s\n\n",vc.vendor);
     }
     
-    convsize=4096/vi.channels;
-
     /* OK, got and parsed all three headers. Initialize the Vorbis
        packet->PCM decoder. */
     vorbis_synthesis_init(&vd,&vi); /* central decode state */
@@ -196,56 +265,13 @@
 	    if(result<0){ /* missing or corrupt data at this page position */
 	      /* no reason to complain; already complained above */
 	    }else{
-	      /* we have a packet.  Decode it */
 	      float **pcm;
 	      int samples;
-	      
 	      if(vorbis_synthesis(&vb,&op)==0) /* test for success! */
 		vorbis_synthesis_blockin(&vd,&vb);
-	      /* 
-		 
-	      **pcm is a multichannel float vector.  In stereo, for
-	      example, pcm[0] is left, and pcm[1] is right.  samples is
-	      the size of each channel.  Convert the float values
-	      (-1.<=range<=1.) to whatever PCM format and write it out */
-	      
 	      while((samples=vorbis_synthesis_pcmout(&vd,&pcm))>0){
-		int j;
-		int clipflag=0;
-		int bout=(samples<convsize?samples:convsize);
-		
-		/* convert floats to 16 bit signed ints (host order) and
-		   interleave */
-		for(i=0;i<vi.channels;i++){
-		  ogg_int16_t *ptr=convbuffer+i;
-		  float  *mono=pcm[i];
-		  for(j=0;j<bout;j++){
-#if 1
-		    int val=mono[j]*32767.f;
-#else /* optional dither */
-		    int val=mono[j]*32767.f+drand48()-0.5f;
-#endif
-		    /* might as well guard against clipping */
-		    if(val>32767){
-		      val=32767;
-		      clipflag=1;
-		    }
-		    if(val<-32768){
-		      val=-32768;
-		      clipflag=1;
-		    }
-		    *ptr=val;
-		    ptr+=vi.channels;
-		  }
-		}
-		
-		if(clipflag)
-		  fprintf(stderr,"Clipping in frame %ld\n",(long)(vd.sequence));
-		
-		
-		fwrite(convbuffer,2*vi.channels,bout,stdout);
-		
-		vorbis_synthesis_read(&vd,bout); /* tell libvorbis how
+		output(pcm, samples, &vi);
+		vorbis_synthesis_read(&vd,samples); /* tell libvorbis how
 						   many samples we
 						   actually consumed */
 	      }