--- /dev/null
+include ../../setup/general/makeapp
--- /dev/null
+# WXXT base directory
+WXBASEDIR=@WXBASEDIR@
+
+# set the OS type for compilation
+OS=@OS@
+# compile a library only
+RULE=gslib
+
+# define common stuff
+
+# define library name
+LIB_TARGET=wxmmedia
+LIB_MAJOR=2
+LIB_MINOR=0
+# define library sources
+ADPCM_SRC=\
+g711.cpp g721.cpp g723_24.cpp g723_40.cpp g72x.cpp
+
+MMEDIA_SRC=\
+mmdata.cpp mmfile.cpp mmsolve.cpp sndsnd.cpp sndfrmt.cpp sndpcm.o \
+snduss.cpp sndfile.cpp sndwav.cpp mmriff.cpp vidbase.cpp vidxanm.cpp \
+cdbase.cpp cdunix.cpp
+
+LIB_SRC= $(ADPCM_SRC:%.cpp=adpcm/%.cpp) $(MMEDIA_SRC)
+
+#define library objects
+LIB_OBJ=\
+$(LIB_SRC:%.cpp=%.o)
+
+#additional things needed for compile
+ADD_COMPILE= -I$(UTILS)/wxthread
+
+all::
+ -mkdir -p adpcm
+
+# include the definitions now
+include ../../../template.mak
+
--- /dev/null
+/*
+ * This source code is a product of Sun Microsystems, Inc. and is provided
+ * for unrestricted use. Users may copy or modify this source code without
+ * charge.
+ *
+ * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING
+ * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun source code is provided with no support and without any obligation on
+ * the part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/*
+ * g711.c
+ *
+ * u-law, A-law and linear PCM conversions.
+ */
+#define SIGN_BIT (0x80) /* Sign bit for a A-law byte. */
+#define QUANT_MASK (0xf) /* Quantization field mask. */
+#define NSEGS (8) /* Number of A-law segments. */
+#define SEG_SHIFT (4) /* Left shift for segment number. */
+#define SEG_MASK (0x70) /* Segment field mask. */
+
+static short seg_end[8] = {0xFF, 0x1FF, 0x3FF, 0x7FF,
+ 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF};
+
+/* copy from CCITT G.711 specifications */
+unsigned char _u2a[128] = { /* u- to A-law conversions */
+ 1, 1, 2, 2, 3, 3, 4, 4,
+ 5, 5, 6, 6, 7, 7, 8, 8,
+ 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24,
+ 25, 27, 29, 31, 33, 34, 35, 36,
+ 37, 38, 39, 40, 41, 42, 43, 44,
+ 46, 48, 49, 50, 51, 52, 53, 54,
+ 55, 56, 57, 58, 59, 60, 61, 62,
+ 64, 65, 66, 67, 68, 69, 70, 71,
+ 72, 73, 74, 75, 76, 77, 78, 79,
+ 81, 82, 83, 84, 85, 86, 87, 88,
+ 89, 90, 91, 92, 93, 94, 95, 96,
+ 97, 98, 99, 100, 101, 102, 103, 104,
+ 105, 106, 107, 108, 109, 110, 111, 112,
+ 113, 114, 115, 116, 117, 118, 119, 120,
+ 121, 122, 123, 124, 125, 126, 127, 128};
+
+unsigned char _a2u[128] = { /* A- to u-law conversions */
+ 1, 3, 5, 7, 9, 11, 13, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 32, 33, 33, 34, 34, 35, 35,
+ 36, 37, 38, 39, 40, 41, 42, 43,
+ 44, 45, 46, 47, 48, 48, 49, 49,
+ 50, 51, 52, 53, 54, 55, 56, 57,
+ 58, 59, 60, 61, 62, 63, 64, 64,
+ 65, 66, 67, 68, 69, 70, 71, 72,
+ 73, 74, 75, 76, 77, 78, 79, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87,
+ 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99, 100, 101, 102, 103,
+ 104, 105, 106, 107, 108, 109, 110, 111,
+ 112, 113, 114, 115, 116, 117, 118, 119,
+ 120, 121, 122, 123, 124, 125, 126, 127};
+
+static int
+search(
+ int val,
+ short *table,
+ int size)
+{
+ int i;
+
+ for (i = 0; i < size; i++) {
+ if (val <= *table++)
+ return (i);
+ }
+ return (size);
+}
+
+/*
+ * linear2alaw() - Convert a 16-bit linear PCM value to 8-bit A-law
+ *
+ * linear2alaw() accepts an 16-bit integer and encodes it as A-law data.
+ *
+ * Linear Input Code Compressed Code
+ * ------------------------ ---------------
+ * 0000000wxyza 000wxyz
+ * 0000001wxyza 001wxyz
+ * 000001wxyzab 010wxyz
+ * 00001wxyzabc 011wxyz
+ * 0001wxyzabcd 100wxyz
+ * 001wxyzabcde 101wxyz
+ * 01wxyzabcdef 110wxyz
+ * 1wxyzabcdefg 111wxyz
+ *
+ * For further information see John C. Bellamy's Digital Telephony, 1982,
+ * John Wiley & Sons, pps 98-111 and 472-476.
+ */
+unsigned char
+linear2alaw(
+ int pcm_val) /* 2's complement (16-bit range) */
+{
+ int mask;
+ int seg;
+ unsigned char aval;
+
+ if (pcm_val >= 0) {
+ mask = 0xD5; /* sign (7th) bit = 1 */
+ } else {
+ mask = 0x55; /* sign bit = 0 */
+ pcm_val = -pcm_val - 8;
+ }
+
+ /* Convert the scaled magnitude to segment number. */
+ seg = search(pcm_val, seg_end, 8);
+
+ /* Combine the sign, segment, and quantization bits. */
+
+ if (seg >= 8) /* out of range, return maximum value. */
+ return (0x7F ^ mask);
+ else {
+ aval = seg << SEG_SHIFT;
+ if (seg < 2)
+ aval |= (pcm_val >> 4) & QUANT_MASK;
+ else
+ aval |= (pcm_val >> (seg + 3)) & QUANT_MASK;
+ return (aval ^ mask);
+ }
+}
+
+/*
+ * alaw2linear() - Convert an A-law value to 16-bit linear PCM
+ *
+ */
+int
+alaw2linear(
+ unsigned char a_val)
+{
+ int t;
+ int seg;
+
+ a_val ^= 0x55;
+
+ t = (a_val & QUANT_MASK) << 4;
+ seg = ((unsigned)a_val & SEG_MASK) >> SEG_SHIFT;
+ switch (seg) {
+ case 0:
+ t += 8;
+ break;
+ case 1:
+ t += 0x108;
+ break;
+ default:
+ t += 0x108;
+ t <<= seg - 1;
+ }
+ return ((a_val & SIGN_BIT) ? t : -t);
+}
+
+#define BIAS (0x84) /* Bias for linear code. */
+
+/*
+ * linear2ulaw() - Convert a linear PCM value to u-law
+ *
+ * In order to simplify the encoding process, the original linear magnitude
+ * is biased by adding 33 which shifts the encoding range from (0 - 8158) to
+ * (33 - 8191). The result can be seen in the following encoding table:
+ *
+ * Biased Linear Input Code Compressed Code
+ * ------------------------ ---------------
+ * 00000001wxyza 000wxyz
+ * 0000001wxyzab 001wxyz
+ * 000001wxyzabc 010wxyz
+ * 00001wxyzabcd 011wxyz
+ * 0001wxyzabcde 100wxyz
+ * 001wxyzabcdef 101wxyz
+ * 01wxyzabcdefg 110wxyz
+ * 1wxyzabcdefgh 111wxyz
+ *
+ * Each biased linear code has a leading 1 which identifies the segment
+ * number. The value of the segment number is equal to 7 minus the number
+ * of leading 0's. The quantization interval is directly available as the
+ * four bits wxyz. * The trailing bits (a - h) are ignored.
+ *
+ * Ordinarily the complement of the resulting code word is used for
+ * transmission, and so the code word is complemented before it is returned.
+ *
+ * For further information see John C. Bellamy's Digital Telephony, 1982,
+ * John Wiley & Sons, pps 98-111 and 472-476.
+ */
+unsigned char
+linear2ulaw(
+ int pcm_val) /* 2's complement (16-bit range) */
+{
+ int mask;
+ int seg;
+ unsigned char uval;
+
+ /* Get the sign and the magnitude of the value. */
+ if (pcm_val < 0) {
+ pcm_val = BIAS - pcm_val;
+ mask = 0x7F;
+ } else {
+ pcm_val += BIAS;
+ mask = 0xFF;
+ }
+
+ /* Convert the scaled magnitude to segment number. */
+ seg = search(pcm_val, seg_end, 8);
+
+ /*
+ * Combine the sign, segment, quantization bits;
+ * and complement the code word.
+ */
+ if (seg >= 8) /* out of range, return maximum value. */
+ return (0x7F ^ mask);
+ else {
+ uval = (seg << 4) | ((pcm_val >> (seg + 3)) & 0xF);
+ return (uval ^ mask);
+ }
+
+}
+
+/*
+ * ulaw2linear() - Convert a u-law value to 16-bit linear PCM
+ *
+ * First, a biased linear code is derived from the code word. An unbiased
+ * output can then be obtained by subtracting 33 from the biased code.
+ *
+ * Note that this function expects to be passed the complement of the
+ * original code word. This is in keeping with ISDN conventions.
+ */
+int
+ulaw2linear(
+ unsigned char u_val)
+{
+ int t;
+
+ /* Complement to obtain normal u-law value. */
+ u_val = ~u_val;
+
+ /*
+ * Extract and bias the quantization bits. Then
+ * shift up by the segment number and subtract out the bias.
+ */
+ t = ((u_val & QUANT_MASK) << 3) + BIAS;
+ t <<= ((unsigned)u_val & SEG_MASK) >> SEG_SHIFT;
+
+ return ((u_val & SIGN_BIT) ? (BIAS - t) : (t - BIAS));
+}
+
+/* A-law to u-law conversion */
+unsigned char
+alaw2ulaw(
+ unsigned char aval)
+{
+ aval &= 0xff;
+ return ((aval & 0x80) ? (0xFF ^ _a2u[aval ^ 0xD5]) :
+ (0x7F ^ _a2u[aval ^ 0x55]));
+}
+
+/* u-law to A-law conversion */
+unsigned char
+ulaw2alaw(
+ unsigned char uval)
+{
+ uval &= 0xff;
+ return ((uval & 0x80) ? (0xD5 ^ (_u2a[0xFF ^ uval] - 1)) :
+ (0x55 ^ (_u2a[0x7F ^ uval] - 1)));
+}
--- /dev/null
+/*
+ * This source code is a product of Sun Microsystems, Inc. and is provided
+ * for unrestricted use. Users may copy or modify this source code without
+ * charge.
+ *
+ * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING
+ * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun source code is provided with no support and without any obligation on
+ * the part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/*
+ * g721.c
+ *
+ * Description:
+ *
+ * g721_encoder(), g721_decoder()
+ *
+ * These routines comprise an implementation of the CCITT G.721 ADPCM
+ * coding algorithm. Essentially, this implementation is identical to
+ * the bit level description except for a few deviations which
+ * take advantage of work station attributes, such as hardware 2's
+ * complement arithmetic and large memory. Specifically, certain time
+ * consuming operations such as multiplications are replaced
+ * with lookup tables and software 2's complement operations are
+ * replaced with hardware 2's complement.
+ *
+ * The deviation from the bit level specification (lookup tables)
+ * preserves the bit level performance specifications.
+ *
+ * As outlined in the G.721 Recommendation, the algorithm is broken
+ * down into modules. Each section of code below is preceded by
+ * the name of the module which it is implementing.
+ *
+ */
+#include "g72x.h"
+
+static short qtab_721[7] = {-124, 80, 178, 246, 300, 349, 400};
+/*
+ * Maps G.721 code word to reconstructed scale factor normalized log
+ * magnitude values.
+ */
+static short _dqlntab[16] = {-2048, 4, 135, 213, 273, 323, 373, 425,
+ 425, 373, 323, 273, 213, 135, 4, -2048};
+
+/* Maps G.721 code word to log of scale factor multiplier. */
+static short _witab[16] = {-12, 18, 41, 64, 112, 198, 355, 1122,
+ 1122, 355, 198, 112, 64, 41, 18, -12};
+/*
+ * Maps G.721 code words to a set of values whose long and short
+ * term averages are computed and then compared to give an indication
+ * how stationary (steady state) the signal is.
+ */
+static short _fitab[16] = {0, 0, 0, 0x200, 0x200, 0x200, 0x600, 0xE00,
+ 0xE00, 0x600, 0x200, 0x200, 0x200, 0, 0, 0};
+
+/*
+ * g721_encoder()
+ *
+ * Encodes the input vale of linear PCM, A-law or u-law data sl and returns
+ * the resulting code. -1 is returned for unknown input coding value.
+ */
+int
+g721_encoder(
+ int sl,
+ int in_coding,
+ struct g72x_state *state_ptr)
+{
+ short sezi, se, sez; /* ACCUM */
+ short d; /* SUBTA */
+ short sr; /* ADDB */
+ short y; /* MIX */
+ short dqsez; /* ADDC */
+ short dq, i;
+
+ switch (in_coding) { /* linearize input sample to 14-bit PCM */
+ case AUDIO_ENCODING_ALAW:
+ sl = alaw2linear(sl) >> 2;
+ break;
+ case AUDIO_ENCODING_ULAW:
+ sl = ulaw2linear(sl) >> 2;
+ break;
+ case AUDIO_ENCODING_LINEAR:
+ sl = ((short)sl) >> 2; /* 14-bit dynamic range */
+ break;
+ default:
+ return (-1);
+ }
+
+ sezi = predictor_zero(state_ptr);
+ sez = sezi >> 1;
+ se = (sezi + predictor_pole(state_ptr)) >> 1; /* estimated signal */
+
+ d = sl - se; /* estimation difference */
+
+ /* quantize the prediction difference */
+ y = step_size(state_ptr); /* quantizer step size */
+ i = quantize(d, y, qtab_721, 7); /* i = ADPCM code */
+
+ dq = reconstruct(i & 8, _dqlntab[i], y); /* quantized est diff */
+
+ sr = (dq < 0) ? se - (dq & 0x3FFF) : se + dq; /* reconst. signal */
+
+ dqsez = sr + sez - se; /* pole prediction diff. */
+
+ update(4, y, _witab[i] << 5, _fitab[i], dq, sr, dqsez, state_ptr);
+
+ return (i);
+}
+
+/*
+ * g721_decoder()
+ *
+ * Description:
+ *
+ * Decodes a 4-bit code of G.721 encoded data of i and
+ * returns the resulting linear PCM, A-law or u-law value.
+ * return -1 for unknown out_coding value.
+ */
+int
+g721_decoder(
+ int i,
+ int out_coding,
+ struct g72x_state *state_ptr)
+{
+ short sezi, sei, sez, se; /* ACCUM */
+ short y; /* MIX */
+ short sr; /* ADDB */
+ short dq;
+ short dqsez;
+
+ i &= 0x0f; /* mask to get proper bits */
+ sezi = predictor_zero(state_ptr);
+ sez = sezi >> 1;
+ sei = sezi + predictor_pole(state_ptr);
+ se = sei >> 1; /* se = estimated signal */
+
+ y = step_size(state_ptr); /* dynamic quantizer step size */
+
+ dq = reconstruct(i & 0x08, _dqlntab[i], y); /* quantized diff. */
+
+ sr = (dq < 0) ? (se - (dq & 0x3FFF)) : se + dq; /* reconst. signal */
+
+ dqsez = sr - se + sez; /* pole prediction diff. */
+
+ update(4, y, _witab[i] << 5, _fitab[i], dq, sr, dqsez, state_ptr);
+
+ switch (out_coding) {
+ case AUDIO_ENCODING_ALAW:
+ return (tandem_adjust_alaw(sr, se, y, i, 8, qtab_721));
+ case AUDIO_ENCODING_ULAW:
+ return (tandem_adjust_ulaw(sr, se, y, i, 8, qtab_721));
+ case AUDIO_ENCODING_LINEAR:
+ return (sr << 2); /* sr was 14-bit dynamic range */
+ default:
+ return (-1);
+ }
+}
--- /dev/null
+/*
+ * This source code is a product of Sun Microsystems, Inc. and is provided
+ * for unrestricted use. Users may copy or modify this source code without
+ * charge.
+ *
+ * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING
+ * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun source code is provided with no support and without any obligation on
+ * the part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/*
+ * g723_24.c
+ *
+ * Description:
+ *
+ * g723_24_encoder(), g723_24_decoder()
+ *
+ * These routines comprise an implementation of the CCITT G.723 24 Kbps
+ * ADPCM coding algorithm. Essentially, this implementation is identical to
+ * the bit level description except for a few deviations which take advantage
+ * of workstation attributes, such as hardware 2's complement arithmetic.
+ *
+ */
+#include "g72x.h"
+
+/*
+ * Maps G.723_24 code word to reconstructed scale factor normalized log
+ * magnitude values.
+ */
+static short _dqlntab[8] = {-2048, 135, 273, 373, 373, 273, 135, -2048};
+
+/* Maps G.723_24 code word to log of scale factor multiplier. */
+static short _witab[8] = {-128, 960, 4384, 18624, 18624, 4384, 960, -128};
+
+/*
+ * Maps G.723_24 code words to a set of values whose long and short
+ * term averages are computed and then compared to give an indication
+ * how stationary (steady state) the signal is.
+ */
+static short _fitab[8] = {0, 0x200, 0x400, 0xE00, 0xE00, 0x400, 0x200, 0};
+
+static short qtab_723_24[3] = {8, 218, 331};
+
+/*
+ * g723_24_encoder()
+ *
+ * Encodes a linear PCM, A-law or u-law input sample and returns its 3-bit code.
+ * Returns -1 if invalid input coding value.
+ */
+int
+g723_24_encoder(
+ int sl,
+ int in_coding,
+ struct g72x_state *state_ptr)
+{
+ short sei, sezi, se, sez; /* ACCUM */
+ short d; /* SUBTA */
+ short y; /* MIX */
+ short sr; /* ADDB */
+ short dqsez; /* ADDC */
+ short dq, i;
+
+ switch (in_coding) { /* linearize input sample to 14-bit PCM */
+ case AUDIO_ENCODING_ALAW:
+ sl = alaw2linear(sl) >> 2;
+ break;
+ case AUDIO_ENCODING_ULAW:
+ sl = ulaw2linear(sl) >> 2;
+ break;
+ case AUDIO_ENCODING_LINEAR:
+ sl = ((short)sl) >> 2; /* sl of 14-bit dynamic range */
+ break;
+ default:
+ return (-1);
+ }
+
+ sezi = predictor_zero(state_ptr);
+ sez = sezi >> 1;
+ sei = sezi + predictor_pole(state_ptr);
+ se = sei >> 1; /* se = estimated signal */
+
+ d = sl - se; /* d = estimation diff. */
+
+ /* quantize prediction difference d */
+ y = step_size(state_ptr); /* quantizer step size */
+ i = quantize(d, y, qtab_723_24, 3); /* i = ADPCM code */
+ dq = reconstruct(i & 4, _dqlntab[i], y); /* quantized diff. */
+
+ sr = (dq < 0) ? se - (dq & 0x3FFF) : se + dq; /* reconstructed signal */
+
+ dqsez = sr + sez - se; /* pole prediction diff. */
+
+ update(3, y, _witab[i], _fitab[i], dq, sr, dqsez, state_ptr);
+
+ return (i);
+}
+
+/*
+ * g723_24_decoder()
+ *
+ * Decodes a 3-bit CCITT G.723_24 ADPCM code and returns
+ * the resulting 16-bit linear PCM, A-law or u-law sample value.
+ * -1 is returned if the output coding is unknown.
+ */
+int
+g723_24_decoder(
+ int i,
+ int out_coding,
+ struct g72x_state *state_ptr)
+{
+ short sezi, sei, sez, se; /* ACCUM */
+ short y; /* MIX */
+ short sr; /* ADDB */
+ short dq;
+ short dqsez;
+
+ i &= 0x07; /* mask to get proper bits */
+ sezi = predictor_zero(state_ptr);
+ sez = sezi >> 1;
+ sei = sezi + predictor_pole(state_ptr);
+ se = sei >> 1; /* se = estimated signal */
+
+ y = step_size(state_ptr); /* adaptive quantizer step size */
+ dq = reconstruct(i & 0x04, _dqlntab[i], y); /* unquantize pred diff */
+
+ sr = (dq < 0) ? (se - (dq & 0x3FFF)) : (se + dq); /* reconst. signal */
+
+ dqsez = sr - se + sez; /* pole prediction diff. */
+
+ update(3, y, _witab[i], _fitab[i], dq, sr, dqsez, state_ptr);
+
+ switch (out_coding) {
+ case AUDIO_ENCODING_ALAW:
+ return (tandem_adjust_alaw(sr, se, y, i, 4, qtab_723_24));
+ case AUDIO_ENCODING_ULAW:
+ return (tandem_adjust_ulaw(sr, se, y, i, 4, qtab_723_24));
+ case AUDIO_ENCODING_LINEAR:
+ return (sr << 2); /* sr was of 14-bit dynamic range */
+ default:
+ return (-1);
+ }
+}
--- /dev/null
+/*
+ * This source code is a product of Sun Microsystems, Inc. and is provided
+ * for unrestricted use. Users may copy or modify this source code without
+ * charge.
+ *
+ * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING
+ * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun source code is provided with no support and without any obligation on
+ * the part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/*
+ * g723_40.c
+ *
+ * Description:
+ *
+ * g723_40_encoder(), g723_40_decoder()
+ *
+ * These routines comprise an implementation of the CCITT G.723 40Kbps
+ * ADPCM coding algorithm. Essentially, this implementation is identical to
+ * the bit level description except for a few deviations which
+ * take advantage of workstation attributes, such as hardware 2's
+ * complement arithmetic.
+ *
+ * The deviation from the bit level specification (lookup tables),
+ * preserves the bit level performance specifications.
+ *
+ * As outlined in the G.723 Recommendation, the algorithm is broken
+ * down into modules. Each section of code below is preceded by
+ * the name of the module which it is implementing.
+ *
+ */
+#include "g72x.h"
+
+/*
+ * Maps G.723_40 code word to ructeconstructed scale factor normalized log
+ * magnitude values.
+ */
+static short _dqlntab[32] = {-2048, -66, 28, 104, 169, 224, 274, 318,
+ 358, 395, 429, 459, 488, 514, 539, 566,
+ 566, 539, 514, 488, 459, 429, 395, 358,
+ 318, 274, 224, 169, 104, 28, -66, -2048};
+
+/* Maps G.723_40 code word to log of scale factor multiplier. */
+static short _witab[32] = {448, 448, 768, 1248, 1280, 1312, 1856, 3200,
+ 4512, 5728, 7008, 8960, 11456, 14080, 16928, 22272,
+ 22272, 16928, 14080, 11456, 8960, 7008, 5728, 4512,
+ 3200, 1856, 1312, 1280, 1248, 768, 448, 448};
+
+/*
+ * Maps G.723_40 code words to a set of values whose long and short
+ * term averages are computed and then compared to give an indication
+ * how stationary (steady state) the signal is.
+ */
+static short _fitab[32] = {0, 0, 0, 0, 0, 0x200, 0x200, 0x200,
+ 0x200, 0x200, 0x400, 0x600, 0x800, 0xA00, 0xC00, 0xC00,
+ 0xC00, 0xC00, 0xA00, 0x800, 0x600, 0x400, 0x200, 0x200,
+ 0x200, 0x200, 0x200, 0, 0, 0, 0, 0};
+
+static short qtab_723_40[15] = {-122, -16, 68, 139, 198, 250, 298, 339,
+ 378, 413, 445, 475, 502, 528, 553};
+
+/*
+ * g723_40_encoder()
+ *
+ * Encodes a 16-bit linear PCM, A-law or u-law input sample and retuens
+ * the resulting 5-bit CCITT G.723 40Kbps code.
+ * Returns -1 if the input coding value is invalid.
+ */
+int
+g723_40_encoder(
+ int sl,
+ int in_coding,
+ struct g72x_state *state_ptr)
+{
+ short sei, sezi, se, sez; /* ACCUM */
+ short d; /* SUBTA */
+ short y; /* MIX */
+ short sr; /* ADDB */
+ short dqsez; /* ADDC */
+ short dq, i;
+
+ switch (in_coding) { /* linearize input sample to 14-bit PCM */
+ case AUDIO_ENCODING_ALAW:
+ sl = alaw2linear(sl) >> 2;
+ break;
+ case AUDIO_ENCODING_ULAW:
+ sl = ulaw2linear(sl) >> 2;
+ break;
+ case AUDIO_ENCODING_LINEAR:
+ sl = ((short) sl) >> 2; /* sl of 14-bit dynamic range */
+ break;
+ default:
+ return (-1);
+ }
+
+ sezi = predictor_zero(state_ptr);
+ sez = sezi >> 1;
+ sei = sezi + predictor_pole(state_ptr);
+ se = sei >> 1; /* se = estimated signal */
+
+ d = sl - se; /* d = estimation difference */
+
+ /* quantize prediction difference */
+ y = step_size(state_ptr); /* adaptive quantizer step size */
+ i = quantize(d, y, qtab_723_40, 15); /* i = ADPCM code */
+
+ dq = reconstruct(i & 0x10, _dqlntab[i], y); /* quantized diff */
+
+ sr = (dq < 0) ? se - (dq & 0x7FFF) : se + dq; /* reconstructed signal */
+
+ dqsez = sr + sez - se; /* dqsez = pole prediction diff. */
+
+ update(5, y, _witab[i], _fitab[i], dq, sr, dqsez, state_ptr);
+
+ return (i);
+}
+
+/*
+ * g723_40_decoder()
+ *
+ * Decodes a 5-bit CCITT G.723 40Kbps code and returns
+ * the resulting 16-bit linear PCM, A-law or u-law sample value.
+ * -1 is returned if the output coding is unknown.
+ */
+int
+g723_40_decoder(
+ int i,
+ int out_coding,
+ struct g72x_state *state_ptr)
+{
+ short sezi, sei, sez, se; /* ACCUM */
+ short y; /* MIX */
+ short sr; /* ADDB */
+ short dq;
+ short dqsez;
+
+ i &= 0x1f; /* mask to get proper bits */
+ sezi = predictor_zero(state_ptr);
+ sez = sezi >> 1;
+ sei = sezi + predictor_pole(state_ptr);
+ se = sei >> 1; /* se = estimated signal */
+
+ y = step_size(state_ptr); /* adaptive quantizer step size */
+ dq = reconstruct(i & 0x10, _dqlntab[i], y); /* estimation diff. */
+
+ sr = (dq < 0) ? (se - (dq & 0x7FFF)) : (se + dq); /* reconst. signal */
+
+ dqsez = sr - se + sez; /* pole prediction diff. */
+
+ update(5, y, _witab[i], _fitab[i], dq, sr, dqsez, state_ptr);
+
+ switch (out_coding) {
+ case AUDIO_ENCODING_ALAW:
+ return (tandem_adjust_alaw(sr, se, y, i, 0x10, qtab_723_40));
+ case AUDIO_ENCODING_ULAW:
+ return (tandem_adjust_ulaw(sr, se, y, i, 0x10, qtab_723_40));
+ case AUDIO_ENCODING_LINEAR:
+ return (sr << 2); /* sr was of 14-bit dynamic range */
+ default:
+ return (-1);
+ }
+}
--- /dev/null
+/*
+ * This source code is a product of Sun Microsystems, Inc. and is provided
+ * for unrestricted use. Users may copy or modify this source code without
+ * charge.
+ *
+ * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING
+ * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun source code is provided with no support and without any obligation on
+ * the part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/*
+ * g72x.c
+ *
+ * Common routines for G.721 and G.723 conversions.
+ */
+
+#include <stdlib.h>
+#include "g72x.h"
+
+static short power2[15] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80,
+ 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000};
+
+/*
+ * quan()
+ *
+ * quantizes the input val against the table of size short integers.
+ * It returns i if table[i - 1] <= val < table[i].
+ *
+ * Using linear search for simple coding.
+ */
+static int
+quan(
+ int val,
+ short *table,
+ int size)
+{
+ int i;
+
+ for (i = 0; i < size; i++)
+ if (val < *table++)
+ break;
+ return (i);
+}
+
+static char quan2_tab[65536];
+static short base2_tab[65536];
+static int init_tabs_done = 0;
+
+inline char quan2 (unsigned short val)
+{
+ return quan2_tab[val];
+}
+
+inline short base2 (unsigned short val)
+{
+ return base2_tab[val];
+}
+
+static void init_quan2_tab (void)
+{
+ long i;
+
+ for (i = 0; i < 65536; i++) {
+ quan2_tab[i] = quan (i, power2, 15);
+ };
+}
+
+static void init_base2_tab (void)
+{
+ long i;
+ short exp;
+
+ for (i = 0; i < 65536; i++) {
+ exp = quan2 (short (i));
+ base2_tab[i] = short ((exp << 6) + ((i << 6) >> exp));
+ };
+}
+
+static void init_tabs (void)
+{
+ if (init_tabs_done) return;
+
+ init_quan2_tab();
+ init_base2_tab();
+
+ init_tabs_done = 1;
+}
+
+/*
+ * fmult()
+ *
+ * returns the integer product of the 14-bit integer "an" and
+ * "floating point" representation (4-bit exponent, 6-bit mantessa) "srn".
+ */
+static int
+fmult(
+ int an,
+ int srn)
+{
+ short anmag, anexp, anmant;
+ short wanexp, wanmant;
+ short retval;
+
+ anmag = (an > 0) ? an : ((-an) & 0x1FFF);
+ anexp = quan2(anmag) - 6;
+ anmant = (anmag == 0) ? 32 :
+ (anexp >= 0) ? anmag >> anexp : anmag << -anexp;
+ wanexp = anexp + ((srn >> 6) & 0xF) - 13;
+
+ wanmant = (anmant * (srn & 077) + 0x30) >> 4;
+ retval = (wanexp >= 0) ? ((wanmant << wanexp) & 0x7FFF) :
+ (wanmant >> -wanexp);
+
+ return (((an ^ srn) < 0) ? -retval : retval);
+}
+
+/*
+ * g72x_init_state()
+ *
+ * This routine initializes and/or resets the g72x_state structure
+ * pointed to by 'state_ptr'.
+ * All the initial state values are specified in the CCITT G.721 document.
+ */
+void
+g72x_init_state(
+ struct g72x_state *state_ptr)
+{
+ int cnta;
+
+ init_tabs ();
+
+ state_ptr->yl = 34816;
+ state_ptr->yu = 544;
+ state_ptr->dms = 0;
+ state_ptr->dml = 0;
+ state_ptr->ap = 0;
+ for (cnta = 0; cnta < 2; cnta++) {
+ state_ptr->a[cnta] = 0;
+ state_ptr->pk[cnta] = 0;
+ state_ptr->sr[cnta] = 32;
+ }
+ for (cnta = 0; cnta < 6; cnta++) {
+ state_ptr->b[cnta] = 0;
+ state_ptr->dq[cnta] = 32;
+ }
+ state_ptr->td = 0;
+}
+
+/*
+ * predictor_zero()
+ *
+ * computes the estimated signal from 6-zero predictor.
+ *
+ */
+int
+predictor_zero(
+ struct g72x_state *state_ptr)
+{
+ int i;
+ int sezi;
+
+ sezi = fmult(state_ptr->b[0] >> 2, state_ptr->dq[0]);
+ for (i = 1; i < 6; i++) /* ACCUM */
+ sezi += fmult(state_ptr->b[i] >> 2, state_ptr->dq[i]);
+ return (sezi);
+}
+/*
+ * predictor_pole()
+ *
+ * computes the estimated signal from 2-pole predictor.
+ *
+ */
+int
+predictor_pole(
+ struct g72x_state *state_ptr)
+{
+ return (fmult(state_ptr->a[1] >> 2, state_ptr->sr[1]) +
+ fmult(state_ptr->a[0] >> 2, state_ptr->sr[0]));
+}
+/*
+ * step_size()
+ *
+ * computes the quantization step size of the adaptive quantizer.
+ *
+ */
+int
+step_size(
+ struct g72x_state *state_ptr)
+{
+ int y;
+ int dif;
+ int al;
+
+ if (state_ptr->ap >= 256)
+ return (state_ptr->yu);
+ else {
+ y = state_ptr->yl >> 6;
+ dif = state_ptr->yu - y;
+ al = state_ptr->ap >> 2;
+ if (dif > 0)
+ y += (dif * al) >> 6;
+ else if (dif < 0)
+ y += (dif * al + 0x3F) >> 6;
+ return (y);
+ }
+}
+
+/*
+ * quantize()
+ *
+ * Given a raw sample, 'd', of the difference signal and a
+ * quantization step size scale factor, 'y', this routine returns the
+ * ADPCM codeword to which that sample gets quantized. The step
+ * size scale factor division operation is done in the log base 2 domain
+ * as a subtraction.
+ */
+int
+quantize(
+ int d, /* Raw difference signal sample */
+ int y, /* Step size multiplier */
+ short *table, /* quantization table */
+ int size) /* table size of short integers */
+{
+ short dqm; /* Magnitude of 'd' */
+ short exp; /* Integer part of base 2 log of 'd' */
+ short mant; /* Fractional part of base 2 log */
+ short dl; /* Log of magnitude of 'd' */
+ short dln; /* Step size scale factor normalized log */
+ int i;
+
+ /*
+ * LOG
+ *
+ * Compute base 2 log of 'd', and store in 'dl'.
+ */
+ dqm = abs(d);
+ exp = quan2(dqm >> 1);
+ mant = ((dqm << 7) >> exp) & 0x7F; /* Fractional portion. */
+ dl = (exp << 7) + mant;
+
+ /*
+ * SUBTB
+ *
+ * "Divide" by step size multiplier.
+ */
+ dln = dl - (y >> 2);
+
+ /*
+ * QUAN
+ *
+ * Obtain codword i for 'd'.
+ */
+ i = quan(dln, table, size);
+ if (d < 0) /* take 1's complement of i */
+ return ((size << 1) + 1 - i);
+ else if (i == 0) /* take 1's complement of 0 */
+ return ((size << 1) + 1); /* new in 1988 */
+ else
+ return (i);
+}
+/*
+ * reconstruct()
+ *
+ * Returns reconstructed difference signal 'dq' obtained from
+ * codeword 'i' and quantization step size scale factor 'y'.
+ * Multiplication is performed in log base 2 domain as addition.
+ */
+int
+reconstruct(
+ int sign, /* 0 for non-negative value */
+ int dqln, /* G.72x codeword */
+ int y) /* Step size multiplier */
+{
+ short dql; /* Log of 'dq' magnitude */
+ short dex; /* Integer part of log */
+ short dqt;
+ short dq; /* Reconstructed difference signal sample */
+
+ dql = dqln + (y >> 2); /* ADDA */
+
+ if (dql < 0) {
+ return ((sign) ? -0x8000 : 0);
+ } else { /* ANTILOG */
+ dex = (dql >> 7) & 15;
+ dqt = 128 + (dql & 127);
+ dq = (dqt << 7) >> (14 - dex);
+ return ((sign) ? (dq - 0x8000) : dq);
+ }
+}
+
+
+/*
+ * update()
+ *
+ * updates the state variables for each output code
+ */
+void
+update(
+ int code_size, /* distinguish 723_40 with others */
+ int y, /* quantizer step size */
+ int wi, /* scale factor multiplier */
+ int fi, /* for long/short term energies */
+ int dq, /* quantized prediction difference */
+ int sr, /* reconstructed signal */
+ int dqsez, /* difference from 2-pole predictor */
+ struct g72x_state *state_ptr) /* coder state pointer */
+{
+ int cnt;
+ short mag; /* Adaptive predictor, FLOAT A */
+ short a2p; /* LIMC */
+ short a1ul; /* UPA1 */
+ short pks1; /* UPA2 */
+ short fa1;
+ char tr; /* tone/transition detector */
+ short ylint, thr2, dqthr;
+ short ylfrac, thr1;
+ short pk0;
+
+ pk0 = (dqsez < 0) ? 1 : 0; /* needed in updating predictor poles */
+
+ mag = dq & 0x7FFF; /* prediction difference magnitude */
+ /* TRANS */
+ ylint = short (state_ptr->yl >> 15); /* exponent part of yl */
+ ylfrac = (state_ptr->yl >> 10) & 0x1F; /* fractional part of yl */
+ thr1 = (32 + ylfrac) << ylint; /* threshold */
+ thr2 = (ylint > 9) ? 31 << 10 : thr1; /* limit thr2 to 31 << 10 */
+ dqthr = (thr2 + (thr2 >> 1)) >> 1; /* dqthr = 0.75 * thr2 */
+ if (state_ptr->td == 0) /* signal supposed voice */
+ tr = 0;
+ else if (mag <= dqthr) /* supposed data, but small mag */
+ tr = 0; /* treated as voice */
+ else /* signal is data (modem) */
+ tr = 1;
+
+ /*
+ * Quantizer scale factor adaptation.
+ */
+
+ /* FUNCTW & FILTD & DELAY */
+ /* update non-steady state step size multiplier */
+ state_ptr->yu = y + ((wi - y) >> 5);
+
+ /* LIMB */
+ if (state_ptr->yu < 544) /* 544 <= yu <= 5120 */
+ state_ptr->yu = 544;
+ else if (state_ptr->yu > 5120)
+ state_ptr->yu = 5120;
+
+ /* FILTE & DELAY */
+ /* update steady state step size multiplier */
+ state_ptr->yl += state_ptr->yu + ((-state_ptr->yl) >> 6);
+
+ /*
+ * Adaptive predictor coefficients.
+ */
+ if (tr == 1) { /* reset a's and b's for modem signal */
+ state_ptr->a[0] = 0;
+ state_ptr->a[1] = 0;
+ state_ptr->b[0] = 0;
+ state_ptr->b[1] = 0;
+ state_ptr->b[2] = 0;
+ state_ptr->b[3] = 0;
+ state_ptr->b[4] = 0;
+ state_ptr->b[5] = 0;
+
+ a2p = 0; /* eliminate Compiler Warnings */
+ } else { /* update a's and b's */
+ pks1 = pk0 ^ state_ptr->pk[0]; /* UPA2 */
+
+ /* update predictor pole a[1] */
+ a2p = state_ptr->a[1] - (state_ptr->a[1] >> 7);
+ if (dqsez != 0) {
+ fa1 = (pks1) ? state_ptr->a[0] : -state_ptr->a[0];
+ if (fa1 < -8191) /* a2p = function of fa1 */
+ a2p -= 0x100;
+ else if (fa1 > 8191)
+ a2p += 0xFF;
+ else
+ a2p += fa1 >> 5;
+
+ if (pk0 ^ state_ptr->pk[1])
+ /* LIMC */
+ if (a2p <= -12160)
+ a2p = -12288;
+ else if (a2p >= 12416)
+ a2p = 12288;
+ else
+ a2p -= 0x80;
+ else if (a2p <= -12416)
+ a2p = -12288;
+ else if (a2p >= 12160)
+ a2p = 12288;
+ else
+ a2p += 0x80;
+ }
+
+ /* TRIGB & DELAY */
+ state_ptr->a[1] = a2p;
+
+ /* UPA1 */
+ /* update predictor pole a[0] */
+ state_ptr->a[0] -= state_ptr->a[0] >> 8;
+ if (dqsez != 0)
+ if (pks1 == 0)
+ state_ptr->a[0] += 192;
+ else
+ state_ptr->a[0] -= 192;
+
+ /* LIMD */
+ a1ul = 15360 - a2p;
+ if (state_ptr->a[0] < -a1ul)
+ state_ptr->a[0] = -a1ul;
+ else if (state_ptr->a[0] > a1ul)
+ state_ptr->a[0] = a1ul;
+
+ /* UPB : update predictor zeros b[6] */
+ for (cnt = 0; cnt < 6; cnt++) {
+ if (code_size == 5) /* for 40Kbps G.723 */
+ state_ptr->b[cnt] -= state_ptr->b[cnt] >> 9;
+ else /* for G.721 and 24Kbps G.723 */
+ state_ptr->b[cnt] -= state_ptr->b[cnt] >> 8;
+ if (dq & 0x7FFF) { /* XOR */
+ if ((dq ^ state_ptr->dq[cnt]) >= 0)
+ state_ptr->b[cnt] += 128;
+ else
+ state_ptr->b[cnt] -= 128;
+ }
+ }
+ }
+
+ for (cnt = 5; cnt > 0; cnt--)
+ state_ptr->dq[cnt] = state_ptr->dq[cnt-1];
+ /* FLOAT A : convert dq[0] to 4-bit exp, 6-bit mantissa f.p. */
+ if (mag == 0) {
+ state_ptr->dq[0] = (dq >= 0) ? 0x20 : 0xFC20;
+ } else {
+ state_ptr->dq[0] = (dq >= 0) ?
+ base2 (mag) : base2 (mag) - 0x400;
+ }
+
+ state_ptr->sr[1] = state_ptr->sr[0];
+ /* FLOAT B : convert sr to 4-bit exp., 6-bit mantissa f.p. */
+ if (sr == 0) {
+ state_ptr->sr[0] = 0x20;
+ } else if (sr > 0) {
+ state_ptr->sr[0] = base2(sr);
+ } else if (sr > -32768) {
+ mag = -sr;
+ state_ptr->sr[0] = base2(mag) - 0x400;
+ } else
+ state_ptr->sr[0] = short (0xFC20);
+
+ /* DELAY A */
+ state_ptr->pk[1] = state_ptr->pk[0];
+ state_ptr->pk[0] = pk0;
+
+ /* TONE */
+ if (tr == 1) /* this sample has been treated as data */
+ state_ptr->td = 0; /* next one will be treated as voice */
+ else if (a2p < -11776) /* small sample-to-sample correlation */
+ state_ptr->td = 1; /* signal may be data */
+ else /* signal is voice */
+ state_ptr->td = 0;
+
+ /*
+ * Adaptation speed control.
+ */
+ state_ptr->dms += (fi - state_ptr->dms) >> 5; /* FILTA */
+ state_ptr->dml += (((fi << 2) - state_ptr->dml) >> 7); /* FILTB */
+
+ if (tr == 1)
+ state_ptr->ap = 256;
+ else if (y < 1536) /* SUBTC */
+ state_ptr->ap += (0x200 - state_ptr->ap) >> 4;
+ else if (state_ptr->td == 1)
+ state_ptr->ap += (0x200 - state_ptr->ap) >> 4;
+ else if (abs((state_ptr->dms << 2) - state_ptr->dml) >=
+ (state_ptr->dml >> 3))
+ state_ptr->ap += (0x200 - state_ptr->ap) >> 4;
+ else
+ state_ptr->ap += (-state_ptr->ap) >> 4;
+}
+
+/*
+ * tandem_adjust(sr, se, y, i, sign)
+ *
+ * At the end of ADPCM decoding, it simulates an encoder which may be receiving
+ * the output of this decoder as a tandem process. If the output of the
+ * simulated encoder differs from the input to this decoder, the decoder output
+ * is adjusted by one level of A-law or u-law codes.
+ *
+ * Input:
+ * sr decoder output linear PCM sample,
+ * se predictor estimate sample,
+ * y quantizer step size,
+ * i decoder input code,
+ * sign sign bit of code i
+ *
+ * Return:
+ * adjusted A-law or u-law compressed sample.
+ */
+int
+tandem_adjust_alaw(
+ int sr, /* decoder output linear PCM sample */
+ int se, /* predictor estimate sample */
+ int y, /* quantizer step size */
+ int i, /* decoder input code */
+ int sign,
+ short *qtab)
+{
+ unsigned char sp; /* A-law compressed 8-bit code */
+ short dx; /* prediction error */
+ char id; /* quantized prediction error */
+ int sd; /* adjusted A-law decoded sample value */
+ int im; /* biased magnitude of i */
+ int imx; /* biased magnitude of id */
+
+ if (sr <= -32768)
+ sr = -1;
+ sp = linear2alaw((sr >> 1) << 3); /* short to A-law compression */
+ dx = (alaw2linear(sp) >> 2) - se; /* 16-bit prediction error */
+ id = quantize(dx, y, qtab, sign - 1);
+
+ if (id == i) { /* no adjustment on sp */
+ return (sp);
+ } else { /* sp adjustment needed */
+ /* ADPCM codes : 8, 9, ... F, 0, 1, ... , 6, 7 */
+ im = i ^ sign; /* 2's complement to biased unsigned */
+ imx = id ^ sign;
+
+ if (imx > im) { /* sp adjusted to next lower value */
+ if (sp & 0x80) {
+ sd = (sp == 0xD5) ? 0x55 :
+ ((sp ^ 0x55) - 1) ^ 0x55;
+ } else {
+ sd = (sp == 0x2A) ? 0x2A :
+ ((sp ^ 0x55) + 1) ^ 0x55;
+ }
+ } else { /* sp adjusted to next higher value */
+ if (sp & 0x80)
+ sd = (sp == 0xAA) ? 0xAA :
+ ((sp ^ 0x55) + 1) ^ 0x55;
+ else
+ sd = (sp == 0x55) ? 0xD5 :
+ ((sp ^ 0x55) - 1) ^ 0x55;
+ }
+ return (sd);
+ }
+}
+
+int
+tandem_adjust_ulaw(
+ int sr, /* decoder output linear PCM sample */
+ int se, /* predictor estimate sample */
+ int y, /* quantizer step size */
+ int i, /* decoder input code */
+ int sign,
+ short *qtab)
+{
+ unsigned char sp; /* u-law compressed 8-bit code */
+ short dx; /* prediction error */
+ char id; /* quantized prediction error */
+ int sd; /* adjusted u-law decoded sample value */
+ int im; /* biased magnitude of i */
+ int imx; /* biased magnitude of id */
+
+ if (sr <= -32768)
+ sr = 0;
+ sp = linear2ulaw(sr << 2); /* short to u-law compression */
+ dx = (ulaw2linear(sp) >> 2) - se; /* 16-bit prediction error */
+ id = quantize(dx, y, qtab, sign - 1);
+ if (id == i) {
+ return (sp);
+ } else {
+ /* ADPCM codes : 8, 9, ... F, 0, 1, ... , 6, 7 */
+ im = i ^ sign; /* 2's complement to biased unsigned */
+ imx = id ^ sign;
+ if (imx > im) { /* sp adjusted to next lower value */
+ if (sp & 0x80)
+ sd = (sp == 0xFF) ? 0x7E : sp + 1;
+ else
+ sd = (sp == 0) ? 0 : sp - 1;
+
+ } else { /* sp adjusted to next higher value */
+ if (sp & 0x80)
+ sd = (sp == 0x80) ? 0x80 : sp - 1;
+ else
+ sd = (sp == 0x7F) ? 0xFE : sp + 1;
+ }
+ return (sd);
+ }
+}
--- /dev/null
+/*
+ * This source code is a product of Sun Microsystems, Inc. and is provided
+ * for unrestricted use. Users may copy or modify this source code without
+ * charge.
+ *
+ * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING
+ * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun source code is provided with no support and without any obligation on
+ * the part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/*
+ * g72x.h
+ *
+ * Header file for CCITT conversion routines.
+ *
+ */
+#ifndef _G72X_H
+#define _G72X_H
+
+#define AUDIO_ENCODING_ULAW (1) /* ISDN u-law */
+#define AUDIO_ENCODING_ALAW (2) /* ISDN A-law */
+#define AUDIO_ENCODING_LINEAR (3) /* PCM 2's-complement (0-center) */
+
+/*
+ * The following is the definition of the state structure
+ * used by the G.721/G.723 encoder and decoder to preserve their internal
+ * state between successive calls. The meanings of the majority
+ * of the state structure fields are explained in detail in the
+ * CCITT Recommendation G.721. The field names are essentially indentical
+ * to variable names in the bit level description of the coding algorithm
+ * included in this Recommendation.
+ */
+struct g72x_state {
+ long yl; /* Locked or steady state step size multiplier. */
+ short yu; /* Unlocked or non-steady state step size multiplier. */
+ short dms; /* Short term energy estimate. */
+ short dml; /* Long term energy estimate. */
+ short ap; /* Linear weighting coefficient of 'yl' and 'yu'. */
+
+ short a[2]; /* Coefficients of pole portion of prediction filter. */
+ short b[6]; /* Coefficients of zero portion of prediction filter. */
+ short pk[2]; /*
+ * Signs of previous two samples of a partially
+ * reconstructed signal.
+ */
+ short dq[6]; /*
+ * Previous 6 samples of the quantized difference
+ * signal represented in an internal floating point
+ * format.
+ */
+ short sr[2]; /*
+ * Previous 2 samples of the quantized difference
+ * signal represented in an internal floating point
+ * format.
+ */
+ char td; /* delayed tone detect, new in 1988 version */
+};
+
+/* External function definitions. */
+
+extern unsigned char linear2alaw (int pcm_val); /* 2's complement (16-bit range) */
+extern int alaw2linear (unsigned char a_val);
+extern unsigned char linear2ulaw (int pcm_val); /* 2's complement (16-bit range) */
+extern int ulaw2linear (unsigned char u_val);
+extern int predictor_zero (struct g72x_state *state_ptr);
+extern int predictor_pole (struct g72x_state *state_ptr);
+extern int step_size (struct g72x_state *state_ptr);
+extern int quantize (int d, int y, short *table, int size);
+extern int reconstruct (int sign, int dqln, int y);
+
+extern void update
+ ( int code_size, int y, int wi, int fi, int dq
+ , int sr, int dqsez, struct g72x_state *state_ptr);
+
+int tandem_adjust_alaw
+ (int sr, int se, int y, int i, int sign, short *qtab);
+
+int tandem_adjust_ulaw
+ (int sr, int se, int y, int i, int sign, short *qtab);
+
+extern void g72x_init_state (struct g72x_state *);
+extern int g721_encoder(
+ int sample,
+ int in_coding,
+ struct g72x_state *state_ptr);
+extern int g721_decoder(
+ int code,
+ int out_coding,
+ struct g72x_state *state_ptr);
+extern int g723_24_encoder(
+ int sample,
+ int in_coding,
+ struct g72x_state *state_ptr);
+extern int g723_24_decoder(
+ int code,
+ int out_coding,
+ struct g72x_state *state_ptr);
+extern int g723_40_encoder(
+ int sample,
+ int in_coding,
+ struct g72x_state *state_ptr);
+extern int g723_40_decoder(
+ int code,
+ int out_coding,
+ struct g72x_state *state_ptr);
+
+#endif /* !_G72X_H */
--- /dev/null
+////////////////////////////////////////////////////////////////////////////////
+// Name: sndsnd.cpp
+// Purpose: wxMMedia
+// Author: Guilhem Lavaux
+// Created: 1997
+// Updated: 1998
+// Copyright: (C) 1997, 1998, Guilhem Lavaux
+// License: wxWindows license
+////////////////////////////////////////////////////////////////////////////////
+#ifdef __GNUG__
+#pragma implementation
+#endif
+#include "cdbase.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+wxCDtime wxCDAudio::CDtoc::GetTrackTime(wxUint8 track) const
+{
+ if (track > total_time.track) {
+ wxCDtime dummy_time = {0, 0, 0, 0};
+ return dummy_time;
+ }
+ return tracks_time[track];
+}
+
+wxCDtime wxCDAudio::CDtoc::GetTrackPos(wxUint8 track) const
+{
+ if (track > total_time.track) {
+ wxCDtime dummy_time = {0, 0, 0, 0};
+ return dummy_time;
+ }
+ return tracks_pos[track];
+}
+
+bool wxCDAudio::Play(const wxCDtime& beg_play)
+{
+ return Play(beg_play, GetToc().GetTotalTime());
+}
+
+bool wxCDAudio::Play(wxUint8 beg_track, wxUint8 end_track)
+{
+ wxCDtime beg_play = GetToc().GetTrackPos(beg_track);
+ wxCDtime end_play;
+
+ if (end_track)
+ end_play = GetToc().GetTrackPos(end_track);
+ else
+ end_play = GetToc().GetTotalTime();
+ return Play(beg_play, end_play);
+}
--- /dev/null
+// -*- c++ -*-
+// /////////////////////////////////////////////////////////////////////////////
+// Name: cdbase.h
+// Purpose: wxMMedia
+// Author: Guilhem Lavaux
+// Created: 1997
+// Updated: 1998
+// Copyright: (C) 1997, 1998, Guilhem Lavaux
+// License: wxWindows license
+// /////////////////////////////////////////////////////////////////////////////
+#ifndef __CDA_base_H__
+#define __CDA_base_H__
+
+#ifdef __GNUG__
+#pragma interface
+#endif
+
+#ifdef WX_PRECOMP
+#include "wx_prec.h"
+#else
+#include "wx/wx.h"
+#endif
+#include "mmtype.h"
+
+typedef struct wxCDtime {
+ wxUint8 track;
+ wxUint8 hour, min, sec;
+} wxCDtime;
+
+///
+class WXDLLEXPORT wxCDAudio : public wxObject {
+ DECLARE_ABSTRACT_CLASS(wxCDAudio)
+public:
+ ///
+ typedef enum { PLAYING, PAUSED, STOPPED } CDstatus;
+ /// Table of contents manager
+ class CDtoc {
+ protected:
+ wxCDtime *tracks_time, *tracks_pos;
+ wxCDtime total_time;
+ public:
+ ///
+ CDtoc(wxCDtime& tot_tm, wxCDtime *trks_tm, wxCDtime *trks_pos)
+ { tracks_time = trks_tm; total_time = tot_tm; tracks_pos = trks_pos; }
+
+ /// Returns the length of the specified track
+ /** @param track track to get length */
+ wxCDtime GetTrackTime(wxUint8 track) const;
+ /** Returns the position of the specified
+ @param track track to get position */
+ wxCDtime GetTrackPos(wxUint8 track) const;
+ /// Returns the total time
+ inline wxCDtime GetTotalTime() const { return total_time; }
+ };
+public:
+ ///
+ wxCDAudio() : wxObject() {}
+ ///
+ virtual ~wxCDAudio() {}
+
+ /// Play audio at the specified position
+ /**
+ * @param beg_play start position
+ * @param end_play end position
+ */
+ virtual bool Play(const wxCDtime& beg_play, const wxCDtime& end_play) = 0;
+ /// Play audio from the specified to the end of the CD audio
+ /**
+ * @param beg_play start position
+ */
+ bool Play(const wxCDtime& beg_play);
+ ///
+ bool Play(wxUint8 beg_track, wxUint8 end_track = 0);
+ /// Pause the audio playing
+ virtual bool Pause() = 0;
+ /// Resume a paused audio playing
+ virtual bool Resume() = 0;
+ /// Get the current CD status
+ virtual CDstatus GetStatus() = 0;
+ /// Get the current playing time
+ virtual wxCDtime GetTime() = 0;
+ /// Returns the table of contents
+ virtual const CDtoc& GetToc() = 0;
+ /// CD ok
+ virtual bool Ok() const = 0;
+};
+
+#endif
--- /dev/null
+////////////////////////////////////////////////////////////////////////////////
+// Name: cdlinux.cpp
+// Purpose: wxMMedia
+// Author: Guilhem Lavaux
+// Created: 1997
+// Updated: 1998
+// Copyright: (C) 1997, 1998, Guilhem Lavaux
+// License: wxWindows license
+////////////////////////////////////////////////////////////////////////////////
+#ifdef __GNUG__
+#pragma implementation "cdunix.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#ifdef __linux__
+#include <linux/cdrom.h>
+#else
+// For Solaris
+#include <sys/cdio.h>
+#endif
+
+#ifdef WX_PRECOMP
+#include "wx/wxprec.h"
+#else
+#include "wx/wx.h"
+#endif
+#include "mmtype.h"
+#include "cdunix.h"
+
+wxCDAudioLinux::wxCDAudioLinux()
+ : wxCDAudio(), m_fd(-1)
+{
+ OpenDevice("/dev/cdrom");
+}
+
+wxCDAudioLinux::wxCDAudioLinux(const char *dev_name)
+ : wxCDAudio(), m_fd(-1)
+{
+ OpenDevice(dev_name);
+}
+
+wxCDAudioLinux::~wxCDAudioLinux()
+{
+ if (m_fd != -1) {
+ close(m_fd);
+ wxDELETE(m_trksize);
+ wxDELETE(m_trkpos);
+ }
+}
+
+void wxCDAudioLinux::OpenDevice(const char *dev_name)
+{
+ struct cdrom_tocentry entry, old_entry;
+ struct cdrom_tochdr diskinf;
+ struct cdrom_msf0 *msf = &entry.cdte_addr.msf,
+ *old_msf = &old_entry.cdte_addr.msf;
+ wxCDtime *the_track;
+ wxCDtime tot_tm;
+ wxUint8 nb_tracks, i;
+ int hour, minute, second;
+
+ if (m_fd != -1)
+ return;
+
+ m_fd = open(dev_name, O_RDONLY);
+ if (m_fd == -1) {
+ m_toc = NULL;
+ return;
+ }
+ m_status = STOPPED;
+
+ ioctl(m_fd, CDROMREADTOCHDR, &diskinf);
+
+ nb_tracks = diskinf.cdth_trk1-diskinf.cdth_trk0+1;
+ m_trksize = new wxCDtime[nb_tracks+1];
+ m_trkpos = new wxCDtime[nb_tracks+1];
+
+ old_msf->minute = 0;
+ old_msf->second = 0;
+ for (i=diskinf.cdth_trk0;i<=diskinf.cdth_trk1;i++) {
+ entry.cdte_track = i;
+ entry.cdte_format = CDROM_MSF;
+ ioctl(m_fd, CDROMREADTOCENTRY, &entry);
+
+ minute = msf->minute - old_msf->minute;
+ second = msf->second - old_msf->second;
+ if (second < 0) {
+ minute--;
+ second += 60;
+ }
+
+ hour = minute / 60;
+ minute %= 60;
+
+ the_track = &m_trksize[i-diskinf.cdth_trk0];
+ the_track->track = i-diskinf.cdth_trk0;
+ the_track->hour = hour;
+ the_track->min = minute;
+ the_track->sec = second;
+
+ the_track = &m_trkpos[i-diskinf.cdth_trk0];
+ the_track->track = i-diskinf.cdth_trk0;
+ the_track->hour = old_msf->minute / 60;
+ the_track->min = old_msf->minute % 60;
+ the_track->sec = old_msf->second;
+ old_entry = entry;
+ }
+
+ entry.cdte_track = CDROM_LEADOUT;
+ entry.cdte_format = CDROM_MSF;
+ ioctl(m_fd, CDROMREADTOCENTRY, &entry);
+
+ tot_tm.track = nb_tracks;
+ tot_tm.hour = msf->minute / 60;
+ tot_tm.min = msf->minute % 60;
+ tot_tm.sec = msf->second % 60;
+
+ m_trksize[nb_tracks].track = nb_tracks;
+ minute = msf->minute - old_msf->minute;
+ second = msf->second - old_msf->second;
+ if (second < 0) {
+ minute--;
+ second += 60;
+ }
+ hour = minute / 60;
+ minute %= 60;
+
+ m_trksize[nb_tracks].hour = hour;
+ m_trksize[nb_tracks].min = minute;
+ m_trksize[nb_tracks].sec = second;
+ m_trkpos[nb_tracks].track = nb_tracks;
+ m_trkpos[nb_tracks].hour = old_msf->minute / 60;
+ m_trkpos[nb_tracks].min = old_msf->minute % 60;
+ m_trkpos[nb_tracks].sec = old_msf->second;
+
+ m_toc = new CDtoc(tot_tm, m_trksize, m_trkpos);
+}
+
+bool wxCDAudioLinux::Play(const wxCDtime& beg_time, const wxCDtime& end_time)
+{
+ struct cdrom_msf track_msf;
+
+ track_msf.cdmsf_min0 = beg_time.hour * 60 + beg_time.min;
+ track_msf.cdmsf_sec0 = beg_time.sec;
+ track_msf.cdmsf_frame0 = 0;
+ track_msf.cdmsf_min1 = end_time.hour * 60 + end_time.min;
+ track_msf.cdmsf_sec1 = end_time.sec;
+ track_msf.cdmsf_frame1 = 0;
+ return (ioctl(m_fd, CDROMPLAYMSF, &track_msf) != -1);
+}
+
+bool wxCDAudioLinux::Pause()
+{
+ return (ioctl(m_fd, CDROMPAUSE, 0) != -1);
+}
+
+bool wxCDAudioLinux::Resume()
+{
+ return (ioctl(m_fd, CDROMRESUME, 0) != -1);
+}
+
+wxCDAudio::CDstatus wxCDAudioLinux::GetStatus()
+{
+ struct cdrom_subchnl subchnl;
+ ioctl(m_fd, CDROMSUBCHNL, &subchnl);
+ switch (subchnl.cdsc_audiostatus) {
+ case CDROM_AUDIO_PLAY: return PLAYING;
+ case CDROM_AUDIO_PAUSED: return PAUSED;
+ case CDROM_AUDIO_COMPLETED: return STOPPED;
+ }
+
+ return STOPPED;
+}
+
+wxCDtime wxCDAudioLinux::GetTime()
+{
+ wxCDtime cdtime;
+ struct cdrom_subchnl subchnl;
+
+ ioctl(m_fd, CDROMSUBCHNL, &subchnl);
+ cdtime.track = subchnl.cdsc_trk;
+ cdtime.min = subchnl.cdsc_reladdr.msf.minute;
+ cdtime.hour = cdtime.min / 60;
+ cdtime.min %= 60;
+ cdtime.sec = subchnl.cdsc_reladdr.msf.second;
+
+ return cdtime;
+}
+
+wxCDAudio::CDtoc& wxCDAudioLinux::GetToc()
+{
+ return *m_toc;
+}
--- /dev/null
+// /////////////////////////////////////////////////////////////////////////////
+// Name: cdunix.h
+// Purpose: wxMMedia
+// Author: Guilhem Lavaux
+// Created: 1997
+// Updated: 1998
+// Copyright: (C) 1997, 1998, Guilhem Lavaux
+// License: wxWindows license
+// /////////////////////////////////////////////////////////////////////////////
+#ifndef __CDUNIXH__
+#define __CDUNIXH__
+
+#ifdef __GNUG__
+#pragma interface
+#endif
+
+#ifdef WX_PRECOMP
+#include "wx/wxprec.h"
+#else
+#include "wx/wx.h"
+#endif
+#include "mmtype.h"
+#include "cdbase.h"
+
+///
+class WXDLLEXPORT wxCDAudioLinux : public wxCDAudio {
+ DECLARE_DYNAMIC_CLASS(wxCDAudioLinux)
+protected:
+ wxCDtime m_time;
+ CDstatus m_status;
+ CDtoc *m_toc;
+ int m_fd;
+ wxCDtime *m_trksize, *m_trkpos;
+public:
+ ///
+ wxCDAudioLinux();
+ ///
+ wxCDAudioLinux(const char *dev_name);
+ ///
+ virtual ~wxCDAudioLinux();
+
+ ///
+ virtual bool Play(const wxCDtime& beg_time, const wxCDtime& end_time);
+ ///
+ virtual bool Pause();
+ ///
+ virtual bool Resume();
+ ///
+ virtual CDstatus GetStatus();
+ ///
+ virtual wxCDtime GetTime();
+ ///
+ virtual CDtoc& GetToc();
+ ///
+ virtual inline bool Ok() const { return (m_fd != -1); }
+protected:
+ ///
+ void OpenDevice(const char *dev_name);
+};
+
+#endif
--- /dev/null
+////////////////////////////////////////////////////////////////////////////////
+// Name: cdwin.cpp
+// Purpose: wxMMedia
+// Author: Guilhem Lavaux
+// Created: 1997
+// Updated: 1998
+// Copyright: (C) 1997, 1998, Guilhem Lavaux
+// License: wxWindows license
+////////////////////////////////////////////////////////////////////////////////
+#ifdef __GNUG__
+#pragma implementation "cdwin.h"
+#endif
+
+#include <windows.h>
+#include <stdio.h>
+#include <mmsystem.h>
+#ifdef WX_PRECOMP
+#include "wx/wxprec.h"
+#else
+#include "wx/wx.h"
+#endif
+#define WXMMEDIA_INTERNAL
+#include "mmtype.h"
+#include "cdbase.h"
+#include "cdwin.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+wxCDAudioWin::wxCDAudioWin(void)
+ : wxCDAudio(), m_trksize(NULL), m_trkpos(NULL), m_ok(TRUE), m_toc(NULL)
+{
+ MCI_OPEN_PARMS open_struct;
+ MCI_SET_PARMS set_struct;
+ DWORD ret;
+
+ m_internal = new CDAW_Internal;
+ open_struct.lpstrDeviceType = "cdaudio";
+ ret = mciSendCommand(NULL, MCI_OPEN, MCI_OPEN_TYPE,
+ (DWORD)&open_struct);
+ if (ret) {
+ m_ok = FALSE;
+ return;
+ }
+ m_internal->dev_id = open_struct.wDeviceID;
+
+ set_struct.dwTimeFormat = MCI_FORMAT_MSF;
+ ret = mciSendCommand(m_internal->dev_id, MCI_SET, MCI_SET_TIME_FORMAT,
+ (DWORD)(LPVOID)&set_struct);
+
+ PrepareToc();
+
+ set_struct.dwTimeFormat = MCI_FORMAT_TMSF;
+ ret = mciSendCommand(m_internal->dev_id, MCI_SET, MCI_SET_TIME_FORMAT,
+ (DWORD)(LPVOID)&set_struct);
+}
+
+wxCDAudioWin::~wxCDAudioWin(void)
+{
+ if (m_ok) {
+ mciSendCommand(m_internal->dev_id, MCI_CLOSE, 0, NULL);
+ delete m_toc;
+ delete[] m_trksize;
+ delete[] m_trkpos;
+ }
+ delete m_internal;
+}
+
+void wxCDAudioWin::PrepareToc(void)
+{
+ MCI_STATUS_PARMS status_struct;
+ MCI_SET_PARMS set_struct;
+ wxUint16 i, nb_m_trksize;
+ wxCDtime total_time, *trk;
+ DWORD ret, tmem;
+
+ if (!m_ok)
+ return;
+
+ status_struct.dwItem = MCI_STATUS_NUMBER_OF_TRACKS;
+ ret = mciSendCommand(m_internal->dev_id, MCI_STATUS, MCI_STATUS_ITEM,
+ (DWORD)&status_struct);
+ nb_m_trksize = status_struct.dwReturn;
+
+ m_trksize = new wxCDtime[nb_m_trksize+1];
+ m_trkpos = new wxCDtime[nb_m_trksize+1];
+
+ status_struct.dwItem = MCI_STATUS_LENGTH;
+ ret = mciSendCommand(m_internal->dev_id, MCI_STATUS, MCI_STATUS_ITEM,
+ (DWORD)&status_struct);
+ total_time.track = nb_m_trksize;
+ tmem = status_struct.dwReturn;
+ total_time.min = MCI_MSF_MINUTE(tmem);
+ total_time.sec = MCI_MSF_SECOND(tmem);
+ total_time.hour = total_time.min / 60;
+ total_time.min %= 60;
+
+ for (i=1;i<=nb_m_trksize;i++) {
+ status_struct.dwItem = MCI_STATUS_POSITION;
+ status_struct.dwTrack = i;
+ ret = mciSendCommand(m_internal->dev_id, MCI_STATUS,
+ MCI_STATUS_ITEM | MCI_TRACK,
+ (DWORD)(LPVOID)&status_struct);
+ tmem = status_struct.dwReturn;
+
+ trk = &m_trkpos[i];
+ trk->track = i;
+ trk->min = MCI_MSF_MINUTE(tmem);
+ trk->sec = MCI_MSF_SECOND(tmem);
+ trk->hour = trk->min / 60;
+ trk->min %= 60;
+
+ status_struct.dwItem = MCI_STATUS_LENGTH;
+ status_struct.dwTrack = i;
+ ret = mciSendCommand(m_internal->dev_id, MCI_STATUS,
+ MCI_STATUS_ITEM | MCI_TRACK,
+ (DWORD)(LPVOID)&status_struct);
+ tmem = status_struct.dwReturn;
+
+ trk = &m_trksize[i];
+ trk->track = i;
+ trk->min = MCI_MSF_MINUTE(tmem);
+ trk->sec = MCI_MSF_SECOND(tmem);
+ trk->hour = trk->min / 60;
+ trk->min %= 60;
+ }
+
+ m_toc = new CDtoc(total_time, m_trksize, m_trkpos);
+}
+
+bool wxCDAudioWin::Play(const wxCDtime& beg_time, const wxCDtime& end_time)
+{
+ DWORD tmsf;
+ MCI_PLAY_PARMS play_struct;
+
+ if (!m_ok)
+ return FALSE;
+
+ tmsf = MCI_MAKE_TMSF(beg_time.track, beg_time.min,
+ beg_time.sec, 0);
+ play_struct.dwFrom = tmsf;
+ tmsf = MCI_MAKE_TMSF(end_time.track, end_time.min,
+ end_time.sec, 0);
+ play_struct.dwTo = tmsf;
+
+ mciSendCommand(m_internal->dev_id, MCI_PLAY, 0, (DWORD)&play_struct);
+ return TRUE;
+}
+
+bool wxCDAudioWin::Pause(void)
+{
+ if (!m_ok)
+ return FALSE;
+
+ return (mciSendCommand(m_internal->dev_id, MCI_PAUSE, 0, 0) == 0);
+}
+
+bool wxCDAudioWin::Resume(void)
+{
+ if (!m_ok)
+ return FALSE;
+
+ return (mciSendCommand(m_internal->dev_id, MCI_RESUME, 0, 0) == 0);
+}
+
+wxCDAudio::CDstatus wxCDAudioWin::GetStatus(void)
+{
+ MCI_STATUS_PARMS status_struct;
+
+ if (!m_ok)
+ return STOPPED;
+
+ status_struct.dwItem = MCI_STATUS_MODE;
+ mciSendCommand(m_internal->dev_id, MCI_STATUS, MCI_STATUS_ITEM,
+ (DWORD)&status_struct);
+ switch (status_struct.dwReturn) {
+ case MCI_MODE_PAUSE:
+ return PAUSED;
+ case MCI_MODE_PLAY:
+ return PLAYING;
+ }
+ return STOPPED;
+}
+
+wxCDtime wxCDAudioWin::GetTime(void)
+{
+ MCI_STATUS_PARMS status_struct;
+ wxCDtime cd_time = {-1, -1, -1, -1};
+
+ if (!m_ok)
+ return cd_time;
+
+ status_struct.dwItem = MCI_STATUS_TIME_FORMAT;
+ mciSendCommand(m_internal->dev_id, MCI_STATUS, MCI_STATUS_ITEM,
+ (DWORD)&status_struct);
+ cd_time.track = MCI_TMSF_TRACK(status_struct.dwReturn);
+ cd_time.min = MCI_TMSF_MINUTE(status_struct.dwReturn);
+ cd_time.sec = MCI_TMSF_SECOND(status_struct.dwReturn);
+ cd_time.hour = cd_time.min / 60;
+ cd_time.min %= 60;
+ return cd_time;
+}
+
+wxCDAudio::CDtoc& wxCDAudioWin::GetToc(void)
+{
+ return *m_toc;
+}
--- /dev/null
+// /////////////////////////////////////////////////////////////////////////////
+// Name: cdwin.h
+// Purpose: wxMMedia
+// Author: Guilhem Lavaux
+// Created: 1997
+// Updated: 1998
+// Copyright: (C) 1997, 1998, Guilhem Lavaux
+// License: wxWindows license
+// /////////////////////////////////////////////////////////////////////////////
+#ifndef __CDA_win_H__
+#define __CDA_win_H__
+
+#ifdef __GNUG__
+#pragma interface
+#endif
+
+#ifdef WX_PRECOMP
+#include "wx/wxprec.h"
+#else
+#include "wx/wx.h"
+#endif
+#include "mmtype.h"
+#include "cdbase.h"
+
+#ifdef WXMMEDIA_INTERNAL
+#include <windows.h>
+#include <mmsystem.h>
+typedef struct CDAW_Internal {
+ MCIDEVICEID dev_id;
+} CDAW_Internal;
+#endif
+
+///
+class WXDLLEXPORT wxCDAudioWin : public wxCDAudio {
+ DECLARE_DYNAMIC_CLASS(wxCDAudioWin)
+protected:
+ struct CDAW_Internal *m_internal;
+ wxCDtime *m_trksize, *m_trkpos;
+ CDtoc *m_toc;
+ bool m_ok;
+public:
+ ///
+ wxCDAudioWin(void);
+ ///
+ wxCDAudioWin(const char *dev_name);
+ ///
+ virtual ~wxCDAudioWin(void);
+
+ ///
+ virtual bool Play(const wxCDtime& beg_time, const wxCDtime& end_time);
+ ///
+ virtual bool Pause(void);
+ ///
+ virtual bool Resume(void);
+ ///
+ virtual CDstatus GetStatus(void);
+ ///
+ virtual wxCDtime GetTime(void);
+ ///
+ virtual CDtoc& GetToc(void);
+ ///
+ virtual inline bool Ok(void) const { return m_ok; }
+protected:
+ void PrepareToc();
+};
+
+#endif
--- /dev/null
+////////////////////////////////////////////////////////////////////////////////
+// Name: mmdata.cpp
+// Purpose: wxMMedia
+// Author: Guilhem Lavaux
+// Created: 1997
+// Updated: 1998
+// Copyright: (C) 1997, 1998, Guilhem Lavaux
+// License: wxWindows license
+////////////////////////////////////////////////////////////////////////////////
+#include "mmfile.h"
+
+#include "sndsnd.h"
+#include "sndfrmt.h"
+#if defined(__UNIX__)
+#include "snduss.h"
+#endif
+#include "sndfrag.h"
+#include "sndfile.h"
+#include "sndwav.h"
+#include "sndaiff.h"
+#include "sndau.h"
+#include "sndpcm.h"
+#include "sndmulaw.h"
+#include "vidbase.h"
+#if defined(__X__) || defined(__WXGTK__)
+#include "vidxanm.h"
+#endif
+#ifdef __WINDOWS__
+#include "sndwin.h"
+#include "cdwin.h"
+#include "vidwin.h"
+#endif
+#include "cdbase.h"
+#ifdef __UNIX__
+#include "cdunix.h"
+#endif
+#include "mmsolve.h"
+// #include "midfile.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+IMPLEMENT_ABSTRACT_CLASS(wxSound, wxObject)
+IMPLEMENT_ABSTRACT_CLASS(wxSndBuffer, wxObject)
+IMPLEMENT_DYNAMIC_CLASS(wxSndSimpleBuffer, wxSndBuffer)
+
+IMPLEMENT_ABSTRACT_CLASS(wxSoundCodec, wxObject)
+IMPLEMENT_DYNAMIC_CLASS(wxSoundPcmCodec, wxSoundCodec)
+IMPLEMENT_DYNAMIC_CLASS(wxSoundMulawCodec, wxSoundCodec)
+
+#ifdef __UNIX__
+IMPLEMENT_DYNAMIC_CLASS(wxUssSound, wxSound)
+#endif
+#ifdef __WINDOWS__
+IMPLEMENT_DYNAMIC_CLASS(wxWinSound, wxSound)
+#endif
+
+IMPLEMENT_ABSTRACT_CLASS(wxSndFileCodec, wxMMediaFile)
+IMPLEMENT_DYNAMIC_CLASS(wxSndWavCodec, wxSndFileCodec)
+IMPLEMENT_DYNAMIC_CLASS(wxSndAuCodec, wxSndFileCodec)
+IMPLEMENT_DYNAMIC_CLASS(wxSndAiffCodec, wxSndFileCodec)
+
+IMPLEMENT_ABSTRACT_CLASS(wxVideoBaseDriver, wxMMediaFile)
+IMPLEMENT_DYNAMIC_CLASS(wxVideoOutput, wxWindow)
+#if defined(__X__) || defined(__WXGTK__)
+IMPLEMENT_DYNAMIC_CLASS(wxVideoXANIM, wxVideoBaseDriver)
+#endif
+#ifdef __WINDOWS__
+IMPLEMENT_DYNAMIC_CLASS(wxVideoWindows, wxVideoBaseDriver)
+#endif
+
+IMPLEMENT_ABSTRACT_CLASS(wxCDAudio, wxObject)
+#ifdef linux
+IMPLEMENT_DYNAMIC_CLASS(wxCDAudioLinux, wxCDAudio)
+#else
+IMPLEMENT_DYNAMIC_CLASS(wxCDAudioWin, wxCDAudio)
+#endif
+
+// IMPLEMENT_ABSTRACT_CLASS(wxMidiFile, wxObject)
+
+wxMediaFileSolve::wxMFileList *wxMediaFileSolve::m_first = NULL;
+wxUint8 wxMediaFileSolve::m_devnum = 0;
+
+MMD_REGISTER_FILE("audio/x-wav", "Wav Player", wxSndWavCodec, "wav")
+MMD_REGISTER_FILE("audio/x-aiff", "Aiff Player", wxSndAiffCodec, "aif")
+MMD_REGISTER_FILE("audio/x-au", "Sun Audio File Player", wxSndAuCodec, "au")
+#if defined(__X__) || defined(__WXGTK__)
+MMD_REGISTER_FILE("video/*", "Video Player", wxVideoXANIM, "mov")
+#else
+MMD_REGISTER_FILE("video/avi", "AVI Player", wxVideoWindows, "avi")
+#endif
--- /dev/null
+// /////////////////////////////////////////////////////////////////////////////
+// Name: mmedia.h
+// Purpose: wxMMedia
+// Author: Guilhem Lavaux
+// Created: 1997
+// Updated: 1998
+// Copyright: (C) 1997, 1998, Guilhem Lavaux
+// License: wxWindows license
+// /////////////////////////////////////////////////////////////////////////////
+#ifndef __MMEDIA_H__
+#define __MMEDIA_H__
+
+#ifdef __WINDOWS__
+
+#include "sndwin.h"
+#define wxSoundDevice wxWinSound
+
+#include "vidwin.h"
+#define wxVideoDevice wxVideoWindows
+
+#else
+
+#include "snduss.h"
+#define wxSoundDevice wxUssSound
+
+#include "vidxanm.h"
+#define wxVideoDevice wxVideoXANIM
+
+#endif
+
+#endif
--- /dev/null
+////////////////////////////////////////////////////////////////////////////////
+// Name: mmfile.cpp
+// Purpose: wxMMedia
+// Author: Guilhem Lavaux
+// Created: 1997
+// Updated: 1998
+// Copyright: (C) 1997, 1998, Guilhem Lavaux
+// License: wxWindows license
+////////////////////////////////////////////////////////////////////////////////
+#ifdef __GNUG__
+#pragma implementation
+#endif
+#ifdef WX_PRECOMP
+#include "wx_prec.h"
+#else
+#include "wx/wx.h"
+#endif
+#include <wx/stream.h>
+#include <wx/fstream.h>
+#include <wx/mstream.h>
+
+#include "mmfile.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+wxMMediaFile::wxMMediaFile()
+ : m_istream(NULL), m_i_temp(NULL), m_ostream(NULL), m_o_temp(NULL),
+ m_tmpfname((char *)NULL), m_mfname((char *)NULL),
+ m_seekable(FALSE)
+{
+}
+
+wxMMediaFile::wxMMediaFile(wxOutputStream& os, bool seekable)
+ : m_istream(NULL), m_i_temp(NULL), m_ostream(&os), m_o_temp(NULL),
+ m_tmpfname((char *)NULL), m_mfname((char *)NULL),
+ m_seekable(seekable)
+{
+}
+
+wxMMediaFile::wxMMediaFile(wxInputStream& is, bool preload, bool seekable)
+ : m_istream(&is), m_i_temp(NULL), m_ostream(NULL), m_o_temp(NULL),
+ m_tmpfname((char *)NULL), m_mfname((char *)NULL),
+ m_seekable(seekable)
+{
+/*
+ if (preload) {
+ wxMemoryStream *tmpstream = new wxMemoryStream();
+
+ m_o_temp = tmpstream;
+ m_i_temp = tmpstream;
+
+ m_o_temp->Write(is);
+ }
+*/
+}
+
+wxMMediaFile::wxMMediaFile(const wxString& fname)
+ : m_istream(NULL), m_i_temp(NULL), m_ostream(NULL), m_o_temp(NULL),
+ m_tmpfname((char *)NULL), m_mfname(fname),
+ m_seekable(TRUE)
+{
+ wxFileStream *s = new wxFileStream(fname);
+
+ m_mfname = fname;
+ m_istream = s;
+ m_ostream = s;
+}
+
+void wxMMediaFile::SetFile(wxInputStream& str, bool preload, bool seekable)
+{
+ CleanUpPrevious();
+ m_istream = &str;
+ m_ostream = NULL;
+ m_seekable = seekable;
+
+/*
+ if (preload) {
+ wxMemoryStream *tmpstream = new wxMemoryStream();
+
+ m_i_temp = tmpstream;
+ m_o_temp = tmpstream;
+
+ m_o_temp->Write(str);
+ }
+*/
+}
+
+void wxMMediaFile::SetFile(wxOutputStream& str, bool seekable)
+{
+ CleanUpPrevious();
+ m_ostream = &str;
+ m_istream = NULL;
+ m_seekable = seekable;
+}
+
+void wxMMediaFile::SetFile(const wxString& fname)
+{
+ CleanUpPrevious();
+
+ m_mfname = fname;
+ wxFileStream *f = new wxFileStream(fname);
+
+ SetFile(*f, FALSE, TRUE);
+}
+
+void wxMMediaFile::CleanUpPrevious()
+{
+ if (m_i_temp) {
+ m_i_temp->SeekI(0);
+
+ if (m_ostream)
+ m_ostream->Write(*m_i_temp);
+
+ delete m_i_temp; // Only one delete because m_tmpo* and m_tmpi* are linked
+
+ if (m_tmpfname)
+ wxRemoveFile(m_tmpfname);
+ }
+
+ if (!m_mfname.IsNull() && m_mfname != "")
+ delete m_istream;
+
+ m_i_temp = NULL;
+ m_o_temp = NULL;
+ m_istream = NULL;
+ m_ostream = NULL;
+}
+
+wxMMediaFile::~wxMMediaFile()
+{
+ CleanUpPrevious();
+}
+
+wxMMtime wxMMediaFile::GetLength()
+{
+ wxMMtime mm_time = {-1, 0, 0};
+ return mm_time;
+}
+
+wxMMtime wxMMediaFile::GetPosition()
+{
+ wxMMtime mm_time = {0, 0, 0};
+ return mm_time;
+}
+
+wxInputStream *wxMMediaFile::GetIRawData()
+{
+ if (!m_istream)
+ return NULL;
+
+ if (!m_seekable && !m_i_temp)
+ CacheIO();
+
+ return (m_i_temp) ? m_i_temp : m_istream;
+}
+
+wxOutputStream *wxMMediaFile::GetORawData()
+{
+ if (!m_ostream)
+ return NULL;
+
+ if (!m_seekable && !m_i_temp)
+ CacheIO();
+
+ return (m_o_temp) ? m_o_temp : m_ostream;
+}
+
+wxString wxMMediaFile::GetCurrentFile()
+{
+ if (!m_istream && !m_ostream)
+ return wxString((char *)NULL);
+
+ if (!m_mfname && !m_i_temp)
+ CacheIO();
+
+ return (!m_tmpfname.IsEmpty()) ? m_tmpfname : m_mfname;
+}
+
+void wxMMediaFile::CacheIO()
+{
+ if ((!m_istream && !m_ostream) || m_i_temp)
+ return;
+
+ m_tmpfname = wxGetTempFileName("mmd");
+
+ wxFileStream *tmpstream = new wxFileStream(m_tmpfname);
+ m_i_temp = tmpstream;
+ m_o_temp = tmpstream;
+
+ if (m_istream)
+ tmpstream->wxOutputStream::Write(*m_istream);
+}
--- /dev/null
+// /////////////////////////////////////////////////////////////////////////////
+// Name: mmfile.h
+// Purpose: wxMMedia
+// Author: Guilhem Lavaux
+// Created: 1997
+// Updated: 1998
+// Copyright: (C) 1997, 1998, Guilhem Lavaux
+// License: wxWindows license
+// /////////////////////////////////////////////////////////////////////////////
+#ifndef __MMD_file_H__
+#define __MMD_file_H__
+
+#ifdef __GNUG__
+#pragma interface
+#endif
+
+#ifdef WX_PRECOMP
+#include "wx_prec.h"
+#else
+#include "wx/wx.h"
+#endif
+#include "wx/string.h"
+#include "wx/stream.h"
+#include "mmtype.h"
+
+///
+typedef enum {
+ wxMMFILE_NOERROR,
+ wxMMFILE_INVALID,
+ wxMMFILE_EOF
+} ///
+ wxMMFileError;
+
+typedef struct {
+ wxInt8 hours;
+ wxUint8 minutes, seconds;
+} wxMMtime;
+
+/// Common base class for multimedia file.
+class wxMMediaFile {
+public:
+ wxMMediaFile();
+ ///
+ wxMMediaFile(wxInputStream& is, bool preload, bool seekable);
+ ///
+ wxMMediaFile(wxOutputStream& is, bool seekable);
+ ///
+ wxMMediaFile(const wxString& fname);
+ ///
+ virtual ~wxMMediaFile();
+
+ ///
+ wxInputStream *GetIRawData();
+ wxOutputStream *GetORawData();
+ ///
+ wxString GetCurrentFile();
+
+ ///
+ virtual void SetFile(wxInputStream& is,
+ bool preload = FALSE, bool seekable = FALSE);
+ ///
+ virtual void SetFile(wxOutputStream& is, bool seekable = FALSE);
+ ///
+ void SetFile(const wxString& fname);
+
+ ///
+ wxMMFileError GetFileError() const { return m_mmerror; }
+ ///
+ virtual wxMMtime GetLength();
+ ///
+ virtual wxMMtime GetPosition();
+ ///
+ virtual bool StartPlay() = 0;
+ ///
+ virtual void StopPlay() = 0;
+protected:
+ ///
+ wxMMFileError m_mmerror;
+ ///
+ wxInputStream *m_istream, *m_i_temp;
+ ///
+ wxOutputStream *m_ostream, *m_o_temp;
+ ///
+ wxString m_tmpfname, m_mfname;
+ ///
+ bool m_seekable;
+
+ ///
+ void CacheIO();
+ ///
+ void CleanUpPrevious();
+};
+
+#endif
--- /dev/null
+////////////////////////////////////////////////////////////////////////////////
+// Name: mmriff.cpp
+// Purpose: wxMMedia
+// Author: Guilhem Lavaux
+// Created: 1997
+// Updated: 1998
+// Copyright: (C) 1997, 1998, Guilhem Lavaux
+// License: wxWindows license
+////////////////////////////////////////////////////////////////////////////////
+#ifdef __GNUG__
+#pragma implementation "mmriff.h"
+#endif
+
+#ifdef WX_PRECOMP
+#include "wx_prec.h"
+#else
+#include "wx/wx.h"
+#endif
+#include "mmfile.h"
+#include "mmriff.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+wxRiffCodec::wxRiffCodec() :
+ riff_i_stream(NULL), riff_o_stream(NULL), chunk_length(INVALID_CHUNK_LEN)
+{
+}
+
+wxRiffCodec::wxRiffCodec(wxInputStream& s) :
+ riff_i_stream(&s), riff_o_stream(NULL), chunk_length(INVALID_CHUNK_LEN)
+{
+}
+
+wxRiffCodec::wxRiffCodec(wxOutputStream& s) :
+ riff_i_stream(NULL), riff_o_stream(&s), chunk_length(INVALID_CHUNK_LEN)
+{
+}
+
+wxRiffCodec::~wxRiffCodec()
+{
+}
+
+bool wxRiffCodec::RiffReset(wxUint8 mode)
+{
+ switch (mode) {
+ case RIFF_READ:
+ if (!riff_i_stream)
+ return FALSE;
+ riff_i_stream->SeekI(0);
+ chunk_length = INVALID_CHUNK_LEN;
+ return TRUE;
+ case RIFF_WRITE:
+ if (!riff_o_stream)
+ return FALSE;
+ riff_o_stream->SeekO(0);
+ chunk_length = INVALID_CHUNK_LEN;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool wxRiffCodec::ReadData(void *data, wxUint32 size)
+{
+ if (!riff_i_stream)
+ return FALSE;
+
+ if (chunk_length != INVALID_CHUNK_LEN && (wxUint32)chunk_length < size) {
+ riff_error = wxMMFILE_EOF;
+ return FALSE;
+ }
+ if (chunk_length != INVALID_CHUNK_LEN)
+ chunk_length -= size;
+
+ bool ret = (riff_i_stream->Read((char *)data, size).LastRead() == size);
+
+ return ret;
+}
+
+bool wxRiffCodec::WriteData(void *data, wxUint32 size)
+{
+ if (!riff_o_stream)
+ return FALSE;
+
+ if (chunk_length < size) {
+ riff_error = wxMMFILE_EOF;
+ return FALSE;
+ }
+ chunk_length -= size;
+
+ riff_o_stream->Write(data, size);
+
+ return TRUE;
+}
+
+bool wxRiffCodec::Read32(wxUint32& i32)
+{
+ wxUint8 i8[4];
+
+ if (!ReadData(i8, 4))
+ return FALSE;
+
+ i32 = i8[0];
+ i32 |= ((wxUint32)i8[1]) << 8;
+ i32 |= ((wxUint32)i8[2]) << 16;
+ i32 |= ((wxUint32)i8[3]) << 24;
+
+ return TRUE;
+}
+
+bool wxRiffCodec::Write32(wxUint32 i32)
+{
+ wxUint8 i8[4];
+
+ i8[0] = i32 & 0xff;
+ i8[1] = (i32 >> 8) & 0xff;
+ i8[2] = (i32 >> 16) & 0xff;
+ i8[3] = (i32 >> 24) & 0xff;
+
+ if (!WriteData(i8, 4))
+ return FALSE;
+
+ return TRUE;
+}
+
+bool wxRiffCodec::Read16(wxUint16& i16)
+{
+ wxUint8 i8[2];
+
+ if (!ReadData(i8, 2))
+ return FALSE;
+
+ i16 = i8[0];
+ i16 |= ((wxUint16)i8[1]) << 8;
+
+ return TRUE;
+}
+
+bool wxRiffCodec::Write16(wxUint16 i16)
+{
+ wxUint8 i8[2];
+
+ i8[0] = i16 & 0xff;
+ i8[1] = (i16 >> 8) & 0xff;
+
+ if (!WriteData(i8, 2))
+ return FALSE;
+
+ return TRUE;
+}
+
+bool wxRiffCodec::Skip(wxUint32 skip)
+{
+ if (!riff_i_stream || (chunk_length != INVALID_CHUNK_LEN && (wxInt32)skip > chunk_length))
+ return FALSE;
+
+ if (chunk_length != INVALID_CHUNK_LEN)
+ chunk_length -= skip;
+ riff_i_stream->SeekI(skip, wxFromCurrent);
+
+ return TRUE;
+}
+
+bool wxRiffCodec::CreateChunk(const wxString& name, wxUint32 size)
+{
+ if (!riff_o_stream || name.Length() != 4)
+ return FALSE;
+
+ if (riff_o_stream->Write(name.GetData(), 4).LastError()) {
+ riff_error = wxMMFILE_EOF;
+ return FALSE;
+ }
+
+ chunk_length = size+4;
+
+ return Write32(size);
+}
+
+bool wxRiffCodec::FindChunk(const wxString& name, bool from_here)
+{
+ char buf[5];
+ wxString str2;
+
+ if (!riff_i_stream)
+ return FALSE;
+
+ if (chunk_length != INVALID_CHUNK_LEN && !from_here)
+ Skip(chunk_length);
+ while (1) {
+ if (riff_i_stream->Read(buf, 4).LastError()) {
+ riff_error = wxMMFILE_EOF;
+ return FALSE;
+ }
+
+ chunk_length = INVALID_CHUNK_LEN;
+ if (!Read32(chunk_length)) {
+ riff_error = wxMMFILE_EOF;
+ return FALSE;
+ }
+
+ buf[4] = 0;
+ str2 = buf;
+ if ((!name.IsNull()) && str2 != name) {
+ Skip(chunk_length);
+ continue;
+ }
+
+ m_chunk = str2;
+
+ return TRUE;
+ }
+
+ return TRUE;
+}
--- /dev/null
+// /////////////////////////////////////////////////////////////////////////////
+// Name: mmriff.h
+// Purpose: wxMMedia
+// Author: Guilhem Lavaux
+// Created: 1998
+// Updated:
+// Copyright: (C) 1998, Guilhem Lavaux
+// License: wxWindows license
+// /////////////////////////////////////////////////////////////////////////////
+/* Real -*- C++ -*- */
+#ifndef __MM_riff_H__
+#define __MM_riff_H__
+#ifdef __GNUG__
+#pragma interface
+#endif
+
+#include "mmtype.h"
+#include "mmfile.h"
+
+#define RIFF_READ 0
+#define RIFF_WRITE 1
+#define INVALID_CHUNK_LEN ((wxUint32)-1)
+
+///
+class wxRiffCodec {
+public:
+ ///
+ wxRiffCodec();
+ ///
+ wxRiffCodec(wxOutputStream& s);
+ ///
+ wxRiffCodec(wxInputStream& s);
+ ///
+ virtual ~wxRiffCodec();
+
+ ///
+ void SetFile(wxInputStream& s) { cout << "RIFF:SetFile(i)" << endl; riff_i_stream = &s; riff_o_stream = NULL; }
+ ///
+ void SetFile(wxOutputStream& s) { cout << "RIFF::SetFile(o)" << endl; riff_i_stream = NULL; riff_o_stream = &s; }
+
+ ///
+ bool Read32(wxUint32& i32);
+ ///
+ bool Read16(wxUint16& i16);
+ ///
+ bool ReadData(void *data, wxUint32 size);
+ ///
+ bool Skip(wxUint32 skip);
+
+ ///
+ bool Write32(wxUint32 i32);
+ ///
+ bool Write16(wxUint16 i16);
+ ///
+ bool WriteData(void *data, wxUint32 size);
+
+ ///
+ inline wxUint32 GetChunkLength() const { return chunk_length; }
+ ///
+ inline const wxString& GetChunkName() const { return m_chunk; }
+
+ ///
+ bool RiffReset(wxUint8 state);
+
+ ///
+ bool FindChunk(const wxString& name = "", bool from_here = FALSE);
+ ///
+ bool CreateChunk(const wxString& name, wxUint32 chunk_size);
+
+ ///
+ inline wxMMFileError GetError() const { return riff_error; }
+
+protected:
+ wxInputStream *riff_i_stream;
+ wxOutputStream *riff_o_stream;
+ wxUint32 chunk_length;
+ wxMMFileError riff_error;
+ wxString m_chunk;
+};
+
+#endif
--- /dev/null
+////////////////////////////////////////////////////////////////////////////////
+// Name: mmsolve.h
+// Purpose: wxMMedia
+// Author: Guilhem Lavaux
+// Created: 1997
+// Updated: 1998
+// Copyright: (C) 1997, 1998, Guilhem Lavaux
+// License: wxWindows license
+////////////////////////////////////////////////////////////////////////////////
+#ifdef __GNUG__
+#pragma implementation
+#endif
+#include "mmsolve.h"
+
+wxMMediaFile *wxMediaFileSolve::ByExtension(const wxString& filename)
+{
+ wxMFileList *list = m_first;
+ wxString tmp, f_ext;
+ int pos = filename.Find('.', TRUE)+1;
+
+ tmp = filename;
+ f_ext = tmp(pos, filename.Length()-pos);
+
+ printf("f_ext = %s\n", f_ext.GetData());
+ while (list) {
+ printf("list->ext = %s\n", list->ext.GetData());
+ if (list->ext.CompareTo(f_ext) == 0) {
+ wxMMediaFile *mmf = list->creator();
+ return mmf;
+ }
+ list = list->next;
+ }
+ return NULL;
+}
+
+wxMMediaFile *wxMediaFileSolve::ByName(const wxString& name)
+{
+ wxMFileList *list = m_first;
+
+ while (list) {
+ if (list->name == name)
+ return (wxMMediaFile *)(list->creator());
+ list = list->next;
+ }
+ return NULL;
+}
+
+bool wxMatchMimeType(const wxString& mime_obj, const wxString& type)
+{
+#ifdef USE_GNU_WXSTRING
+ wxString mime2_obj = mime_obj;
+ wxString type2 = type;
+#define mime_obj mime2_obj
+#define type type2
+#endif
+
+ if (mime_obj.Find('*') != -1) {
+ wxString part_str1[2], part_str2[2];
+
+ part_str1[0] = mime_obj.Left('/');
+ part_str1[1] = mime_obj.After('/');
+
+ part_str2[0] = type.Left('/');
+ part_str2[1] = type.After('/');
+
+ if (part_str1[0] == "*" && part_str1[1] == "*")
+ return TRUE;
+
+ if (part_str1[0] == "*" && part_str1[1] == part_str2[1])
+ return TRUE;
+
+ if (part_str1[1] == "*" && part_str1[0] == part_str2[1])
+ return TRUE;
+
+ return FALSE;
+ }
+ if (mime_obj == type)
+ return TRUE;
+ return FALSE;
+}
+
+wxMMediaFile *wxMediaFileSolve::ByType(const wxString& type)
+{
+ wxMFileList *list = m_first;
+
+ while (list) {
+ if (wxMatchMimeType(*(list->mime_type), type))
+ return (wxMMediaFile *)(list->creator());
+ list = list->next;
+ }
+ return NULL;
+}
+
+void wxMediaFileSolve::ListMDevice(wxString*& names, wxUint8& devices)
+{
+ wxMFileList *list = m_first;
+ wxUint8 d = 0;
+
+ if (!m_devnum) {
+ names = NULL;
+ return;
+ }
+ devices = m_devnum;
+ names = new wxString[devices];
+
+ while (list) {
+ names[d++] = list->name;
+ list = list->next;
+ }
+}
+
+wxMMDfileRegister::wxMMDfileRegister(wxMediaFileCreator cbk,
+ char *mtype, char *ext, char *name)
+{
+ wxMediaFileSolve::wxMFileList *entry = new wxMediaFileSolve::wxMFileList;
+
+ entry->next = wxMediaFileSolve::m_first;
+ entry->creator = cbk;
+ entry->mime_type = wxString(mtype);
+ entry->name = wxString(name);
+ entry->ext = wxString(ext);
+ wxMediaFileSolve::m_devnum++;
+ wxMediaFileSolve::m_first = entry;
+}
--- /dev/null
+// /////////////////////////////////////////////////////////////////////////////
+// Name: mmsolve.h
+// Purpose: wxMMedia
+// Author: Guilhem Lavaux
+// Created: 1997
+// Updated: 1998
+// Copyright: (C) 1997, 1998, Guilhem Lavaux
+// License: wxWindows license
+// /////////////////////////////////////////////////////////////////////////////
+#ifndef __MMD_solve_H__
+#define __MMD_solve_H__
+#ifdef __GNUG__
+#pragma interface
+#endif
+
+#ifdef WX_PRECOMP
+#include "wx/wxprec.h"
+#else
+#include "wx/wx.h"
+#endif
+#include "mmfile.h"
+
+/** @name Solver classes */
+//@{
+
+typedef wxMMediaFile *(*wxMediaFileCreator)();
+
+/** wxMediaFileSolve is a class to do name resolution on multimedia files
+ * @memo Multimedia file solver
+ * @author Guilhem Lavaux
+ */
+class WXDLLEXPORT wxMediaFileSolve : public wxObject {
+protected:
+ typedef struct wxMFileList {
+ wxMediaFileCreator creator;
+ wxString mime_type, name, ext;
+ wxMFileList *next;
+ } wxMFileList;
+
+ static wxMFileList *m_first;
+ static wxUint8 m_devnum;
+
+ friend class wxMMDfileRegister;
+public:
+ wxMediaFileSolve() : wxObject() {}
+ ~wxMediaFileSolve() {}
+
+ /** It resolves using the extension of the specified filename
+ * @memo
+ * @return the multimedia codec
+ * @param filename
+ */
+ static wxMMediaFile *ByExtension(const wxString& filename);
+
+ /** It resolves using the real name of a codec
+ * @memo
+ * @return the multimedia codec
+ * @param devname
+ */
+ static wxMMediaFile *ByName(const wxString& devname);
+
+ /** It resolves using a mime type
+ * @memo
+ * @return the multimedia codec
+ * @param mimetype
+ */
+ static wxMMediaFile *ByType(const wxString& mimetype);
+
+ /** It lists all codecs currently registered in "names". "names" is allocated
+ * by it and devices returns the number of codecs the list contains
+ * @memo
+ * @return nothing
+ * @param names an array
+ * @param devices
+ */
+ static void ListMDevice(wxString*& names, wxUint8& devices);
+};
+
+///
+class wxMMDfileRegister {
+public:
+ ///
+ wxMMDfileRegister(wxMediaFileCreator cbk, char *mtype, char *ext, char *name);
+};
+
+#define MMD_REGISTER_FILE(mtype, name, class, ext) \
+static wxMMediaFile *wxMediaFileConstructor_##class() { return new class(); } \
+wxMMDfileRegister mmd_##class(wxMediaFileConstructor_##class, mtype, ext, name);
+
+//@}
+
+#endif
--- /dev/null
+// /////////////////////////////////////////////////////////////////////////////
+// Name: mmtype.h
+// Purpose: wxMMedia (imported from wxSocket)
+// Author: Guilhem Lavaux
+// Created: 1997
+// Updated: 1998
+// Copyright: (C) 1997, 1998, Guilhem Lavaux
+// License: wxWindows license
+// /////////////////////////////////////////////////////////////////////////////
+
+#ifndef __SOCKTYPEH__
+#define __SOCKTYPEH__
+
+#ifdef __UNIX__
+#include <stl_config.h>
+#endif
+
+/// Type to use for 8 bits unsigned integers
+typedef unsigned char wxUint8;
+/// Type to use for 16 bits unsigned integers
+typedef unsigned short wxUint16;
+/// Type to use for 32 bits unsigned integers
+typedef unsigned long wxUint32;
+#if HAVE_UINT64
+/// Type to use for 64 bits unsigned integers
+typedef unsigned long long wxUint64;
+#endif
+
+/// Type to use for 8 bits signed integers
+typedef char wxInt8;
+/// Type to use for 16 bits signed integers
+typedef short wxInt16;
+/// Type to use for 32 bits signed integers
+typedef long wxInt32;
+#if HAVE_UINT64
+/// Type to use for 64 bits signed integers
+typedef long long wxInt64;
+#endif
+
+#endif
+
--- /dev/null
+////////////////////////////////////////////////////////////////////////////////
+// Name: sndaiff.cpp
+// Purpose: wxMMedia
+// Author: Guilhem Lavaux
+// Created: 1997
+// Updated: February 1998
+// Copyright: (C) 1997, 1998, Guilhem Lavaux
+// License: wxWindows license
+////////////////////////////////////////////////////////////////////////////////
+#ifdef __GNUG__
+#pragma implementation "sndaiff.h"
+#endif
+
+#ifdef WX_PRECOMP
+#include "wx/wxprec.h"
+#else
+#include "wx/wx.h"
+#endif
+#include "wx/datstrm.h"
+#include "sndaiff.h"
+#include "sndpcm.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#define READ_DATA(n) m_istream->Read(tmp_buf,n)
+#define WRITE_DATA(n) m_ostream->Write(tmp_buf,n)
+
+#define READ_STRING(s,n) \
+ READ_DATA(n); \
+ tmp_buf[n] = 0; \
+ s = tmp_buf;
+
+#define WRITE_STRING(s,n) WRITE_DATA((const char *)s, n)
+
+#define READ32(i) \
+ READ_DATA(4); \
+ i = (unsigned long)tmp_buf[3] | \
+ ((unsigned long)tmp_buf[2] << 8) | \
+ ((unsigned long)tmp_buf[1] << 16) | \
+ ((unsigned long)tmp_buf[0] << 24);
+
+#define WRITE32(i) \
+ tmp_buf[3] = i & 0xFF; \
+ tmp_buf[2] = (i >> 8) & 0xFF; \
+ tmp_buf[1] = (i >> 16) & 0xFF; \
+ tmp_buf[0] = (i >> 24) & 0xFF; \
+ WRITE_DATA(4);
+
+#define READ16(i) \
+ READ_DATA(2); \
+ i = (unsigned short)tmp_buf[1] | \
+ ((unsigned short)tmp_buf[0] << 8);
+
+wxSndAiffCodec::wxSndAiffCodec()
+ : wxSndFileCodec()
+{
+ m_sndtime.hours = -1;
+}
+
+wxSndAiffCodec::wxSndAiffCodec(wxOutputStream& s, bool seekable)
+ : wxSndFileCodec(s, seekable)
+{
+ if (!seekable)
+ CacheIO();
+ m_sndtime.hours = -1;
+}
+
+wxSndAiffCodec::wxSndAiffCodec(wxInputStream& s, bool preload, bool seekable)
+ : wxSndFileCodec(s, preload, seekable)
+{
+ if (!seekable)
+ CacheIO();
+ m_sndtime.hours = -1;
+}
+
+wxSndAiffCodec::wxSndAiffCodec(const wxString& fname)
+ : wxSndFileCodec(fname)
+{
+ m_sndtime.hours = -1;
+}
+
+wxUint32 wxSndAiffCodec::PrepareToPlay()
+{
+ char tmp_buf[5];
+ wxString chunk_name;
+
+ m_istream->SeekI(0, wxFromStart);
+
+ wxSndFileCodec::m_mmerror = wxMMFILE_INVALID;
+
+ READ_STRING(chunk_name, 4);
+ if (chunk_name != "FORM")
+ return 0;
+ m_istream->SeekI(4, wxFromCurrent);
+
+ READ_STRING(chunk_name, 4);
+ if (chunk_name != "AIFF" && chunk_name != "AIFC")
+ return 0;
+
+ // To check whether the file is good
+ m_spos = 0;
+ m_slen = 0;
+ m_sndformat.SetSampleRate(0);
+ while (1) {
+ READ_STRING(chunk_name, 4);
+ READ32(m_chunksize);
+
+ if (chunk_name == "SSND")
+ ParseSSND();
+ if (chunk_name == "COMM")
+ ParseCOMM();
+ else
+ m_istream->SeekI(m_chunksize, wxFromCurrent);
+
+ if (m_spos && m_sndformat.GetSampleRate())
+ break;
+ }
+
+ m_sndmode = wxSND_OUTPUT;
+
+ wxUint32 sec1 = m_slen / m_sndformat.GetCodec()->GetByteRate(),
+ sec2 = sec1 % 3600;
+
+ m_sndtime.hours = sec1 / 3600;
+ m_sndtime.minutes = sec2 / 60;
+ m_sndtime.seconds = sec2 % 60;
+
+ wxSndFileCodec::m_mmerror = wxMMFILE_NOERROR;
+
+ m_istream->SeekI(m_spos, wxFromStart);
+ return m_slen;
+}
+
+void wxSndAiffCodec::ParseCOMM()
+{
+ wxDataInputStream data_s(*m_istream);
+ char tmp_buf[10];
+ wxUint16 channels;
+ wxUint32 srate, num_samples;
+ wxUint16 bps;
+
+ READ16(channels);
+ READ32(num_samples);
+ READ16(bps);
+
+ srate = (wxUint32)data_s.ReadDouble();
+ m_sndformat.SetSampleRate(srate);
+ m_sndformat.SetBps(bps);
+ m_sndformat.SetChannels(channels);
+ m_sndformat.SetByteOrder(wxSND_SAMPLE_BE);
+ m_sndformat.SetSign(wxSND_SAMPLE_UNSIGNED);
+ ChangeCodec(WXSOUND_PCM);
+
+ m_istream->SeekI(m_chunksize-18, wxFromCurrent);
+}
+
+void wxSndAiffCodec::ParseSSND()
+{
+ wxDataInputStream data_s(*m_istream);
+ char tmp_buf[10];
+
+ READ32(m_spos);
+ m_istream->SeekI(4, wxFromCurrent);
+
+ m_slen = m_chunksize - m_spos;
+ m_spos += m_istream->TellI();
+}
+
+wxSndAiffCodec::~wxSndAiffCodec()
+{
+}
+
+bool wxSndAiffCodec::OnNeedData(char *buf, wxUint32 size)
+{
+ m_istream->Read(buf, size);
+ return TRUE;
+}
+
+bool wxSndAiffCodec::OnWriteData(char *buf, wxUint32 size)
+{
+ return ( !(m_ostream->Write(buf, size).LastError()) );
+}
+
+bool wxSndAiffCodec::PrepareToRecord(wxUint32 m_fsize)
+{
+/*
+ wxUint32 total_size;
+ char tmp_buf[10];
+
+ m_ostream->SeekO(0, wxBeginPosition);
+
+ m_ostream->Write("FORM", 4);
+ WRITE32(total_size);
+
+ m_ostream->Write("AIFF", 4);
+
+ WriteCOMM();
+ WriteSSND(m_fsize);
+
+*/
+ return TRUE;
+}
+
+void wxSndAiffCodec::SetFile(wxInputStream& s, bool preload, bool seekable)
+{
+ wxMMediaFile::SetFile(s, preload, seekable);
+ if (!seekable)
+ CacheIO();
+}
+
+void wxSndAiffCodec::SetFile(wxOutputStream& s, bool seekable)
+{
+ wxMMediaFile::SetFile(s, seekable);
+ if (!seekable)
+ CacheIO();
+}
--- /dev/null
+// /////////////////////////////////////////////////////////////////////////////
+// Name: sndaiff.h
+// Purpose: wxMMedia Aiff Codec
+// Author: Guilhem Lavaux
+// Created: 1997
+// Updated: February 1998
+// Copyright: (C) 1997, 1998, Guilhem Lavaux
+// License: wxWindows license
+// /////////////////////////////////////////////////////////////////////////////
+/* Real -*- C++ -*- */
+#ifndef __SND_aiff_H__
+#define __SND_aiff_H__
+#ifdef __GNUG__
+#pragma interface
+#endif
+
+#include "mmriff.h"
+#include "sndfile.h"
+
+///
+class wxSndAiffCodec : public wxSndFileCodec {
+ ///
+ DECLARE_DYNAMIC_CLASS(wxSndAiffCodec)
+public:
+ ///
+ wxSndAiffCodec();
+ ///
+ wxSndAiffCodec(wxInputStream& s, bool preload = FALSE, bool seekable = TRUE);
+ ///
+ wxSndAiffCodec(wxOutputStream& s, bool seekable = TRUE);
+ ///
+ wxSndAiffCodec(const wxString& fname);
+ ///
+ virtual ~wxSndAiffCodec();
+
+ virtual bool OnNeedData(char *buf, wxUint32 size);
+ virtual bool OnWriteData(char *buf, wxUint32 size);
+
+ virtual wxUint32 PrepareToPlay();
+ virtual bool PrepareToRecord(wxUint32 file_size);
+
+ virtual void SetFile(wxInputStream& s, bool preload = FALSE,
+ bool seekable = FALSE);
+ virtual void SetFile(wxOutputStream& s,
+ bool seekable = FALSE);
+protected:
+ void ParseCOMM();
+ void ParseSSND();
+
+ void WriteCOMM();
+ void WriteSSND(wxUint32 file_size);
+
+protected:
+ wxUint32 m_spos, m_slen;
+ wxUint32 m_chunksize;
+};
+
+#endif
--- /dev/null
+// /////////////////////////////////////////////////////////////////////////////
+// Name: sndau.cpp
+// Purpose: wxMMedia Sun Audio File Codec
+// Author: Guilhem Lavaux
+// Created: 1998
+// Updated:
+// Copyright: (C) 1998, Guilhem Lavaux
+// License: wxWindows license
+// /////////////////////////////////////////////////////////////////////////////
+#ifdef __GNUG__
+#pragma implementation "sndau.h"
+#endif
+
+#include "mmriff.h"
+#include "sndfile.h"
+#include "sndau.h"
+
+#define AU_ISDN_ULAW 1
+#define AU_PCM_8BITS 2
+#define AU_PCM_16BITS 3
+#define AU_ADPCM 23
+
+wxSndAuCodec::wxSndAuCodec()
+ : wxSndFileCodec()
+{
+}
+
+wxSndAuCodec::wxSndAuCodec(wxInputStream& s, bool preload, bool seekable)
+ : wxSndFileCodec(s, preload, seekable)
+{
+}
+
+wxSndAuCodec::wxSndAuCodec(wxOutputStream& s, bool seekable)
+ : wxSndFileCodec(s, seekable)
+{
+}
+
+wxSndAuCodec::wxSndAuCodec(const wxString& fname)
+ : wxSndFileCodec(fname)
+{
+}
+
+wxSndAuCodec::~wxSndAuCodec()
+{
+}
+
+wxUint32 wxSndAuCodec::PrepareToPlay()
+{
+ wxString id;
+ char temp_buf[5];
+ int offset, srate, codec, ch_count;
+ size_t len;
+
+ m_istream->SeekI(0);
+
+ m_istream->Read(temp_buf, 4);
+ temp_buf[4] = 0;
+
+ id = temp_buf;
+ if (id != ".snd") {
+ m_mmerror = wxMMFILE_INVALID;
+ return 0;
+ }
+
+#define READ_BE_32(i) \
+m_istream->Read(temp_buf, 4); \
+i = (unsigned long)temp_buf[0] << 24; \
+i |= (unsigned long)temp_buf[1] << 16; \
+i |= (unsigned long)temp_buf[2] << 8; \
+i |= (unsigned long)temp_buf[3];
+
+ READ_BE_32(offset);
+ READ_BE_32(len);
+ READ_BE_32(codec);
+ READ_BE_32(srate);
+ READ_BE_32(ch_count);
+
+ m_sndformat.SetSampleRate(srate);
+ m_sndformat.SetChannels(ch_count);
+ switch (codec) {
+ case AU_ISDN_ULAW:
+ ChangeCodec(WXSOUND_ULAW);
+ break;
+ case AU_PCM_8BITS:
+ ChangeCodec(WXSOUND_PCM);
+ m_sndformat.SetByteOrder(wxSND_SAMPLE_LE);
+ m_sndformat.SetSign(wxSND_SAMPLE_SIGNED);
+ break;
+ case AU_PCM_16BITS:
+ ChangeCodec(WXSOUND_PCM);
+ m_sndformat.SetByteOrder(wxSND_SAMPLE_LE);
+ m_sndformat.SetSign(wxSND_SAMPLE_SIGNED);
+ break;
+ case AU_ADPCM:
+ ChangeCodec(WXSOUND_ADPCM);
+ break;
+ }
+ return len;
+}
+
+bool wxSndAuCodec::OnNeedData(char *buf, wxUint32 size)
+{
+ return m_istream->Read(buf, size).LastError();
+}
+
+bool wxSndAuCodec::OnWriteData(char *buf, wxUint32 size)
+{
+ return m_ostream->Write(buf, size).LastError();
+}
+
+bool wxSndAuCodec::PrepareToRecord(wxUint32 file_size)
+{
+ return FALSE;
+}
--- /dev/null
+// /////////////////////////////////////////////////////////////////////////////
+// Name: sndau.h
+// Purpose: wxMMedia Sun Audio File Codec
+// Author: Guilhem Lavaux
+// Created: 1998
+// Updated:
+// Copyright: (C) 1998, Guilhem Lavaux
+// License: wxWindows license
+// /////////////////////////////////////////////////////////////////////////////
+/* Real -*- C++ -*- */
+#ifndef __SND_au_H__
+#define __SND_au_H__
+#ifdef __GNUG__
+#pragma interface
+#endif
+
+#include "mmriff.h"
+#include "sndfile.h"
+
+///
+class wxSndAuCodec : public wxSndFileCodec {
+ ///
+ DECLARE_DYNAMIC_CLASS(wxSndAuCodec)
+public:
+ ///
+ wxSndAuCodec();
+ ///
+ wxSndAuCodec(wxInputStream& s, bool preload = FALSE, bool seekable = TRUE);
+ ///
+ wxSndAuCodec(wxOutputStream& s, bool seekable = TRUE);
+ ///
+ wxSndAuCodec(const wxString& fname);
+ ///
+ virtual ~wxSndAuCodec();
+
+ bool OnNeedData(char *buf, wxUint32 size);
+ bool OnWriteData(char *buf, wxUint32 size);
+
+ wxUint32 PrepareToPlay();
+ bool PrepareToRecord(wxUint32 file_size);
+
+protected:
+ wxUint32 m_spos, m_slen;
+ wxUint32 m_chunksize;
+};
+
+#endif
--- /dev/null
+////////////////////////////////////////////////////////////////////////////////
+// Name: sndfile.cpp
+// Purpose: wxMMedia
+// Author: Guilhem Lavaux
+// Created: 1997
+// Updated: 1998
+// Copyright: (C) 1997, 1998, Guilhem Lavaux
+// License: wxWindows license
+////////////////////////////////////////////////////////////////////////////////
+#ifdef __GNUG__
+#pragma implementation "sndfile.h"
+#endif
+
+#include "mmedia.h"
+#include "sndfile.h"
+#ifdef WX_PRECOMP
+#include <wx/wxprec.h>
+#else
+#include <wx/wx.h>
+#endif
+#include <wx/module.h>
+#include "sndfrmt.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+wxSndFileCodec::wxSndFileCodec()
+ : wxMMediaFile(), wxSndBuffer(),
+ m_fstate(wxSFILE_STOPPED)
+{
+}
+
+wxSndFileCodec::wxSndFileCodec(wxOutputStream& s, bool seekable)
+ : wxMMediaFile(s, seekable),
+ wxSndBuffer(),
+ m_fstate(wxSFILE_STOPPED)
+{
+}
+
+wxSndFileCodec::wxSndFileCodec(wxInputStream& s, bool preload, bool seekable)
+ : wxMMediaFile(s, preload, seekable),
+ wxSndBuffer(),
+ m_fstate(wxSFILE_STOPPED)
+{
+}
+
+wxSndFileCodec::wxSndFileCodec(const wxString& fname)
+ : wxMMediaFile(fname), wxSndBuffer(),
+ m_fstate(wxSFILE_STOPPED)
+{
+}
+
+wxSndFileCodec::~wxSndFileCodec()
+{
+}
+
+void wxSndFileCodec::Play(wxSound& snd)
+{
+ if (m_fstate != wxSFILE_STOPPED || IsSet(wxSND_BUFLOCKED))
+ return;
+
+ if (!(m_fsize = PrepareToPlay()))
+ return;
+
+ m_fpos = 0;
+ m_fstate = wxSFILE_PLAYING;
+
+ Set(wxSND_BUFREADY | wxSND_KEEPQUEUED);
+ snd.QueueBuffer(*this);
+}
+
+void wxSndFileCodec::Stop(wxSound& snd)
+{
+ if (m_fstate == wxSFILE_STOPPED)
+ return;
+
+ snd.UnqueueBuffer(*this);
+ Clear(wxSND_BUFREADY | wxSND_KEEPQUEUED);
+ m_fstate = wxSFILE_STOPPED;
+}
+
+void wxSndFileCodec::Record(wxSound& snd,
+ const wxSoundDataFormat& format,
+ wxUint32 seconds)
+{
+ wxUint32 byterate;
+
+ if (m_fstate != wxSFILE_STOPPED)
+ return;
+
+ m_sndformat = format;
+ byterate = m_sndformat.GetCodec()->GetByteRate();
+
+ m_fsize = seconds*byterate;
+ if (!PrepareToRecord(m_fsize))
+ return;
+ if (IsSet(wxSND_BUFLOCKED))
+ return;
+
+ wxUint32 sec1 = m_fsize / byterate,
+ sec2 = sec1 % 3600;
+
+ m_sndtime.hours = sec1 / 3600;
+ m_sndtime.minutes = sec2 / 60;
+ m_sndtime.seconds = sec2 % 60;
+
+ m_fdone = m_fpos = 0;
+ m_fstate = wxSFILE_RECORDING;
+
+ m_sndmode = wxSND_INPUT;
+
+ Set(wxSND_BUFREADY | wxSND_KEEPQUEUED);
+ snd.QueueBuffer(*this);
+}
+
+void wxSndFileCodec::OnNeedOutputData(char *data, wxUint32& size)
+{
+ wxUint32 datas_left = m_fsize-m_fpos;
+
+ if (m_fstate != wxSFILE_PLAYING) {
+ size = 0;
+ return;
+ }
+
+ if (!datas_left) {
+ size = 0;
+ m_fpos = 0;
+ m_fstate = wxSFILE_STOPPED;
+ Clear(wxSND_KEEPQUEUED);
+ return;
+ }
+
+ if (size > datas_left)
+ size = datas_left;
+
+ if (!OnNeedData(data, size)) {
+ size = 0;
+ m_fpos = 0;
+ m_fstate = wxSFILE_STOPPED;
+ Clear(wxSND_KEEPQUEUED);
+ return;
+ }
+
+ m_fpos += size;
+}
+
+void wxSndFileCodec::OnBufferInFinished(char *iobuf, wxUint32& size)
+{
+ wxUint32 datas_left = m_fsize-m_fdone;
+
+ if (m_fstate != wxSFILE_RECORDING) {
+ size = 0;
+ return;
+ }
+
+ if (!datas_left) {
+ size = 0;
+ Clear(wxSND_KEEPQUEUED); // To be sure.
+ return;
+ }
+
+ if (size > datas_left)
+ size = datas_left;
+
+ OnWriteData(iobuf, size);
+ m_fdone += size;
+}
+
+wxMMtime wxSndFileCodec::GetPosition()
+{
+ wxMMtime mm_time;
+ wxUint32 sec1, sec2;
+ wxUint32 byterate;
+
+ byterate = m_sndformat.GetCodec()->GetByteRate();
+
+ if (m_fpos && byterate) {
+ sec1 = m_fpos / byterate;
+ sec2 = sec1 % 3600;
+ mm_time.hours = sec1 / 3600;
+ mm_time.minutes = sec2 / 60;
+ mm_time.seconds = sec2 % 60;
+ } else {
+ mm_time.hours = 0;
+ mm_time.minutes = 0;
+ mm_time.seconds = 0;
+ }
+
+ return mm_time;
+}
+
+wxMMtime wxSndFileCodec::GetLength()
+{
+ if (m_sndtime.hours == -1 && m_istream)
+ PrepareToPlay();
+
+ return m_sndtime;
+}
+
+bool wxSndFileCodec::TranslateBuffer(wxSndBuffer& buf)
+{
+#define TMP_BUFSIZE 10240
+
+ wxUint32 buf_size;
+ wxStreamBuffer *tmp_buf;
+ wxSoundCodec *codec_in, *codec_out;
+ wxSoundDataFormat std_format;
+
+ if (!m_ostream || !buf.RestartBuffer(wxSND_OUTPUT))
+ return FALSE;
+
+ m_sndformat = buf.GetFormat();
+ codec_in = buf.GetCurrentCodec();
+
+ m_fdone = 0;
+
+ if (!PrepareToRecord(m_fsize))
+ return FALSE;
+
+ codec_out = GetCurrentCodec();
+ m_fsize = (int)(((float)buf.GetSize() / codec_in->GetByteRate()) *
+ codec_out->GetByteRate());
+
+ if (!PrepareToRecord(m_fsize))
+ return FALSE;
+
+ codec_out = GetCurrentCodec();
+ codec_in->InitIO(m_sndformat);
+ codec_out->InitIO(m_sndformat);
+
+ tmp_buf = new wxStreamBuffer(wxStreamBuffer::read_write);
+ tmp_buf->Fixed(TRUE);
+ tmp_buf->Flushable(FALSE);
+ tmp_buf->SetBufferIO(TMP_BUFSIZE);
+
+ m_fstate = wxSFILE_RECORDING;
+
+ while (m_fdone < m_fsize) {
+ tmp_buf->ResetBuffer();
+ codec_in->SetOutStream(tmp_buf);
+ codec_in->Decode();
+
+ tmp_buf->ResetBuffer();
+ codec_out->SetInStream(tmp_buf);
+ codec_out->Encode();
+
+ buf.OnBufferOutFinished();
+ }
+ delete tmp_buf;
+
+ m_fstate = wxSFILE_STOPPED;
+
+ return TRUE;
+}
+
+bool wxSndFileCodec::RestartBuffer(wxSndMode mode)
+{
+ if (IsSet(wxSND_BUFLOCKED))
+ return FALSE;
+
+ m_fdone = 0;
+ m_fpos = 0;
+
+ if (mode == wxSND_OUTPUT && m_istream) {
+ m_fsize = PrepareToPlay();
+ m_fstate = wxSFILE_PLAYING;
+ return TRUE;
+ }
+ if (mode == wxSND_INPUT && m_ostream) {
+ m_fsize = 0;
+ m_fstate = wxSFILE_RECORDING;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+wxUint32 wxSndFileCodec::GetSize() const
+{
+ return m_fsize;
+}
+
+wxUint32 wxSndFileCodec::Available() const
+{
+ return m_fsize-m_fpos;
+}
+
+//
+// Simple API
+//
+static wxSoundDevice *dev_snd = NULL;
+
+bool wxSndFileCodec::StartPlay()
+{
+ if (!dev_snd)
+ dev_snd = new wxSoundDevice;
+
+ Play(*dev_snd);
+
+ return TRUE;
+}
+
+void wxSndFileCodec::StopPlay()
+{
+ if (!dev_snd)
+ return;
+
+ Stop(*dev_snd);
+ m_fpos = 0;
+}
+
+class wxSoundModule : public wxModule {
+ DECLARE_DYNAMIC_CLASS(wxSoundModule)
+public:
+ virtual bool OnInit() { return TRUE; }
+ virtual void OnExit() {
+ if (dev_snd)
+ delete dev_snd;
+ }
+};
+
+IMPLEMENT_DYNAMIC_CLASS(wxSoundModule, wxModule)
--- /dev/null
+// /////////////////////////////////////////////////////////////////////////////
+// Name: sndfile.h
+// Purpose: wxMMedia
+// Author: Guilhem Lavaux
+// Created: 1997
+// Updated: 1998
+// Copyright: (C) 1997, 1998, Guilhem Lavaux
+// License: wxWindows license
+// /////////////////////////////////////////////////////////////////////////////
+/* Real -*- C++ -*- */
+#ifndef __SND_file_H__
+#define __SND_file_H__
+
+#ifdef __GNUG__
+#pragma interface
+#endif
+
+#include "mmfile.h"
+#include "sndsnd.h"
+
+///
+class wxSndFileCodec : public wxMMediaFile, public wxSndBuffer {
+ ///
+ DECLARE_ABSTRACT_CLASS(wxSndFileCodec)
+public:
+
+ typedef enum {
+ wxSFILE_STOPPED,
+ wxSFILE_PLAYING,
+ wxSFILE_RECORDING
+ } FileState;
+
+protected:
+ wxUint32 m_fsize, m_fpos, m_fdone;
+ FileState m_fstate;
+ wxMMtime m_sndtime;
+public:
+
+ ///
+ wxSndFileCodec();
+ ///
+ wxSndFileCodec(wxInputStream& s, bool preload, bool seekable);
+ ///
+ wxSndFileCodec(wxOutputStream& s, bool seekable);
+ ///
+ wxSndFileCodec(const wxString& fname);
+ ///
+ virtual ~wxSndFileCodec();
+
+ ///
+ void Play(wxSound& snd);
+ ///
+ void Stop(wxSound& snd);
+ ///
+ void Record(wxSound& snd,
+ const wxSoundDataFormat& format, wxUint32 seconds);
+
+ ///
+ void OnNeedOutputData(char *data, wxUint32& size);
+ ///
+ void OnBufferInFinished(char *iobuf, wxUint32& size);
+
+ ///
+ virtual bool OnNeedData(char *buf, wxUint32 size) = 0;
+ ///
+ virtual bool OnWriteData(char *buf, wxUint32 size) = 0;
+ ///
+ virtual wxUint32 PrepareToPlay() = 0;
+ ///
+ virtual bool PrepareToRecord(wxUint32 file_size) = 0;
+ ///
+ virtual bool TranslateBuffer(wxSndBuffer& buf);
+ ///
+ virtual bool RestartBuffer(wxSndMode mode);
+ ///
+ virtual wxUint32 GetSize() const;
+ ///
+ virtual wxUint32 Available() const;
+ ///
+ virtual wxMMtime GetLength();
+
+ ///
+ wxMMtime GetPosition();
+
+ ///
+ virtual bool StartPlay();
+ ///
+ virtual void StopPlay();
+};
+
+#endif
--- /dev/null
+////////////////////////////////////////////////////////////////////////////////
+// Name: sndfrag.cpp
+// Purpose: wxMMedia
+// Author: Guilhem Lavaux
+// Created: 1997
+// Updated: 1998
+// Copyright: (C) 1997, 1998, Guilhem Lavaux
+// License: wxWindows license
+////////////////////////////////////////////////////////////////////////////////
+#ifdef __GNUG__
+#pragma implementation "sndfrag.h"
+#endif
+#include <stdio.h>
+#ifdef WX_PRECOMP
+#include "wx_prec.h"
+#else
+#include "wx/wx.h"
+#endif
+#include "sndfrag.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+wxFragmentBuffer::wxFragmentBuffer(wxSound& io_drv)
+ : m_iodrv(&io_drv), m_maxoq(0), m_maxiq(0),
+ m_optrs(NULL), m_iptrs(NULL), m_lstoptrs(NULL), m_lstiptrs(NULL),
+ m_buf2free(FALSE), m_dontq(FALSE), m_freeing(FALSE)
+{
+}
+
+wxFragmentBuffer::~wxFragmentBuffer()
+{
+}
+
+void wxFragmentBuffer::AbortBuffer(wxSndBuffer *buf)
+{
+ for (wxUint8 i=0;i<m_maxoq;i++)
+ if (m_lstoptrs[i].buffers->Member(buf)) {
+ if (m_lstoptrs[i].state == wxBUFFER_PLAYING)
+ // TODO: Do something.
+ ;
+ m_lstoptrs[i].state = wxBUFFER_TOFREE;
+ }
+
+ for (wxUint8 i=0;i<m_maxiq;i++)
+ if (m_lstiptrs[i].buffers->Member(buf)) {
+ if (m_lstiptrs[i].state == wxBUFFER_PLAYING)
+ // Do something.
+ ;
+ m_lstiptrs[i].state = wxBUFFER_TOFREE;
+ }
+}
+
+wxFragmentBuffer::wxFragBufPtr *wxFragmentBuffer::FindFreeBuffer(
+ wxFragBufPtr *list, wxUint8 max_queue)
+{
+ if (!list)
+ return NULL;
+
+ for (wxUint8 i=0;i<max_queue;i++) {
+ if (list[i].state == wxBUFFER_FREE)
+ return &list[i];
+ }
+
+ return NULL;
+}
+
+bool wxFragmentBuffer::NotifyOutputBuffer(wxSndBuffer *buf)
+{
+ wxFragBufPtr *ptr;
+ char *raw_buf;
+ wxUint32 rawbuf_size;
+
+ if (!m_iodrv->OnSetupDriver(*buf, wxSND_OUTPUT))
+ return FALSE;
+
+ while (1) {
+ // Find the first free (at least partly free) output buffer
+ ptr = FindFreeBuffer(m_lstoptrs, m_maxoq);
+ // No free : go out !
+ if (!ptr)
+ return FALSE;
+
+ // Find the end of the buffer
+ raw_buf = ptr->data + ptr->ptr;
+ rawbuf_size = ptr->size - ptr->ptr;
+
+ // Fill it up
+ buf->OnNeedOutputData(raw_buf, rawbuf_size);
+
+ // No data to fill the buffer: dequeue the current wxSndBuffer
+ if (!rawbuf_size) {
+ if (buf->IsNotSet(wxSND_KEEPQUEUED)) {
+ buf->Set(wxSND_UNQUEUEING);
+ m_iodrv->m_buffers.DeleteObject(buf);
+ }
+ return TRUE;
+ }
+
+ // Data: append it to the list
+ ptr->buffers->Append(buf);
+
+ ptr->ptr += rawbuf_size;
+
+ // Output buffer full: send it to the driver
+ if (ptr->ptr == ptr->size) {
+ ptr->state = wxBUFFER_FFILLED;
+ OnBufferFilled(ptr, wxSND_OUTPUT);
+ }
+ }
+}
+
+bool wxFragmentBuffer::NotifyInputBuffer(wxSndBuffer *buf)
+{
+ wxFragBufPtr *ptr;
+ char *raw_buf;
+ wxUint32 rawbuf_size;
+
+ if (!m_iodrv->OnSetupDriver(*buf, wxSND_INPUT))
+ return FALSE;
+
+ while (1) {
+ ptr = FindFreeBuffer(m_lstiptrs, m_maxiq);
+ if (!ptr)
+ return FALSE;
+
+ raw_buf = ptr->data + ptr->ptr;
+ rawbuf_size = ptr->size - ptr->ptr;
+
+ rawbuf_size = (buf->Available() < rawbuf_size) ? buf->Available() : rawbuf_size;
+
+ if (!rawbuf_size) {
+
+ if (buf->IsNotSet(wxSND_KEEPQUEUED)) {
+ buf->Set(wxSND_UNQUEUEING);
+ m_iodrv->m_buffers.DeleteObject(buf);
+ }
+
+ // Get data now when there isn't anymore buffer in the queue
+ if (!LastBuffer() && ptr->ptr) {
+ ptr->state = wxBUFFER_FFILLED;
+ if (!OnBufferFilled(ptr, wxSND_INPUT))
+ return FALSE;
+ }
+ return TRUE;
+ }
+ ptr->buffers->Append(buf);
+
+ ptr->ptr += rawbuf_size;
+
+ // Input buffer full => get data
+ if (ptr->ptr == ptr->size) {
+ ptr->state = wxBUFFER_FFILLED;
+ if (!OnBufferFilled(ptr, wxSND_INPUT))
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+void wxFragmentBuffer::FreeBufToFree(bool force)
+{
+ wxUint8 i;
+ // Garbage collecting
+
+ m_dontq = TRUE;
+ m_buf2free = FALSE;
+
+ for (i=0;i<m_maxoq;i++) {
+ if ((m_lstoptrs[i].state == wxBUFFER_TOFREE) ||
+ (force && m_lstoptrs[i].state == wxBUFFER_FFILLED))
+ ClearBuffer(&m_lstoptrs[i]);
+ }
+
+ for (i=0;i<m_maxiq;i++) {
+ if ((m_lstiptrs[i].state == wxBUFFER_TOFREE) ||
+ (force && m_lstoptrs[i].state == wxBUFFER_FFILLED))
+ ClearBuffer(&m_lstiptrs[i]);
+ }
+
+ m_dontq = FALSE;
+}
+
+void wxFragmentBuffer::ClearBuffer(wxFragBufPtr *ptr)
+{
+ wxNode *node;
+ wxSndBuffer *buf;
+ char *data;
+ wxUint32 size, data_read;
+
+ data = ptr->data;
+ size = ptr->size;
+
+ node = ptr->buffers->First();
+
+ while (node) {
+ buf = (wxSndBuffer *)node->Data();
+
+ if (buf->GetMode() == wxSND_OUTPUT) {
+ buf->OnBufferOutFinished();
+ } else {
+ data_read = buf->OnBufferInFinished(data, size);
+
+ data += data_read;
+ size -= data_read;
+ }
+
+ if (buf->IsSet(wxSND_UNQUEUEING))
+ buf->Clear(wxSND_UNQUEUEING | wxSND_BUFLOCKED | wxSND_BUFREADY);
+
+ delete node;
+ node = ptr->buffers->First();
+ }
+
+ ptr->ptr = 0;
+ ptr->state = wxBUFFER_FREE;
+}
+
+void wxFragmentBuffer::OnBufferFinished(wxFragBufPtr *ptr)
+{
+ wxNode *node;
+ wxSndBuffer *buf;
+ bool ret = TRUE;
+
+ if (m_freeing) {
+ ptr->state = wxBUFFER_TOFREE;
+ m_buf2free = TRUE;
+ return;
+ }
+ m_freeing = TRUE;
+
+ // Clean up the old buffer.
+ if (ptr && ptr->state != wxBUFFER_FREE)
+ ClearBuffer(ptr);
+
+ // Garbage collecting ...
+ if (m_buf2free)
+ FreeBufToFree();
+
+ // If we are queueing, return immediately.
+ if (m_dontq) {
+ m_freeing = FALSE;
+ return;
+ }
+
+ node = m_iodrv->m_buffers.First();
+
+ while (node && ret) {
+ buf = (wxSndBuffer *)node->Data();
+ node = node->Next();
+
+ buf->HardLock();
+
+ // Stop request on this buffer.
+ if (buf->IsSet(wxSND_BUFSTOP)) {
+ buf->Clear(wxSND_BUFSTOP);
+ continue;
+ }
+ if (buf->GetMode() == wxSND_OUTPUT)
+ ret = NotifyOutputBuffer(buf);
+ else
+ ret = NotifyInputBuffer(buf);
+
+ buf->HardUnlock();
+ }
+ m_freeing = FALSE;
+}
--- /dev/null
+// /////////////////////////////////////////////////////////////////////////////
+// Name: sndfrag.h
+// Purpose: wxMMedia
+// Author: Guilhem Lavaux
+// Created: 1997
+// Updated: 1998
+// Copyright: (C) 1997, 1998, Guilhem Lavaux
+// License: wxWindows license
+// /////////////////////////////////////////////////////////////////////////////
+#ifndef __SND_frag_H__
+#define __SND_frag_H__
+#ifdef __GNUG__
+#pragma interface
+#endif
+
+#ifdef WX_PRECOMP
+#include "wx_prec.h"
+#else
+#include "wx/wx.h"
+#endif
+#include "sndsnd.h"
+
+///
+class wxFragmentBuffer {
+protected:
+ wxSound *m_iodrv;
+
+ ///
+ wxUint8 m_maxoq, m_maxiq;
+
+ ///
+ typedef enum {
+ wxBUFFER_FREE,
+ wxBUFFER_FFILLED,
+ wxBUFFER_TOFREE
+ } BufState;
+public:
+ ///
+ typedef struct {
+ char *data;
+ ///
+ char *user_data;
+ ///
+ wxUint32 size, ptr;
+ ///
+ wxList *buffers;
+ ///
+ BufState state;
+ } wxFragBufPtr;
+protected:
+ ///
+ wxFragBufPtr *m_optrs, *m_iptrs;
+ ///
+ wxFragBufPtr *m_lstoptrs, *m_lstiptrs;
+ ///
+ bool m_buf2free, m_dontq, m_freeing;
+public:
+ ///
+ wxFragmentBuffer(wxSound& io_drv);
+ ///
+ virtual ~wxFragmentBuffer();
+
+ ///
+ virtual void AllocIOBuffer() = 0;
+ ///
+ virtual void FreeIOBuffer() = 0;
+
+ ///
+ void AbortBuffer(wxSndBuffer *buf);
+
+ ///
+ wxFragBufPtr *FindFreeBuffer(wxFragBufPtr *list, wxUint8 max_queue);
+ ///
+ bool NotifyOutputBuffer(wxSndBuffer *buf);
+ ///
+ bool NotifyInputBuffer(wxSndBuffer *buf);
+
+ ///
+ void OnBufferFinished(wxFragBufPtr *ptr);
+
+ ///
+ virtual bool OnBufferFilled(wxFragBufPtr *ptr, wxSndMode mode) = 0;
+
+ ///
+ inline wxSndBuffer *LastBuffer() {
+ wxNode *node = m_iodrv->m_buffers.Last();
+
+ if (!node) return NULL;
+ return (wxSndBuffer *)node->Data();
+ }
+ ///
+ inline wxSndBuffer *FirstBuffer() {
+ wxNode *node = m_iodrv->m_buffers.First();
+
+ if (!node) return NULL;
+ return (wxSndBuffer *)node->Data();
+ }
+protected:
+ void FreeBufToFree(bool force = FALSE);
+ void ClearBuffer(wxFragBufPtr *ptr);
+};
+
+#endif
--- /dev/null
+#ifdef __GNUG__
+#pragma implementation "sndfrmt.h"
+#endif
+#include "sndsnd.h"
+#include "sndfrmt.h"
+#include "sndpcm.h"
+#include <dmalloc.h>
+
+// ----------------------------------------------------------------------------
+// wxSoundDataFormat
+// ----------------------------------------------------------------------------
+
+wxSoundDataFormat::wxSoundDataFormat()
+{
+ m_srate = 22050;
+ m_bps = 8;
+ m_channels = 1;
+ m_codno = 1;
+ m_codec = NULL;
+ m_codchange = FALSE;
+ m_codcreate = TRUE;
+}
+
+wxSoundDataFormat::~wxSoundDataFormat()
+{
+ wxDELETE(m_codec);
+}
+
+void wxSoundDataFormat::SetChannels(int channels)
+{
+ m_channels = channels;
+}
+
+void wxSoundDataFormat::SetBps(int bps)
+{
+ m_bps = bps;
+ CodecChange();
+}
+
+void wxSoundDataFormat::SetSign(int sign)
+{
+ m_sign = sign;
+ CodecChange();
+}
+
+void wxSoundDataFormat::SetByteOrder(int byteorder)
+{
+ m_byteorder = byteorder;
+ CodecChange();
+}
+
+void wxSoundDataFormat::SetCodecNo(int codno)
+{
+ m_codno = codno;
+ m_codchange = TRUE;
+ CodecChange();
+}
+
+wxSoundCodec *wxSoundDataFormat::GetCodec()
+{
+ if (!m_codcreate)
+ return NULL;
+
+ if (m_codchange)
+ wxDELETEA(m_codec);
+
+ if (m_codec)
+ return m_codec;
+
+ m_codchange = FALSE;
+ m_codec = wxSoundCodec::Get(m_codno);
+
+ return m_codec;
+}
+
+void wxSoundDataFormat::CodecChange()
+{
+ wxSoundCodec *codec = GetCodec();
+
+ if (!codec)
+ return;
+
+ switch (m_codno) {
+ case WXSOUND_PCM: {
+ wxSoundPcmCodec *pcm_codec = (wxSoundPcmCodec *)codec;
+
+ pcm_codec->SetBits(m_bps);
+ pcm_codec->SetByteOrder(m_byteorder);
+ pcm_codec->SetSign(m_sign);
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+wxSoundDataFormat& wxSoundDataFormat::operator =(const wxSoundDataFormat& format)
+{
+ wxDELETE(m_codec);
+
+ m_srate = format.m_srate;
+ m_bps = format.m_bps;
+ m_channels = format.m_channels;
+ m_codno = format.m_codno;
+ m_sign = format.m_sign;
+ m_byteorder = format.m_byteorder;
+
+ return *this;
+}
+
+bool wxSoundDataFormat::operator ==(const wxSoundDataFormat& format) const
+{
+ if (m_codno != format.m_codno || m_srate != format.m_srate ||
+ m_bps != format.m_bps || m_channels != format.m_channels)
+ return FALSE;
+
+ if (m_codno == WXSOUND_PCM &&
+ (m_sign != format.m_sign || m_byteorder != format.m_byteorder))
+ return FALSE;
+
+ return TRUE;
+}
+
+// ----------------------------------------------------------------------------
+// wxSoundCodec
+// ----------------------------------------------------------------------------
+
+#include "sndpcm.h"
+//#include "sndadpcm.h"
+//#include "sndalaw.h"
+#include "sndmulaw.h"
+
+static wxClassInfo *l_sound_formats[] = {
+ NULL,
+ CLASSINFO(wxSoundPcmCodec),
+ NULL, // CLASSINFO(wxSoundAdpcmCodec),
+ NULL,
+ NULL,
+ NULL,
+ NULL, // CLASSINFO(wxSoundAlawCodec),
+ NULL // CLASSINFO(wxSoundMulawCodec)
+};
+
+static int l_nb_formats = WXSIZEOF(l_sound_formats);
+
+wxSoundCodec::wxSoundCodec()
+{
+ m_in_sound = NULL;
+ m_out_sound = NULL;
+ m_init = TRUE;
+}
+
+wxSoundCodec::~wxSoundCodec()
+{
+}
+
+void wxSoundCodec::InitIO(const wxSoundDataFormat& format)
+{
+ m_io_format = format;
+}
+
+void wxSoundCodec::InitMode(int mode)
+{
+ wxStreamBuffer *buf_snd;
+
+ m_mode = (mode == 0) ? ENCODING : DECODING;
+ if (!m_chain_codec) {
+ if (mode == ENCODING) {
+ m_out_sound = new wxStreamBuffer(*this, wxStreamBuffer::write);
+ m_out_sound->SetBufferIO(1024);
+ } else {
+ m_in_sound = new wxStreamBuffer(*this, wxStreamBuffer::read);
+ m_in_sound->SetBufferIO(1024);
+ }
+ }
+ if (m_chain_codec) {
+ if (m_chain_before) {
+ m_chain_codec->SetInStream(m_in_sound);
+ buf_snd = new wxStreamBuffer(wxStreamBuffer::read_write);
+ buf_snd->Fixed(FALSE);
+ m_chain_codec->SetOutStream(buf_snd);
+ m_chain_codec->Decode();
+ buf_snd->Seek(0, wxFromStart);
+ m_in_sound = buf_snd;
+ } else {
+ buf_snd = new wxStreamBuffer(wxStreamBuffer::read_write);
+ buf_snd->Fixed(FALSE);
+
+ m_chain_codec->SetInStream(buf_snd);
+ m_chain_codec->SetOutStream(m_out_sound);
+ m_out_sound = buf_snd;
+
+ buf_snd->Seek(0, wxFromStart);
+ }
+ }
+}
+
+void wxSoundCodec::ExitMode()
+{
+ if (m_chain_codec) {
+ if (m_chain_before) {
+ delete m_in_sound;
+ m_in_sound = m_chain_codec->GetInStream();
+ } else {
+ delete m_out_sound;
+ m_out_sound = m_chain_codec->GetOutStream();
+ }
+ }
+}
+
+bool wxSoundCodec::ChainCodecBefore(wxSoundDataFormat& format)
+{
+ m_chain_codec = format.GetCodec();
+
+ if (!m_chain_codec)
+ return FALSE;
+
+ m_chain_before = TRUE;
+ return TRUE;
+}
+
+bool wxSoundCodec::ChainCodecAfter(wxSoundDataFormat& format)
+{
+ m_chain_codec = format.GetCodec();
+
+ if (!m_chain_codec)
+ return FALSE;
+
+ m_chain_before = FALSE;
+ return TRUE;
+}
+
+void wxSoundCodec::CopyToOutput()
+{
+ m_out_sound->Write(m_in_sound);
+}
+
+size_t wxSoundCodec::Available()
+{
+ return m_io_sndbuf->Available();
+}
+
+size_t wxSoundCodec::OnSysRead(void *buffer, size_t bsize)
+{
+ wxUint32 s = bsize;
+ m_io_sndbuf->OnNeedOutputData((char *)buffer, s);
+ return bsize;
+}
+
+size_t wxSoundCodec::OnSysWrite(const void *buffer, size_t bsize)
+{
+ wxUint32 s = bsize;
+ m_io_sndbuf->OnBufferInFinished((char *)buffer, s);
+ return bsize;
+}
+
+wxSoundCodec *wxSoundCodec::Get(int no)
+{
+ if (no < 0 || no >= l_nb_formats)
+ return NULL;
+
+ if (!l_sound_formats[no])
+ return NULL;
+
+ return (wxSoundCodec *)l_sound_formats[no]->CreateObject();
+}
--- /dev/null
+#ifndef __SNDFRMT_H__
+#define __SNDFRMT_H__
+
+#ifdef __GNUG__
+#pragma interface
+#endif
+
+#include <wx/object.h>
+
+class wxSndBuffer;
+
+// Standard Microsoft types (why change ?)
+#define WXSOUND_PCM 0x0001
+#define WXSOUND_ADPCM 0x0002
+#define WXSOUND_ALAW 0x0006
+#define WXSOUND_ULAW 0x0007
+
+class wxSoundCodec;
+class wxSoundDataFormat {
+ public:
+ wxSoundDataFormat();
+ ~wxSoundDataFormat();
+
+ void SetSampleRate(int srate) { m_srate = srate; }
+ void SetChannels(int channels);
+ void SetStereo(bool on);
+ void SetCodecNo(int no);
+ void SetCodecCreate(bool create) { m_codcreate = create; }
+
+ int GetSampleRate() const { return m_srate; }
+ int GetChannels() const { return m_channels; }
+ bool GetStereo() const { return (m_channels == 2); }
+ int GetCodecNo() const { return m_codno; }
+
+ wxSoundCodec *GetCodec();
+
+ wxSoundDataFormat& operator =(const wxSoundDataFormat& format);
+ bool operator ==(const wxSoundDataFormat& format) const;
+ bool operator !=(const wxSoundDataFormat& format) const
+ { return !(operator ==(format)); }
+
+ /// PCM format
+ void SetByteOrder(int order);
+ void SetSign(int sign);
+ int GetByteOrder() const { return m_byteorder; }
+ int GetSign() const { return m_sign; }
+
+ void SetBps(int bps);
+ int GetBps() const { return m_bps; }
+
+ protected:
+ void CodecChange();
+
+ protected:
+ int m_srate, m_bps, m_channels, m_codno;
+ int m_byteorder, m_sign;
+ bool m_codchange, m_codcreate;
+ wxSoundCodec *m_codec;
+};
+
+class wxSoundCodec : public wxObject, public wxStreamBase {
+ DECLARE_ABSTRACT_CLASS(wxSoundCodec)
+ public:
+ wxSoundCodec();
+ virtual ~wxSoundCodec();
+
+ void SetIOBuffer(wxSndBuffer *sndbuf) { m_io_sndbuf = sndbuf; }
+ size_t Available();
+
+ void InitIO(const wxSoundDataFormat& format);
+ void InitMode(int mode);
+ void ExitMode();
+
+ inline void SetInStream(wxStreamBuffer *s)
+ { m_in_sound = s; }
+ inline void SetOutStream(wxStreamBuffer *s)
+ { m_out_sound = s; }
+ inline wxStreamBuffer *GetInStream() const { return m_in_sound; }
+ inline wxStreamBuffer *GetOutStream() const { return m_out_sound; }
+
+ inline bool Good() const { return (m_in_sound->Stream()->LastError() == wxStream_NOERROR) && (m_out_sound->Stream()->LastError() == wxStream_NOERROR); }
+
+ virtual size_t GetByteRate() const = 0;
+ virtual wxSoundDataFormat GetPreferredFormat(int codec = 0) const = 0;
+
+ virtual void Decode() = 0;
+ virtual void Encode() = 0;
+
+ static wxSoundCodec *Get(int no);
+
+ protected:
+ void CopyToOutput();
+
+ unsigned short Convert8_16(unsigned char s) { return (s & 0xff) << 8; }
+ unsigned char Convert16_8(unsigned short s) { return (s & 0xff00) >> 8; }
+
+ bool ChainCodecBefore(wxSoundDataFormat& cod_to);
+ bool ChainCodecAfter(wxSoundDataFormat& cod_to);
+
+ // -------------
+ // wxStream part
+ // -------------
+ size_t OnSysWrite(const void *buffer, size_t bsize);
+ size_t OnSysRead(void *buffer, size_t bsize);
+
+ protected:
+ wxSndBuffer *m_io_sndbuf;
+ wxSoundDataFormat m_io_format;
+ wxStreamBuffer *m_in_sound, *m_out_sound;
+ wxSoundCodec *m_chain_codec;
+ bool m_init, m_chain_before;
+
+ enum {
+ ENCODING = 0,
+ DECODING
+ } m_mode;
+};
+
+#endif
--- /dev/null
+#ifdef __GNUG__
+#pragma implementation "sndmulaw.h"
+#endif
+
+#include "sndsnd.h"
+#include "sndfrmt.h"
+#include "sndmulaw.h"
+#include "adpcm/g72x.h"
+
+wxSoundMulawCodec::wxSoundMulawCodec()
+ : wxSoundCodec()
+{
+}
+
+wxSoundMulawCodec::~wxSoundMulawCodec()
+{
+}
+
+void wxSoundMulawCodec::Decode()
+{
+ int smp;
+ wxSoundDataFormat pref_frmt;
+
+ pref_frmt = GetPreferredFormat(0);
+ if (m_io_format != pref_frmt)
+ ChainCodecAfter(pref_frmt);
+
+ InitMode(DECODING);
+
+ while (!Good()) {
+ smp = ulaw2linear(m_in_sound->GetChar());
+#ifdef USE_BE_MACH
+ m_out_sound->PutChar((smp & 0xff00) >> 8);
+ m_out_sound->PutChar(smp & 0xff);
+#else
+ m_out_sound->PutChar(smp & 0xff);
+ m_out_sound->PutChar((smp & 0xff00) >> 8);
+#endif
+ }
+}
+
+void wxSoundMulawCodec::Encode()
+{
+ int smp;
+ wxSoundDataFormat pref_frmt;
+
+ pref_frmt = GetPreferredFormat(0);
+ if (m_io_format != pref_frmt)
+ ChainCodecBefore(pref_frmt);
+
+ InitMode(ENCODING);
+
+ while (!Good()) {
+#ifdef USE_BE_MACH
+ smp = ((unsigned short)m_in_sound->GetChar()) << 8;
+ smp |= m_in_sound->GetChar() & 0xff;
+#else
+ smp = m_in_sound->GetChar() & 0xff;
+ smp |= ((unsigned short)m_in_sound->GetChar()) << 8;
+#endif
+ m_out_sound->PutChar(linear2ulaw(smp));
+ }
+}
+
+size_t wxSoundMulawCodec::GetByteRate() const
+{
+ return m_srate;
+}
+
+wxSoundDataFormat wxSoundMulawCodec::GetPreferredFormat(int WXUNUSED(no)) const
+{
+ wxSoundDataFormat format;
+
+ format.SetCodecNo(WXSOUND_PCM);
+ format.SetSampleRate(m_srate);
+ format.SetBps(16);
+ format.SetChannels(1);
+ format.SetSign(wxSND_SAMPLE_SIGNED);
+#ifdef USE_BE_MACH
+ format.SetByteOrder(wxSND_SAMPLE_BE);
+#else
+ format.SetByteOrder(wxSND_SAMPLE_LE);
+#endif
+ return format;
+}
--- /dev/null
+#ifndef __MEDIA_SNDMULAW_H__
+#define __MEDIA_SNDMULAW_H__
+
+#ifdef __GNUG__
+#pragma interface
+#endif
+
+#include "sndfrmt.h"
+
+class wxSoundMulawCodec : public wxSoundCodec {
+ DECLARE_DYNAMIC_CLASS(wxSoundMulawCodec)
+ public:
+ wxSoundMulawCodec();
+ virtual ~wxSoundMulawCodec();
+
+ void SetSampleRate(int srate) { m_srate = srate; }
+
+ size_t GetByteRate() const;
+ wxSoundDataFormat GetPreferredFormat(int codec = 0) const;
+
+ void Decode();
+ void Encode();
+
+ protected:
+ int m_srate;
+};
+
+#endif
--- /dev/null
+#ifdef __GNUG__
+#pragma implementation "sndpcm.h"
+#endif
+#include "sndsnd.h"
+#include "sndpcm.h"
+#include <dmalloc.h>
+
+#define WX_BIG_ENDIAN 0
+
+wxSoundPcmCodec::wxSoundPcmCodec()
+ : wxSoundCodec()
+{
+ m_orig_format.SetCodecCreate(FALSE);
+ m_orig_format.SetCodecNo(1);
+ m_char_bool = FALSE;
+}
+
+wxSoundPcmCodec::~wxSoundPcmCodec()
+{
+}
+
+size_t wxSoundPcmCodec::GetByteRate() const
+{
+ return (m_orig_format.GetBps()/8)*
+ m_orig_format.GetSampleRate()*
+ m_orig_format.GetChannels();
+}
+
+wxSoundDataFormat wxSoundPcmCodec::GetPreferredFormat(int codec) const
+{
+ wxSoundDataFormat prefFormat;
+
+ prefFormat = m_orig_format;
+ prefFormat.SetCodecNo(WXSOUND_PCM);
+ return prefFormat;
+}
+
+// ---------------------------------------------------------------------------
+// Main part of the decoder
+// ---------------------------------------------------------------------------
+
+void wxSoundPcmCodec::Decode()
+{
+ InitMode(DECODING);
+ if (m_io_format == m_orig_format) {
+ CopyToOutput();
+ ExitMode();
+ return;
+ }
+
+ // Swap bytes
+ switch (m_io_format.GetBps()) {
+ case 8:
+ InputSign8();
+ break;
+ case 16:
+ InputSwapAndSign16();
+ break;
+ case 32:
+ case 64:
+ default:
+ break;
+ }
+ ExitMode();
+}
+
+// ---------------------------------------------------------------------------
+// Change the sign of a 8-bit sample.
+
+#define GET() (m_in_sound->GetChar())
+#define PUT(c) (m_out_sound->PutChar(c))
+#define OUT_ERROR() (out->LastError() == wxStream_NOERROR)
+#define IN_ERROR() (in->LastError() == wxStream_NOERROR)
+
+void wxSoundPcmCodec::InputSign8()
+{
+ unsigned char signer = 0;
+ wxStreamBase *in = m_out_sound->Stream(), *out = m_in_sound->Stream();
+
+ if (m_io_format.GetSign() != m_orig_format.GetSign())
+ signer = 128;
+
+ while (IN_ERROR() && OUT_ERROR())
+ PUT(GET() + signer);
+
+}
+
+// ---------------------------------------------------------------------------
+// Swap bytes and change the sign of a 16-bit sample.
+
+void wxSoundPcmCodec::InputSwapAndSign16()
+{
+ unsigned short signer1 = 0, signer2 = 0;
+ wxStreamBase *in = m_out_sound->Stream(), *out = m_in_sound->Stream();
+ bool swap = (m_io_format.GetByteOrder() != m_orig_format.GetByteOrder());
+ char temp;
+
+ if (m_io_format.GetSign() != m_orig_format.GetSign()) {
+ if (m_io_format.GetByteOrder() == wxSND_SAMPLE_LE)
+ signer2 = 0x80;
+ else
+ signer1 = 0x80;
+ }
+
+ if (swap) {
+ while (IN_ERROR() && OUT_ERROR()) {
+ temp = GET() ^ signer1;
+ PUT(GET() ^ signer2);
+ if (OUT_ERROR()) {
+ m_char_bool = TRUE;
+ m_char_stack = temp;
+ break;
+ }
+ PUT(temp);
+ }
+ } else {
+ while (IN_ERROR() && OUT_ERROR()) {
+ PUT(GET() ^ signer1);
+ if (OUT_ERROR()) {
+ m_char_bool = TRUE;
+ m_char_stack = temp;
+ break;
+ }
+ PUT(GET() ^ signer2);
+ }
+ }
+}
+
+// ---------------------------------------------------------------------------
+// Encoder part.
+// ---------------------------------------------------------------------------
+
+void wxSoundPcmCodec::OutputSign8()
+{
+ wxStreamBase *in = m_out_sound->Stream(), *out = m_in_sound->Stream();
+ unsigned char signer = 0;
+
+ if (m_io_format.GetSign() != m_orig_format.GetSign())
+ signer = 128;
+
+ while (IN_ERROR() && OUT_ERROR())
+ PUT((char)(GET() + signer));
+}
+
+// ---------------------------------------------------------------------------
+
+void wxSoundPcmCodec::OutputSwapAndSign16()
+{
+ bool swap = (m_io_format.GetByteOrder() != m_orig_format.GetByteOrder());
+ unsigned short signer1 = 0, signer2 = 0;
+ char temp;
+ wxStreamBase *in = m_out_sound->Stream(), *out = m_in_sound->Stream();
+
+ if (m_char_bool) {
+ PUT(GET());
+ PUT(m_char_stack);
+ m_char_bool = FALSE;
+ }
+
+ if (m_io_format.GetSign() != m_orig_format.GetSign())
+ if (m_io_format.GetByteOrder() == wxSND_SAMPLE_LE)
+ signer1 = 0x80;
+ else
+ signer2 = 0x80;
+
+ if (swap) {
+ while (IN_ERROR()) {
+ temp = GET();
+ PUT(GET() ^ signer1);
+ if (OUT_ERROR()) {
+ m_char_stack = temp ^ signer2;
+ m_char_bool = TRUE;
+ break;
+ }
+ PUT(temp ^ signer2);
+ }
+ } else {
+ while (IN_ERROR()) {
+ PUT(GET() ^ signer1);
+ if (!OUT_ERROR()) {
+ m_char_stack = GET() ^ signer2;
+ m_char_bool = TRUE;
+ break;
+ }
+ PUT(GET() ^ signer2);
+ }
+ }
+
+}
+
+// ---------------------------------------------------------------------------
+
+void wxSoundPcmCodec::Encode()
+{
+ InitMode(ENCODING);
+ if (m_io_format == m_orig_format) {
+ CopyToOutput();
+ ExitMode();
+ return;
+ }
+
+ // Swap bytes
+ switch (m_io_format.GetBps()) {
+ case 8:
+ OutputSign8();
+ break;
+ case 16:
+ OutputSwapAndSign16();
+ break;
+ case 32:
+ case 64:
+ default:
+ break;
+ }
+ ExitMode();
+}
--- /dev/null
+#ifndef __SNDPCM_H__
+#define __SNDPCM_H__
+
+#ifdef __GNUG__
+#pragma interface
+#endif
+
+#include "sndfrmt.h"
+
+class wxSoundPcmCodec : public wxSoundCodec {
+ DECLARE_DYNAMIC_CLASS(wxSoundPcmCodec)
+ public:
+ wxSoundPcmCodec();
+ virtual ~wxSoundPcmCodec();
+
+ void SetSampleRate(int srate) { m_orig_format.SetSampleRate(srate); }
+ void SetBits(int bits) { m_orig_format.SetBps(bits); }
+ void SetByteOrder(int order) { m_orig_format.SetByteOrder(order); }
+ void SetSign(int sample_sign) { m_orig_format.SetSign(sample_sign); }
+
+ size_t GetByteRate() const;
+ wxSoundDataFormat GetPreferredFormat(int codec = 0) const;
+
+ void Decode();
+ void Encode();
+
+ protected:
+ void InputSign8();
+ void InputSwapAndSign16();
+ void OutputSign8();
+ void OutputSwapAndSign16();
+
+ protected:
+ wxSoundDataFormat m_orig_format;
+ char m_char_stack;
+ bool m_char_bool;
+};
+
+#endif
--- /dev/null
+////////////////////////////////////////////////////////////////////////////////
+// Name: sndsnd.cpp
+// Purpose: wxMMedia
+// Author: Guilhem Lavaux
+// Created: 1997
+// Updated: 1998
+// Copyright: (C) 1997, 1998, Guilhem Lavaux
+// License: wxWindows license
+////////////////////////////////////////////////////////////////////////////////
+#ifdef __GNUG__
+#pragma implementation "sndsnd.h"
+#endif
+#ifdef WX_PRECOMP
+#include "wx_prec.h"
+#else
+#include "wx/wx.h"
+#endif
+#include "sndsnd.h"
+#include "sndfrmt.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#define PROCESS_EVENT() wxYield()
+// #define PROCESS_EVENT()
+
+// ----------------------------------------------------------------------------
+// wxSndBuffer: base sound buffer class
+// ----------------------------------------------------------------------------
+
+
+wxSndBuffer::wxSndBuffer()
+ : m_sndmode(wxSND_OUTPUT), m_sndflags(0), m_sndoutput(NULL), m_sndcodec(NULL)
+{
+}
+
+wxSndBuffer::~wxSndBuffer()
+{
+}
+
+void wxSndBuffer::Set(wxSndFlags flags)
+{
+ m_sndflags |= flags;
+
+ if ((m_sndflags & wxSND_BUFAUTO) && (flags & wxSND_BUFREADY))
+ m_sndoutput->QueueBuffer(*this);
+}
+
+void wxSndBuffer::SetError(wxSndError error)
+{
+ if (error == wxSND_NOERROR)
+ Clear(wxSND_BUFERR);
+ else
+ Set(wxSND_BUFERR);
+
+ m_snderror = error;
+}
+
+wxSndError wxSndBuffer::GetError()
+{
+ if (IsNotSet(wxSND_BUFERR))
+ return wxSND_NOERROR;
+ Clear(wxSND_BUFERR);
+ return m_snderror;
+}
+
+void wxSndBuffer::OnPlayFinished()
+{
+}
+
+void wxSndBuffer::OnBufferOutFinished()
+{
+}
+
+void wxSndBuffer::OnBufferInFinished(char *WXUNUSED(iobuf),
+ wxUint32& WXUNUSED(size))
+{
+}
+
+bool wxSndBuffer::Wait()
+{
+ if (IsNotSet(wxSND_BUFLOCKED))
+ return FALSE;
+
+ while (IsSet(wxSND_BUFLOCKED))
+ PROCESS_EVENT();
+
+ return IsNotSet(wxSND_BUFERR);
+}
+
+void wxSndBuffer::HardLock()
+{
+ m_mutex.Lock();
+}
+
+void wxSndBuffer::HardUnlock()
+{
+ m_mutex.Unlock();
+}
+
+void wxSndBuffer::ChangeCodec(int no)
+{
+ wxDELETE(m_sndcodec);
+
+ m_sndformat.SetCodecNo(no);
+ m_sndcodec = m_sndformat.GetCodec();
+ m_sndcodec->SetIOBuffer(this);
+}
+
+// ----------------------------------------------------------------------------
+// wxSndSimpleBuffer: the simplest sound buffer
+// ----------------------------------------------------------------------------
+
+
+wxSndSimpleBuffer::wxSndSimpleBuffer(char *buffer, wxUint32 bufsize,
+ wxSndMode mode)
+ : wxSndBuffer()
+{
+ m_sndbuf = buffer;
+ m_sndsize = bufsize;
+ m_sndmode = mode;
+
+ m_sndptr = 0;
+}
+
+wxSndSimpleBuffer::~wxSndSimpleBuffer()
+{
+}
+
+void wxSndSimpleBuffer::OnNeedOutputData(char *iobuf, wxUint32& size)
+{
+ char *buf = m_sndbuf + m_sndptr;
+ wxUint32 nbdata_left = m_sndsize - m_sndptr;
+
+ if (m_sndptr >= m_sndsize) {
+ size = 0;
+ return;
+ }
+
+ if (size > nbdata_left)
+ size = nbdata_left;
+
+ m_sndptr += size;
+
+ memcpy(iobuf, buf, size);
+}
+
+void wxSndSimpleBuffer::OnBufferOutFinished()
+{
+ if (m_sndptr >= m_sndsize)
+ OnPlayFinished();
+}
+
+void wxSndSimpleBuffer::OnBufferInFinished(char *iobuf, wxUint32& size)
+{
+ char *raw_buf = m_sndbuf + m_sndptr;
+ wxUint32 data_left = m_sndsize - m_sndptr;
+
+ if (!data_left) {
+ size = 0;
+ return;
+ }
+
+ if (size > data_left)
+ size = data_left;
+
+ memcpy(raw_buf, iobuf, size);
+ m_sndptr += size;
+}
+
+void wxSndSimpleBuffer::SetData(char *buffer, wxUint32 bufsize,
+ wxSndMode mode)
+{
+ m_sndbuf = buffer;
+ m_sndsize = bufsize;
+ m_sndmode = mode;
+}
+
+bool wxSndSimpleBuffer::RestartBuffer(wxSndMode mode)
+{
+ m_sndptr = 0;
+ return TRUE;
+}
+
+wxUint32 wxSndSimpleBuffer::GetSize() const
+{
+ return m_sndsize;
+}
+
+wxUint32 wxSndSimpleBuffer::Available() const
+{
+ return m_sndsize - m_sndptr;
+}
+
+// ----------------------------------------------------------------------------
+// wxSound: base sound driver implementation
+// ----------------------------------------------------------------------------
+
+wxSound::wxSound()
+ : wxObject(),
+ m_lastbuf(NULL), m_sndcbk(NULL), m_snderror(wxSND_NOERROR)
+{
+ m_buffers.Clear();
+}
+
+wxSound::~wxSound()
+{
+ wxNode *node = m_buffers.First();
+
+ while (node) {
+ wxSndBuffer *buf = (wxSndBuffer *)node->Data();
+
+ buf->Clear(wxSND_BUFLOCKED);
+ }
+}
+
+bool wxSound::QueueBuffer(wxSndBuffer& buf)
+{
+ if (buf.IsSet(wxSND_BUFLOCKED) || buf.IsNotSet(wxSND_BUFREADY))
+ return FALSE;
+
+ buf.Set(wxSND_BUFLOCKED);
+ buf.SetOutput(*this);
+
+ m_buffers.Append(&buf);
+ return Wakeup(buf);
+}
+
+bool wxSound::UnqueueBuffer(wxSndBuffer& buf)
+{
+ wxNode *node;
+
+ if (buf.IsNotSet(wxSND_BUFLOCKED))
+ return FALSE;
+
+ node = m_buffers.Member(&buf);
+ if (!node)
+ return FALSE;
+
+ StopBuffer(buf);
+ node = m_buffers.Member(&buf);
+ if (node)
+ delete node;
+
+ return TRUE;
+}
+
+void wxSound::Callback(wxSndCallback cbk)
+{
+ m_sndcbk = cbk;
+}
+
+void wxSound::SetClientData(char *cdata)
+{
+ m_cdata = cdata;
+}
+
+void wxSound::OnPlayBuffer(wxSndBuffer& buf)
+{
+ m_lastbuf = &buf;
+ if (m_sndcbk)
+ m_sndcbk(*this, buf, m_cdata);
+}
--- /dev/null
+/* Real -*- C++ -*- */
+// /////////////////////////////////////////////////////////////////////////////
+// Name: sndsnd.h
+// Purpose: wxMMedia
+// Author: Guilhem Lavaux
+// Created: 1997
+// Updated: 1998
+// Copyright: (C) 1997, 1998, Guilhem Lavaux
+// License: wxWindows license
+// /////////////////////////////////////////////////////////////////////////////
+#ifndef __WX_SND_SOUND_H__
+#define __WX_SND_SOUND_H__
+#ifdef __GNUG__
+#pragma interface
+#endif
+
+#ifdef WX_PRECOMP
+#include "wx_prec.h"
+#else
+#include "wx/wx.h"
+#endif
+#include <wx/thread.h>
+#include "sndfrmt.h"
+#include "mmtype.h"
+
+class wxSound;
+class wxSndBuffer;
+
+typedef enum {
+ wxSND_OUTPUT,
+ wxSND_INPUT,
+ wxSND_DUPLEX,
+ wxSND_OTHER_IO
+} /// The possible sound output modes
+ wxSndMode;
+
+typedef enum {
+ wxSND_NOERROR = 0,
+ wxSND_NOCAPS,
+ wxSND_CANTOPEN,
+ wxSND_NOMEM,
+ wxSND_READERR,
+ wxSND_WRITEERR,
+ wxSND_CANTSET
+} /// Sound errors
+ wxSndError;
+
+/// Sound callback
+typedef void (*wxSndCallback)(wxSound&, wxSndBuffer&, char *);
+
+/// Sound flags
+typedef wxUint16 wxSndFlags;
+
+/** @name Sound buffer flags */
+/// buffer ready
+#define wxSND_BUFREADY 0x0001
+/// an error occured
+#define wxSND_BUFERR 0x0002
+/// buffer is in use
+#define wxSND_BUFLOCKED 0x0004
+/// the driver mustn't unqueue it
+#define wxSND_KEEPQUEUED 0x0008
+/// automatic: when BUFREADY is set play the buffer
+#define wxSND_BUFAUTO 0x0010
+///
+#define wxSND_UNFINISHED 0x0020
+/// buffer is nearly being unqueued
+#define wxSND_UNQUEUEING 0x0040
+/// driver wants the buffer stop
+#define wxSND_BUFSTOP 0x0080
+/// buffer will loop
+#define wxSND_LOOP 0x0100
+
+/** @name Sound data format */
+/// little endian
+#define wxSND_SAMPLE_LE 0
+/// big endian
+#define wxSND_SAMPLE_BE 1
+/// unsigned samples
+#define wxSND_SAMPLE_UNSIGNED 0
+/// signed samples
+#define wxSND_SAMPLE_SIGNED 1
+
+/** @name wxSndBuffer
+ * @memo wxSndBuffer is the basic class for all the sound codec.
+ * @author Guilhem Lavaux
+ */
+class wxSndBuffer : public wxObject {
+ /// It is an abstract class
+ DECLARE_ABSTRACT_CLASS(wxSndBuffer)
+protected:
+ wxMutex m_mutex;
+ /// output mode
+ wxSndMode m_sndmode;
+ /// last error
+ wxSndError m_snderror;
+ /// some flag
+ wxSndFlags m_sndflags;
+ /// last sound driver used
+ wxSound *m_sndoutput;
+ /// sound data format
+ wxSoundDataFormat m_sndformat;
+ /// current sound codec
+ wxSoundCodec *m_sndcodec;
+public:
+ /** @name constructor and destructor */
+ //@{
+ /// Construct an uninitialized wxSndBuffer
+ wxSndBuffer();
+ /// Destroy
+ virtual ~wxSndBuffer();
+ //@}
+
+ /** @name Functions returning the current state */
+ //@{
+ /// @return current mode
+ inline wxSndMode GetMode() const { return m_sndmode; }
+ /// @return sound data format
+ inline wxSoundDataFormat& GetFormat() { return m_sndformat; }
+ /// @return the size of the buffer
+ virtual wxUint32 GetSize() const = 0;
+ /// @return bytes left
+ virtual wxUint32 Available() const = 0;
+
+ /** enable the specified flags
+ * @param flags
+ */
+ void Set(wxSndFlags flags);
+ /** disable the specified flags
+ * @param flags
+ */
+ inline void Clear(wxSndFlags flags)
+ { m_sndflags &= ~flags; }
+ /** Check if the specified flags is set
+ * @param flags
+ * @return TRUE if all flags is set
+ */
+ inline bool IsSet(wxSndFlags flags) const
+ { return ((m_sndflags & flags) == flags); }
+ /** Check if the specified flags is not set
+ * @param flags
+ * @return TRUE if at least one flag is not set
+ */
+ inline bool IsNotSet(wxSndFlags flags) const
+ { return ((m_sndflags & flags) != flags); }
+ /** Check if the buffer is currently being played
+ * @return TRUE
+ if the buffer is being played
+ */
+ inline bool IsPlaying() const
+ { return IsSet(wxSND_BUFLOCKED); }
+ //@}
+
+ ///
+ inline void SetOutput(wxSound& snd)
+ { m_sndoutput = &snd; }
+ ///
+ inline wxSoundCodec *GetCurrentCodec() const
+ { return m_sndcodec; }
+ ///
+ void HardLock();
+ ///
+ void HardUnlock();
+
+ ///
+ wxSndError GetError();
+ ///
+ void SetError(wxSndError err);
+
+ ///
+ virtual bool Wait();
+ ///
+ virtual bool RestartBuffer(wxSndMode mode) = 0;
+ ///
+ virtual bool Abort() { return TRUE; }
+
+ ///
+ virtual void OnPlayFinished();
+
+ /** Data exchanging functions */
+ //@{
+ ///
+ virtual void OnNeedOutputData(char *io_buf, wxUint32& size) = 0;
+ ///
+ virtual void OnBufferOutFinished();
+ ///
+ virtual void OnBufferInFinished(char *iobuf, wxUint32& size);
+ //@}
+
+protected:
+ void ChangeCodec(int no);
+};
+
+class wxSndSimpleBuffer : public wxSndBuffer {
+ DECLARE_DYNAMIC_CLASS(wxSndSimpleBuffer)
+protected:
+ /// sound buffer
+ char *m_sndbuf;
+ /// size of the sound buffer
+ wxUint32 m_sndsize;
+ /// current position in the sound buffer
+ wxUint32 m_sndptr;
+public:
+ wxSndSimpleBuffer(char *buffer = NULL, wxUint32 bufsize = 0,
+ wxSndMode mode = wxSND_OUTPUT);
+ virtual ~wxSndSimpleBuffer();
+
+ void SetData(char *buffer, wxUint32 bufsize,
+ wxSndMode mode = wxSND_OUTPUT);
+ inline void SetSoundFormat(const wxSoundDataFormat& format);
+
+ void OnNeedOutputData(char *io_buf, wxUint32& size);
+ void OnNeedInputData(wxUint32& size);
+
+ void OnBufferOutFinished();
+ void OnBufferInFinished(char *iobuf, wxUint32& size);
+
+ bool RestartBuffer(wxSndMode mode);
+ wxUint32 GetSize() const;
+ wxUint32 Available() const;
+};
+
+///
+class wxSound : public wxObject {
+ ///
+ DECLARE_ABSTRACT_CLASS(wxSound)
+protected:
+ friend class wxFragmentBuffer;
+
+ ///
+ wxSndBuffer *m_lastbuf;
+ ///
+ wxList m_buffers;
+ ///
+ wxSndCallback m_sndcbk;
+ ///
+ wxSndError m_snderror;
+ ///
+ char *m_cdata;
+public:
+ ///
+ wxSound();
+ ///
+ virtual ~wxSound();
+
+ ///
+ virtual bool QueueBuffer(wxSndBuffer& buf);
+ ///
+ virtual bool UnqueueBuffer(wxSndBuffer& buf);
+ ///
+ inline wxSndBuffer *LastBufferPlayed()
+ { return m_lastbuf; }
+
+ ///
+ wxSndError GetError() { return m_snderror; }
+
+ ///
+ void Callback(wxSndCallback cbk);
+ ///
+ void SetClientData(char *cdata);
+ ///
+ virtual void OnPlayBuffer(wxSndBuffer& buf);
+protected:
+ ///
+ virtual bool Wakeup(wxSndBuffer& buf) = 0;
+ ///
+ virtual void StopBuffer(wxSndBuffer& buf) = 0;
+
+ ///
+ virtual inline bool OnSetupDriver(wxSndBuffer& WXUNUSED(buf),
+ wxSndMode WXUNUSED(mode))
+ { return TRUE; }
+};
+
+#endif
--- /dev/null
+////////////////////////////////////////////////////////////////////////////////
+// Name: snduss.cpp
+// Purpose: wxMMedia
+// Author: Guilhem Lavaux
+// Created: 1997
+// Updated: 1998
+// Copyright: (C) 1997, 1998, Guilhem Lavaux
+// License: wxWindows license
+////////////////////////////////////////////////////////////////////////////////
+#ifdef __GNUG__
+#pragma implementation "snduss.h"
+#endif
+
+#include <sys/soundcard.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <time.h>
+#include <dmalloc.h>
+
+#include "wx/app.h"
+#include "wx/utils.h"
+
+#define WXMMEDIA_INTERNAL
+#include "snduss.h"
+#include "sndfrmt.h"
+
+wxUssSound::wxUssSound()
+ : wxSound(),
+ m_srate(0), m_bps(0), m_stereo(0),
+ m_mode(wxSND_OTHER_IO),
+ m_stop_thrd(TRUE), m_sleeping(FALSE)
+{
+ m_fd = -1;
+ m_ussformat.SetCodecNo(WXSOUND_PCM);
+ m_ussformat.SetSign(wxSND_SAMPLE_SIGNED);
+ m_ussformat.SetByteOrder(wxSND_SAMPLE_LE);
+
+ m_sndbuf = new wxStreamBuffer(wxStreamBuffer::read_write);
+ m_sndbuf->Flushable(FALSE);
+ m_sndbuf->Fixed(TRUE);
+}
+
+wxUssSound::~wxUssSound()
+{
+ if (!m_stop_thrd) {
+ m_stop_thrd = TRUE;
+ if (m_sleeping) {
+ m_sleep_mtx.Lock();
+ m_sleep_cond.Signal();
+ m_sleep_mtx.Unlock();
+ }
+ Join();
+ }
+
+ if (m_fd != -1)
+ close(m_fd);
+}
+
+bool wxUssSound::Wakeup(wxSndBuffer& WXUNUSED(buf))
+{
+ printf("Waking up (wxUssSound::Wakeup) ...\n");
+ if (m_stop_thrd) {
+ m_stop_thrd = FALSE;
+ Entry();
+// wxThread::Create();
+ }
+
+ if (m_sleeping) {
+ m_sleep_mtx.Lock();
+ m_sleep_cond.Signal();
+ m_sleep_mtx.Unlock();
+ }
+
+ return TRUE;
+}
+
+void wxUssSound::StopBuffer(wxSndBuffer& buf)
+{
+ buf.HardLock();
+ buf.Set(wxSND_BUFSTOP);
+ buf.HardUnlock();
+ while (buf.IsSet(wxSND_BUFSTOP))
+ wxYield();
+// usleep(0);
+}
+
+void wxUssSound::USS_Sleep()
+{
+ bool ret;
+
+ printf("Asleeping ...\n");
+ m_sleeping = TRUE;
+ m_sleep_mtx.Lock();
+ ret = m_sleep_cond.Wait(m_sleep_mtx, 10, 0);
+ m_sleep_mtx.Unlock();
+ m_sleeping = FALSE;
+
+ printf("Waking up ...\n");
+ if (!ret)
+ m_stop_thrd = TRUE;
+}
+
+bool wxUssSound::DoInput(wxSndBuffer *buf)
+{
+ wxUint32 bufsize;
+ wxSoundCodec *codec = buf->GetFormat().GetCodec();
+
+ m_sndbuf->ResetBuffer();
+ codec->SetInStream(m_sndbuf);
+ codec->InitIO(m_ussformat);
+
+ bufsize = codec->Available();
+ if (bufsize > m_max_bufsize)
+ bufsize = m_max_bufsize;
+
+ if (!bufsize) {
+ buf->Clear(wxSND_BUFLOCKED | wxSND_BUFREADY);
+ return false;
+ }
+ read(m_fd, m_sndbuf, bufsize);
+ codec->Encode();
+
+ return true;
+}
+
+bool wxUssSound::DoOutput(wxSndBuffer *buf)
+{
+ wxSoundCodec *codec = buf->GetCurrentCodec();
+
+ m_sndbuf->ResetBuffer();
+ codec->SetOutStream(m_sndbuf);
+ codec->InitIO(m_ussformat);
+
+ if (!codec->Available()) {
+ buf->Clear(wxSND_BUFLOCKED | wxSND_BUFREADY);
+ return false;
+ }
+ codec->Decode();
+ write(m_fd, m_sndbuf, m_sndbuf->GetIntPosition());
+
+ // Well ... it's not accurate ! :-|
+ buf->OnBufferOutFinished();
+
+ return true;
+}
+
+void *wxUssSound::Entry()
+{
+ wxNode *node;
+ wxSndBuffer *buf;
+
+ while (!m_stop_thrd) {
+ node = m_buffers.First();
+ if (!node) {
+ USS_Sleep();
+ continue;
+ }
+ buf = (wxSndBuffer *)node->Data();
+ if (!OnSetupDriver(*buf, buf->GetMode()))
+ continue;
+
+ buf->HardLock();
+ if (buf->IsSet(wxSND_BUFSTOP)) {
+ buf->HardUnlock();
+ delete node;
+ continue;
+ }
+ switch(m_mode) {
+ case wxSND_INPUT:
+ if (!DoInput(buf))
+ delete node;
+ break;
+ case wxSND_OUTPUT:
+ if (!DoOutput(buf))
+ delete node;
+ break;
+ case wxSND_DUPLEX:
+ case wxSND_OTHER_IO:
+ break;
+ }
+ buf->HardUnlock();
+ }
+ return NULL;
+}
+
+bool wxUssSound::OnSetupDriver(wxSndBuffer& buf, wxSndMode WXUNUSED(mode))
+{
+ wxSoundDataFormat format;
+ wxSoundCodec *codec;
+
+ codec = buf.GetFormat().GetCodec();
+ format = codec->GetPreferredFormat(WXSOUND_PCM);
+
+ if ((format.GetSampleRate() != m_srate) ||
+ (format.GetBps() != m_bps) ||
+ (format.GetStereo() != m_stereo)) {
+
+ if (!SetupSound(format.GetSampleRate(), format.GetBps(),
+ format.GetStereo())) {
+ m_buffers.DeleteObject(&buf);
+ buf.Clear(wxSND_BUFLOCKED | wxSND_BUFREADY);
+ buf.SetError(wxSND_CANTSET);
+ return false;
+ }
+ m_mode = wxSND_OTHER_IO;
+ }
+
+ if (buf.GetMode() != m_mode) {
+ m_mode = buf.GetMode();
+ return false;
+ }
+
+ return true;
+}
+
+wxUint32 wxUssSound::GetNbFragments()
+{
+ struct audio_buf_info frag_info;
+
+ ioctl(m_fd, SNDCTL_DSP_GETOSPACE, &frag_info);
+
+ return frag_info.fragstotal;
+}
+
+wxUint32 wxUssSound::GetFragmentSize()
+{
+ return m_max_bufsize;
+}
+
+bool wxUssSound::SetupSound(wxUint16 srate, wxUint8 bps, bool stereo)
+{
+ int tmp;
+ unsigned long tmp_ul;
+
+ if (m_fd != -1) {
+ delete m_sndbuf;
+ fsync(m_fd);
+ close(m_fd);
+ }
+
+ m_fd = open("/dev/dsp", O_RDWR);
+
+ tmp = stereo;
+ if (ioctl(m_fd, SNDCTL_DSP_STEREO, &tmp) < 0)
+ return FALSE;
+ m_stereo = tmp;
+
+ tmp_ul = srate;
+ if (ioctl(m_fd, SNDCTL_DSP_SPEED, &tmp_ul) < 0)
+ return FALSE;
+ m_srate = tmp_ul;
+
+ tmp = bps;
+ if (ioctl(m_fd, SNDCTL_DSP_SAMPLESIZE, &tmp) < 0)
+ return FALSE;
+ m_bps = tmp;
+
+ ioctl(m_fd, SNDCTL_DSP_GETBLKSIZE, &tmp);
+ m_max_bufsize = tmp;
+ m_sndbuf->SetBufferIO(m_max_bufsize);
+
+ m_ussformat.SetBps(m_bps);
+ m_ussformat.SetChannels((m_stereo) ? 2 : 1);
+ m_ussformat.SetSampleRate(m_srate);
+
+ return TRUE;
+}
--- /dev/null
+// /////////////////////////////////////////////////////////////////////////////
+// Name: snduss.h
+// Purpose: wxMMedia
+// Author: Guilhem Lavaux
+// Created: 1997
+// Updated: 1998
+// Copyright: (C) 1997, 1998, Guilhem Lavaux
+// License: wxWindows license
+// /////////////////////////////////////////////////////////////////////////////
+/* Real -*- C++ -*- */
+#ifndef __SND_ussnd_H__
+#define __SND_ussnd_H__
+#ifdef __GNUG__
+#pragma interface
+#endif
+
+#include <wx/thread.h>
+#include "sndsnd.h"
+#include "sndfrag.h"
+#include "sndfrmt.h"
+
+///
+class wxUssSound : public wxSound, public wxThread {
+ ///
+ DECLARE_DYNAMIC_CLASS(wxUssSound)
+public:
+ wxUssSound();
+ ///
+ virtual ~wxUssSound();
+
+ ///
+ void OnNeedBuffer();
+protected:
+ ///
+ virtual bool Wakeup(wxSndBuffer& buf);
+ ///
+ void USS_Sleep();
+ ///
+ virtual void StopBuffer(wxSndBuffer& buf);
+
+ ///
+ bool OnSetupDriver(wxSndBuffer& buf, wxSndMode mode);
+
+ ///
+ bool SetupSound(wxUint16 srate, wxUint8 bps, bool stereo);
+
+ ///
+ wxUint32 GetNbFragments();
+ ///
+ wxUint32 GetFragmentSize();
+ ///
+ void ThreadEntryPoint();
+
+protected:
+ ///
+ wxUint16 m_srate;
+ ///
+ wxUint8 m_bps;
+ ///
+ wxUint32 m_max_bufsize;
+ ///
+ bool m_stereo;
+ ///
+ wxSndMode m_mode;
+ ///
+ wxSoundDataFormat m_ussformat;
+ ///
+ wxStreamBuffer *m_sndbuf;
+ ///
+ bool m_stop_thrd, m_sleeping;
+ /// Sound file descriptor.
+ int m_fd;
+ /// Thread sleep mutexes and conditions.
+ wxMutex m_sleep_mtx;
+ wxCondition m_sleep_cond;
+
+ ///
+ bool DoInput(wxSndBuffer *buf);
+ bool DoOutput(wxSndBuffer *buf);
+
+ ///
+ virtual void *Entry();
+};
+
+#endif
--- /dev/null
+////////////////////////////////////////////////////////////////////////////////
+// Name: sndwav.cpp
+// Purpose: wxMMedia
+// Author: Guilhem Lavaux
+// Created: 1997
+// Updated: February 1998
+// Copyright: (C) 1997, 1998, Guilhem Lavaux
+// License: wxWindows license
+////////////////////////////////////////////////////////////////////////////////
+#ifdef __GNUG__
+#pragma implementation "sndwav.h"
+#endif
+
+#ifdef WX_PRECOMP
+#include "wx_prec.h"
+#else
+#include "wx/wx.h"
+#endif
+#include "sndwav.h"
+#include "sndfrmt.h"
+#include "sndpcm.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+wxSndWavCodec::wxSndWavCodec()
+ : wxSndFileCodec(), riff_codec()
+{
+ m_sndtime.hours = -1;
+}
+
+wxSndWavCodec::wxSndWavCodec(wxOutputStream& s, bool seekable)
+ : wxSndFileCodec(s, seekable)
+{
+ if (!seekable)
+ CacheIO();
+ riff_codec = wxRiffCodec(*m_ostream);
+ m_sndtime.hours = -1;
+}
+
+wxSndWavCodec::wxSndWavCodec(wxInputStream& s, bool preload, bool seekable)
+ : wxSndFileCodec(s, preload, seekable)
+{
+ if (!seekable)
+ CacheIO();
+
+ riff_codec = wxRiffCodec(*m_istream);
+ m_sndtime.hours = -1;
+}
+
+wxSndWavCodec::wxSndWavCodec(const wxString& fname)
+ : wxSndFileCodec(fname)
+{
+ riff_codec = wxRiffCodec(*m_istream);
+ m_sndtime.hours = -1;
+}
+
+wxUint32 wxSndWavCodec::PrepareToPlay()
+{
+ if (!riff_codec.RiffReset(RIFF_READ))
+ return 0;
+
+ if (!riff_codec.FindChunk("RIFF", TRUE)) {
+ wxSndFileCodec::m_mmerror = wxMMFILE_INVALID;
+ return 0;
+ }
+
+ char tmp_buf[5];
+ riff_codec.ReadData(tmp_buf, 4);
+ tmp_buf[4] = 0;
+ if (wxString("WAVE") != tmp_buf) {
+ wxSndFileCodec::m_mmerror = wxMMFILE_INVALID;
+ return 0;
+ }
+ if (!riff_codec.FindChunk("fmt ", TRUE))
+ return 0;
+
+ riff_codec.Read16(wav_hdr.format);
+ riff_codec.Read16(wav_hdr.channels);
+ riff_codec.Read32(wav_hdr.sample_fq);
+ riff_codec.Read32(wav_hdr.byte_p_sec);
+ riff_codec.Read16(wav_hdr.byte_p_spl);
+ riff_codec.Read16(wav_hdr.bits_p_spl);
+
+ if (!riff_codec.FindChunk("data"))
+ return 0;
+
+ m_sndformat.SetSampleRate(wav_hdr.sample_fq);
+ m_sndformat.SetBps(wav_hdr.bits_p_spl);
+ m_sndformat.SetChannels(wav_hdr.channels);
+ m_sndmode = wxSND_OUTPUT;
+ ChangeCodec(wav_hdr.format);
+
+ m_sndformat.SetSampleRate(wav_hdr.sample_fq);
+ m_sndformat.SetBps(wav_hdr.bits_p_spl);
+ m_sndformat.SetChannels(wav_hdr.channels);
+
+ if (wav_hdr.format == WXSOUND_PCM) {
+ m_sndformat.SetSign(wxSND_SAMPLE_SIGNED);
+ m_sndformat.SetByteOrder(wxSND_SAMPLE_LE);
+ }
+
+ wxUint32 sec1 = riff_codec.GetChunkLength() / wav_hdr.byte_p_sec,
+ sec2 = sec1 % 3600;
+
+ m_sndtime.hours = sec1 / 3600;
+ m_sndtime.minutes = sec2 / 60;
+ m_sndtime.seconds = sec2 % 60;
+
+ wxSndFileCodec::m_mmerror = wxMMFILE_NOERROR;
+
+ return riff_codec.GetChunkLength();
+}
+
+wxSndWavCodec::~wxSndWavCodec()
+{
+}
+
+bool wxSndWavCodec::OnNeedData(char *buf, wxUint32 size)
+{
+ return riff_codec.ReadData(buf, size);
+}
+
+bool wxSndWavCodec::OnWriteData(char *buf, wxUint32 size)
+{
+ return riff_codec.WriteData(buf, size);
+}
+
+bool wxSndWavCodec::PrepareToRecord(wxUint32 m_fsize)
+{
+ wxUint32 total_size;
+
+ if (!riff_codec.RiffReset(RIFF_WRITE))
+ return FALSE;
+
+ total_size = 16 + sizeof(wav_hdr) + m_fsize;
+
+ if (!riff_codec.CreateChunk("RIFF", total_size))
+ return FALSE;
+ riff_codec.WriteData("WAVE", 4);
+ if (!riff_codec.CreateChunk("fmt ", sizeof(wav_hdr)))
+ return FALSE;
+
+ wav_hdr.format = 1; // PCM_WAV_FORMAT
+ wav_hdr.channels = m_sndformat.GetChannels();
+ wav_hdr.sample_fq = m_sndformat.GetSampleRate();
+ wav_hdr.byte_p_spl = (m_sndformat.GetBps() / 8) * wav_hdr.channels;
+ wav_hdr.byte_p_sec = m_sndformat.GetCodec()->GetByteRate();
+ wav_hdr.bits_p_spl = m_sndformat.GetBps();
+ ChangeCodec(WXSOUND_PCM);
+
+ if (wav_hdr.format == WXSOUND_PCM) {
+ m_sndformat.SetSign(wxSND_SAMPLE_SIGNED);
+ m_sndformat.SetByteOrder(wxSND_SAMPLE_LE);
+ }
+
+ riff_codec.Write16(wav_hdr.format);
+ riff_codec.Write16(wav_hdr.channels);
+ riff_codec.Write32(wav_hdr.sample_fq);
+ riff_codec.Write32(wav_hdr.byte_p_sec);
+ riff_codec.Write16(wav_hdr.byte_p_spl);
+ riff_codec.Write16(wav_hdr.bits_p_spl);
+
+ if (!riff_codec.CreateChunk("data", m_fsize))
+ return FALSE;
+ return TRUE;
+}
+
+void wxSndWavCodec::SetFile(wxInputStream& s, bool preload, bool seekable)
+{
+ wxMMediaFile::SetFile(s, preload, seekable);
+ if (!seekable)
+ CacheIO();
+
+ riff_codec.SetFile((seekable) ? s : *m_istream);
+}
+
+void wxSndWavCodec::SetFile(wxOutputStream& s, bool seekable)
+{
+ wxMMediaFile::SetFile(s, seekable);
+ if (!seekable)
+ CacheIO();
+
+ riff_codec.SetFile((seekable) ? s : *m_ostream);
+}
--- /dev/null
+// /////////////////////////////////////////////////////////////////////////////
+// Name: sndwav.h
+// Purpose: wxMMedia
+// Author: Guilhem Lavaux
+// Created: 1997
+// Updated: February 1998
+// Copyright: (C) 1997, 1998, Guilhem Lavaux
+// License: wxWindows license
+// /////////////////////////////////////////////////////////////////////////////
+/* Real -*- C++ -*- */
+#ifndef __SND_wav_H__
+#define __SND_wav_H__
+#ifdef __GNUG__
+#pragma interface
+#endif
+
+#include "mmriff.h"
+#include "sndfile.h"
+
+///
+class wxSndWavCodec : public wxSndFileCodec {
+ ///
+ DECLARE_DYNAMIC_CLASS(wxSndWavCodec)
+public:
+ ///
+ wxSndWavCodec();
+ ///
+ wxSndWavCodec(wxInputStream& s, bool preload = FALSE, bool seekable = TRUE);
+ ///
+ wxSndWavCodec(wxOutputStream& s, bool seekable = TRUE);
+ ///
+ wxSndWavCodec(const wxString& fname);
+ ///
+ virtual ~wxSndWavCodec();
+
+ virtual bool OnNeedData(char *buf, wxUint32 size);
+ virtual bool OnWriteData(char *buf, wxUint32 size);
+
+ virtual wxUint32 PrepareToPlay();
+ virtual bool PrepareToRecord(wxUint32 file_size);
+
+ virtual void SetFile(wxInputStream& s, bool preload = FALSE,
+ bool seekable = FALSE);
+ virtual void SetFile(wxOutputStream& s,
+ bool seekable = FALSE);
+
+protected:
+ wxRiffCodec riff_codec;
+ struct {
+ wxUint16 format;
+ wxUint16 channels;
+ wxUint32 sample_fq;
+ wxUint32 byte_p_sec;
+ wxUint16 byte_p_spl;
+ wxUint16 bits_p_spl;
+ } wav_hdr;
+};
+
+#endif
--- /dev/null
+////////////////////////////////////////////////////////////////////////////////
+// Name: sndwin.cpp
+// Purpose: wxMMedia
+// Author: Guilhem Lavaux
+// Created: 1997
+// Updated: 1998
+// Copyright: (C) 1997, 1998, Guilhem Lavaux
+// License: wxWindows license
+////////////////////////////////////////////////////////////////////////////////
+#ifdef WX_PRECOMP
+#include "wx/wxprec.h"
+#else
+#include "wx/wx.h"
+#endif
+#include <wx/msw/private.h>
+
+#define WXMMEDIA_INTERNAL
+#include "sndwin.h"
+
+#define MMD_WIN_IO_BSIZE 16384
+
+#include <mmsystem.h>
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+wxSndWinFragment::wxSndWinFragment(wxSound& io_drv)
+ : wxFragmentBuffer(io_drv)
+{
+}
+
+wxSndWinFragment::~wxSndWinFragment(void)
+{
+}
+
+void wxSndWinFragment::AllocIOBuffer(void)
+{
+ wxWinSound *w_snd = (wxWinSound *) m_iodrv;
+ wxUint8 i;
+
+ m_maxoq = 5;
+ m_maxiq = 5;
+
+ m_lstoptrs = m_optrs = new wxFragBufPtr[m_maxoq];
+ m_lstiptrs = m_iptrs = new wxFragBufPtr[m_maxiq];
+
+ for (i=0;i<m_maxoq;i++) {
+ m_lstoptrs[i].size = MMD_WIN_IO_BSIZE;
+ m_lstoptrs[i].ptr = 0;
+ m_lstoptrs[i].buffers = new wxList();
+ m_lstoptrs[i].state = wxBUFFER_FREE;
+
+ w_snd->PrepareHeader(m_lstoptrs[i], wxSND_OUTPUT);
+ }
+
+ for (i=0;i<m_maxiq;i++) {
+ m_lstiptrs[i].size = MMD_WIN_IO_BSIZE;
+ m_lstiptrs[i].ptr = 0;
+ m_lstiptrs[i].buffers = new wxList();
+ m_lstiptrs[i].state = wxBUFFER_FREE;
+
+ w_snd->PrepareHeader(m_lstiptrs[i], wxSND_INPUT);
+ }
+}
+
+void wxSndWinFragment::FreeIOBuffer(void)
+{
+ wxWinSound *w_snd = (wxWinSound *)m_iodrv;
+ wxUint8 i;
+
+ if (!m_lstoptrs && !m_lstiptrs)
+ return;
+
+ for (i=0;i<m_maxoq;i++) {
+ w_snd->UnprepareHeader(m_lstoptrs[i], wxSND_OUTPUT);
+ delete m_lstoptrs[i].buffers;
+ }
+
+ for (i=0;i<m_maxiq;i++) {
+ w_snd->UnprepareHeader(m_lstiptrs[i], wxSND_INPUT);
+ delete m_lstiptrs[i].buffers;
+ }
+
+ delete[] m_lstoptrs;
+ delete[] m_lstiptrs;
+
+ m_lstoptrs = m_lstiptrs = NULL;
+ m_maxoq = m_maxiq = 0;
+}
+
+void wxSndWinFragment::WaitForAll()
+{
+ bool buf_busy = TRUE;
+ int i;
+
+ m_dontq = TRUE;
+
+ while (buf_busy) {
+ buf_busy = FALSE;
+
+ for (i=0;i<m_maxoq;i++) {
+ if (m_lstoptrs[i].state == wxBUFFER_FFILLED) {
+ buf_busy = TRUE;
+ break;
+ }
+ }
+ wxYield();
+ }
+
+ m_dontq = FALSE;
+ FreeBufToFree(TRUE);
+}
+
+bool wxSndWinFragment::OnBufferFilled(wxFragBufPtr *ptr, wxSndMode mode)
+{
+ wxSndWinInfo *info = (wxSndWinInfo *)ptr->user_data;
+ wxWinSound *w_snd = (wxWinSound *)m_iodrv;
+ MMRESULT result;
+
+ switch (mode) {
+ case wxSND_INPUT:
+ result = waveInAddBuffer(w_snd->internal->devin_id, info->hdr,
+ sizeof(WAVEHDR));
+ break;
+ case wxSND_OUTPUT:
+ result = waveOutWrite(w_snd->internal->devout_id, info->hdr,
+ sizeof(WAVEHDR));
+ printf("WINOUT: result=%d\n", result);
+ break;
+ }
+ return TRUE;
+}
+
+wxWinSound::wxWinSound(void)
+ : wxSound(),
+ fragments(*this)
+{
+ internal = new wxWinSoundInternal;
+ internal->devout_id = 0;
+ internal->devin_id = 0;
+ internal->sndWin = 0;
+
+ wout_opened = FALSE;
+ win_opened = FALSE;
+ curr_o_srate = (wxUint32)-1;
+ curr_o_bps = (wxUint8)-1;
+ curr_o_stereo = (bool)-1;
+ curr_i_srate = (wxUint32)-1;
+ curr_i_bps = (wxUint8)-1;
+ curr_i_stereo = (bool)-1;
+}
+
+wxWinSound::~wxWinSound(void)
+{
+ int i;
+
+ fragments.WaitForAll();
+
+ if (wout_opened)
+ waveOutReset(internal->devout_id);
+ if (win_opened)
+ waveInReset(internal->devout_id);
+
+ fragments.FreeIOBuffer();
+
+ if (wout_opened)
+ waveOutClose(internal->devout_id);
+ if (win_opened)
+ waveInClose(internal->devin_id);
+
+ if (internal->sndWin)
+ ::DestroyWindow(internal->sndWin);
+
+ delete internal;
+}
+
+bool wxWinSound::Wakeup(wxSndBuffer& buf)
+{
+ if (!Reopen(buf, FALSE)) {
+ buf.Clear(wxSND_BUFLOCKED);
+ return FALSE;
+ }
+
+ fragments.OnBufferFinished(NULL);
+ return TRUE;
+}
+
+void wxWinSound::PrepareHeader(wxFragmentBuffer::wxFragBufPtr& frag,
+ wxSndMode mode)
+{
+ wxSndWinInfo *info;
+ WAVEHDR *hdr;
+
+ if ((mode == wxSND_INPUT && !win_opened) ||
+ (mode == wxSND_OUTPUT && !wout_opened))
+ return;
+
+ info = new wxSndWinInfo;
+
+ info->h_data = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, frag.size);
+ info->h_hdr = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, sizeof(WAVEHDR));
+
+ info->data = (char *)GlobalLock(info->h_data);
+ hdr = info->hdr = (WAVEHDR *)GlobalLock(info->h_hdr);
+
+ memset(hdr, 0, sizeof(*hdr));
+ hdr->lpData = info->data;
+ hdr->dwBufferLength = frag.size;
+ hdr->dwUser = (DWORD)&frag;
+ hdr->dwFlags = WHDR_DONE;
+
+ if (mode == wxSND_INPUT) {
+ MMRESULT result = waveInPrepareHeader(internal->devin_id, hdr,
+ sizeof(WAVEHDR));
+
+ printf("prepareIn = %d\n", result);
+ if (result != MMSYSERR_NOERROR)
+ wxExit();
+ } else {
+ MMRESULT result = waveOutPrepareHeader(internal->devout_id, hdr,
+ sizeof(WAVEHDR));
+ printf("prepareOut = %d\n", result);
+ if (result != MMSYSERR_NOERROR)
+ wxExit();
+ }
+
+ frag.user_data = (char *)info;
+ frag.data = info->data;
+}
+
+void wxWinSound::UnprepareHeader(wxFragmentBuffer::wxFragBufPtr& frag,
+ wxSndMode mode)
+{
+ wxSndWinInfo *info = (wxSndWinInfo *)frag.user_data;
+
+ if ((mode == wxSND_INPUT && !win_opened) ||
+ (mode == wxSND_OUTPUT && !wout_opened))
+ return;
+
+ MMRESULT result;
+
+ if (mode == wxSND_INPUT) {
+ result = waveInUnprepareHeader(internal->devin_id, info->hdr, sizeof(*info->hdr));
+ } else {
+ result = waveOutUnprepareHeader(internal->devout_id, info->hdr, sizeof(*info->hdr));
+ }
+
+ printf("unprepare = %d\n", result);
+
+ GlobalUnlock(info->h_hdr);
+ GlobalUnlock(info->h_data);
+
+ GlobalFree(info->h_hdr);
+ GlobalFree(info->h_data);
+
+ delete info;
+}
+
+extern char wxCanvasClassName[];
+
+LRESULT APIENTRY _EXPORT wxSoundHandlerWndProc(HWND hWnd, UINT message,
+ WPARAM wParam, LPARAM lParam)
+{
+ switch (message) {
+ case MM_WOM_DONE: {
+ wxWinSound *snd_drv = (wxWinSound *)GetWindowLong(hWnd, GWL_USERDATA);
+ WAVEHDR *hdr = (WAVEHDR *)lParam;
+ wxFragmentBuffer::wxFragBufPtr *buf =
+ (wxFragmentBuffer::wxFragBufPtr *)hdr->dwUser;
+
+ // To be sure ...
+ hdr->dwFlags |= WHDR_DONE;
+
+ snd_drv->fragments.OnBufferFinished(buf);
+ break;
+ }
+ case MM_WOM_OPEN:
+ printf("wave Open ack\n");
+ break;
+ case MM_WOM_CLOSE:
+ printf("wave Close ack\n");
+ break;
+ default:
+ return DefWindowProc(hWnd, message, wParam, lParam);
+ }
+ return (LRESULT)0;
+}
+
+void wxWinSound::StopBuffer(wxSndBuffer& buf)
+{
+ buf.HardLock();
+ buf.Set(wxSND_BUFSTOP);
+ fragments.AbortBuffer(buf);
+ buf.HardUnlock();
+
+ while (buf.IsSet(wxSND_BUFSTOP))
+ wxYield();
+}
+
+bool wxWinSound::Reopen(wxSndBuffer& buf, bool force)
+{
+ WAVEFORMATEX wformat;
+
+ if ((buf.GetSampleRate() != curr_o_srate) ||
+ (buf.GetBps() != curr_o_bps) ||
+ (buf.GetStereo() != curr_o_stereo) ||
+ (buf.GetMode() != curr_mode))
+ force = TRUE;
+
+ if (force) {
+ wxUint32 *curr_srate =
+ (buf.GetMode() == wxSND_OUTPUT) ? &curr_o_srate : &curr_i_srate;
+ wxUint8 *curr_bps =
+ (buf.GetMode() == wxSND_OUTPUT) ? &curr_o_bps : &curr_i_bps;
+ bool *curr_stereo =
+ (buf.GetMode() == wxSND_OUTPUT) ? &curr_o_stereo : &curr_i_stereo;
+
+ fragments.WaitForAll();
+ fragments.FreeIOBuffer();
+
+ if (!internal->sndWin) {
+ FARPROC proc = MakeProcInstance((FARPROC)wxSoundHandlerWndProc, wxGetInstance());
+
+ internal->sndWin = ::CreateWindow(wxCanvasClassName, NULL, 0,
+ 0, 0, 0, 0, NULL, (HMENU) NULL,
+ wxGetInstance(), 0);
+
+ ::SetWindowLong(internal->sndWin, GWL_WNDPROC,
+ (LONG)proc);
+ ::SetWindowLong(internal->sndWin, GWL_USERDATA, (LONG) this);
+ }
+
+ if (wout_opened) {
+ waveOutClose(internal->devout_id);
+ wout_opened = FALSE;
+ }
+ if (win_opened) {
+ waveInClose(internal->devin_id);
+ win_opened = FALSE;
+ }
+
+ *curr_srate = buf.GetSampleRate();
+ *curr_bps = buf.GetBps();
+ *curr_stereo = buf.GetStereo();
+ wformat.wFormatTag = WAVE_FORMAT_PCM;
+ wformat.nChannels = curr_o_stereo+1;
+
+ wformat.nSamplesPerSec = curr_o_srate;
+ wformat.nBlockAlign = curr_o_bps / 8 * wformat.nChannels;
+ wformat.nAvgBytesPerSec =
+ wformat.nSamplesPerSec * wformat.nBlockAlign;
+ wformat.wBitsPerSample = curr_o_bps;
+ wformat.cbSize = 0;
+
+ if (buf.GetMode() == wxSND_OUTPUT) {
+ MMRESULT result = waveOutOpen(&internal->devout_id,
+ WAVE_MAPPER, &wformat,
+ (DWORD)internal->sndWin, (DWORD)this,
+ CALLBACK_WINDOW);
+ if (result != MMSYSERR_NOERROR)
+ return FALSE;
+ internal->devin_id = 0;
+ wout_opened = TRUE;
+ curr_mode = wxSND_OUTPUT;
+
+ fragments.AllocIOBuffer();
+ }
+ else {
+ MMRESULT result = waveInOpen(&internal->devin_id,
+ WAVE_MAPPER, &wformat,
+ (DWORD)internal->sndWin, (DWORD)this,
+ CALLBACK_FUNCTION);
+ if (result != MMSYSERR_NOERROR)
+ return FALSE;
+ internal->devout_id = 0;
+ win_opened = TRUE;
+ curr_mode = wxSND_INPUT;
+
+ fragments.AllocIOBuffer();
+ }
+ }
+ return TRUE;
+}
--- /dev/null
+// /////////////////////////////////////////////////////////////////////////////
+// Name: sndwin.h
+// Purpose: wxMMedia
+// Author: Guilhem Lavaux
+// Created: 1997
+// Updated: 1998
+// Copyright: (C) 1997, 1998, Guilhem Lavaux
+// License: wxWindows license
+// /////////////////////////////////////////////////////////////////////////////
+/* Real -*- C++ -*- */
+#ifndef __SND_win_H__
+#define __SND_win_H__
+
+#include "sndsnd.h"
+#include "sndfrag.h"
+
+#ifdef WXMMEDIA_INTERNAL
+#include <wx/msw/private.h>
+#include <windows.h>
+#include <mmsystem.h>
+
+typedef struct wxWinSoundInternal {
+ HWAVEOUT devout_id;
+ HWAVEIN devin_id;
+ HWND sndWin;
+} wxWinSoundInternal;
+
+typedef struct wxSndWinInfo {
+ HGLOBAL h_data, h_hdr;
+
+ char *data;
+ WAVEHDR *hdr;
+} wxSndWinInfo;
+
+#endif
+
+/** Sound buffer fragmenter: windows specific implementation
+ * @author Guilhem Lavaux
+ */
+class wxSndWinFragment : public wxFragmentBuffer {
+public:
+ wxSndWinFragment(wxSound& io_drv);
+ virtual ~wxSndWinFragment(void);
+
+ virtual void AllocIOBuffer(void);
+ virtual void FreeIOBuffer(void);
+
+ virtual bool OnBufferFilled(wxFragBufPtr *ptr, wxSndMode mode);
+
+ void WaitForAll();
+};
+
+///
+class wxWinSound : public wxSound {
+ ///
+ DECLARE_DYNAMIC_CLASS(wxWinSound)
+protected:
+ struct wxWinSoundInternal *internal;
+
+ ///
+ bool wout_opened, win_opened;
+ ///
+ wxUint32 curr_o_srate, curr_i_srate;
+ ///
+ wxUint8 curr_o_bps, curr_i_bps;
+ ///
+ bool curr_o_stereo, curr_i_stereo;
+ ///
+ wxSndMode curr_mode;
+
+ ///
+ wxSndWinFragment fragments;
+
+#ifdef WXMMEDIA_INTERNAL
+ ///
+ friend LRESULT APIENTRY _EXPORT wxSoundHandlerWndProc(HWND win,
+ UINT message,
+ WPARAM wParam, LPARAM lParam);
+
+#endif
+
+public:
+ ///
+ wxWinSound(void);
+ ///
+ virtual ~wxWinSound(void);
+
+ ///
+ void OnNeedBuffer(wxSndMode mode);
+ ///
+ void StopBuffer(wxSndBuffer& buf);
+protected:
+ ///
+ virtual bool Wakeup(wxSndBuffer& buf);
+
+ ///
+ bool Reopen(wxSndBuffer& buf, bool force);
+
+ ///
+ friend class wxSndWinFragment;
+
+ ///
+ void PrepareHeader(wxFragmentBuffer::wxFragBufPtr& frag, wxSndMode mode);
+ ///
+ void UnprepareHeader(wxFragmentBuffer::wxFragBufPtr& frag, wxSndMode mode);
+};
+
+#endif
--- /dev/null
+static unsigned char ulaw_dsp[] = {
+ 3, 7, 11, 15, 19, 23, 27, 31,
+ 35, 39, 43, 47, 51, 55, 59, 63,
+ 66, 68, 70, 72, 74, 76, 78, 80,
+ 82, 84, 86, 88, 90, 92, 94, 96,
+ 98, 99, 100, 101, 102, 103, 104, 105,
+ 106, 107, 108, 109, 110, 111, 112, 113,
+ 113, 114, 114, 115, 115, 116, 116, 117,
+ 117, 118, 118, 119, 119, 120, 120, 121,
+ 121, 121, 122, 122, 122, 122, 123, 123,
+ 123, 123, 124, 124, 124, 124, 125, 125,
+ 125, 125, 125, 125, 126, 126, 126, 126,
+ 126, 126, 126, 126, 127, 127, 127, 127,
+ 127, 127, 127, 127, 127, 127, 127, 127,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 253, 249, 245, 241, 237, 233, 229, 225,
+ 221, 217, 213, 209, 205, 201, 197, 193,
+ 190, 188, 186, 184, 182, 180, 178, 176,
+ 174, 172, 170, 168, 166, 164, 162, 160,
+ 158, 157, 156, 155, 154, 153, 152, 151,
+ 150, 149, 148, 147, 146, 145, 144, 143,
+ 143, 142, 142, 141, 141, 140, 140, 139,
+ 139, 138, 138, 137, 137, 136, 136, 135,
+ 135, 135, 134, 134, 134, 134, 133, 133,
+ 133, 133, 132, 132, 132, 132, 131, 131,
+ 131, 131, 131, 131, 130, 130, 130, 130,
+ 130, 130, 130, 130, 129, 129, 129, 129,
+ 129, 129, 129, 129, 129, 129, 129, 129,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128,
+};
+
+static unsigned char dsp_ulaw[] = {
+ 0, 0, 0, 0, 0, 1, 1, 1,
+ 1, 2, 2, 2, 2, 3, 3, 3,
+ 3, 4, 4, 4, 4, 5, 5, 5,
+ 5, 6, 6, 6, 6, 7, 7, 7,
+ 7, 8, 8, 8, 8, 9, 9, 9,
+ 9, 10, 10, 10, 10, 11, 11, 11,
+ 11, 12, 12, 12, 12, 13, 13, 13,
+ 13, 14, 14, 14, 14, 15, 15, 15,
+ 15, 16, 16, 17, 17, 18, 18, 19,
+ 19, 20, 20, 21, 21, 22, 22, 23,
+ 23, 24, 24, 25, 25, 26, 26, 27,
+ 27, 28, 28, 29, 29, 30, 30, 31,
+ 31, 32, 33, 34, 35, 36, 37, 38,
+ 39, 40, 41, 42, 43, 44, 45, 46,
+ 47, 49, 51, 53, 55, 57, 59, 61,
+ 63, 66, 70, 74, 78, 84, 92, 104,
+ 254, 231, 219, 211, 205, 201, 197, 193,
+ 190, 188, 186, 184, 182, 180, 178, 176,
+ 175, 174, 173, 172, 171, 170, 169, 168,
+ 167, 166, 165, 164, 163, 162, 161, 160,
+ 159, 159, 158, 158, 157, 157, 156, 156,
+ 155, 155, 154, 154, 153, 153, 152, 152,
+ 151, 151, 150, 150, 149, 149, 148, 148,
+ 147, 147, 146, 146, 145, 145, 144, 144,
+ 143, 143, 143, 143, 142, 142, 142, 142,
+ 141, 141, 141, 141, 140, 140, 140, 140,
+ 139, 139, 139, 139, 138, 138, 138, 138,
+ 137, 137, 137, 137, 136, 136, 136, 136,
+ 135, 135, 135, 135, 134, 134, 134, 134,
+ 133, 133, 133, 133, 132, 132, 132, 132,
+ 131, 131, 131, 131, 130, 130, 130, 130,
+ 129, 129, 129, 129, 128, 128, 128, 128,
+};
--- /dev/null
+////////////////////////////////////////////////////////////////////////////////
+// Name: vidbdrv.cpp
+// Purpose: wxMMedia
+// Author: Guilhem Lavaux
+// Created: 1997
+// Updated: 1998
+// Copyright: (C) 1997, 1998, Guilhem Lavaux
+// License: wxWindows license
+////////////////////////////////////////////////////////////////////////////////
+#ifdef __GNUG__
+#pragma implementation "vidbase.h"
+#endif
+#include <wx/fstream.h>
+#include "vidbase.h"
+#ifdef WX_PRECOMP
+#include "wx_prec.h"
+#else
+#include "wx/wx.h"
+#endif
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+wxVideoOutput::wxVideoOutput()
+ : wxWindow()
+{
+ dyn_size = TRUE;
+}
+
+wxVideoOutput::wxVideoOutput(wxWindow *parent, const wxWindowID id, const wxPoint& position,
+ const wxSize& size, const long style,
+ const wxString& name)
+ : wxWindow(parent, id, position, size, style, name)
+{
+ dyn_size = TRUE;
+}
+
+///
+wxVideoOutput::~wxVideoOutput()
+{
+}
+
+wxVideoBaseDriver::wxVideoBaseDriver()
+ : wxMMediaFile()
+{
+}
+
+wxVideoBaseDriver::wxVideoBaseDriver(wxInputStream& str, bool seekable)
+ : wxMMediaFile(str, FALSE, seekable)
+{
+}
+
+wxVideoBaseDriver::wxVideoBaseDriver(const wxString& fname)
+ : wxMMediaFile(fname)
+{
+}
+
+wxVideoBaseDriver::~wxVideoBaseDriver()
+{
+}
+
+bool wxVideoBaseDriver::AttachOutput(wxVideoOutput& output)
+{
+ video_output = &output;
+ return TRUE;
+}
+
+void wxVideoBaseDriver::DetachOutput()
+{
+ video_output = NULL;
+}
+
+// Use an external frame for video output
+
+wxFrame *wxVideoCreateFrame(wxVideoBaseDriver *vid_drv)
+{
+ wxFrame *frame = new wxFrame(NULL, -1, "Video Output", wxDefaultPosition, wxSize(100, 100));
+ wxVideoOutput *vid_out = new wxVideoOutput(frame, -1);
+
+ vid_out->DynamicSize(TRUE);
+ vid_drv->AttachOutput(*vid_out);
+ frame->Layout();
+ frame->Show(TRUE);
+
+ return frame;
+}
--- /dev/null
+// /////////////////////////////////////////////////////////////////////////////
+// Name: vidbase.h
+// Purpose: wxMMedia
+// Author: Guilhem Lavaux
+// Created: 1997
+// Updated: 1998
+// Copyright: (C) 1997, 1998, Guilhem Lavaux
+// CVS: $Id$
+// License: wxWindows license
+// /////////////////////////////////////////////////////////////////////////////
+/* Real -*- C++ -*- */
+#ifndef __VID_bdrv_H__
+#define __VID_bdrv_H__
+
+#ifdef __GNUG__
+#pragma interface
+#endif
+
+#include "mmtype.h"
+#include "mmfile.h"
+#include "wx/string.h"
+#include "wx/window.h"
+
+///
+typedef enum {
+ wxVIDEO_MSAVI,
+ wxVIDEO_MPEG,
+ wxVIDEO_QT,
+ wxVIDEO_GIF,
+ wxVIDEO_JMOV,
+ wxVIDEO_FLI,
+ wxVIDEO_IFF,
+ wxVIDEO_SGI,
+ wxVIDEO_MPEG2
+} ///
+ wxVideoType;
+
+///
+class wxVideoBaseDriver;
+class wxVideoOutput : public wxWindow {
+ ///
+ DECLARE_DYNAMIC_CLASS(wxVideoOutput)
+protected:
+ bool dyn_size;
+public:
+ ///
+ wxVideoOutput();
+ ///
+ wxVideoOutput(wxWindow *parent, const wxWindowID id,
+ const wxPoint& pos = wxDefaultPosition,
+ const wxSize& size = wxDefaultSize, const long style = 0,
+ const wxString& name = "video_output");
+ ///
+ virtual ~wxVideoOutput();
+
+ ///
+ bool DynamicSize() { return dyn_size; }
+ ///
+ void DynamicSize(bool dyn) { dyn_size = dyn; }
+};
+
+///
+class wxVideoBaseDriver : public wxObject, public wxMMediaFile {
+ ///
+ DECLARE_ABSTRACT_CLASS(wxVideoBaseDriver)
+protected:
+ wxVideoOutput *video_output;
+public:
+ friend class wxVideoOutput;
+
+ ///
+ wxVideoBaseDriver();
+ ///
+ wxVideoBaseDriver(wxInputStream& str, bool seekable = FALSE);
+ ///
+ wxVideoBaseDriver(const wxString& fname);
+ ///
+ virtual ~wxVideoBaseDriver();
+
+ ///
+ virtual bool Pause() = 0;
+ ///
+ virtual bool Resume() = 0;
+
+ ///
+ virtual bool SetVolume(wxUint8 vol) = 0;
+ ///
+ virtual bool Resize(wxUint16 w, wxUint16 h) = 0;
+
+ ///
+ virtual bool IsCapable(wxVideoType WXUNUSED(v_type)) { return FALSE; }
+
+ ///
+ virtual void OnFinished() {}
+
+ ///
+ virtual bool AttachOutput(wxVideoOutput& output);
+ ///
+ virtual void DetachOutput();
+};
+
+extern wxFrame *wxVideoCreateFrame(wxVideoBaseDriver *vid_drv);
+
+
+#endif
--- /dev/null
+////////////////////////////////////////////////////////////////////////////////
+// Name: vidwin.h
+// Purpose: wxMMedia
+// Author: Guilhem Lavaux
+// Created: February 1998
+// Updated:
+// Copyright: (C) 1998, Guilhem Lavaux
+// License: wxWindows license
+////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __GNUG__
+#pragma implementation "vidwin.h"
+#endif
+
+#if 0
+#include "wx/wxprec.h"
+#else
+#include "wx/wx.h"
+#endif
+
+#define WXMMEDIA_INTERNAL
+#include <windows.h>
+#include <mmsystem.h>
+#include <digitalv.h>
+#include "mmtype.h"
+#include "mmfile.h"
+#include "vidwin.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+wxVideoWindows::wxVideoWindows(void)
+{
+}
+
+wxVideoWindows::wxVideoWindows(wxInputStream& str, bool seekable)
+ : wxVideoBaseDriver(str, seekable)
+{
+ OpenFile(GetCurrentFile());
+}
+
+wxVideoWindows::wxVideoWindows(const char *fname)
+ : wxVideoBaseDriver(fname)
+{
+ OpenFile(fname);
+}
+
+wxVideoWindows::~wxVideoWindows(void)
+{
+ mciSendCommand(internal->dev_id, MCI_CLOSE, 0, 0);
+
+ if (internal)
+ delete internal;
+}
+
+void wxVideoWindows::OpenFile(const char *fname)
+{
+ MCI_DGV_OPEN_PARMS open_struct;
+ DWORD ret;
+
+ internal = new VIDW_Internal;
+
+ open_struct.lpstrDeviceType = "avivideo";
+ open_struct.lpstrElementName = (LPSTR)fname;
+ open_struct.hWndParent = 0;
+
+ ret = mciSendCommand(0, MCI_OPEN,
+ MCI_OPEN_ELEMENT|MCI_DGV_OPEN_PARENT|MCI_OPEN_TYPE|MCI_DGV_OPEN_32BIT,
+ (DWORD)(LPVOID)&open_struct);
+ internal->dev_id = open_struct.wDeviceID;
+}
+
+bool wxVideoWindows::Pause(void)
+{
+ return (mciSendCommand(internal->dev_id, MCI_PAUSE, 0, 0) == 0);
+}
+
+bool wxVideoWindows::Resume(void)
+{
+ return (mciSendCommand(internal->dev_id, MCI_PAUSE, 0, 0) == 0);
+}
+
+bool wxVideoWindows::SetVolume(wxUint8 vol)
+{
+ return TRUE;
+}
+
+bool wxVideoWindows::Resize(wxUint16 w, wxUint16 h)
+{
+ return TRUE;
+}
+
+bool wxVideoWindows::IsCapable(wxVideoType v_type)
+{
+ return (v_type == wxVIDEO_MSAVI);
+}
+
+bool wxVideoWindows::AttachOutput(wxVideoOutput& output)
+{
+ MCI_DGV_WINDOW_PARMS win_struct;
+
+ if (!wxVideoBaseDriver::AttachOutput(output))
+ return FALSE;
+
+ win_struct.hWnd = (HWND)output.GetHWND();
+ mciSendCommand(internal->dev_id, MCI_WINDOW,
+ MCI_DGV_WINDOW_HWND, (DWORD)(LPVOID)&win_struct);
+ return TRUE;
+}
+
+void wxVideoWindows::DetachOutput(void)
+{
+ MCI_DGV_WINDOW_PARMS win_struct;
+
+ wxVideoBaseDriver::DetachOutput();
+
+ win_struct.hWnd = 0;
+ mciSendCommand(internal->dev_id, MCI_WINDOW,
+ MCI_DGV_WINDOW_HWND, (DWORD)(LPVOID)&win_struct);
+}
+
+bool wxVideoWindows::StartPlay(void)
+{
+ return (mciSendCommand(internal->dev_id, MCI_PLAY, 0, NULL) == 0);
+}
+
+void wxVideoWindows::StopPlay(void)
+{
+ mciSendCommand(internal->dev_id, MCI_STOP, 0, NULL);
+}
--- /dev/null
+// /////////////////////////////////////////////////////////////////////////////
+// Name: vidwin.h
+// Purpose: wxMMedia
+// Author: Guilhem Lavaux
+// Created: February 1998
+// Updated:
+// Copyright: (C) 1998, Guilhem Lavaux
+// License: wxWindows license
+// /////////////////////////////////////////////////////////////////////////////
+/* Real -*- C++ -*- */
+#ifndef __VID_windows_H__
+#define __VID_windows_H__
+
+#ifdef __GNUG__
+#pragma interface
+#endif
+
+#include "mmtype.h"
+#include "mmfile.h"
+#ifdef WX_PRECOMP
+#include "wx/wxprec.h"
+#else
+#include "wx/wx.h"
+#endif
+#include "vidbase.h"
+
+#ifdef WXMMEDIA_INTERNAL
+#include <windows.h>
+#include <mmsystem.h>
+
+typedef struct VIDW_Internal {
+ MCIDEVICEID dev_id;
+} VIDW_Internal;
+#endif
+
+class wxVideoWindows : public wxVideoBaseDriver {
+ DECLARE_DYNAMIC_CLASS(wxVideoWindows)
+protected:
+ struct VIDW_Internal *internal;
+
+ void OpenFile(const char *fname);
+public:
+ wxVideoWindows(void);
+ wxVideoWindows(wxInputStream& str, bool seekable = FALSE);
+ wxVideoWindows(const char *fname);
+ virtual ~wxVideoWindows(void);
+
+ virtual bool StartPlay(void);
+ virtual void StopPlay(void);
+ virtual bool Pause(void);
+ virtual bool Resume(void);
+
+ virtual bool SetVolume(wxUint8 vol);
+ virtual bool Resize(wxUint16 w, wxUint16 h);
+
+ virtual bool IsCapable(wxVideoType v_type);
+
+ virtual bool AttachOutput(wxVideoOutput& output);
+ virtual void DetachOutput(void);
+};
+
+#endif
--- /dev/null
+////////////////////////////////////////////////////////////////////////////////
+// Name: vidxanm.cpp
+// Purpose: wxMMedia
+// Author: Guilhem Lavaux
+// Created: 1997
+// Updated: 1998
+// Copyright: (C) 1997, 1998, Guilhem Lavaux
+// License: wxWindows license
+////////////////////////////////////////////////////////////////////////////////
+#ifdef __GNUG__
+#pragma implementation "vidxanm.h"
+#endif
+#define WXMMEDIA_INTERNAL
+#ifdef __XT__
+#define Uses_XLib
+#define Uses_XtIntrinsic
+#endif
+#include "vidbase.h"
+#include "vidxanm.h"
+#ifdef WX_PRECOMP
+#include "wx_prec.h"
+#else
+#include "wx/wx.h"
+#endif
+#include <X11/Xlib.h>
+#include <X11/Intrinsic.h>
+#ifdef __WXGTK__
+#include <gdk/gdk.h>
+#include <gdk/gdkprivate.h>
+#endif
+
+wxVideoXANIM::wxVideoXANIM()
+ : wxVideoBaseDriver()
+{
+ internal = new wxXANIMinternal;
+ xanim_started = false;
+ paused = false;
+}
+
+wxVideoXANIM::wxVideoXANIM(wxInputStream& str)
+ : wxVideoBaseDriver(str, false)
+{
+ internal = new wxXANIMinternal;
+ xanim_started = false;
+ paused = false;
+}
+
+wxVideoXANIM::wxVideoXANIM(const wxString& fname)
+ : wxVideoBaseDriver(fname)
+{
+ internal = new wxXANIMinternal;
+ xanim_started = false;
+}
+
+wxVideoXANIM::~wxVideoXANIM()
+{
+ if (xanim_started)
+ StopPlay();
+ delete internal;
+}
+
+bool wxVideoXANIM::StartPlay()
+{
+ if (!paused && xanim_started)
+ return true;
+ if (!video_output)
+ wxVideoCreateFrame(this);
+
+ if (SendCommand(" ")) {
+ paused = false;
+ return true;
+ }
+ return false;
+}
+
+bool wxVideoXANIM::Pause()
+{
+ if (!paused && SendCommand(" ")) {
+ paused = TRUE;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool wxVideoXANIM::Resume()
+{
+ if (paused && SendCommand(" ")) {
+ paused = FALSE;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+void wxVideoXANIM::StopPlay()
+{
+ if (!xanim_started)
+ return;
+
+ SendCommand("q");
+
+ xanim_started = FALSE;
+ paused = FALSE;
+}
+
+bool wxVideoXANIM::SetVolume(wxUint8 vol)
+{
+ if (vol > 100)
+ vol = 100;
+
+ wxString str_vol("v%d", vol);
+ return SendCommand(str_vol.GetData());
+}
+
+bool wxVideoXANIM::Resize(wxUint16 WXUNUSED(w), wxUint16 WXUNUSED(h))
+{
+ // Not implemented
+ // Actually, I think that we just need to resize the output window ...
+ return FALSE;
+}
+
+bool wxVideoXANIM::IsCapable(wxVideoType v_type)
+{
+ if (v_type == wxVIDEO_MSAVI || v_type == wxVIDEO_MPEG ||
+ v_type == wxVIDEO_QT || v_type == wxVIDEO_GIF || v_type == wxVIDEO_JMOV ||
+ v_type == wxVIDEO_FLI || v_type == wxVIDEO_IFF || v_type == wxVIDEO_SGI)
+ return true;
+ else
+ return false;
+}
+
+bool wxVideoXANIM::AttachOutput(wxVideoOutput& out)
+{
+ if (!wxVideoBaseDriver::AttachOutput(out))
+ return false;
+
+ return RestartXANIM();
+}
+
+void wxVideoXANIM::DetachOutput()
+{
+ SendCommand("q");
+ xanim_started = false;
+ paused = false;
+
+ wxVideoBaseDriver::DetachOutput();
+}
+
+bool wxVideoXANIM::SendCommand(const char *command, char **ret,
+ wxUint32 *size)
+{
+ if (!xanim_started)
+ if (!RestartXANIM())
+ return false;
+
+ // Send a command to XAnim through X11 Property
+ XChangeProperty(internal->xanim_dpy, internal->xanim_window,
+ internal->xanim_atom,
+ XA_STRING, 8, PropModeReplace, (unsigned char *)command,
+ strlen(command));
+ XFlush(internal->xanim_dpy);
+ if (ret) {
+ int prop_format;
+ Atom prop_type;
+ unsigned long extra;
+
+ XGetWindowProperty(internal->xanim_dpy, internal->xanim_window,
+ internal->xanim_ret, 0, 16, True, AnyPropertyType,
+ &prop_type, &prop_format, (unsigned long *)size,
+ &extra, (unsigned char **)ret);
+ }
+ return true;
+}
+
+bool wxVideoXANIM::RestartXANIM()
+{
+ wxString xanim_command;
+ int ret;
+ Atom prop_type;
+ int prop_format;
+ unsigned long nitems;
+ unsigned long extra;
+ char prop[4];
+ bool xanim_chg_size;
+
+ if (!video_output || xanim_started || !GetCurrentFile())
+ return false;
+
+ // Check if we can change the size of the window dynamicly
+ xanim_chg_size = video_output->DynamicSize();
+ // Get current display
+#ifdef __XT__
+ internal->xanim_dpy = wxAPP_DISPLAY;
+#endif
+#ifdef __WXGTK__
+ internal->xanim_dpy = gdk_display;
+#endif
+ // Get the window id
+#ifdef __XT__
+ internal->xanim_window = XtWindow(video_output->FWidget());
+#else
+ internal->xanim_window =
+ ((GdkWindowPrivate *)video_output->m_widget->window)->xwindow;
+#endif
+ // Get the XANIM atom
+ internal->xanim_atom = XInternAtom(internal->xanim_dpy,
+ "XANIM_PROPERTY", False);
+
+ // Build the command
+ xanim_command.sprintf(__XANIM_COMMAND__ " +W%d +Wp +f +B -Zr +q +Zpe +Ae "
+ "+Av70 %s %s", internal->xanim_window,
+ (xanim_chg_size == true) ? "+Sr" : "",
+ (const char *)GetCurrentFile());
+ // Execute it
+ if (!wxExecute(xanim_command, false))
+ return false;
+
+ // Wait for XAnim to be ready
+ nitems = 0;
+ while (nitems == 0) {
+ ret = XGetWindowProperty(internal->xanim_dpy, internal->xanim_window,
+ internal->xanim_atom,
+ 0, 4, False, AnyPropertyType, &prop_type,
+ &prop_format, &nitems, &extra,
+ (unsigned char **)&prop);
+// wxYield();
+ }
+
+ xanim_started = true;
+
+ return true;
+}
--- /dev/null
+// /////////////////////////////////////////////////////////////////////////////
+// Name: vidxanm.h
+// Purpose: wxMMedia
+// Author: Guilhem Lavaux
+// Created: 1997
+// Updated: 1998
+// Copyright: (C) 1997, 1998, Guilhem Lavaux
+// License: wxWindows license
+// /////////////////////////////////////////////////////////////////////////////
+/* Real -*- C++ -*- */
+#ifndef __VID_xanim_H__
+#define __VID_xanim_H__
+
+#ifdef __GNUG__
+#pragma interface
+#endif
+
+#if defined(WXMMEDIA_INTERNAL) && (defined(__X__) || defined(__WXGTK__))
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#endif
+
+#include "vidbase.h"
+
+#ifdef WXMMEDIA_INTERNAL
+typedef struct wxXANIMinternal {
+ Display *xanim_dpy;
+ Window xanim_window;
+ Atom xanim_atom, xanim_ret;
+} wxXANIMinternal;
+
+#ifndef __XANIM_COMMAND__
+#define __XANIM_COMMAND__ "/usr/X11R6/bin/xanim"
+#endif
+#endif
+
+class wxVideoXANIM : public wxVideoBaseDriver {
+ DECLARE_DYNAMIC_CLASS(wxVideoXANIM)
+protected:
+ bool xanim_started, paused;
+ struct wxXANIMinternal *internal;
+public:
+ wxVideoXANIM();
+ wxVideoXANIM(wxInputStream& str);
+ wxVideoXANIM(const wxString& fname);
+ virtual ~wxVideoXANIM();
+
+ virtual bool StartPlay();
+ virtual bool Pause();
+ virtual bool Resume();
+ virtual void StopPlay();
+
+ virtual bool SetVolume(wxUint8 vol);
+ virtual bool Resize(wxUint16 w, wxUint16 h);
+
+ virtual bool IsCapable(wxVideoType v_type);
+
+ virtual bool AttachOutput(wxVideoOutput& output);
+ virtual void DetachOutput();
+
+protected:
+ ///
+ bool RestartXANIM();
+ ///
+ bool SendCommand(const char *command, char **ret = NULL,
+ wxUint32 *size = NULL);
+};
+
+#endif
--- /dev/null
+/////////////////////////////////////////////////////////////////////////////
+// Name: wave.cpp
+// Purpose: wxWave class
+// Author: Guilhem Lavaux / API by Julian Smart
+// Modified by:
+// Created: 04/23/98
+// RCS-ID: $Id$
+// Copyright: (c) Guilhem Lavaux
+// Licence: wxWindows license
+/////////////////////////////////////////////////////////////////////////////
+#ifdef __GNUG__
+#pragma implementation "wave.h"
+#endif
+
+#include <wx/fstream.h>
+#include "wave.h"
+
+wxWave::wxWave()
+{
+ m_wave = NULL;
+ m_iowave = NULL;
+}
+
+wxWave::wxWave(const wxString& fileName, bool isResource = FALSE)
+{
+ Create(fileName, isResource);
+}
+
+wxWave::~wxWave()
+{
+ Free();
+}
+
+bool wxWave::Create(const wxString& sFileName, bool isResource = FALSE)
+{
+ m_iowave = new wxFileInputStream(sFileName);
+ m_wave = new wxSndWavCodec(*m_iowave);
+
+ return TRUE;
+}
+
+bool wxWave::Play(bool async, bool looped) const
+{
+ if (!m_wave)
+ return FALSE;
+
+ if (looped)
+ m_wave->Set(wxSND_LOOP);
+ if (!m_wave->StartPlay());
+ return FALSE;
+ if (!async)
+ m_wave->Wait();
+
+ m_wave->Clear(wxSND_LOOP);
+ return TRUE;
+}
+
+bool wxWave::Free()
+{
+ if (m_wave) {
+ delete m_wave;
+ delete m_iowave;
+ }
+ return TRUE;
+}
--- /dev/null
+/////////////////////////////////////////////////////////////////////////////
+// Name: wave.h
+// Purpose: wxWave class
+// Author: Julian Smart
+// Modified by: Guilhem Lavaux for wxMMedia (02/05/1998)
+// Created: 01/02/97
+// RCS-ID: $Id$
+// Copyright: (c) Julian Smart and Markus Holzem
+// Licence: wxWindows license
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef __WAVEH__
+#define __WAVEH__
+
+#ifdef __GNUG__
+#pragma interface
+#endif
+
+#include <wx/object.h>
+#include <wx/string.h>
+#include "sndwav.h"
+
+class wxWave : public wxObject
+{
+public:
+ wxWave();
+ wxWave(const wxString& fileName, bool isResource = FALSE);
+ ~wxWave();
+
+public:
+ bool Create(const wxString& sFileName, bool isResource = FALSE);
+ bool IsOk() const { return (m_wave ? TRUE : FALSE); };
+ bool Play(bool async = TRUE, bool looped = FALSE) const;
+
+protected:
+ bool Free();
+
+protected:
+ wxInputStream *m_iowave;
+ wxSndWavCodec *m_wave;
+};
+
+#endif