From aa2e74040e9b1f66effd8607825e0a6bd7cf683d Mon Sep 17 00:00:00 2001
From: Jack Moffitt <jack@xiph.org>
Date: Wed, 27 Sep 2000 06:12:32 +0000
Subject: [PATCH] brought up to date with postbeta2

git-svn-id: http://svn.xiph.org/trunk/ao@698 0101bb08-14d6-0310-b084-bc0e0c8e3800
---
 include/ao/ao.h | 12 +++++-------
 src/ao_alsa.c   |  5 +++--
 src/ao_oss.c    |  6 +++---
 src/ao_wav.c    | 52 ++++++++++++++++++++++++++++++++++++++++++++++---
 src/audio_out.c | 13 ++++++++++++-
 5 files changed, 72 insertions(+), 16 deletions(-)

diff --git a/include/ao/ao.h b/include/ao/ao.h
index c1042b4..87d7102 100644
--- a/include/ao/ao.h
+++ b/include/ao/ao.h
@@ -1,6 +1,6 @@
 /*
  *
- *  ao.h 
+ *  audio_out.h 
  *    
  *	Original Copyright (C) Aaron Holtzman - May 1999
  *      Modifications Copyright (C) Stan Seibert - July 2000
@@ -24,13 +24,10 @@
  *
  */
 
-#ifndef __AO_H__
-#define __AO_H__
-
 #include <stdlib.h>
 
-/* Type sizes */
-#include <ao/os_types.h>
+// Type sizes
+#include "config.h"
 
 /* --- Structures --- */
 
@@ -90,6 +87,7 @@ typedef struct ao_device_s
 /* Total number of drivers */
 #define AO_DRIVERS 12
 
+
 /* --- Functions --- */
 
 int ao_get_driver_id (const char *short_name);
@@ -108,4 +106,4 @@ int ao_append_option (ao_option_t **options, const char* op_str);
 
 void ao_free_options (ao_option_t* options);
 
-#endif  /* __AO_H__ */
+int ao_is_big_endian();
diff --git a/src/ao_alsa.c b/src/ao_alsa.c
index 2caa05d..20ef05a 100644
--- a/src/ao_alsa.c
+++ b/src/ao_alsa.c
@@ -31,7 +31,7 @@
 #include <string.h>
 
 #include <sys/asoundlib.h>
-#include <ao/ao.h>
+#include "audio_out.h"
 
 #define AO_ALSA_BUF_SIZE 32768
 
@@ -91,7 +91,8 @@ ao_alsa_open (uint_32 bits, uint_32 rate, uint_32 channels, ao_option_t *options
 	{
 	case 8  : param.format.format = SND_PCM_SFMT_S8;
 		  break;
-	case 16 : param.format.format = SND_PCM_SFMT_S16_LE;
+        case 16 : param.format.format = ao_is_big_endian() ?
+		    SND_PCM_SFMT_S16_BE : SND_PCM_SFMT_S16_LE;
 		  break;
 	default : return NULL;
 	}
diff --git a/src/ao_oss.c b/src/ao_oss.c
index d5d5a7e..395f5b3 100644
--- a/src/ao_oss.c
+++ b/src/ao_oss.c
@@ -39,7 +39,7 @@
 #endif
 #include <sys/ioctl.h>
 
-#include <ao/ao.h>
+#include "audio_out.h"
 
 static ao_info_t ao_oss_info =
 {
@@ -120,8 +120,8 @@ ao_oss_open(uint_32 bits, uint_32 rate, uint_32 channels, ao_option_t *options)
 	{
 	case 8: tmp = AFMT_S8;
 		break;
-	case 16: tmp = AFMT_S16_LE;
-		break;
+        case 16: tmp = ao_is_big_endian() ? AFMT_S16_BE : AFMT_S16_LE;
+	        break;
 	default:fprintf(stderr,"libao - Unsupported number of bits: %d.",
 			bits);
 		goto ERR;
diff --git a/src/ao_wav.c b/src/ao_wav.c
index b529823..0c542e2 100644
--- a/src/ao_wav.c
+++ b/src/ao_wav.c
@@ -32,7 +32,7 @@
 #include <fcntl.h>
 #include <signal.h>
 
-#include <ao/ao.h>
+#include "audio_out.h"
 
 #define WAVE_FORMAT_PCM  0x0001
 #define FORMAT_MULAW     0x0101
@@ -49,6 +49,8 @@
 #define WRITE_U16(buf, x) *(buf)     = (unsigned char)(x&0xff);\
 						  *((buf)+1) = (unsigned char)((x>>8)&0xff);
 
+#define DEFAULT_SWAP_BUFFER_SIZE 2048
+
 struct riff_struct 
 {
   unsigned char id[4];   /* RIFF */
@@ -94,6 +96,9 @@ typedef struct ao_wav_internal_s
 {
 	char *output_file;
 	int fd;
+	int byte_swap;
+	char *swap_buffer;
+	int buffer_size;
 	struct wave_header wave;
 } ao_wav_internal_t;
 
@@ -147,7 +152,19 @@ ao_wav_open(uint_32 bits, uint_32 rate, uint_32 channels, ao_option_t *options)
 
 	// Grab options here
 	ao_wav_parse_options(state, options);
-
+	state->byte_swap = (bits == 16) && (ao_is_big_endian());
+	if (state->byte_swap)
+	{
+		state->buffer_size = DEFAULT_SWAP_BUFFER_SIZE;
+		state->swap_buffer = calloc(sizeof(char), state->buffer_size);
+	       
+		if (state->swap_buffer == NULL)
+		{
+			fprintf(stderr, "ao_wav: Could not allocate byte-swapping buffer.\n");
+			goto ERR;
+		}
+	}
+		
 	state->fd=open(state->output_file,O_WRONLY | O_TRUNC | O_CREAT, 0644);
 
 	if(state->fd < 0) 
@@ -201,7 +218,36 @@ ERR:
 static void
 ao_wav_play(ao_internal_t *state, void *output_samples, uint_32 num_bytes)
 {
-  	write( ((ao_wav_internal_t *) state)->fd, output_samples, num_bytes );
+	int i;
+	ao_wav_internal_t *s = (ao_wav_internal_t *) state;
+
+	/* Swap all of the bytes if things are not little_endian */
+	if (s->byte_swap)
+	{
+		/* Resize buffer larger if needed */
+		if (num_bytes > s->buffer_size)
+		{
+			s->swap_buffer = realloc(s->swap_buffer, sizeof(char)*num_bytes);
+			if (s->swap_buffer == NULL) {
+				fprintf(stderr, "ao_wav: Could not resize swap buffer.\n");
+				return;
+			}
+			else
+				s->buffer_size = num_bytes;
+		}
+
+		/* Swap the bytes into the swap buffer (so we don't
+		 mess up the output_samples buffer) */
+		for(i = 0; i < num_bytes/2; i+=2)
+		{
+			s->swap_buffer[i]   = ((char *) output_samples)[i+1];
+			s->swap_buffer[i+1] = ((char *) output_samples)[i];
+		}
+
+		write(s->fd, s->swap_buffer, num_bytes );
+	}
+	else    /* Otherwise just write the output buffer directly */
+		write(s->fd, output_samples, num_bytes );
 }
 
 
diff --git a/src/audio_out.c b/src/audio_out.c
index b94d667..59fb739 100644
--- a/src/audio_out.c
+++ b/src/audio_out.c
@@ -27,7 +27,8 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
-#include <ao/ao.h>
+#include <assert.h>
+#include "audio_out.h"
 
 /* --- Function Tables --- */
 
@@ -268,3 +269,13 @@ void ao_free_options (ao_option_t* options)
 		options = rest;
 	}
 }
+
+/* Helper function lifted from lib/vorbisfile.c */
+int ao_is_big_endian() {
+	uint_16 pattern = 0xbabe;
+	unsigned char *bytewise = (unsigned char *)&pattern;
+	if (bytewise[0] == 0xba) return 1;
+	
+	assert(bytewise[0] == 0xbe);
+	return 0;
+}
-- 
GitLab