--- ./libao/audio_out.c.org	2002-05-22 14:35:22.000000000 +0900
+++ ./libao/audio_out.c	2005-08-22 20:48:09.000000000 +0900
@@ -45,8 +45,10 @@
 extern ao_open_t ao_wavdolby_open;
 extern ao_open_t ao_aif_open;
 extern ao_open_t ao_aifdolby_open;
+extern ao_open_t ao_aifindiv_open;
 extern ao_open_t ao_peak_open;
 extern ao_open_t ao_peakdolby_open;
+extern ao_open_t ao_peakindiv_open;
 extern ao_open_t ao_null_open;
 extern ao_open_t ao_null4_open;
 extern ao_open_t ao_null6_open;
@@ -77,8 +79,10 @@
     {"wavdolby", ao_wavdolby_open},
     {"aif", ao_aif_open},
     {"aifdolby", ao_aifdolby_open},
+    {"aifindiv", ao_aifindiv_open},
     {"peak", ao_peak_open},
     {"peakdolby", ao_peakdolby_open},
+    {"peakindiv", ao_peakindiv_open},
     {"null", ao_null_open},
     {"null4", ao_null4_open},
     {"null6", ao_null6_open},
--- ./libao/audio_out_aif.c.org	2002-04-28 19:23:02.000000000 +0900
+++ ./libao/audio_out_aif.c	2005-08-22 22:03:38.000000000 +0900
@@ -40,6 +40,16 @@
     int size;
 } aif_instance_t;
 
+typedef struct indiv_instance_s {
+    ao_instance_t ao;
+    int sample_rate;
+    int set_params;
+    int flags;
+    int size;
+    int exist;
+    FILE * fp[6];
+} indiv_instance_t;
+
 static uint8_t aif_header[] = {
     'F', 'O', 'R', 'M', 0xff, 0xff, 0xff, 0xfe, 'A', 'I', 'F', 'F',
     'C', 'O', 'M', 'M', 0, 0, 0, 18,
@@ -47,6 +57,13 @@
     'S', 'S', 'N', 'D', 0xff, 0xff, 0xff, 0xd8, 0, 0, 0, 0, 0, 0, 0, 0
 };
 
+static uint8_t indiv_header[] = {
+    'F', 'O', 'R', 'M', 0xff, 0xff, 0xff, 0xfe, 'A', 'I', 'F', 'F',
+    'C', 'O', 'M', 'M', 0, 0, 0, 18,
+    0, 1, 0x7f, 0xff, 0xff, 0xe8, 0, 16, 0x40, 0x0e, -1, -1, 0, 0, 0, 0, 0, 0,
+    'S', 'S', 'N', 'D', 0xff, 0xff, 0xff, 0xd8, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
 static int aif_setup (ao_instance_t * _instance, int sample_rate, int * flags,
 		      sample_t * level, sample_t * bias)
 {
@@ -77,7 +94,7 @@
     buf[1] = value;
 }
 
-static int aif_play (ao_instance_t * _instance, int flags, sample_t * _samples)
+/*static */int aif_play (ao_instance_t * _instance, int flags, sample_t * _samples)
 {
     aif_instance_t * instance = (aif_instance_t *) _instance;
     int16_t int16_samples[256*2];
@@ -107,6 +124,233 @@
     return 0;
 }
 
+int aif_lpcm (ao_instance_t * _instance, sample_t gain, uint8_t * samples, size_t size)
+{
+    aif_instance_t * instance = (aif_instance_t *) _instance;
+
+    if (instance->set_params) {
+	instance->set_params = 0;
+	store2 (aif_header + 30, instance->sample_rate);
+	fwrite (aif_header, sizeof (aif_header), 1, stdout);
+    }
+
+    if (gain) {
+	int16_t * p;
+	int16_t sample;
+	size_t i;
+	sample_t f;
+
+	p = (int16_t *) samples;
+	for (i = 0; i < size; i += 2) {
+	    f = (sample_t) *p * gain;
+	    if (f < 0) {
+		f -= 0.5;
+		if (f < -32768.) f = -32768.;
+	    } else {
+		f += 0.5;
+		if (f > 32767.) f = 32767.;
+	    }
+	    sample = f;
+	    fwrite (&sample, 2, 1, stdout);
+	    p++;
+	}
+    } else {
+	fwrite (samples, size, 1, stdout);
+    }
+
+    instance->size += size;
+    return 0;
+}
+
+
+static inline int16_t convert (int32_t i)
+{
+    if (i > 0x43c07fff)
+	return 32767;
+    else if (i < 0x43bf8000)
+	return -32768;
+    else
+	return i - 0x43c00000;
+}
+
+enum {
+    chLFE = 0x01,
+    chLf = 0x02,
+    chC = 0x04,
+    chRf = 0x08,
+    chLs = 0x10,
+    chRs = 0x20
+};
+
+static void float_to_int (float * _f, int16_t * s16, int flags, int * exist)
+{
+    int i;
+    int32_t * f = (int32_t *) _f;
+
+    switch (flags) {
+    case A52_MONO:
+        *exist |= chC;
+	for (i = 0; i < 256; i++) {
+	    s16[i] = s16[i+256] = 0;
+	    s16[i+512] = convert (f[i]);
+	    s16[i+768] = s16[i+1024] = s16[i+1280] = 0;
+	}
+	s16_BE (&s16[i+512], 1);
+	break;
+    case A52_CHANNEL:
+    case A52_STEREO:
+    case A52_DOLBY:
+        *exist |= chLf | chRf;
+	for (i = 0; i < 256; i++) {
+	    s16[i] = 0;
+	    s16[i+256] = convert (f[i]);
+	    s16[i+512] = 0;
+	    s16[i+768] = convert (f[i+256]);
+	    s16[i+1024] = s16[i+1280] = 0;
+	}
+	s16_BE (&s16[i+256], 1);
+	s16_BE (&s16[i+768], 1);
+	break;
+    case A52_3F:
+        *exist |= chLf | chC | chRf;
+	for (i = 0; i < 256; i++) {
+	    s16[i] = 0;
+	    s16[i+256] = convert (f[i]);
+	    s16[i+512] = convert (f[i+256]);
+	    s16[i+768] = convert (f[i+512]);
+	    s16[i+1024] = s16[i+1280] = 0;
+	}
+	s16_BE (&s16[i+256], 3);
+	break;
+    case A52_2F2R:
+        *exist |= chLf | chRf | chLs | chRs;
+        for (i = 0; i < 256; i++) {
+	    s16[i] = 0;
+	    s16[i+256] = convert (f[i]);
+	    s16[i+512] = 0;
+	    s16[i+768] = convert (f[i+256]);
+	    s16[i+1024] = convert (f[i+512]);
+	    s16[i+1280] = convert (f[i+768]);
+	}
+	s16_BE (&s16[i+256], 1);
+	s16_BE (&s16[i+768], 3);
+	break;
+    case A52_3F2R:
+        *exist |= chLf | chC | chRf | chLs | chRs;
+	for (i = 0; i < 256; i++) {
+	    s16[i] = 0;
+	    s16[i+256] = convert (f[i]);
+	    s16[i+512] = convert (f[i+256]);
+	    s16[i+768] = convert (f[i+512]);
+	    s16[i+1024] = convert (f[i+768]);
+	    s16[i+1280] = convert (f[i+1024]);
+	}
+	s16_BE (&s16[i+256], 5);
+	break;
+    case A52_MONO | A52_LFE:
+        *exist |= chLFE | chC;
+	for (i = 0; i < 256; i++) {
+	    s16[i] = convert (f[i]);
+	    s16[i+256] = 0;
+	    s16[i+512] = convert (f[i+256]);
+	    s16[i+768] = s16[i+1024] = s16[i+1280] = 0;
+	}
+	s16_BE (s16, 1);
+	s16_BE (&s16[i+512], 1);
+	break;
+    case A52_CHANNEL | A52_LFE:
+    case A52_STEREO | A52_LFE:
+    case A52_DOLBY | A52_LFE:
+        *exist |= chLFE | chLf | chRf;
+	for (i = 0; i < 256; i++) {
+	    s16[i] = convert (f[i]);
+	    s16[i+256] = convert (f[i+256]);
+	    s16[i+512] = 0;
+	    s16[i+768] = convert (f[i+512]);
+	    s16[i+1024] = s16[i+1280] = 0;
+	}
+	s16_BE (s16, 2);
+	s16_BE (&s16[i+768], 1);
+	break;
+    case A52_3F | A52_LFE:
+        *exist |= chLFE | chLf | chC | chRf;
+	for (i = 0; i < 256; i++) {
+	    s16[i] = convert (f[i]);
+	    s16[i+256] = convert (f[i+256]);
+	    s16[i+512] = convert (f[i+512]);
+	    s16[i+768] = convert (f[i+768]);
+	    s16[i+1024] = s16[i+1280] = 0;
+	}
+	s16_BE (s16, 4);
+	break;
+    case A52_2F2R | A52_LFE:
+        *exist |= chLFE | chLf | chRf | chLs | chRs;
+	for (i = 0; i < 256; i++) {
+	    s16[i] = convert (f[i]);
+	    s16[i+256] = convert (f[i+256]);
+	    s16[i+512] = 0;
+	    s16[i+768] = convert (f[i+512]);
+	    s16[i+1024] = convert (f[i+768]);
+	    s16[i+1280] = convert (f[i+1024]);
+	}
+	s16_BE (s16, 2);
+	s16_BE (&s16[i+768], 3);
+	break;
+    case A52_3F2R | A52_LFE:
+        *exist |= chLFE | chLf | chC | chRf | chLs | chRs;
+	for (i = 0; i < 256; i++) {
+	    s16[i] = convert (f[i]);
+	    s16[i+256] = convert (f[i+256]);
+	    s16[i+512] = convert (f[i+512]);
+	    s16[i+768] = convert (f[i+768]);
+	    s16[i+1024] = convert (f[i+1024]);
+	    s16[i+1280] = convert (f[i+1280]);
+	}
+	s16_BE (s16, 6);
+	break;
+    }
+}
+
+int indiv_play (ao_instance_t * _instance, int flags, sample_t * _samples)
+{
+    indiv_instance_t * instance = (indiv_instance_t *) _instance;
+    int16_t int16_samples[256*6];
+    int i;
+    FILE *fp;
+
+#ifdef LIBA52_DOUBLE
+    float samples[256 * 6];
+
+    for (i = 0; i < 256 * 6; i++)
+	samples[i] = _samples[i];
+#else
+    float * samples = _samples;
+#endif
+
+    flags &= A52_CHANNEL_MASK | A52_LFE;
+
+    if (instance->set_params) {
+	instance->set_params = 0;
+	store2 (indiv_header + 30, instance->sample_rate);
+	fp = instance->fp[0];
+	for (i = 0; i < 6; i++) {
+	    fwrite (indiv_header, sizeof (indiv_header), 1, fp);
+	    fp++;
+	}
+    }
+
+    float_to_int (samples, int16_samples, flags, &instance->exist);
+    fp = instance->fp[0];
+    for (i = 0; i < 6; i++) {
+        fwrite (&int16_samples[i*256], sizeof (int16_t) * 256, 1, fp);
+	fp++;
+    }
+
+    instance->size += 256 * sizeof (int16_t);
+
+    return 0;
+}
+
 static void aif_close (ao_instance_t * _instance)
 {
     aif_instance_t * instance = (aif_instance_t *) _instance;
@@ -149,3 +393,70 @@
 {
     return aif_open (A52_DOLBY);
 }
+
+void indiv_close (ao_instance_t * _instance)
+{
+    indiv_instance_t * instance = (indiv_instance_t *) _instance;
+    FILE *fp;
+    int i, j;
+    char str[15];
+
+    for (i = 0; i < 6; i++) {
+	fp = instance->fp[i];
+	if (fseek (fp, 0, SEEK_SET) < 0) {
+	    fclose (fp);
+	    continue;
+	}
+
+	store4 (indiv_header + 4, instance->size + 46);
+	store4 (indiv_header + 22, instance->size / 2);
+	store4 (indiv_header + 42, instance->size + 8);
+	fwrite (indiv_header, sizeof (indiv_header), 1, fp);
+	fclose (fp);
+    }
+
+    j = 1;
+    for (i = 0; i < 6; i++) {
+        if (!(instance->exist & j)) {
+            sprintf(str, "a52_out_%d.aiff", i);
+            remove(str);
+        }
+        j <<= 1;
+    }
+}
+
+ao_instance_t * ao_aifindiv_open (void)
+{
+    indiv_instance_t * instance;
+    int i, j;
+    char str[15];
+
+    instance = malloc (sizeof (indiv_instance_t));
+    if (instance == NULL)
+	return NULL;
+
+    instance->ao.setup = aif_setup;
+    instance->ao.play = indiv_play;
+    instance->ao.close = indiv_close;
+
+    instance->sample_rate = 0;
+    instance->set_params = 1;
+    instance->flags = A52_3F2R | A52_LFE;
+    instance->size = 0;
+    instance->exist = 0;
+
+    for (i = 0; i < 6; i++) {
+	sprintf(str, "a52_out_%d.aiff", i);
+	instance->fp[i] = fopen(str, "w+b");
+	if (!instance->fp[i]) {
+	    for (j = 0; j < i; j++) {
+		fclose(instance->fp[j]);
+	    }
+	    fprintf (stderr, "Can not open work file: %s\n", str);
+	    free (instance);
+	    return NULL;
+	}
+    }
+
+    return (ao_instance_t *) instance;
+}
--- ./libao/audio_out_peak.c.org	2002-05-22 14:35:22.000000000 +0900
+++ ./libao/audio_out_peak.c	2005-08-23 14:32:55.000000000 +0900
@@ -27,7 +27,7 @@
     return 0;
 }
 
-static int peak_play (ao_instance_t * _instance, int flags, sample_t * samples)
+/*static */int peak_play (ao_instance_t * _instance, int flags, sample_t * samples)
 {
     peak_instance_t * instance = (peak_instance_t *) _instance;
     int i;
@@ -40,6 +40,64 @@
     return 0;
 }
 
+/*static */int peak_lpcm (ao_instance_t * _instance, sample_t * samples, int size)
+{
+    peak_instance_t * instance = (peak_instance_t *) _instance;
+    sample_t * p;
+    sample_t sample;
+    int i;
+
+    p = samples;
+    for (i = 0; i < size; i += 2) {
+        sample = *p;
+	if (instance->peak < fabs(sample))
+	    instance->peak = fabs(sample);
+	p++;
+    }
+
+    return 0;
+}
+
+#define compare256(p) do {\
+    int i;\
+    sample_t * samples = p;\
+    for (i = 0; i < 256; i++)\
+        if (instance->peak < fabs(samples[i]))\
+            instance->peak = fabs(samples[i]);\
+} while (0)
+
+/*static */int peakindiv_play (ao_instance_t * _instance, int flags, sample_t * samples)
+{
+    peak_instance_t * instance = (peak_instance_t *) _instance;
+
+    flags &= A52_CHANNEL_MASK | A52_LFE;
+
+    switch (flags) {    /* don't break */
+    case A52_3F2R | A52_LFE:
+      compare256 (&samples[1280]);
+    case A52_3F2R:
+    case A52_2F2R | A52_LFE:
+        compare256 (&samples[1024]);
+    case A52_2F2R:
+    case A52_3F | A52_LFE:
+        compare256 (&samples[768]);
+    case A52_3F:
+    case A52_CHANNEL | A52_LFE:
+    case A52_STEREO | A52_LFE:
+    case A52_DOLBY | A52_LFE:
+        compare256 (&samples[512]);
+    case A52_CHANNEL:
+    case A52_STEREO:
+    case A52_DOLBY:
+    case A52_MONO | A52_LFE:
+        compare256 (&samples[256]);
+    case A52_MONO:
+        compare256 (samples);
+    }
+
+    return 0;
+}
+
 static void peak_close (ao_instance_t * _instance)
 {
     peak_instance_t * instance = (peak_instance_t *) _instance;
@@ -74,3 +132,16 @@
 {
     return peak_open (A52_DOLBY);
 }
+
+ao_instance_t * ao_peakindiv_open (void)
+{
+    peak_instance_t * instance;
+
+    instance = (peak_instance_t *) peak_open(A52_3F2R | A52_LFE);
+    if (instance == NULL)
+	return NULL;
+
+    instance->ao.play = peakindiv_play;
+
+    return (ao_instance_t *) instance;
+}
--- ./src/a52dec.c.org	2002-06-28 12:11:49.000000000 +0900
+++ ./src/a52dec.c	2005-08-22 22:11:02.000000000 +0900
@@ -261,7 +261,7 @@
 
 		length = a52_syncinfo (buf, &flags, &sample_rate, &bit_rate);
 		if (!length) {
-		    fprintf (stderr, "skip\n");
+		    fprintf (stderr, "skip\r");
 		    for (bufptr = buf; bufptr < buf + 6; bufptr++)
 			bufptr[0] = bufptr[1];
 		    continue;
@@ -299,6 +299,19 @@
     }
 }
 
+int aif_play (ao_instance_t * _instance, int flags, sample_t * _samples);
+int aif_lpcm (ao_instance_t * _instance, sample_t gain, uint8_t * samples, size_t size);
+int peak_play (ao_instance_t * _instance, int flags, sample_t * _samples);
+int peak_lpcm (ao_instance_t * _instance, uint8_t * samples, size_t size);
+
+void decode_lpcm (uint8_t * samples, size_t size)
+{
+    if (output->play == aif_play)
+	aif_lpcm (output, gain, samples, size);
+    else if (output->play == peak_play)
+	peak_lpcm (output, samples, size);
+}
+
 #define DEMUX_PAYLOAD_START 1
 static int demux (uint8_t * buf, uint8_t * end, int flags)
 {
@@ -325,6 +338,7 @@
 #define DEMUX_HEADER 0
 #define DEMUX_DATA 1
 #define DEMUX_SKIP 2
+#define DEMUX_LPCM 3
     static int state = DEMUX_SKIP;
     static int state_bytes = 0;
     static uint8_t head_buf[268];
@@ -390,6 +404,16 @@
 	}
 	buf += state_bytes;
 	break;
+    case DEMUX_LPCM:
+	if (demux_pid || (state_bytes > end - buf)) {
+	    decode_lpcm (buf, end - buf);
+	    state_bytes -= end - buf;
+	    return 0;
+	}
+	decode_lpcm (buf, state_bytes);
+	buf += state_bytes;
+	print_fps (0);
+	break;
     }
 
     while (1) {
@@ -468,11 +492,44 @@
 		/* header points to the mpeg1 pes header */
 	    }
 	    if ((!demux_pid) && ((header-1)[len] != demux_track)) {
-		DONEBYTES (len);
-		bytes = 6 + (header[4] << 8) + header[5] - len;
-		if (bytes <= 0)
-		    continue;
-		goto skip;
+		if ((header-1)[len] == (demux_track | 0x20)) {
+		    len += 6;
+		    NEEDBYTES (len);
+
+		    if ((output->play == aif_play || output->play == peak_play)
+		      && (header[len - 2] & 0xf0) <= 0x10
+		      && (header[len - 2] & 0x07) == 0x01
+		      && header[len - 1] == 0x80) {
+			int sample_rate;
+			sample_t level, bias;
+
+			if (header[len - 2] & 0x10) sample_rate = 96000;
+			else sample_rate = 48000;
+			if (!ao_setup (output, sample_rate, &flags, &level, &bias)) {
+			    DONEBYTES (len);
+			    bytes = 6 + (header[4] << 8) + header[5] - len;
+			    if (bytes > end - buf) {
+				decode_lpcm (buf, end - buf);
+				state = DEMUX_LPCM;
+				state_bytes = bytes - (end - buf);
+				return 0;
+			    } else if (bytes <= 0)
+				continue;
+			    decode_lpcm (buf, bytes);
+			    buf += bytes;
+			    print_fps (0);
+			    break;
+			}
+		    }
+		    goto next;
+		} else {
+		next:
+		    DONEBYTES (len);
+		    bytes = 6 + (header[4] << 8) + header[5] - len;
+		    if (bytes <= 0)
+			continue;
+		    goto skip;
+		}
 	    }
 	    len += 3;
 	    NEEDBYTES (len);
