Re: ff_audio_multichannel_support

Torsten Jager <[email protected]> Sat, 11 May 2013 15:51:41 +0200
Newsgroups gmane.comp.video.xine.devel
Message-ID <[email protected]>
Hello,

> this is a link to a sample (hd + eac3)
>
> 35 s 30 Mo
>
> http://dl.free.fr/rXcfoUIhr

OK, fetched sample successfully.
(Took some hacks ;-)
As I thought, the crash is gone.

Although there is still no surround.
This is because eac3 defines side surround instead of rear one:

left        center        right
                bass

side left    YOU      side right


rear left             rear right

Xine does not distinguish between side and rear so I treat
them the same for now.

[ff_audio_channel_mixer_4.diff]
ff_audio_dec: fix multichannel playback


Torsten

------------------------------------------------------------------------------
Learn Graph Databases - Download FREE O'Reilly Book
"Graph Databases" is the definitive new guide to graph databases and 
their applications. This 200-page book is written by three acclaimed 
leaders in the field. The early access version is available now. 
Download your free book today! http://p.sf.net/sfu/neotech_d2d_may

_______________________________________________
xine-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/xine-devel
ff_audio_channel_mixer_4.diff (text/x-patch, 21.9 KB)
--- xine-lib-1.2-20130415/src/combined/ffmpeg/ff_audio_decoder.c	2013-04-15 22:10:34.000000000 +0200
+++ xine-lib-1.2-20130415/src/combined/ffmpeg/ff_audio_decoder.c	2013-05-10 22:53:18.000000000 +0200
@@ -46,6 +46,8 @@
 
 #define AUDIOBUFSIZE (64 * 1024)
 
+#define MAX_CHANNELS 6
+
 typedef struct {
   audio_decoder_class_t   decoder_class;
 
@@ -78,6 +80,11 @@ typedef struct ff_audio_decoder_s {
 #if AVAUDIO > 3
   AVFrame          *av_frame;
 #endif
+
+  int8_t            map[MAX_CHANNELS], left[4], right[4];
+  int               front_mixes, downmix_shift;
+  int               ao_channels, ao_mode;
+  int64_t           ff_map;
 } ff_audio_decoder_t;
 
 
@@ -368,6 +387,140 @@ static void ff_audio_output_close(ff_aud
   this->audio_channels = 0;
 }
 
+static void ff_map_channels (ff_audio_decoder_t *this) {
+  int i, j;
+  uint64_t ff_map;
+  int caps = this->stream->audio_out->get_capabilities (this->stream->audio_out);
+  /* ff: see names[] below; xine: L R RL RR C LFE */
+  const int8_t base_map[] = {0, 1, 4, 5, 2, 3, -1, -1, -1, 2, 3};
+  int8_t name_map[MAX_CHANNELS];
+  const int modes[] = {
+    AO_CAP_MODE_MONO, AO_CAP_MODE_STEREO,
+    AO_CAP_MODE_4CHANNEL, AO_CAP_MODE_4_1CHANNEL,
+    AO_CAP_MODE_5CHANNEL, AO_CAP_MODE_5_1CHANNEL
+  };
+  const int num_modes = sizeof (modes) / sizeof (modes[0]);
+  const int8_t mode_channels[]   = {1, 2, 4, 6, 6, 6};
+  const int8_t wishlist[] = {
+    0, 1, 2, 3, 4, 5, /* mono */
+    1, 2, 3, 4, 5, 0, /* stereo */
+    5, 4, 3, 2, 1, 0, /* center + lfe */
+    4, 5, 2, 3, 1, 0, /* center */
+    3, 5, 2, 4, 1, 0, /* lfe */
+    2, 3, 4, 5, 1, 0  /* 4.0 */
+  };
+  const int8_t *tries;
+
+  /* safety kludge for very old libavcodec */
+#ifdef AV_CH_FRONT_LEFT
+  ff_map = this->context->channel_layout;
+#else
+  ff_map = (1 << this->context->channels) - 1;
+#endif
+
+  /* nothing altered */
+  if (ff_map == this->ff_map)
+    return;
+  this->ff_map = ff_map;
+
+  /* silence out */
+  for (i = 0; i < MAX_CHANNELS; i++)
+    this->map[i] = -1;
+  for (i = 0; i < 4; i++)
+    this->left[i] = this->right[i] = -1;
+
+  /* set up raw map and ao mode wishlist */
+  if (this->context->channels == 1) { /* mono */
+    name_map[0] = 2;
+    this->left[0] = this->right[0] = 0;
+    tries = wishlist + 0 * num_modes;
+  } else if (this->context->channels == 2) { /* stereo */
+    name_map[0] = 0;
+    name_map[1] = 1;
+    this->left[0] = 0;
+    this->right[0] = 1;
+    tries = wishlist + 1 * num_modes;
+  } else {
+    for (i = j = 0; i < sizeof (base_map) / sizeof (base_map[0]); i++) {
+      if ((ff_map >> i) & 1) {
+        int8_t target = base_map[i];
+        if ((target >= 0) && (this->map[target] < 0))
+          this->map[target] = j;
+        name_map[j] = i; /* for debug output below */
+        j++;
+      }
+    }
+    this->left[0]  = this->map[0] < 0 ? 0 : this->map[0];
+    this->map[0]   = -1;
+    this->right[0] = this->map[1] < 0 ? 1 : this->map[1];
+    this->map[1]   = -1;
+    tries = wishlist
+      + (2 + (this->map[4] < 0 ? 2 : 0) + (this->map[5] < 0 ? 1 : 0)) * num_modes;
+  }
+  this->front_mixes = 1;
+
+  /* find ao mode */
+  for (i = 0; i < num_modes; i++) if (caps & modes[tries[i]]) break;
+  i = i == num_modes ? 1 : tries[i];
+  this->ao_mode = modes[i];
+  this->ao_channels = mode_channels[i];
+
+  /* mix center to front */
+  if ((this->map[4] >= 0) && !((0x30 >> i) & 1)) {
+    this->left[this->front_mixes]    = this->map[4];
+    this->right[this->front_mixes++] = this->map[4];
+    this->map[4] = -1;
+  }
+  /* mix lfe to front */
+  if ((this->map[5] >= 0) && !((0x28 >> i) & 1)) {
+    this->left[this->front_mixes]    = this->map[5];
+    this->right[this->front_mixes++] = this->map[5];
+    this->map[5] = -1;
+  }
+  /* mix surround to front */
+  if ((this->map[2] >= 0) && (this->map[3] >= 0) && !((0x3c >> i) & 1)) {
+    this->left[this->front_mixes]    = this->map[2];
+    this->right[this->front_mixes++] = this->map[3];
+    this->map[2] = -1;
+    this->map[3] = -1;
+  }
+
+  this->downmix_shift = this->front_mixes > 1 ? 1 : 0;
+  /* this will be on the safe side but usually too soft?? */
+#if 0
+  if (this->front_mixes > 2)
+    this->downmix_shift = 2;
+#endif
+
+  if (this->stream->xine->verbosity >= XINE_VERBOSITY_LOG) {
+    const int8_t *names[] = {
+      "left", "right", "center", "bass",
+      "rear left", "rear right",
+      "half left", "half right",
+      "rear center",
+      "side left", "side right"
+    };
+    int8_t buf[200];
+    int p = sprintf (buf, "ff_audio_dec: channel layout: ");
+    int8_t *indx = this->left;
+    for (i = 0; i < 2; i++) {
+      buf[p++] = '[';
+      for (j = 0; j < this->front_mixes; j++)
+        p += sprintf (buf + p, "%s%s", names[name_map[indx[j]]], (j < this->front_mixes - 1) ? " + " : "");
+      buf[p++] = ']';
+      buf[p++] = ' ';
+      indx = this->right;
+    }
+    for (i = 2; i < this->ao_channels; i++)
+      p += sprintf (buf + p, "[%s] ",
+        ((this->map[i] < 0) || (this->map[i] > 5)) ? (const int8_t *)"-" : names[name_map[this->map[i]]]);
+    buf[p++] = '\n';
+    fwrite (buf, 1, p, stdout);
+  }
+}
+
+#define CLIP_16(v) ((v + 0x8000) & ~0xffff ? (v >> 31) ^ 0x7fff : v)
+
 static int ff_audio_decode (ff_audio_decoder_t *this,
   int16_t *decode_buffer, int *decode_buffer_size, uint8_t *buf, int size) {
   int consumed;
@@ -408,7 +561,7 @@ static int ff_audio_decode (ff_audio_dec
   avpkt.flags = AV_PKT_FLAG_KEY;
 #  if AVAUDIO > 3
   int got_frame;
-  const float gain = this->class->gain;
+  float gain = this->class->gain;
   if (!this->av_frame)
     this->av_frame = avcodec_alloc_frame ();
 
@@ -416,92 +569,231 @@ static int ff_audio_decode (ff_audio_dec
   if ((consumed >= 0) && got_frame) {
     int16_t *q = decode_buffer;
     int samples = this->av_frame->nb_samples;
-    int channels = this->context->channels;
-    int bytes, i, j;
+    int channels = this->ao_channels;
+    int bytes, i, j, shift = this->downmix_shift;
     /* limit buffer */
-    if (channels > 12)
-      channels = 12;
     if (*decode_buffer_size < samples * channels * 2)
       samples = *decode_buffer_size / (channels * 2);
     bytes = samples * channels * 2;
     *decode_buffer_size = bytes;
-    /* convert to packed int16_t. I guess there is something
-       in libavfilter but also another dependency... */
+    /* TJ. convert to packed int16_t while respecting the user's speaker arrangement.
+       I tried to speed up and not to pull in libswresample. */
+    for (i = 2; i < channels; i++) if (this->map[i] < 0) {
+      /* clear if there is an upmix mute channel */
+      memset (q, 0, bytes);
+      break;
+    }
+    /* For mono output, downmix to stereo first */
+    if ((channels == 1) && (this->audio_channels > 1))
+      channels = 2;
+    gain /= (float)(1 << shift);
     switch (this->context->sample_fmt) {
+#define MIX_AUDIO(stype,planar,idx,num,dindx) {\
+    stype *p1, *p2, *p3, *p4;\
+    int i, sstep;\
+    int8_t *x = idx;\
+    int16_t *dptr = (int16_t *)decode_buffer + dindx;\
+    if (planar) {\
+      p1 = (stype *)this->av_frame->extended_data[x[0]];\
+      sstep = 1;\
+    } else {\
+      p1 = (stype *)this->av_frame->extended_data[0] + x[0];\
+      sstep = this->audio_channels;\
+    }\
+    if (num == 1) {\
+      for (i = 0; i < samples; i++) {\
+        int32_t v = MIX_FIX(*p1);\
+        p1       += sstep;\
+        v       >>= shift;\
+        *dptr     = (v);\
+        dptr     += channels;\
+      }\
+    } else {\
+      if (planar)\
+        p2 = (stype *)this->av_frame->extended_data[x[1]];\
+      else\
+        p2 = (stype *)this->av_frame->extended_data[0] + x[1];\
+      if (num == 2) {\
+        for (i = 0; i < samples; i++) {\
+          int32_t v = MIX_FIX(*p1);\
+          p1       += sstep;\
+          v        += MIX_FIX(*p2);\
+          p2       += sstep;\
+          v       >>= shift;\
+          *dptr     = CLIP_16(v);\
+          dptr     += channels;\
+        }\
+      } else {\
+        if (planar)\
+          p3 = (stype *)this->av_frame->extended_data[x[2]];\
+        else\
+          p3 = (stype *)this->av_frame->extended_data[0] + x[2];\
+        if (num == 3) {\
+          for (i = 0; i < samples; i++) {\
+            int32_t v = MIX_FIX(*p1);\
+            p1       += sstep;\
+            v        += MIX_FIX(*p2);\
+            p2       += sstep;\
+            v        += MIX_FIX(*p3);\
+            p3       += sstep;\
+            v       >>= shift;\
+            *dptr     = CLIP_16(v);\
+            dptr     += channels;\
+          }\
+        } else {\
+          if (planar)\
+            p4 = (stype *)this->av_frame->extended_data[x[3]];\
+          else\
+            p4 = (stype *)this->av_frame->extended_data[0] + x[3];\
+          for (i = 0; i < samples; i++) {\
+            int32_t v = MIX_FIX(*p1);\
+            p1       += sstep;\
+            v        += MIX_FIX(*p2);\
+            p2       += sstep;\
+            v        += MIX_FIX(*p3);\
+            p3       += sstep;\
+            v        += MIX_FIX(*p4);\
+            p4       += sstep;\
+            v       >>= shift;\
+            *dptr     = CLIP_16(v);\
+            dptr     += channels;\
+          }\
+        }\
+      }\
+    }\
+  }
+#define MIX_FIX(v) (((int16_t)(v)<<8)^0x8000)
       case AV_SAMPLE_FMT_U8P:
-        if (channels > 1) {
-          uint8_t *p[12];
-          for (i = 0; i < channels; i++)
-            p[i] = (uint8_t *)this->av_frame->extended_data[i];
-          for (i = samples; i; i--) {
-            for (j = 0; j < channels; j++)
-              *q++ = ((uint16_t)(*p[j]++) << 8) ^ 0x8000;
-          }
-          break;
-        }
+        MIX_AUDIO (uint8_t, 1, this->left,  this->front_mixes, 0);
+        MIX_AUDIO (uint8_t, 1, this->right, this->front_mixes, 1);
+        for (j = 0; j < channels; j++) if (this->map[j] >= 0)
+          MIX_AUDIO (uint8_t, 1, this->map + j, 1, j);
+      break;
       case AV_SAMPLE_FMT_U8:
-        {
-          uint8_t *p = (uint8_t *)this->av_frame->extended_data[0];
-          for (i = samples * channels; i; i--)
-            *q++ = ((uint16_t)(*p++) << 8) ^ 0x8000;
-        }
+        MIX_AUDIO (uint8_t, 0, this->left,  this->front_mixes, 0);
+        MIX_AUDIO (uint8_t, 0, this->right, this->front_mixes, 1);
+        for (j = 0; j < channels; j++) if (this->map[j] >= 0)
+          MIX_AUDIO (uint8_t, 0, this->map + j, 1, j);
       break;
+#undef MIX_FIX
+#define MIX_FIX(v) (v)
       case AV_SAMPLE_FMT_S16P:
-        if (channels > 1) {
-          int16_t *p[12];
-          for (i = 0; i < channels; i++)
-            p[i] = (int16_t *)this->av_frame->extended_data[i];
-          for (i = samples; i; i--) {
-            for (j = 0; j < channels; j++)
-              *q++ = *p[j]++;
-          }
-          break;
-        }
+        MIX_AUDIO (int16_t, 1, this->left,  this->front_mixes, 0);
+        MIX_AUDIO (int16_t, 1, this->right, this->front_mixes, 1);
+        for (j = 0; j < channels; j++) if (this->map[j] >= 0)
+          MIX_AUDIO (int16_t, 1, this->map + j, 1, j);
+      break;
       case AV_SAMPLE_FMT_S16:
-        xine_fast_memcpy (q, this->av_frame->extended_data[0], bytes);
+        MIX_AUDIO (int16_t, 0, this->left,  this->front_mixes, 0);
+        MIX_AUDIO (int16_t, 0, this->right, this->front_mixes, 1);
+        for (j = 0; j < channels; j++) if (this->map[j] >= 0)
+          MIX_AUDIO (int16_t, 0, this->map + j, 1, j);
       break;
+#undef MIX_FIX
+#define MIX_FIX(v) ((v)>>16)
       case AV_SAMPLE_FMT_S32P:
-        if (channels > 1) {
-          int32_t *p[12];
-          for (i = 0; i < channels; i++)
-            p[i] = (int32_t *)this->av_frame->extended_data[i];
-          for (i = samples; i; i--) {
-            for (j = 0; j < channels; j++)
-              *q++ = *p[j]++ >> 16;
-          }
-          break;
-        }
+        MIX_AUDIO (int32_t, 1, this->left,  this->front_mixes, 0);
+        MIX_AUDIO (int32_t, 1, this->right, this->front_mixes, 1);
+        for (j = 0; j < channels; j++) if (this->map[j] >= 0)
+          MIX_AUDIO (int32_t, 1, this->map + j, 1, j);
+      break;
       case AV_SAMPLE_FMT_S32:
-        {
-          int32_t *p = (int32_t *)this->av_frame->extended_data[0];
-          for (i = samples * channels; i; i--)
-            *q++ = *p++ >> 16;
-        }
+        MIX_AUDIO (int32_t, 0, this->left,  this->front_mixes, 0);
+        MIX_AUDIO (int32_t, 0, this->right, this->front_mixes, 1);
+        for (j = 0; j < channels; j++) if (this->map[j] >= 0)
+          MIX_AUDIO (int32_t, 0, this->map + j, 1, j);
       break;
+#undef MIX_FIX
+#undef MIX_AUDIO
+#define MIX_AUDIO(stype,planar,idx,num,dindx) {\
+    stype *p1, *p2, *p3, *p4;\
+    int i, sstep;\
+    int8_t *x = idx;\
+    int16_t *dptr = (int16_t *)decode_buffer + dindx;\
+    if (planar) {\
+      p1 = (stype *)this->av_frame->extended_data[x[0]];\
+      sstep = 1;\
+    } else {\
+      p1 = (stype *)this->av_frame->extended_data[0] + x[0];\
+      sstep = this->audio_channels;\
+    }\
+    if (num == 1) {\
+      for (i = 0; i < samples; i++) {\
+        int32_t v = (*p1) * gain;\
+        p1       += sstep;\
+        *dptr     = CLIP_16(v);\
+        dptr     += channels;\
+      }\
+    } else {\
+      if (planar)\
+        p2 = (stype *)this->av_frame->extended_data[x[1]];\
+      else\
+        p2 = (stype *)this->av_frame->extended_data[0] + x[1];\
+      if (num == 2) {\
+        for (i = 0; i < samples; i++) {\
+          int32_t v = (*p1 + *p2) * gain;\
+          p1       += sstep;\
+          p2       += sstep;\
+          *dptr     = CLIP_16(v);\
+          dptr     += channels;\
+        }\
+      } else {\
+        if (planar)\
+          p3 = (stype *)this->av_frame->extended_data[x[2]];\
+        else\
+          p3 = (stype *)this->av_frame->extended_data[0] + x[2];\
+        if (num == 3) {\
+          for (i = 0; i < samples; i++) {\
+            int32_t v = (*p1 + *p2 + *p3) * gain;\
+            p1       += sstep;\
+            p2       += sstep;\
+            p3       += sstep;\
+            *dptr     = CLIP_16(v);\
+            dptr     += channels;\
+          }\
+        } else {\
+          if (planar)\
+            p4 = (stype *)this->av_frame->extended_data[x[3]];\
+          else\
+            p4 = (stype *)this->av_frame->extended_data[0] + x[3];\
+          for (i = 0; i < samples; i++) {\
+            int32_t v = (*p1 + *p2 + *p3 + *p4) * gain;\
+            p1       += sstep;\
+            p2       += sstep;\
+            p3       += sstep;\
+            p4       += sstep;\
+            *dptr     = CLIP_16(v);\
+            dptr     += channels;\
+          }\
+        }\
+      }\
+    }\
+  }
       case AV_SAMPLE_FMT_FLTP: /* the most popular one */
-        if (channels > 1) {
-          float *p[12];
-          for (i = 0; i < channels; i++)
-            p[i] = (float *)this->av_frame->extended_data[i];
-          for (i = samples; i; i--) {
-            for (j = 0; j < channels; j++) {
-              int v = *p[j]++ * gain;
-              *q++ = (v + 0x8000) & ~0xffff ? (v >> 31) ^ 0x7fff : v;
-            }
-          }
-          break;
-        }
+        MIX_AUDIO (float, 1, this->left,  this->front_mixes, 0);
+        MIX_AUDIO (float, 1, this->right, this->front_mixes, 1);
+        for (j = 0; j < channels; j++) if (this->map[j] >= 0)
+          MIX_AUDIO (float, 1, this->map + j, 1, j);
+      break;
       case AV_SAMPLE_FMT_FLT:
-        {
-          float *p = (float *)this->av_frame->extended_data[0];
-          for (i = samples * channels; i; i--) {
-            int v = *p++ * gain;
-            *q++ = (v + 0x8000) & ~0xffff ? (v >> 31) ^ 0x7fff : v;
-          }
-        }
+        MIX_AUDIO (float, 0, this->left,  this->front_mixes, 0);
+        MIX_AUDIO (float, 0, this->right, this->front_mixes, 1);
+        for (j = 0; j < channels; j++) if (this->map[j] >= 0)
+          MIX_AUDIO (float, 0, this->map + j, 1, j);
       break;
       default: ;
     }
+    if (channels > this->ao_channels) {
+      /* final mono downmix */
+      int16_t *p = decode_buffer;
+      q = p;
+      for (i = samples; i; i--) {
+        int v = *p++;
+        v += *p++;
+        *q++ = v >> 1;
+      }
+      *decode_buffer_size = samples * 2;
+    }
   } else *decode_buffer_size = 0;
 #  else
   consumed = avcodec_decode_audio3 (this->context, decode_buffer, decode_buffer_size, &avpkt);
@@ -605,9 +897,10 @@ static void ff_audio_decode_data (audio_
 	    /* pts applies only to first audio packet */
 	    buf->pts = 0;
 	  } else {
+	    ff_map_channels (this);
 	    this->output_open = (this->stream->audio_out->open) (this->stream->audio_out,
 								 this->stream, this->audio_bits, this->audio_sample_rate,
-								 _x_ao_channels2mode(this->audio_channels));
+								 this->ao_mode);
 	    if (!this->output_open) {
 	      xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
 		      "ffmpeg_audio_dec: error opening audio output\n");
@@ -617,6 +910,84 @@ static void ff_audio_decode_data (audio_
 	  }
 	}
 
+#if AVAUDIO < 4
+        /* Old style postprocessing */
+        if (codec_type == BUF_AUDIO_WMAPRO) {
+          /* the above codecs output float samples, not 16-bit integers */
+          int samples = decode_buffer_size / sizeof(float);
+          float gain  = this->class->gain;
+          float *p    = (float *)this->decode_buffer;
+          int16_t *q  = (int16_t *)this->decode_buffer;
+          int i;
+          for (i = samples; i; i--) {
+            int v = *p++ * gain;
+            *q++ = CLIP_16 (v);
+          }
+          decode_buffer_size = samples * 2;
+        }
+
+        if ((this->ao_channels != this->audio_channels) || (this->ao_channels > 2)) {
+          /* Channel reordering and/or mixing */
+          int samples     = decode_buffer_size / (this->audio_channels * 2);
+          int channels    = this->ao_channels;
+          int ff_channels = this->audio_channels;
+          int16_t *p      = (int16_t *)this->decode_buffer;
+          int16_t *q      = p;
+          int shift       = this->downmix_shift, i, j;
+          /* downmix mono output to stereo first */
+          if ((channels == 1) && (ff_channels > 1))
+            channels = 2;
+          /* move to end of buf for in-place editing */
+          p += AVCODEC_MAX_AUDIO_FRAME_SIZE - decode_buffer_size;
+          if (p >= q + decode_buffer_size)
+            xine_fast_memcpy (p, q, decode_buffer_size);
+          else
+            memmove (p, q, decode_buffer_size);
+          /* not very optimized but it only hits when playing multichannel audio through
+             old ffmpeg - and its still better than previous code there */
+          if (this->front_mixes < 2) {
+            /* just reorder and maybe upmix */
+            for (i = samples; i; i--) {
+              q[0] = p[0];
+              q[1] = p[this->right[0]];
+              for (j = 2; j < channels; j++)
+                q[j] = this->map[j] < 0 ? 0 : p[this->map[j]];
+              p += ff_channels;
+              q += channels;
+            }
+          } else {
+            /* downmix */
+            for (i = samples; i; i--) {
+              int left  = p[0];
+              int right = p[this->right[0]];
+              for (j = 1; j < this->front_mixes; j++) {
+                left  += p[this->left[j]];
+                right += p[this->right[j]];
+              }
+              left  >>= shift;
+              q[0]    = CLIP_16 (left);
+              right >>= shift;
+              q[1]    = CLIP_16 (right);
+              for (j = 2; j < channels; j++)
+                q[j] = this->map[j] < 0 ? 0 : p[this->map[j]] >> shift;
+              p += ff_channels;
+              q += channels;
+            }
+          }
+          /* final mono downmix */
+          if (channels > this->ao_channels) {
+            p = (int16_t *)this->decode_buffer;
+            q = p;
+            for (i = samples; i; i--) {
+              int v = *p++;
+              v += *p++;
+              *q++ = v >> 1;
+            }
+          }
+          decode_buffer_size = samples * this->ao_channels * 2;
+        }
+#endif
+
         /* dispatch the decoded audio */
         out = 0;
         while (out < decode_buffer_size) {
@@ -636,40 +1007,16 @@ static void ff_audio_decode_data (audio_
           }
 
           /* fill up this buffer */
-#if AVAUDIO < 4
-          if (codec_type == BUF_AUDIO_WMAPRO) {
-            /* the above codecs output float samples, not 16-bit integers */
-            int bytes_per_sample = sizeof(float);
-            if (((decode_buffer_size - out) * 2 / bytes_per_sample) > audio_buffer->mem_size)
-              bytes_to_send = audio_buffer->mem_size * bytes_per_sample / 2;
-            else
-              bytes_to_send = decode_buffer_size - out;
-
-            int16_t *int_buffer = calloc(1, bytes_to_send * 2 / bytes_per_sample);
-            int i;
-            for (i = 0; i < (bytes_to_send / bytes_per_sample); i++) {
-              float *float_sample = (float *)&this->decode_buffer[i * bytes_per_sample + out];
-              int_buffer[i] = (int16_t)lrintf(*float_sample * 32768.);
-            }
+          if ((decode_buffer_size - out) > audio_buffer->mem_size)
+            bytes_to_send = audio_buffer->mem_size;
+          else
+            bytes_to_send = decode_buffer_size - out;
 
-            out += bytes_to_send;
-            bytes_to_send = bytes_to_send * 2 / bytes_per_sample;
-            xine_fast_memcpy(audio_buffer->mem, int_buffer, bytes_to_send);
-            free(int_buffer);
-          } else
-#endif
-          {
-            if ((decode_buffer_size - out) > audio_buffer->mem_size)
-              bytes_to_send = audio_buffer->mem_size;
-            else
-              bytes_to_send = decode_buffer_size - out;
-
-            xine_fast_memcpy(audio_buffer->mem, &this->decode_buffer[out], bytes_to_send);
-            out += bytes_to_send;
-          }
+          xine_fast_memcpy(audio_buffer->mem, &this->decode_buffer[out], bytes_to_send);
+          out += bytes_to_send;
 
           /* byte count / 2 (bytes / sample) / channels */
-          audio_buffer->num_frames = bytes_to_send / 2 / this->audio_channels;
+          audio_buffer->num_frames = bytes_to_send / 2 / this->ao_channels;
 
           audio_buffer->vpts = buf->pts;