changeset 4486:e69bed07cb27

further work on the RoQ audio decoder
author melanson
date Sat, 02 Feb 2002 22:45:39 +0000
parents eaa4a2242552
children e642ff2d5c6d
files dec_audio.c dec_video.c roqav.c roqav.h
diffstat 4 files changed, 108 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/dec_audio.c	Sat Feb 02 22:35:47 2002 +0000
+++ b/dec_audio.c	Sat Feb 02 22:45:39 2002 +0000
@@ -20,6 +20,8 @@
 
 #include "dec_audio.h"
 
+#include "roqav.h"
+
 //==========================================================================
 
 #include "libao2/afmt.h"
@@ -433,6 +435,13 @@
   sh_audio->ds->ss_div=FOX62_ADPCM_SAMPLES_PER_BLOCK;
   sh_audio->ds->ss_mul=FOX62_ADPCM_BLOCK_SIZE;
   break;
+case AFM_ROQAUDIO:
+  // minsize was stored in wf->nBlockAlign by the RoQ demuxer
+  sh_audio->audio_out_minsize=sh_audio->wf->nBlockAlign;
+  sh_audio->ds->ss_div=FOX62_ADPCM_SAMPLES_PER_BLOCK;
+  sh_audio->ds->ss_mul=FOX62_ADPCM_BLOCK_SIZE;
+  sh_audio->context = roq_decode_audio_init();
+  break;
 case AFM_MPEG:
   // MPEG Audio:
   sh_audio->audio_out_minsize=4608;
@@ -726,6 +735,11 @@
   sh_audio->i_bps=FOX62_ADPCM_BLOCK_SIZE*
     (sh_audio->channels*sh_audio->samplerate) / FOX62_ADPCM_SAMPLES_PER_BLOCK;
   break;
+case AFM_ROQAUDIO:
+  sh_audio->channels=sh_audio->wf->nChannels;
+  sh_audio->samplerate=sh_audio->wf->nSamplesPerSec;
+  sh_audio->i_bps = (sh_audio->channels * 22050) / 2;
+  break;
 case AFM_MPEG: {
   // MPEG Audio:
   dec_audio_sh=sh_audio; // save sh_audio for the callback:
@@ -1166,6 +1180,27 @@
           (unsigned short*)buf,ibuf);
         break;
       }
+      case AFM_ROQAUDIO:
+      {
+        static unsigned char *ibuf = NULL;
+        unsigned char header_data[6];
+        int read_len;
+
+        if (!ibuf)
+          ibuf = (unsigned char *)malloc(sh_audio->audio_out_minsize / 2);
+
+        // figure out how much data to read
+        if (demux_read_data(sh_audio->ds, header_data, 6) != 6)
+          break; // EOF
+        read_len = (header_data[5] << 24) | (header_data[4] << 16) |
+          (header_data[3] << 8) | header_data[2];
+        read_len += 2;  // 16-bit arguments
+        if (demux_read_data(sh_audio->ds, ibuf, read_len) != read_len)
+          break;
+        len = 2 * roq_decode_audio((unsigned short *)buf, ibuf,
+          read_len, sh_audio->channels, sh_audio->context);          
+        break;
+      }
 #ifdef USE_LIBAC3
       case AFM_AC3: // AC3 decoder
         //printf("{1:%d}",avi_header.idx_pos);fflush(stdout);
--- a/dec_video.c	Sat Feb 02 22:35:47 2002 +0000
+++ b/dec_video.c	Sat Feb 02 22:45:39 2002 +0000
@@ -34,6 +34,8 @@
 
 #include "dec_video.h"
 
+#include "roqav.h"
+
 // ===================================================================
 
 extern double video_time_usage;
@@ -424,6 +426,15 @@
 mp_image_setfmt(sh_video->image,out_fmt);
 
 switch(sh_video->codec->driver){
+ case VFM_ROQVIDEO:
+#ifdef USE_MP_IMAGE
+   sh_video->image->type=MP_IMGTYPE_STATIC;
+#else
+   sh_video->our_out_buffer = 
+     (char*)memalign(64, sh_video->disp_w * sh_video->disp_h * 1.5);
+#endif
+   sh_video->context = roq_decode_video_init();
+   break;
  case VFM_CINEPAK: {
 #ifdef USE_MP_IMAGE
    sh_video->image->type=MP_IMGTYPE_STATIC;
@@ -1080,6 +1091,11 @@
       sh_video->disp_w, sh_video->disp_h, (out_fmt==IMGFMT_YUY2)?16:(out_fmt&255));
    blit_frame = 3;
    break;
+ case VFM_ROQVIDEO:
+   roq_decode_video(start, in_size, sh_video->our_out_buffer,
+     sh_video->disp_w, sh_video->disp_h, sh_video->context);
+   blit_frame = 3;
+   break;
 } // switch
 //------------------------ frame decoded. --------------------
 
--- a/roqav.c	Sat Feb 02 22:35:47 2002 +0000
+++ b/roqav.c	Sat Feb 02 22:45:39 2002 +0000
@@ -1,17 +1,24 @@
 /*
         RoQ A/V decoder for the MPlayer program
         by Mike Melanson
-        based on Dr. Tim Ferguson's RoQ document found at:
+        based on Dr. Tim Ferguson's RoQ document and accompanying source
+        code found at:
           http://www.csse.monash.edu.au/~timf/videocodec.html
 */
 
 #include "config.h"
 #include "bswap.h"
 #include <stdio.h>
+#include <stdlib.h>
 
 #define LE_16(x) (le2me_16(*(unsigned short *)(x)))
 #define LE_32(x) (le2me_32(*(unsigned int *)(x)))
 
+#define CLAMP_S16(x)  if (x < -32768) x = -32768; \
+  else if (x > 32767) x = 32767;
+#define SE_16BIT(x)  if (x & 0x8000) x -= 0x10000;
+// sign extend a 4-bit value
+
 void *roq_decode_video_init(void)
 {
 }
@@ -26,14 +33,62 @@
 {
 }
 
+// Initialize the RoQ audio decoder, which is to say, initialize the table
+// of squares.
 void *roq_decode_audio_init(void)
 {
+  short *square_array;
+  short square;
+  int i;
+
+  square_array = (short *)malloc(256 * sizeof(short));
+  if (!square_array)
+    return NULL;
+
+  for (i = 0; i < 128; i++)
+  {
+    square = i * i;
+    square_array[i] = square;
+    square_array[i + 128] = -square;
+  }
+
+  return square_array;
 }
 
 int roq_decode_audio(
   unsigned short *output,
   unsigned char *input,
+  int encoded_size,
   int channels,
   void *context)
 {
+  short *square_array = (short *)context;
+  int i;
+  int predictor[2];
+  int channel_number = 0;
+
+  // prepare the initial predictors
+  if (channels == 1)
+    predictor[0] = LE_16(&input[0]);
+  else
+  {
+    predictor[0] = input[1] << 8;
+    predictor[1] = input[0] << 8;
+  }
+  SE_16BIT(predictor[0]);
+  SE_16BIT(predictor[1]);
+
+  // decode the samples
+  for (i = 2; i < encoded_size; i++)
+  {
+    predictor[channel_number] += square_array[input[i]];
+    CLAMP_S16(predictor[channel_number]);
+    output[i - 2] = predictor[channel_number];
+
+    // toggle channel
+    channel_number ^= channels - 1;
+  }
+
+  // return the number of samples decoded
+  return (encoded_size - 2);
 }
--- a/roqav.h	Sat Feb 02 22:35:47 2002 +0000
+++ b/roqav.h	Sat Feb 02 22:45:39 2002 +0000
@@ -7,6 +7,6 @@
 
 void *roq_decode_audio_init(void);
 int roq_decode_audio(unsigned short *output, unsigned char *input,
-  int channels, void *context);
+  int encoded_size, int channels, void *context);
 
 #endif // ROQAV_H