--- a/src/audio/SDL_audiocvt.c Sat Aug 21 11:34:24 2004 +0000
+++ b/src/audio/SDL_audiocvt.c Sat Aug 21 12:27:02 2004 +0000
@@ -175,6 +175,244 @@
}
}
+/* Discard top 4 channels */
+void SDL_ConvertStrip(SDL_AudioCVT *cvt, Uint16 format)
+{
+ int i;
+ Sint32 lsample, rsample;
+
+#ifdef DEBUG_CONVERT
+ fprintf(stderr, "Converting down to stereo\n");
+#endif
+ switch (format&0x8018) {
+
+ case AUDIO_U8: {
+ Uint8 *src, *dst;
+
+ src = cvt->buf;
+ dst = cvt->buf;
+ for ( i=cvt->len_cvt/6; i; --i ) {
+ lsample = src[0];
+ rsample = src[1];
+ dst[0] = lsample;
+ dst[1] = rsample;
+ src += 6;
+ dst += 2;
+ }
+ }
+ break;
+
+ case AUDIO_S8: {
+ Sint8 *src, *dst;
+
+ src = (Sint8 *)cvt->buf;
+ dst = (Sint8 *)cvt->buf;
+ for ( i=cvt->len_cvt/6; i; --i ) {
+ lsample = src[0];
+ rsample = src[1];
+ dst[0] = lsample;
+ dst[1] = rsample;
+ src += 6;
+ dst += 2;
+ }
+ }
+ break;
+
+ case AUDIO_U16: {
+ Uint8 *src, *dst;
+
+ src = cvt->buf;
+ dst = cvt->buf;
+ if ( (format & 0x1000) == 0x1000 ) {
+ for ( i=cvt->len_cvt/12; i; --i ) {
+ lsample = (Uint16)((src[0]<<8)|src[1]);
+ rsample = (Uint16)((src[2]<<8)|src[3]);
+ dst[1] = (lsample&0xFF);
+ lsample >>= 8;
+ dst[0] = (lsample&0xFF);
+ dst[3] = (rsample&0xFF);
+ rsample >>= 8;
+ dst[2] = (rsample&0xFF);
+ src += 12;
+ dst += 4;
+ }
+ } else {
+ for ( i=cvt->len_cvt/12; i; --i ) {
+ lsample = (Uint16)((src[1]<<8)|src[0]);
+ rsample = (Uint16)((src[3]<<8)|src[2]);
+ dst[0] = (lsample&0xFF);
+ lsample >>= 8;
+ dst[1] = (lsample&0xFF);
+ dst[2] = (rsample&0xFF);
+ rsample >>= 8;
+ dst[3] = (rsample&0xFF);
+ src += 12;
+ dst += 4;
+ }
+ }
+ }
+ break;
+
+ case AUDIO_S16: {
+ Uint8 *src, *dst;
+
+ src = cvt->buf;
+ dst = cvt->buf;
+ if ( (format & 0x1000) == 0x1000 ) {
+ for ( i=cvt->len_cvt/12; i; --i ) {
+ lsample = (Sint16)((src[0]<<8)|src[1]);
+ rsample = (Sint16)((src[2]<<8)|src[3]);
+ dst[1] = (lsample&0xFF);
+ lsample >>= 8;
+ dst[0] = (lsample&0xFF);
+ dst[3] = (rsample&0xFF);
+ rsample >>= 8;
+ dst[2] = (rsample&0xFF);
+ src += 12;
+ dst += 4;
+ }
+ } else {
+ for ( i=cvt->len_cvt/12; i; --i ) {
+ lsample = (Sint16)((src[1]<<8)|src[0]);
+ rsample = (Sint16)((src[3]<<8)|src[2]);
+ dst[0] = (lsample&0xFF);
+ lsample >>= 8;
+ dst[1] = (lsample&0xFF);
+ dst[2] = (rsample&0xFF);
+ rsample >>= 8;
+ dst[3] = (rsample&0xFF);
+ src += 12;
+ dst += 4;
+ }
+ }
+ }
+ break;
+ }
+ cvt->len_cvt /= 3;
+ if ( cvt->filters[++cvt->filter_index] ) {
+ cvt->filters[cvt->filter_index](cvt, format);
+ }
+}
+
+
+/* Discard top 2 channels of 6 */
+void SDL_ConvertStrip_2(SDL_AudioCVT *cvt, Uint16 format)
+{
+ int i;
+ Sint32 lsample, rsample;
+
+#ifdef DEBUG_CONVERT
+ fprintf(stderr, "Converting 6 down to quad\n");
+#endif
+ switch (format&0x8018) {
+
+ case AUDIO_U8: {
+ Uint8 *src, *dst;
+
+ src = cvt->buf;
+ dst = cvt->buf;
+ for ( i=cvt->len_cvt/4; i; --i ) {
+ lsample = src[0];
+ rsample = src[1];
+ dst[0] = lsample;
+ dst[1] = rsample;
+ src += 4;
+ dst += 2;
+ }
+ }
+ break;
+
+ case AUDIO_S8: {
+ Sint8 *src, *dst;
+
+ src = (Sint8 *)cvt->buf;
+ dst = (Sint8 *)cvt->buf;
+ for ( i=cvt->len_cvt/4; i; --i ) {
+ lsample = src[0];
+ rsample = src[1];
+ dst[0] = lsample;
+ dst[1] = rsample;
+ src += 4;
+ dst += 2;
+ }
+ }
+ break;
+
+ case AUDIO_U16: {
+ Uint8 *src, *dst;
+
+ src = cvt->buf;
+ dst = cvt->buf;
+ if ( (format & 0x1000) == 0x1000 ) {
+ for ( i=cvt->len_cvt/8; i; --i ) {
+ lsample = (Uint16)((src[0]<<8)|src[1]);
+ rsample = (Uint16)((src[2]<<8)|src[3]);
+ dst[1] = (lsample&0xFF);
+ lsample >>= 8;
+ dst[0] = (lsample&0xFF);
+ dst[3] = (rsample&0xFF);
+ rsample >>= 8;
+ dst[2] = (rsample&0xFF);
+ src += 8;
+ dst += 4;
+ }
+ } else {
+ for ( i=cvt->len_cvt/8; i; --i ) {
+ lsample = (Uint16)((src[1]<<8)|src[0]);
+ rsample = (Uint16)((src[3]<<8)|src[2]);
+ dst[0] = (lsample&0xFF);
+ lsample >>= 8;
+ dst[1] = (lsample&0xFF);
+ dst[2] = (rsample&0xFF);
+ rsample >>= 8;
+ dst[3] = (rsample&0xFF);
+ src += 8;
+ dst += 4;
+ }
+ }
+ }
+ break;
+
+ case AUDIO_S16: {
+ Uint8 *src, *dst;
+
+ src = cvt->buf;
+ dst = cvt->buf;
+ if ( (format & 0x1000) == 0x1000 ) {
+ for ( i=cvt->len_cvt/8; i; --i ) {
+ lsample = (Sint16)((src[0]<<8)|src[1]);
+ rsample = (Sint16)((src[2]<<8)|src[3]);
+ dst[1] = (lsample&0xFF);
+ lsample >>= 8;
+ dst[0] = (lsample&0xFF);
+ dst[3] = (rsample&0xFF);
+ rsample >>= 8;
+ dst[2] = (rsample&0xFF);
+ src += 8;
+ dst += 4;
+ }
+ } else {
+ for ( i=cvt->len_cvt/8; i; --i ) {
+ lsample = (Sint16)((src[1]<<8)|src[0]);
+ rsample = (Sint16)((src[3]<<8)|src[2]);
+ dst[0] = (lsample&0xFF);
+ lsample >>= 8;
+ dst[1] = (lsample&0xFF);
+ dst[2] = (rsample&0xFF);
+ rsample >>= 8;
+ dst[3] = (rsample&0xFF);
+ src += 8;
+ dst += 4;
+ }
+ }
+ }
+ break;
+ }
+ cvt->len_cvt /= 2;
+ if ( cvt->filters[++cvt->filter_index] ) {
+ cvt->filters[cvt->filter_index](cvt, format);
+ }
+}
/* Duplicate a mono channel to both stereo channels */
void SDL_ConvertStereo(SDL_AudioCVT *cvt, Uint16 format)
@@ -213,6 +451,337 @@
}
}
+
+/* Duplicate a stereo channel to a pseudo-5.1 stream */
+void SDL_ConvertSurround(SDL_AudioCVT *cvt, Uint16 format)
+{
+ int i;
+
+#ifdef DEBUG_CONVERT
+ fprintf(stderr, "Converting stereo to surround\n");
+#endif
+ switch (format&0x8018) {
+
+ case AUDIO_U8: {
+ Uint8 *src, *dst, lf, rf, ce;
+
+ src = (Uint8 *)(cvt->buf+cvt->len_cvt);
+ dst = (Uint8 *)(cvt->buf+cvt->len_cvt*3);
+ for ( i=cvt->len_cvt; i; --i ) {
+ dst -= 6;
+ src -= 2;
+ lf = src[0];
+ rf = src[1];
+ ce = (lf/2) + (rf/2);
+ dst[0] = lf;
+ dst[1] = rf;
+ dst[2] = lf - ce;
+ dst[3] = rf - ce;
+ dst[4] = ce;
+ dst[5] = ce;
+ }
+ }
+ break;
+
+ case AUDIO_S8: {
+ Sint8 *src, *dst, lf, rf, ce;
+
+ src = cvt->buf+cvt->len_cvt;
+ dst = cvt->buf+cvt->len_cvt*3;
+ for ( i=cvt->len_cvt; i; --i ) {
+ dst -= 6;
+ src -= 2;
+ lf = src[0];
+ rf = src[1];
+ ce = (lf/2) + (rf/2);
+ dst[0] = lf;
+ dst[1] = rf;
+ dst[2] = lf - ce;
+ dst[3] = rf - ce;
+ dst[4] = ce;
+ dst[5] = ce;
+ }
+ }
+ break;
+
+ case AUDIO_U16: {
+ Uint8 *src, *dst;
+ Uint16 lf, rf, ce, lr, rr;
+
+ src = cvt->buf+cvt->len_cvt;
+ dst = cvt->buf+cvt->len_cvt*3;
+
+ if ( (format & 0x1000) == 0x1000 ) {
+ for ( i=cvt->len_cvt/4; i; --i ) {
+ dst -= 12;
+ src -= 4;
+ lf = (Uint16)((src[0]<<8)|src[1]);
+ rf = (Uint16)((src[2]<<8)|src[3]);
+ ce = (lf/2) + (rf/2);
+ rr = lf - ce;
+ lr = rf - ce;
+ dst[1] = (lf&0xFF);
+ dst[0] = ((lf>>8)&0xFF);
+ dst[3] = (rf&0xFF);
+ dst[2] = ((rf>>8)&0xFF);
+
+ dst[1+4] = (lr&0xFF);
+ dst[0+4] = ((lr>>8)&0xFF);
+ dst[3+4] = (rr&0xFF);
+ dst[2+4] = ((rr>>8)&0xFF);
+
+ dst[1+8] = (ce&0xFF);
+ dst[0+8] = ((ce>>8)&0xFF);
+ dst[3+8] = (ce&0xFF);
+ dst[2+8] = ((ce>>8)&0xFF);
+ }
+ } else {
+ for ( i=cvt->len_cvt/4; i; --i ) {
+ dst -= 12;
+ src -= 4;
+ lf = (Uint16)((src[1]<<8)|src[0]);
+ rf = (Uint16)((src[3]<<8)|src[2]);
+ ce = (lf/2) + (rf/2);
+ rr = lf - ce;
+ lr = rf - ce;
+ dst[0] = (lf&0xFF);
+ dst[1] = ((lf>>8)&0xFF);
+ dst[2] = (rf&0xFF);
+ dst[3] = ((rf>>8)&0xFF);
+
+ dst[0+4] = (lr&0xFF);
+ dst[1+4] = ((lr>>8)&0xFF);
+ dst[2+4] = (rr&0xFF);
+ dst[3+4] = ((rr>>8)&0xFF);
+
+ dst[0+8] = (ce&0xFF);
+ dst[1+8] = ((ce>>8)&0xFF);
+ dst[2+8] = (ce&0xFF);
+ dst[3+8] = ((ce>>8)&0xFF);
+ }
+ }
+ }
+ break;
+
+ case AUDIO_S16: {
+ Uint8 *src, *dst;
+ Sint16 lf, rf, ce, lr, rr;
+
+ src = cvt->buf+cvt->len_cvt;
+ dst = cvt->buf+cvt->len_cvt*3;
+
+ if ( (format & 0x1000) == 0x1000 ) {
+ for ( i=cvt->len_cvt/4; i; --i ) {
+ dst -= 12;
+ src -= 4;
+ lf = (Sint16)((src[0]<<8)|src[1]);
+ rf = (Sint16)((src[2]<<8)|src[3]);
+ ce = (lf/2) + (rf/2);
+ rr = lf - ce;
+ lr = rf - ce;
+ dst[1] = (lf&0xFF);
+ dst[0] = ((lf>>8)&0xFF);
+ dst[3] = (rf&0xFF);
+ dst[2] = ((rf>>8)&0xFF);
+
+ dst[1+4] = (lr&0xFF);
+ dst[0+4] = ((lr>>8)&0xFF);
+ dst[3+4] = (rr&0xFF);
+ dst[2+4] = ((rr>>8)&0xFF);
+
+ dst[1+8] = (ce&0xFF);
+ dst[0+8] = ((ce>>8)&0xFF);
+ dst[3+8] = (ce&0xFF);
+ dst[2+8] = ((ce>>8)&0xFF);
+ }
+ } else {
+ for ( i=cvt->len_cvt/4; i; --i ) {
+ dst -= 12;
+ src -= 4;
+ lf = (Sint16)((src[1]<<8)|src[0]);
+ rf = (Sint16)((src[3]<<8)|src[2]);
+ ce = (lf/2) + (rf/2);
+ rr = lf - ce;
+ lr = rf - ce;
+ dst[0] = (lf&0xFF);
+ dst[1] = ((lf>>8)&0xFF);
+ dst[2] = (rf&0xFF);
+ dst[3] = ((rf>>8)&0xFF);
+
+ dst[0+4] = (lr&0xFF);
+ dst[1+4] = ((lr>>8)&0xFF);
+ dst[2+4] = (rr&0xFF);
+ dst[3+4] = ((rr>>8)&0xFF);
+
+ dst[0+8] = (ce&0xFF);
+ dst[1+8] = ((ce>>8)&0xFF);
+ dst[2+8] = (ce&0xFF);
+ dst[3+8] = ((ce>>8)&0xFF);
+ }
+ }
+ }
+ break;
+ }
+ cvt->len_cvt *= 3;
+ if ( cvt->filters[++cvt->filter_index] ) {
+ cvt->filters[cvt->filter_index](cvt, format);
+ }
+}
+
+
+/* Duplicate a stereo channel to a pseudo-4.0 stream */
+void SDL_ConvertSurround_4(SDL_AudioCVT *cvt, Uint16 format)
+{
+ int i;
+
+#ifdef DEBUG_CONVERT
+ fprintf(stderr, "Converting stereo to quad\n");
+#endif
+ switch (format&0x8018) {
+
+ case AUDIO_U8: {
+ Uint8 *src, *dst, lf, rf, ce;
+
+ src = (Uint8 *)(cvt->buf+cvt->len_cvt);
+ dst = (Uint8 *)(cvt->buf+cvt->len_cvt*2);
+ for ( i=cvt->len_cvt; i; --i ) {
+ dst -= 4;
+ src -= 2;
+ lf = src[0];
+ rf = src[1];
+ ce = (lf/2) + (rf/2);
+ dst[0] = lf;
+ dst[1] = rf;
+ dst[2] = lf - ce;
+ dst[3] = rf - ce;
+ }
+ }
+ break;
+
+ case AUDIO_S8: {
+ Sint8 *src, *dst, lf, rf, ce;
+
+ src = cvt->buf+cvt->len_cvt;
+ dst = cvt->buf+cvt->len_cvt*2;
+ for ( i=cvt->len_cvt; i; --i ) {
+ dst -= 4;
+ src -= 2;
+ lf = src[0];
+ rf = src[1];
+ ce = (lf/2) + (rf/2);
+ dst[0] = lf;
+ dst[1] = rf;
+ dst[2] = lf - ce;
+ dst[3] = rf - ce;
+ }
+ }
+ break;
+
+ case AUDIO_U16: {
+ Uint8 *src, *dst;
+ Uint16 lf, rf, ce, lr, rr;
+
+ src = cvt->buf+cvt->len_cvt;
+ dst = cvt->buf+cvt->len_cvt*2;
+
+ if ( (format & 0x1000) == 0x1000 ) {
+ for ( i=cvt->len_cvt/4; i; --i ) {
+ dst -= 8;
+ src -= 4;
+ lf = (Uint16)((src[0]<<8)|src[1]);
+ rf = (Uint16)((src[2]<<8)|src[3]);
+ ce = (lf/2) + (rf/2);
+ rr = lf - ce;
+ lr = rf - ce;
+ dst[1] = (lf&0xFF);
+ dst[0] = ((lf>>8)&0xFF);
+ dst[3] = (rf&0xFF);
+ dst[2] = ((rf>>8)&0xFF);
+
+ dst[1+4] = (lr&0xFF);
+ dst[0+4] = ((lr>>8)&0xFF);
+ dst[3+4] = (rr&0xFF);
+ dst[2+4] = ((rr>>8)&0xFF);
+ }
+ } else {
+ for ( i=cvt->len_cvt/4; i; --i ) {
+ dst -= 8;
+ src -= 4;
+ lf = (Uint16)((src[1]<<8)|src[0]);
+ rf = (Uint16)((src[3]<<8)|src[2]);
+ ce = (lf/2) + (rf/2);
+ rr = lf - ce;
+ lr = rf - ce;
+ dst[0] = (lf&0xFF);
+ dst[1] = ((lf>>8)&0xFF);
+ dst[2] = (rf&0xFF);
+ dst[3] = ((rf>>8)&0xFF);
+
+ dst[0+4] = (lr&0xFF);
+ dst[1+4] = ((lr>>8)&0xFF);
+ dst[2+4] = (rr&0xFF);
+ dst[3+4] = ((rr>>8)&0xFF);
+ }
+ }
+ }
+ break;
+
+ case AUDIO_S16: {
+ Uint8 *src, *dst;
+ Sint16 lf, rf, ce, lr, rr;
+
+ src = cvt->buf+cvt->len_cvt;
+ dst = cvt->buf+cvt->len_cvt*2;
+
+ if ( (format & 0x1000) == 0x1000 ) {
+ for ( i=cvt->len_cvt/4; i; --i ) {
+ dst -= 8;
+ src -= 4;
+ lf = (Sint16)((src[0]<<8)|src[1]);
+ rf = (Sint16)((src[2]<<8)|src[3]);
+ ce = (lf/2) + (rf/2);
+ rr = lf - ce;
+ lr = rf - ce;
+ dst[1] = (lf&0xFF);
+ dst[0] = ((lf>>8)&0xFF);
+ dst[3] = (rf&0xFF);
+ dst[2] = ((rf>>8)&0xFF);
+
+ dst[1+4] = (lr&0xFF);
+ dst[0+4] = ((lr>>8)&0xFF);
+ dst[3+4] = (rr&0xFF);
+ dst[2+4] = ((rr>>8)&0xFF);
+ }
+ } else {
+ for ( i=cvt->len_cvt/4; i; --i ) {
+ dst -= 8;
+ src -= 4;
+ lf = (Sint16)((src[1]<<8)|src[0]);
+ rf = (Sint16)((src[3]<<8)|src[2]);
+ ce = (lf/2) + (rf/2);
+ rr = lf - ce;
+ lr = rf - ce;
+ dst[0] = (lf&0xFF);
+ dst[1] = ((lf>>8)&0xFF);
+ dst[2] = (rf&0xFF);
+ dst[3] = ((rf>>8)&0xFF);
+
+ dst[0+4] = (lr&0xFF);
+ dst[1+4] = ((lr>>8)&0xFF);
+ dst[2+4] = (rr&0xFF);
+ dst[3+4] = ((rr>>8)&0xFF);
+ }
+ }
+ }
+ break;
+ }
+ cvt->len_cvt *= 2;
+ if ( cvt->filters[++cvt->filter_index] ) {
+ cvt->filters[cvt->filter_index](cvt, format);
+ }
+}
+
+
/* Convert 8-bit to 16-bit - LSB */
void SDL_Convert16LSB(SDL_AudioCVT *cvt, Uint16 format)
{
@@ -374,6 +943,173 @@
}
}
+
+/* Convert rate up by multiple of 2, for stereo */
+void SDL_RateMUL2_c2(SDL_AudioCVT *cvt, Uint16 format)
+{
+ int i;
+ Uint8 *src, *dst;
+
+#ifdef DEBUG_CONVERT
+ fprintf(stderr, "Converting audio rate * 2\n");
+#endif
+ src = cvt->buf+cvt->len_cvt;
+ dst = cvt->buf+cvt->len_cvt*2;
+ switch (format & 0xFF) {
+ case 8:
+ for ( i=cvt->len_cvt/2; i; --i ) {
+ src -= 2;
+ dst -= 4;
+ dst[0] = src[0];
+ dst[1] = src[1];
+ dst[2] = src[0];
+ dst[3] = src[1];
+ }
+ break;
+ case 16:
+ for ( i=cvt->len_cvt/4; i; --i ) {
+ src -= 4;
+ dst -= 8;
+ dst[0] = src[0];
+ dst[1] = src[1];
+ dst[2] = src[2];
+ dst[3] = src[3];
+ dst[4] = src[0];
+ dst[5] = src[1];
+ dst[6] = src[2];
+ dst[7] = src[3];
+ }
+ break;
+ }
+ cvt->len_cvt *= 2;
+ if ( cvt->filters[++cvt->filter_index] ) {
+ cvt->filters[cvt->filter_index](cvt, format);
+ }
+}
+
+/* Convert rate up by multiple of 2, for quad */
+void SDL_RateMUL2_c4(SDL_AudioCVT *cvt, Uint16 format)
+{
+ int i;
+ Uint8 *src, *dst;
+
+#ifdef DEBUG_CONVERT
+ fprintf(stderr, "Converting audio rate * 2\n");
+#endif
+ src = cvt->buf+cvt->len_cvt;
+ dst = cvt->buf+cvt->len_cvt*2;
+ switch (format & 0xFF) {
+ case 8:
+ for ( i=cvt->len_cvt/4; i; --i ) {
+ src -= 4;
+ dst -= 8;
+ dst[0] = src[0];
+ dst[1] = src[1];
+ dst[2] = src[2];
+ dst[3] = src[3];
+ dst[4] = src[0];
+ dst[5] = src[1];
+ dst[6] = src[2];
+ dst[7] = src[3];
+ }
+ break;
+ case 16:
+ for ( i=cvt->len_cvt/8; i; --i ) {
+ src -= 8;
+ dst -= 16;
+ dst[0] = src[0];
+ dst[1] = src[1];
+ dst[2] = src[2];
+ dst[3] = src[3];
+ dst[4] = src[4];
+ dst[5] = src[5];
+ dst[6] = src[6];
+ dst[7] = src[7];
+ dst[8] = src[0];
+ dst[9] = src[1];
+ dst[10] = src[2];
+ dst[11] = src[3];
+ dst[12] = src[4];
+ dst[13] = src[5];
+ dst[14] = src[6];
+ dst[15] = src[7];
+ }
+ break;
+ }
+ cvt->len_cvt *= 2;
+ if ( cvt->filters[++cvt->filter_index] ) {
+ cvt->filters[cvt->filter_index](cvt, format);
+ }
+}
+
+
+/* Convert rate up by multiple of 2, for 5.1 */
+void SDL_RateMUL2_c6(SDL_AudioCVT *cvt, Uint16 format)
+{
+ int i;
+ Uint8 *src, *dst;
+
+#ifdef DEBUG_CONVERT
+ fprintf(stderr, "Converting audio rate * 2\n");
+#endif
+ src = cvt->buf+cvt->len_cvt;
+ dst = cvt->buf+cvt->len_cvt*2;
+ switch (format & 0xFF) {
+ case 8:
+ for ( i=cvt->len_cvt/6; i; --i ) {
+ src -= 6;
+ dst -= 12;
+ dst[0] = src[0];
+ dst[1] = src[1];
+ dst[2] = src[2];
+ dst[3] = src[3];
+ dst[4] = src[4];
+ dst[5] = src[5];
+ dst[6] = src[0];
+ dst[7] = src[1];
+ dst[8] = src[2];
+ dst[9] = src[3];
+ dst[10] = src[4];
+ dst[11] = src[5];
+ }
+ break;
+ case 16:
+ for ( i=cvt->len_cvt/12; i; --i ) {
+ src -= 12;
+ dst -= 24;
+ dst[0] = src[0];
+ dst[1] = src[1];
+ dst[2] = src[2];
+ dst[3] = src[3];
+ dst[4] = src[4];
+ dst[5] = src[5];
+ dst[6] = src[6];
+ dst[7] = src[7];
+ dst[8] = src[8];
+ dst[9] = src[9];
+ dst[10] = src[10];
+ dst[11] = src[11];
+ dst[12] = src[0];
+ dst[13] = src[1];
+ dst[14] = src[2];
+ dst[15] = src[3];
+ dst[16] = src[4];
+ dst[17] = src[5];
+ dst[18] = src[6];
+ dst[19] = src[7];
+ dst[20] = src[8];
+ dst[21] = src[9];
+ dst[22] = src[10];
+ dst[23] = src[11];
+ }
+ break;
+ }
+ cvt->len_cvt *= 2;
+ if ( cvt->filters[++cvt->filter_index] ) {
+ cvt->filters[cvt->filter_index](cvt, format);
+ }
+}
+
/* Convert rate down by multiple of 2 */
void SDL_RateDIV2(SDL_AudioCVT *cvt, Uint16 format)
{
@@ -408,6 +1144,137 @@
}
}
+
+/* Convert rate down by multiple of 2, for stereo */
+void SDL_RateDIV2_c2(SDL_AudioCVT *cvt, Uint16 format)
+{
+ int i;
+ Uint8 *src, *dst;
+
+#ifdef DEBUG_CONVERT
+ fprintf(stderr, "Converting audio rate / 2\n");
+#endif
+ src = cvt->buf;
+ dst = cvt->buf;
+ switch (format & 0xFF) {
+ case 8:
+ for ( i=cvt->len_cvt/4; i; --i ) {
+ dst[0] = src[0];
+ dst[1] = src[1];
+ src += 4;
+ dst += 2;
+ }
+ break;
+ case 16:
+ for ( i=cvt->len_cvt/8; i; --i ) {
+ dst[0] = src[0];
+ dst[1] = src[1];
+ dst[2] = src[2];
+ dst[3] = src[3];
+ src += 8;
+ dst += 4;
+ }
+ break;
+ }
+ cvt->len_cvt /= 2;
+ if ( cvt->filters[++cvt->filter_index] ) {
+ cvt->filters[cvt->filter_index](cvt, format);
+ }
+}
+
+
+/* Convert rate down by multiple of 2, for quad */
+void SDL_RateDIV2_c4(SDL_AudioCVT *cvt, Uint16 format)
+{
+ int i;
+ Uint8 *src, *dst;
+
+#ifdef DEBUG_CONVERT
+ fprintf(stderr, "Converting audio rate / 2\n");
+#endif
+ src = cvt->buf;
+ dst = cvt->buf;
+ switch (format & 0xFF) {
+ case 8:
+ for ( i=cvt->len_cvt/8; i; --i ) {
+ dst[0] = src[0];
+ dst[1] = src[1];
+ dst[2] = src[2];
+ dst[3] = src[3];
+ src += 8;
+ dst += 4;
+ }
+ break;
+ case 16:
+ for ( i=cvt->len_cvt/16; i; --i ) {
+ dst[0] = src[0];
+ dst[1] = src[1];
+ dst[2] = src[2];
+ dst[3] = src[3];
+ dst[4] = src[4];
+ dst[5] = src[5];
+ dst[6] = src[6];
+ dst[7] = src[7];
+ src += 16;
+ dst += 8;
+ }
+ break;
+ }
+ cvt->len_cvt /= 2;
+ if ( cvt->filters[++cvt->filter_index] ) {
+ cvt->filters[cvt->filter_index](cvt, format);
+ }
+}
+
+/* Convert rate down by multiple of 2, for 5.1 */
+void SDL_RateDIV2_c6(SDL_AudioCVT *cvt, Uint16 format)
+{
+ int i;
+ Uint8 *src, *dst;
+
+#ifdef DEBUG_CONVERT
+ fprintf(stderr, "Converting audio rate / 2\n");
+#endif
+ src = cvt->buf;
+ dst = cvt->buf;
+ switch (format & 0xFF) {
+ case 8:
+ for ( i=cvt->len_cvt/12; i; --i ) {
+ dst[0] = src[0];
+ dst[1] = src[1];
+ dst[2] = src[2];
+ dst[3] = src[3];
+ dst[4] = src[4];
+ dst[5] = src[5];
+ src += 12;
+ dst += 6;
+ }
+ break;
+ case 16:
+ for ( i=cvt->len_cvt/24; i; --i ) {
+ dst[0] = src[0];
+ dst[1] = src[1];
+ dst[2] = src[2];
+ dst[3] = src[3];
+ dst[4] = src[4];
+ dst[5] = src[5];
+ dst[6] = src[6];
+ dst[7] = src[7];
+ dst[8] = src[8];
+ dst[9] = src[9];
+ dst[10] = src[10];
+ dst[11] = src[11];
+ src += 24;
+ dst += 12;
+ }
+ break;
+ }
+ cvt->len_cvt /= 2;
+ if ( cvt->filters[++cvt->filter_index] ) {
+ cvt->filters[cvt->filter_index](cvt, format);
+ }
+}
+
/* Very slow rate conversion routine */
void SDL_RateSLOW(SDL_AudioCVT *cvt, Uint16 format)
{
@@ -511,6 +1378,8 @@
Uint16 src_format, Uint8 src_channels, int src_rate,
Uint16 dst_format, Uint8 dst_channels, int dst_rate)
{
+/*printf("Build format %04x->%04x, channels %u->%u, rate %d->%d\n",
+ src_format, dst_format, src_channels, dst_channels, src_rate, dst_rate);*/
/* Start off with no conversion necessary */
cvt->needed = 0;
cvt->filter_index = 0;
@@ -554,6 +1423,29 @@
/* Last filter: Mono/Stereo conversion */
if ( src_channels != dst_channels ) {
+ if ( (src_channels == 1) && (dst_channels > 1) ) {
+ cvt->filters[cvt->filter_index++] =
+ SDL_ConvertStereo;
+ cvt->len_mult *= 2;
+ src_channels = 2;
+ cvt->len_ratio *= 2;
+ }
+ if ( (src_channels == 2) &&
+ (dst_channels == 6) ) {
+ cvt->filters[cvt->filter_index++] =
+ SDL_ConvertSurround;
+ src_channels = 6;
+ cvt->len_mult *= 3;
+ cvt->len_ratio *= 3;
+ }
+ if ( (src_channels == 2) &&
+ (dst_channels == 4) ) {
+ cvt->filters[cvt->filter_index++] =
+ SDL_ConvertSurround_4;
+ src_channels = 4;
+ cvt->len_mult *= 2;
+ cvt->len_ratio *= 2;
+ }
while ( (src_channels*2) <= dst_channels ) {
cvt->filters[cvt->filter_index++] =
SDL_ConvertStereo;
@@ -561,6 +1453,20 @@
src_channels *= 2;
cvt->len_ratio *= 2;
}
+ if ( (src_channels == 6) &&
+ (dst_channels <= 2) ) {
+ cvt->filters[cvt->filter_index++] =
+ SDL_ConvertStrip;
+ src_channels = 2;
+ cvt->len_ratio /= 3;
+ }
+ if ( (src_channels == 6) &&
+ (dst_channels == 4) ) {
+ cvt->filters[cvt->filter_index++] =
+ SDL_ConvertStrip_2;
+ src_channels = 4;
+ cvt->len_ratio /= 2;
+ }
/* This assumes that 4 channel audio is in the format:
Left {front/back} + Right {front/back}
so converting to L/R stereo works properly.
@@ -588,13 +1494,25 @@
if ( src_rate > dst_rate ) {
hi_rate = src_rate;
lo_rate = dst_rate;
- rate_cvt = SDL_RateDIV2;
+ switch (src_channels) {
+ case 1: rate_cvt = SDL_RateDIV2; break;
+ case 2: rate_cvt = SDL_RateDIV2_c2; break;
+ case 4: rate_cvt = SDL_RateDIV2_c4; break;
+ case 6: rate_cvt = SDL_RateDIV2_c6; break;
+ default: return -1;
+ }
len_mult = 1;
len_ratio = 0.5;
} else {
hi_rate = dst_rate;
lo_rate = src_rate;
- rate_cvt = SDL_RateMUL2;
+ switch (src_channels) {
+ case 1: rate_cvt = SDL_RateMUL2; break;
+ case 2: rate_cvt = SDL_RateMUL2_c2; break;
+ case 4: rate_cvt = SDL_RateMUL2_c4; break;
+ case 6: rate_cvt = SDL_RateMUL2_c6; break;
+ default: return -1;
+ }
len_mult = 2;
len_ratio = 2.0;
}
--- a/src/audio/alsa/SDL_alsa_audio.c Sat Aug 21 11:34:24 2004 +0000
+++ b/src/audio/alsa/SDL_alsa_audio.c Sat Aug 21 12:27:02 2004 +0000
@@ -163,13 +163,15 @@
#endif /* ALSA_DYNAMIC */
-static const char *get_audio_device()
+static const char *get_audio_device(int channels)
{
const char *device;
device = getenv("AUDIODEV"); /* Is there a standard variable name? */
if ( device == NULL ) {
- device = DEFAULT_DEVICE;
+ if (channels == 6) device = "surround51";
+ else if (channels == 4) device = "surround40";
+ else device = DEFAULT_DEVICE;
}
return device;
}
@@ -186,7 +188,7 @@
if (LoadALSALibrary() < 0) {
return available;
}
- status = SDL_NAME(snd_pcm_open)(&handle, get_audio_device(), SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
+ status = SDL_NAME(snd_pcm_open)(&handle, get_audio_device(2), SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
if ( status >= 0 ) {
available = 1;
SDL_NAME(snd_pcm_close)(handle);
@@ -319,7 +321,9 @@
Uint16 test_format;
/* Open the audio device */
- status = SDL_NAME(snd_pcm_open)(&pcm_handle, get_audio_device(), SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
+ /* Name of device should depend on # channels in spec */
+ status = SDL_NAME(snd_pcm_open)(&pcm_handle, get_audio_device(spec->channels), SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
+
if ( status < 0 ) {
SDL_SetError("Couldn't open audio device: %s", SDL_NAME(snd_strerror)(status));
return(-1);