--- a52dec-0.7.4/libao/audio_out.c Wed May 22 07:35:22 2002 +++ a52dec-0.7.4-hp/libao/audio_out.c Sat Oct 11 18:13:26 2003 @@ -43,6 +43,17 @@ extern ao_open_t ao_windolby_open; extern ao_open_t ao_wav_open; extern ao_open_t ao_wavdolby_open; +extern ao_open_t ao_wav4_open; +extern ao_open_t ao_wav6_open; +extern ao_open_t ao_wavext_open; +extern ao_open_t ao_wavextdolby_open; +extern ao_open_t ao_wavext4_open; +extern ao_open_t ao_wavext6_open; +extern ao_open_t ao_wavextauto_open; +extern ao_open_t ao_au_open; +extern ao_open_t ao_audolby_open; +extern ao_open_t ao_au4_open; +extern ao_open_t ao_au6_open; extern ao_open_t ao_aif_open; extern ao_open_t ao_aifdolby_open; extern ao_open_t ao_peak_open; @@ -75,6 +86,17 @@ #endif {"wav", ao_wav_open}, {"wavdolby", ao_wavdolby_open}, + {"wav4", ao_wav4_open}, + {"wav6", ao_wav6_open}, + {"wavext", ao_wavext_open}, + {"wavextdolby", ao_wavextdolby_open}, + {"wavext4", ao_wavext4_open}, + {"wavext6", ao_wavext6_open}, + {"wavextauto", ao_wavextauto_open}, + {"au", ao_au_open}, + {"audolby", ao_audolby_open}, + {"au4", ao_au4_open}, + {"au6", ao_au6_open}, {"aif", ao_aif_open}, {"aifdolby", ao_aifdolby_open}, {"peak", ao_peak_open}, --- a52dec-0.7.4/libao/audio_out_wav.c Sun Apr 28 12:23:02 2002 +++ a52dec-0.7.4-hp/libao/audio_out_wav.c Fri Mar 14 20:35:19 2003 @@ -71,33 +71,60 @@ buf[3] = value >> 24; } +static void store16 (uint8_t * buf, int value) +{ + buf[0] = value; + buf[1] = value >> 8; +} + static int wav_play (ao_instance_t * _instance, int flags, sample_t * _samples) { wav_instance_t * instance = (wav_instance_t *) _instance; - int16_t int16_samples[256*2]; + int16_t int16_samples[256*6]; + int chans = -1; + int j; + int16_t t; #ifdef LIBA52_DOUBLE - float samples[256 * 2]; + float samples[256 * 6]; int i; - for (i = 0; i < 256 * 2; i++) + for (i = 0; i < 256 * 6; i++) samples[i] = _samples[i]; #else float * samples = _samples; #endif + chans = channels_multi (flags); + flags &= A52_CHANNEL_MASK | A52_LFE; + if (instance->set_params) { instance->set_params = 0; + store16 (wav_header + 22, chans); store (wav_header + 24, instance->sample_rate); - store (wav_header + 28, instance->sample_rate * 4); + store (wav_header + 28, instance->sample_rate * 2 * chans); + store16 (wav_header + 32, 2 * chans); fwrite (wav_header, sizeof (wav_header), 1, stdout); } - float2s16_2 (samples, int16_samples); - s16_LE (int16_samples, 2); - fwrite (int16_samples, 256 * sizeof (int16_t) * 2, 1, stdout); + float2s16_multi (samples, int16_samples, flags); + s16_LE (int16_samples, chans); + /* 2ch: L,R */ + /* 4ch: L,R,LS,RS */ + /* 6ch(a52): L,R,LS,RS,C,LFE */ + /* 6ch(wav): L,R,C,LFE,LS,RS */ + if (chans==6) + for (j = 0; j < 256 * 6; j += 6) { + t = int16_samples[j+2]; + int16_samples[j+2] = int16_samples[j+4]; + int16_samples[j+4] = t; + t = int16_samples[j+3]; + int16_samples[j+3] = int16_samples[j+5]; + int16_samples[j+5] = t; + } + fwrite (int16_samples, 256 * sizeof (int16_t) * chans, 1, stdout); - instance->size += 256 * sizeof (int16_t) * 2; + instance->size += 256 * sizeof (int16_t) * chans; return 0; } @@ -143,3 +170,14 @@ { return wav_open (A52_DOLBY); } + +ao_instance_t * ao_wav4_open (void) +{ + return wav_open (A52_2F2R); +} + +ao_instance_t * ao_wav6_open (void) +{ + return wav_open (A52_3F2R | A52_LFE); +} + --- a52dec-0.7.4/libao/audio_out_wavext.c Thu Jan 1 01:00:00 1970 +++ a52dec-0.7.4-hp/libao/audio_out_wavext.c Sat Oct 11 19:22:26 2003 @@ -0,0 +1,207 @@ +/* + * audio_out_wavext.c + * Copyright (C) 2000-2002 Michel Lespinasse + * Copyright (C) 1999-2000 Aaron Holtzman + * + * This file is part of a52dec, a free ATSC A-52 stream decoder. + * See http://liba52.sourceforge.net/ for updates. + * + * a52dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * a52dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" + +#include +#include +#include +#include + +#include "a52.h" +#include "audio_out.h" +#include "audio_out_internal.h" + +typedef struct wavext_instance_s { + ao_instance_t ao; + int sample_rate; + int set_params; + int flags; + uint32_t speaker_flags; + int size; +} wavext_instance_t; + +static uint8_t wavext_header[] = { + 'R', 'I', 'F', 'F', 0xf0, 0xff, 0xff, 0xff, 'W', 'A', 'V', 'E', + 'f', 'm', 't', ' ', 40, 0, 0, 0, + 0xfe, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, + 22, 0, 16, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0x10, 0x00, 0x80, 0, 0, 0xaa, 0, 0x38, 0x9b, 0x71, + 'd', 'a', 't', 'a', 0xb4, 0xff, 0xff, 0xff +}; + +static int wavext_setup (ao_instance_t * _instance, int sample_rate, int * flags, + sample_t * level, sample_t * bias) +{ + wavext_instance_t * instance = (wavext_instance_t *) _instance; + + if ((instance->set_params == 0) && (instance->sample_rate != sample_rate)) + return 1; + instance->sample_rate = sample_rate; + + *flags = instance->flags; + *level = 1; + *bias = 384; + + return 0; +} + +static void store (uint8_t * buf, int value) +{ + buf[0] = value; + buf[1] = value >> 8; + buf[2] = value >> 16; + buf[3] = value >> 24; +} + +static void store16 (uint8_t * buf, int value) +{ + buf[0] = value; + buf[1] = value >> 8; +} + +static int wav_channels (int flags, uint32_t * speaker_flags) +{ + static const uint16_t speaker_tbl[] = { + 3, 4, 3, 7, 0x103, 0x107, 0x33, 0x37, 4, 4, 3 + }; + static const uint8_t nfchans_tbl[] = { + 2, 1, 2, 3, 3, 4, 4, 5, 1, 1, 2 + }; + int chans; + + *speaker_flags = speaker_tbl[flags & A52_CHANNEL_MASK]; + chans = nfchans_tbl[flags & A52_CHANNEL_MASK]; + + if (flags & A52_LFE) { + *speaker_flags |= 8; /* WAVE_SPEAKER_LOW_FREQUENCY */ + chans++; + } + + return chans; +} + +static int wavext_play (ao_instance_t * _instance, int flags, sample_t * _samples) +{ + wavext_instance_t * instance = (wavext_instance_t *) _instance; + int16_t int16_samples[256*6]; + int chans = -1; + int j; + int16_t t; + uint32_t speaker_flags; + +#ifdef LIBA52_DOUBLE + float samples[256 * 6]; + int i; + + for (i = 0; i < 256 * 6; i++) + samples[i] = _samples[i]; +#else + float * samples = _samples; +#endif + + chans = wav_channels (flags, &speaker_flags); + + if (instance->set_params) { + instance->set_params = 0; + instance->speaker_flags = speaker_flags; + store16 (wavext_header + 22, chans); + store (wavext_header + 24, instance->sample_rate); + store (wavext_header + 28, instance->sample_rate * 2 * chans); + store16 (wavext_header + 32, 2 * chans); + store (wavext_header + 40, speaker_flags); + fwrite (wavext_header, sizeof (wavext_header), 1, stdout); + } + else if (speaker_flags != instance->speaker_flags) + return 1; + + float2s16_wav (samples, int16_samples, flags); + s16_LE (int16_samples, chans); + /* 2ch: L,R */ + /* 4ch: L,R,LS,RS */ + /* 6ch(a52): L,R,LS,RS,C,LFE */ + /* 6ch(wav): L,R,C,LFE,LS,RS */ + fwrite (int16_samples, 256 * sizeof (int16_t) * chans, 1, stdout); + + instance->size += 256 * sizeof (int16_t) * chans; + + return 0; +} + +static void wavext_close (ao_instance_t * _instance) +{ + wavext_instance_t * instance = (wavext_instance_t *) _instance; + + if (fseek (stdout, 0, SEEK_SET) < 0) + return; + + store (wavext_header + 4, instance->size + 60); + store (wavext_header + 64, instance->size); + fwrite (wavext_header, sizeof (wavext_header), 1, stdout); +} + +static ao_instance_t * wavext_open (int flags) +{ + wavext_instance_t * instance; + + instance = malloc (sizeof (wavext_instance_t)); + if (instance == NULL) + return NULL; + + instance->ao.setup = wavext_setup; + instance->ao.play = wavext_play; + instance->ao.close = wavext_close; + + instance->sample_rate = 0; + instance->set_params = 1; + instance->flags = flags; + instance->size = 0; + + return (ao_instance_t *) instance; +} + +ao_instance_t * ao_wavext_open (void) +{ + return wavext_open (A52_STEREO); +} + +ao_instance_t * ao_wavextdolby_open (void) +{ + return wavext_open (A52_DOLBY); +} + +ao_instance_t * ao_wavext4_open (void) +{ + return wavext_open (A52_2F2R); +} + +ao_instance_t * ao_wavext6_open (void) +{ + return wavext_open (A52_3F2R | A52_LFE); +} + +ao_instance_t * ao_wavextauto_open (void) +{ + return wavext_open (-1); +} + --- a52dec-0.7.4/libao/audio_out_au.c Thu Jan 1 01:00:00 1970 +++ a52dec-0.7.4-hp/libao/audio_out_au.c Sat Oct 11 18:49:03 2003 @@ -0,0 +1,179 @@ +/* + * audio_out_au.c + * Copyright (C) 2000-2002 Michel Lespinasse + * Copyright (C) 1999-2000 Aaron Holtzman + * + * This file is part of a52dec, a free ATSC A-52 stream decoder. + * See http://liba52.sourceforge.net/ for updates. + * + * a52dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * a52dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" + +#include +#include +#include +#include + +#include "a52.h" +#include "audio_out.h" +#include "audio_out_internal.h" + +typedef struct au_instance_s { + ao_instance_t ao; + int sample_rate; + int set_params; + int flags; + int size; +} au_instance_t; + +static uint8_t au_header[] = { + '.', 's', 'n', 'd', 0, 0, 0, 28, -1, -1, -1, -1, + 0, 0, 0, 3, 0x00, 0x00, 0xbb, 0x80, 0, 0, 0, 2, + 0, 0, 0, 0 +}; + +static int au_setup (ao_instance_t * _instance, int sample_rate, int * flags, + sample_t * level, sample_t * bias) +{ + au_instance_t * instance = (au_instance_t *) _instance; + + if ((instance->set_params == 0) && (instance->sample_rate != sample_rate)) + return 1; + instance->sample_rate = sample_rate; + + *flags = instance->flags; + *level = 1; + *bias = 384; + + return 0; +} + +static void store (uint8_t * buf, int value) +{ + buf[3] = value; + buf[2] = value >> 8; + buf[1] = value >> 16; + buf[0] = value >> 24; +} + +static void store16 (uint8_t * buf, int value) +{ + buf[1] = value; + buf[0] = value >> 8; +} + +static int au_play (ao_instance_t * _instance, int flags, sample_t * _samples) +{ + au_instance_t * instance = (au_instance_t *) _instance; + int16_t int16_samples[256*6]; + int chans = -1; + int j; + int16_t t; + +#ifdef LIBA52_DOUBLE + float samples[256 * 6]; + int i; + + for (i = 0; i < 256 * 6; i++) + samples[i] = _samples[i]; +#else + float * samples = _samples; +#endif + + chans = channels_multi (flags); + flags &= A52_CHANNEL_MASK | A52_LFE; + + if (instance->set_params) { + instance->set_params = 0; + store (au_header + 20, chans); + store (au_header + 16, instance->sample_rate); + fwrite (au_header, sizeof (au_header), 1, stdout); + } + + float2s16_multi (samples, int16_samples, flags); + s16_BE (int16_samples, chans); + /* 2ch: L,R */ + /* 4ch: L,R,LS,RS */ + /* 6ch(a52): L,R,LS,RS,C,LFE */ + /* 6ch(au): L,R,C,LFE,LS,RS */ + if (chans==6) + for (j = 0; j < 256 * 6; j += 6) { + t = int16_samples[j+2]; + int16_samples[j+2] = int16_samples[j+4]; + int16_samples[j+4] = t; + t = int16_samples[j+3]; + int16_samples[j+3] = int16_samples[j+5]; + int16_samples[j+5] = t; + } + fwrite (int16_samples, 256 * sizeof (int16_t) * chans, 1, stdout); + + instance->size += 256 * sizeof (int16_t) * chans; + + return 0; +} + +static void au_close (ao_instance_t * _instance) +{ + au_instance_t * instance = (au_instance_t *) _instance; + + if (fseek (stdout, 0, SEEK_SET) < 0) + return; + + store (au_header + 8, instance->size); + fwrite (au_header, sizeof (au_header), 1, stdout); +} + +static ao_instance_t * au_open (int flags) +{ + au_instance_t * instance; + + instance = malloc (sizeof (au_instance_t)); + if (instance == NULL) + return NULL; + + instance->ao.setup = au_setup; + instance->ao.play = au_play; + instance->ao.close = au_close; + + instance->sample_rate = 0; + instance->set_params = 1; + instance->flags = flags; + instance->size = 0; + + return (ao_instance_t *) instance; +} + +ao_instance_t * ao_au_open (void) +{ + return au_open (A52_STEREO); +} + +ao_instance_t * ao_audolby_open (void) +{ + return au_open (A52_DOLBY); +} + +ao_instance_t * ao_au4_open (void) +{ + return au_open (A52_2F2R); +} + +ao_instance_t * ao_au6_open (void) +{ + return au_open (A52_3F2R | A52_LFE); +} + --- a52dec-0.7.4/libao/float2s16.c Sun Feb 17 09:58:54 2002 +++ a52dec-0.7.4-hp/libao/float2s16.c Sat Oct 11 18:50:19 2003 @@ -38,6 +38,16 @@ return i - 0x43c00000; } +void float2s16_1 (float * _f, int16_t * s16) +{ + int i; + int32_t * f = (int32_t *) _f; + + for (i = 0; i < 256; i++) { + s16[1*i] = convert (f[i]); + } +} + void float2s16_2 (float * _f, int16_t * s16) { int i; @@ -49,6 +59,18 @@ } } +void float2s16_3 (float * _f, int16_t * s16) +{ + int i; + int32_t * f = (int32_t *) _f; + + for (i = 0; i < 256; i++) { + s16[3*i] = convert (f[i]); + s16[3*i+1] = convert (f[i+256]); + s16[3*i+2] = convert (f[i+512]); + } +} + void float2s16_4 (float * _f, int16_t * s16) { int i; @@ -95,6 +117,8 @@ switch (flags) { case A52_MONO: + case A52_CHANNEL1: + case A52_CHANNEL2: for (i = 0; i < 256; i++) { s16[5*i] = s16[5*i+1] = s16[5*i+2] = s16[5*i+3] = 0; s16[5*i+4] = convert (f[i]); @@ -120,6 +144,8 @@ float2s16_5 (_f, s16); break; case A52_MONO | A52_LFE: + case A52_CHANNEL1 | A52_LFE: + case A52_CHANNEL2 | A52_LFE: for (i = 0; i < 256; i++) { s16[6*i] = s16[6*i+1] = s16[6*i+2] = s16[6*i+3] = 0; s16[6*i+4] = convert (f[i+256]); @@ -166,6 +192,115 @@ } break; } +} + +void float2s16_wav (float * _f, int16_t * s16, int flags) +{ + int i; + int32_t * f = (int32_t *) _f; + + switch (flags) { + case A52_MONO: + case A52_CHANNEL1: + case A52_CHANNEL2: + float2s16_1 (_f, s16); + break; + case A52_CHANNEL: + case A52_STEREO: + case A52_DOLBY: + float2s16_2 (_f, s16); + break; + case A52_3F: + for (i = 0; i < 256; i++) { + s16[3*i] = convert (f[i]); + s16[3*i+1] = convert (f[i+512]); + s16[3*i+2] = convert (f[i+256]); + } + break; + case A52_2F1R: + float2s16_3 (_f, s16); + break; + case A52_3F1R: + for (i = 0; i < 256; i++) { + s16[4*i] = convert (f[i]); + s16[4*i+1] = convert (f[i+512]); + s16[4*i+2] = convert (f[i+256]); + s16[4*i+3] = convert (f[i+768]); + } + break; + case A52_2F2R: + float2s16_4 (_f, s16); + break; + case A52_3F2R: + for (i = 0; i < 256; i++) { + s16[5*i] = convert (f[i]); + s16[5*i+1] = convert (f[i+512]); + s16[5*i+2] = convert (f[i+256]); + s16[5*i+3] = convert (f[i+768]); + s16[5*i+4] = convert (f[i+1024]); + } + break; + case A52_MONO | A52_LFE: + case A52_CHANNEL1 | A52_LFE: + case A52_CHANNEL2 | A52_LFE: + for (i = 0; i < 256; i++) { + s16[2*i] = convert (f[i+256]); + s16[2*i+1] = convert (f[i]); + } + break; + case A52_CHANNEL | A52_LFE: + case A52_STEREO | A52_LFE: + case A52_DOLBY | A52_LFE: + for (i = 0; i < 256; i++) { + s16[3*i] = convert (f[i+256]); + s16[3*i+1] = convert (f[i+512]); + s16[3*i+2] = convert (f[i]); + } + break; + case A52_3F | A52_LFE: + for (i = 0; i < 256; i++) { + s16[4*i] = convert (f[i+256]); + s16[4*i+1] = convert (f[i+768]); + s16[4*i+2] = convert (f[i+512]); + s16[4*i+3] = convert (f[i]); + } + break; + case A52_2F1R | A52_LFE: + for (i = 0; i < 256; i++) { + s16[4*i] = convert (f[i+256]); + s16[4*i+1] = convert (f[i+512]); + s16[4*i+2] = convert (f[i]); + s16[4*i+3] = convert (f[i+768]); + } + case A52_3F1R | A52_LFE: + for (i = 0; i < 256; i++) { + s16[5*i] = convert (f[i+256]); + s16[5*i+1] = convert (f[i+768]); + s16[5*i+2] = convert (f[i+512]); + s16[5*i+3] = convert (f[i]); + s16[5*i+4] = convert (f[i+1024]); + } + break; + case A52_2F2R | A52_LFE: + for (i = 0; i < 256; i++) { + s16[5*i] = convert (f[i+256]); + s16[5*i+1] = convert (f[i+512]); + s16[5*i+2] = convert (f[i]); + s16[5*i+3] = convert (f[i+768]); + s16[5*i+4] = convert (f[i+1024]); + } + break; + case A52_3F2R | A52_LFE: + for (i = 0; i < 256; i++) { + s16[6*i] = convert (f[i+256]); + s16[6*i+1] = convert (f[i+768]); + s16[6*i+2] = convert (f[i+512]); + s16[6*i+3] = convert (f[i]); + s16[6*i+4] = convert (f[i+1024]); + s16[6*i+5] = convert (f[i+1280]); + } + break; + } } void s16_swap (int16_t * s16, int channels) --- a52dec-0.7.4/libao/Makefile.in Sun Jul 28 05:50:56 2002 +++ a52dec-0.7.4-hp/libao/Makefile.in Fri Mar 14 20:35:19 2003 @@ -77,7 +77,7 @@ VERSION = @VERSION@ noinst_LIBRARIES = libao.a -libao_a_SOURCES = audio_out.c float2s16.c audio_out_null.c audio_out_float.c audio_out_oss.c audio_out_solaris.c audio_out_al.c audio_out_win.c audio_out_wav.c audio_out_aif.c audio_out_peak.c +libao_a_SOURCES = audio_out.c float2s16.c audio_out_null.c audio_out_float.c audio_out_oss.c audio_out_solaris.c audio_out_al.c audio_out_win.c audio_out_wav.c audio_out_aif.c audio_out_peak.c audio_out_wavext.c audio_out_au.c EXTRA_DIST = configure.incl audio_out_internal.h @@ -96,7 +96,8 @@ audio_out_null.$(OBJEXT) audio_out_float.$(OBJEXT) \ audio_out_oss.$(OBJEXT) audio_out_solaris.$(OBJEXT) \ audio_out_al.$(OBJEXT) audio_out_win.$(OBJEXT) audio_out_wav.$(OBJEXT) \ -audio_out_aif.$(OBJEXT) audio_out_peak.$(OBJEXT) +audio_out_aif.$(OBJEXT) audio_out_peak.$(OBJEXT) \ +audio_out_wavext.$(OBJEXT) audio_out_au.$(OBJEXT) AR = ar CFLAGS = @CFLAGS@ COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)