* Added wxMMedia in the repository so people interrested in it can work on it
* WARNING! It is quite unstable on Windows and it doesn't work on Linux for the moment because I didn't finish fixing the CODEC stream. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@975 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
1
utils/wxMMedia/Makefile
Normal file
1
utils/wxMMedia/Makefile
Normal file
@@ -0,0 +1 @@
|
||||
include ../../setup/general/makeapp
|
38
utils/wxMMedia/Makefile.in
Normal file
38
utils/wxMMedia/Makefile.in
Normal file
@@ -0,0 +1,38 @@
|
||||
# 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
|
||||
|
283
utils/wxMMedia/adpcm/g711.cpp
Normal file
283
utils/wxMMedia/adpcm/g711.cpp
Normal file
@@ -0,0 +1,283 @@
|
||||
/*
|
||||
* 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)));
|
||||
}
|
173
utils/wxMMedia/adpcm/g721.cpp
Normal file
173
utils/wxMMedia/adpcm/g721.cpp
Normal file
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
}
|
158
utils/wxMMedia/adpcm/g723_24.cpp
Normal file
158
utils/wxMMedia/adpcm/g723_24.cpp
Normal file
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
}
|
178
utils/wxMMedia/adpcm/g723_40.cpp
Normal file
178
utils/wxMMedia/adpcm/g723_40.cpp
Normal file
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
}
|
608
utils/wxMMedia/adpcm/g72x.cpp
Normal file
608
utils/wxMMedia/adpcm/g72x.cpp
Normal file
@@ -0,0 +1,608 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
}
|
123
utils/wxMMedia/adpcm/g72x.h
Normal file
123
utils/wxMMedia/adpcm/g72x.h
Normal file
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* 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 */
|
52
utils/wxMMedia/cdbase.cpp
Normal file
52
utils/wxMMedia/cdbase.cpp
Normal file
@@ -0,0 +1,52 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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);
|
||||
}
|
88
utils/wxMMedia/cdbase.h
Normal file
88
utils/wxMMedia/cdbase.h
Normal file
@@ -0,0 +1,88 @@
|
||||
// -*- 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
|
198
utils/wxMMedia/cdunix.cpp
Normal file
198
utils/wxMMedia/cdunix.cpp
Normal file
@@ -0,0 +1,198 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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;
|
||||
}
|
61
utils/wxMMedia/cdunix.h
Normal file
61
utils/wxMMedia/cdunix.h
Normal file
@@ -0,0 +1,61 @@
|
||||
// /////////////////////////////////////////////////////////////////////////////
|
||||
// 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
|
208
utils/wxMMedia/cdwin.cpp
Normal file
208
utils/wxMMedia/cdwin.cpp
Normal file
@@ -0,0 +1,208 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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;
|
||||
}
|
67
utils/wxMMedia/cdwin.h
Normal file
67
utils/wxMMedia/cdwin.h
Normal file
@@ -0,0 +1,67 @@
|
||||
// /////////////////////////////////////////////////////////////////////////////
|
||||
// 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
|
92
utils/wxMMedia/mmdata.cpp
Normal file
92
utils/wxMMedia/mmdata.cpp
Normal file
@@ -0,0 +1,92 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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
|
31
utils/wxMMedia/mmedia.h
Normal file
31
utils/wxMMedia/mmedia.h
Normal file
@@ -0,0 +1,31 @@
|
||||
// /////////////////////////////////////////////////////////////////////////////
|
||||
// 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
|
194
utils/wxMMedia/mmfile.cpp
Normal file
194
utils/wxMMedia/mmfile.cpp
Normal file
@@ -0,0 +1,194 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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);
|
||||
}
|
94
utils/wxMMedia/mmfile.h
Normal file
94
utils/wxMMedia/mmfile.h
Normal file
@@ -0,0 +1,94 @@
|
||||
// /////////////////////////////////////////////////////////////////////////////
|
||||
// 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
|
215
utils/wxMMedia/mmriff.cpp
Normal file
215
utils/wxMMedia/mmriff.cpp
Normal file
@@ -0,0 +1,215 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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;
|
||||
}
|
81
utils/wxMMedia/mmriff.h
Normal file
81
utils/wxMMedia/mmriff.h
Normal file
@@ -0,0 +1,81 @@
|
||||
// /////////////////////////////////////////////////////////////////////////////
|
||||
// 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
|
124
utils/wxMMedia/mmsolve.cpp
Normal file
124
utils/wxMMedia/mmsolve.cpp
Normal file
@@ -0,0 +1,124 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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;
|
||||
}
|
92
utils/wxMMedia/mmsolve.h
Normal file
92
utils/wxMMedia/mmsolve.h
Normal file
@@ -0,0 +1,92 @@
|
||||
// /////////////////////////////////////////////////////////////////////////////
|
||||
// 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
|
41
utils/wxMMedia/mmtype.h
Normal file
41
utils/wxMMedia/mmtype.h
Normal file
@@ -0,0 +1,41 @@
|
||||
// /////////////////////////////////////////////////////////////////////////////
|
||||
// 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
|
||||
|
218
utils/wxMMedia/sndaiff.cpp
Normal file
218
utils/wxMMedia/sndaiff.cpp
Normal file
@@ -0,0 +1,218 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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();
|
||||
}
|
58
utils/wxMMedia/sndaiff.h
Normal file
58
utils/wxMMedia/sndaiff.h
Normal file
@@ -0,0 +1,58 @@
|
||||
// /////////////////////////////////////////////////////////////////////////////
|
||||
// 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
|
114
utils/wxMMedia/sndau.cpp
Normal file
114
utils/wxMMedia/sndau.cpp
Normal file
@@ -0,0 +1,114 @@
|
||||
// /////////////////////////////////////////////////////////////////////////////
|
||||
// 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;
|
||||
}
|
47
utils/wxMMedia/sndau.h
Normal file
47
utils/wxMMedia/sndau.h
Normal file
@@ -0,0 +1,47 @@
|
||||
// /////////////////////////////////////////////////////////////////////////////
|
||||
// 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
|
323
utils/wxMMedia/sndfile.cpp
Normal file
323
utils/wxMMedia/sndfile.cpp
Normal file
@@ -0,0 +1,323 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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)
|
91
utils/wxMMedia/sndfile.h
Normal file
91
utils/wxMMedia/sndfile.h
Normal file
@@ -0,0 +1,91 @@
|
||||
// /////////////////////////////////////////////////////////////////////////////
|
||||
// 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
|
268
utils/wxMMedia/sndfrag.cpp
Normal file
268
utils/wxMMedia/sndfrag.cpp
Normal file
@@ -0,0 +1,268 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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;
|
||||
}
|
103
utils/wxMMedia/sndfrag.h
Normal file
103
utils/wxMMedia/sndfrag.h
Normal file
@@ -0,0 +1,103 @@
|
||||
// /////////////////////////////////////////////////////////////////////////////
|
||||
// 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
|
266
utils/wxMMedia/sndfrmt.cpp
Normal file
266
utils/wxMMedia/sndfrmt.cpp
Normal file
@@ -0,0 +1,266 @@
|
||||
#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();
|
||||
}
|
119
utils/wxMMedia/sndfrmt.h
Normal file
119
utils/wxMMedia/sndfrmt.h
Normal file
@@ -0,0 +1,119 @@
|
||||
#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
|
85
utils/wxMMedia/sndmulaw.cpp
Normal file
85
utils/wxMMedia/sndmulaw.cpp
Normal file
@@ -0,0 +1,85 @@
|
||||
#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;
|
||||
}
|
28
utils/wxMMedia/sndmulaw.h
Normal file
28
utils/wxMMedia/sndmulaw.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#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
|
216
utils/wxMMedia/sndpcm.cpp
Normal file
216
utils/wxMMedia/sndpcm.cpp
Normal file
@@ -0,0 +1,216 @@
|
||||
#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();
|
||||
}
|
39
utils/wxMMedia/sndpcm.h
Normal file
39
utils/wxMMedia/sndpcm.h
Normal file
@@ -0,0 +1,39 @@
|
||||
#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
|
264
utils/wxMMedia/sndsnd.cpp
Normal file
264
utils/wxMMedia/sndsnd.cpp
Normal file
@@ -0,0 +1,264 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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);
|
||||
}
|
275
utils/wxMMedia/sndsnd.h
Normal file
275
utils/wxMMedia/sndsnd.h
Normal file
@@ -0,0 +1,275 @@
|
||||
/* 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
|
268
utils/wxMMedia/snduss.cpp
Normal file
268
utils/wxMMedia/snduss.cpp
Normal file
@@ -0,0 +1,268 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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;
|
||||
}
|
85
utils/wxMMedia/snduss.h
Normal file
85
utils/wxMMedia/snduss.h
Normal file
@@ -0,0 +1,85 @@
|
||||
// /////////////////////////////////////////////////////////////////////////////
|
||||
// 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
|
186
utils/wxMMedia/sndwav.cpp
Normal file
186
utils/wxMMedia/sndwav.cpp
Normal file
@@ -0,0 +1,186 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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);
|
||||
}
|
59
utils/wxMMedia/sndwav.h
Normal file
59
utils/wxMMedia/sndwav.h
Normal file
@@ -0,0 +1,59 @@
|
||||
// /////////////////////////////////////////////////////////////////////////////
|
||||
// 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
|
384
utils/wxMMedia/sndwin.cpp
Normal file
384
utils/wxMMedia/sndwin.cpp
Normal file
@@ -0,0 +1,384 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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;
|
||||
}
|
108
utils/wxMMedia/sndwin.h
Normal file
108
utils/wxMMedia/sndwin.h
Normal file
@@ -0,0 +1,108 @@
|
||||
// /////////////////////////////////////////////////////////////////////////////
|
||||
// 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
|
69
utils/wxMMedia/ulaw.h
Normal file
69
utils/wxMMedia/ulaw.h
Normal file
@@ -0,0 +1,69 @@
|
||||
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,
|
||||
};
|
87
utils/wxMMedia/vidbase.cpp
Normal file
87
utils/wxMMedia/vidbase.cpp
Normal file
@@ -0,0 +1,87 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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;
|
||||
}
|
105
utils/wxMMedia/vidbase.h
Normal file
105
utils/wxMMedia/vidbase.h
Normal file
@@ -0,0 +1,105 @@
|
||||
// /////////////////////////////////////////////////////////////////////////////
|
||||
// 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
|
131
utils/wxMMedia/vidwin.cpp
Normal file
131
utils/wxMMedia/vidwin.cpp
Normal file
@@ -0,0 +1,131 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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);
|
||||
}
|
62
utils/wxMMedia/vidwin.h
Normal file
62
utils/wxMMedia/vidwin.h
Normal file
@@ -0,0 +1,62 @@
|
||||
// /////////////////////////////////////////////////////////////////////////////
|
||||
// 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
|
231
utils/wxMMedia/vidxanm.cpp
Normal file
231
utils/wxMMedia/vidxanm.cpp
Normal file
@@ -0,0 +1,231 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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;
|
||||
}
|
69
utils/wxMMedia/vidxanm.h
Normal file
69
utils/wxMMedia/vidxanm.h
Normal file
@@ -0,0 +1,69 @@
|
||||
// /////////////////////////////////////////////////////////////////////////////
|
||||
// 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
|
65
utils/wxMMedia/wave.cpp
Normal file
65
utils/wxMMedia/wave.cpp
Normal file
@@ -0,0 +1,65 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// 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;
|
||||
}
|
43
utils/wxMMedia/wave.h
Normal file
43
utils/wxMMedia/wave.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// 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
|
Reference in New Issue
Block a user