opusdec, opusenc: Fix float WAV on big endian host
authorMark Harris <mark.hsj@gmail.com>
Sat, 15 Sep 2018 03:43:34 +0000 (20:43 -0700)
committerMark Harris <mark.hsj@gmail.com>
Sat, 15 Sep 2018 04:50:21 +0000 (21:50 -0700)
WAV uses little endian for floats so they must be byte-swapped.

src/audio-in.c
src/opusdec.c
src/opusenc.c
src/wav_io.h

index 7f0e841..66b5d04 100644 (file)
@@ -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 @@ long wav_ieee_read(void *in, float *buffer, int samples)
 
     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;
 }
index 37c74ae..6c1a917 100644 (file)
@@ -511,7 +511,7 @@ opus_int64 audio_write(float *pcm, int channels, int frame_size, FILE *fout,
        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 @@ opus_int64 audio_write(float *pcm, int channels, int frame_size, FILE *fout,
             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;
      }
index 6d8fea7..87b54b6 100644 (file)
@@ -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"
index 24055ce..d382a13 100644 (file)
@@ -55,6 +55,36 @@ static inline opus_int32 le_int(opus_int32 i)
 #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);