shithub: opus-tools

Download patch

ref: 37016e01527e98e3d2240d0d49454a4abc5631c5
parent: 7b4a6289ed0b1d27ea0660dbac1908d0ad6ec3df
author: Mark Harris <mark.hsj@gmail.com>
date: Fri Sep 14 16:43:34 EDT 2018

opusdec, opusenc: Fix float WAV on big endian host

WAV uses little endian for floats so they must be byte-swapped.

--- a/src/audio-in.c
+++ b/src/audio-in.c
@@ -73,6 +73,7 @@
 #include <ogg/ogg.h>
 #include "encoder.h"
 #include "opus_header.h"
+#include "wav_io.h"
 #include "flac.h"
 
 /* Macros for handling potentially large file offsets */
@@ -816,7 +817,7 @@
 
     for (i=0; i < realsamples; i++)
         for (j=0; j < f->channels; j++)
-            buffer[i*f->channels+j] = buf[i*f->channels + f->channel_permute[j]];
+            buffer[i*f->channels+j] = get_le_float(buf + i*f->channels + f->channel_permute[j]);
 
     return realsamples;
 }
--- a/src/opusdec.c
+++ b/src/opusdec.c
@@ -511,7 +511,7 @@
        frame_size -= in_len;
      } else {
        output=pcm;
-       out_len=frame_size;
+       out_len=frame_size<maxout?(unsigned)frame_size:(unsigned)maxout;
        frame_size=0;
      }
 
@@ -534,25 +534,30 @@
             out[i]=le_short(out[i]);
         }
      }
+     else if (le_short(1)!=(1)) {
+       /* ensure the floats are little endian */
+       for (i=0;i<(int)out_len*channels;i++)
+         put_le_float(buf+i, output[i]);
+       output = buf;
+     }
 
      if (maxout>0)
      {
 #if defined WIN32 || defined _WIN32
        if (!file) {
-         ret=WIN_Play_Samples(out, sizeof(short) * channels * (out_len<maxout?out_len:maxout));
+         ret=WIN_Play_Samples(out, sizeof(short) * channels * out_len);
          if (ret>0) ret/=sizeof(short)*channels;
          else fprintf(stderr, "Error playing audio.\n");
        } else
 #elif defined HAVE_LIBSNDIO
        if (!file) {
-         ret=sio_write(hdl, out, sizeof(short) * channels * (out_len<maxout?out_len:maxout));
+         ret=sio_write(hdl, out, sizeof(short) * channels * out_len);
          if (ret>0) ret/=sizeof(short)*channels;
          else fprintf(stderr, "Error playing audio.\n");
        } else
 #endif
          ret=fwrite(fp?(char *)output:(char *)out,
-          (fp?sizeof(float):sizeof(short))*channels,
-          out_len<maxout?out_len:maxout, fout);
+          (fp?sizeof(float):sizeof(short))*channels, out_len, fout);
        sampout+=ret;
        maxout-=ret;
      }
--- a/src/opusenc.c
+++ b/src/opusenc.c
@@ -70,7 +70,6 @@
 #include <opus_multistream.h>
 #include <opusenc.h>
 
-#include "wav_io.h"
 #include "opus_header.h"
 #include "encoder.h"
 #include "diag_range.h"
--- a/src/wav_io.h
+++ b/src/wav_io.h
@@ -55,6 +55,36 @@
 #endif
 }
 
+static inline float get_le_float(float *ptr)
+{
+#if !defined(__LITTLE_ENDIAN__) && ( defined(WORDS_BIGENDIAN) || defined(__BIG_ENDIAN__) )
+    float val;
+    char *lebytes = (char *)ptr;
+    char *nebytes = (char *)&val;
+    nebytes[0] = lebytes[3];
+    nebytes[1] = lebytes[2];
+    nebytes[2] = lebytes[1];
+    nebytes[3] = lebytes[0];
+    return val;
+#else
+    return *ptr;
+#endif
+}
+
+static inline void put_le_float(float *ptr, float val)
+{
+#if !defined(__LITTLE_ENDIAN__) && ( defined(WORDS_BIGENDIAN) || defined(__BIG_ENDIAN__) )
+    char *lebytes = (char *)ptr;
+    char *nebytes = (char *)&val;
+    lebytes[0] = nebytes[3];
+    lebytes[1] = nebytes[2];
+    lebytes[2] = nebytes[1];
+    lebytes[3] = nebytes[0];
+#else
+    *ptr = val;
+#endif
+}
+
 void adjust_wav_mapping(int mapping_family, int channels, unsigned char *stream_map);
 
 int write_wav_header(FILE *file, int rate, int mapping_family, int channels, int fp);