1 /* Copyright 1991, 1992, 1993 Guido van Rossum And Sundry Contributors.
2 * This source code is freely redistributable and may be used for
3 * any purpose. This copyright notice must be maintained.
4 * Guido van Rossum And Sundry Contributors are not responsible for
5 * the consequences of using this software.
9 * GSM 06.10 courtesy Communications and Operating Systems Research Group,
10 * Technische Universitaet Berlin
12 * Source code and more information on this format can be obtained from
13 * http://www.quut.com/gsm/
15 * Written 26 Jan 1995 by Andrew Pam
16 * Portions Copyright (c) 1995 Serious Cybernetics
18 * July 19, 1998 - Chris Bagwell (cbagwell@sprynet.com)
19 * Added GSM support to SOX from patches floating around with the help
20 * of Dima Barsky (ess2db@ee.surrey.ac.uk).
22 * Nov. 26, 1999 - Stan Brooks (stabro@megsinet.com)
23 * Rewritten to support multiple channels
38 /* sizeof(gsm_frame) */
39 #define FRAMESIZE (size_t)33
40 /* samples per gsm_frame */
47 gsm_signal
*samplePtr
;
48 gsm_signal
*sampleTop
;
53 static int gsmstart_rw(sox_format_t
* ft
, int w
)
55 priv_t
*p
= (priv_t
*) ft
->priv
;
58 ft
->encoding
.encoding
= SOX_ENCODING_GSM
;
60 ft
->signal
.rate
= 8000;
62 if (ft
->signal
.channels
== 0)
63 ft
->signal
.channels
= 1;
65 p
->channels
= ft
->signal
.channels
;
66 if (p
->channels
> MAXCHANS
|| p
->channels
<= 0)
68 lsx_fail_errno(ft
,SOX_EFMT
,"gsm: channels(%d) must be in 1-16", ft
->signal
.channels
);
72 for (ch
=0; ch
<p
->channels
; ch
++) {
73 p
->handle
[ch
] = gsm_create();
76 lsx_fail_errno(ft
,errno
,"unable to create GSM stream");
80 p
->frames
= lsx_malloc(p
->channels
*FRAMESIZE
);
81 p
->samples
= lsx_malloc(BLOCKSIZE
* (p
->channels
+1) * sizeof(gsm_signal
));
82 p
->sampleTop
= p
->samples
+ BLOCKSIZE
*p
->channels
;
83 p
->samplePtr
= (w
)? p
->samples
: p
->sampleTop
;
87 static int sox_gsmstartread(sox_format_t
* ft
)
89 return gsmstart_rw(ft
,0);
92 static int sox_gsmstartwrite(sox_format_t
* ft
)
94 return gsmstart_rw(ft
,1);
98 * Read up to len samples from file.
99 * Convert to signed longs.
101 * Return number of samples read.
104 static size_t sox_gsmread(sox_format_t
* ft
, sox_sample_t
*buf
, size_t samp
)
109 priv_t
*p
= (priv_t
*) ft
->priv
;
115 while (p
->samplePtr
< p
->sampleTop
&& done
< samp
)
117 SOX_SIGNED_16BIT_TO_SAMPLE(*(p
->samplePtr
)++,);
119 if (done
>=samp
) break;
121 r
= lsx_readbuf(ft
, p
->frames
, p
->channels
* FRAMESIZE
);
122 if (r
!= p
->channels
* FRAMESIZE
)
125 p
->samplePtr
= p
->samples
;
126 for (ch
=0; ch
<chans
; ch
++) {
130 gbuff
= p
->sampleTop
;
131 if (gsm_decode(p
->handle
[ch
], p
->frames
+ ch
*FRAMESIZE
, gbuff
) < 0)
133 lsx_fail_errno(ft
,errno
,"error during GSM decode");
137 gsp
= p
->samples
+ ch
;
138 for (i
=0; i
<BLOCKSIZE
; i
++) {
148 static int gsmflush(sox_format_t
* ft
)
152 priv_t
*p
= (priv_t
*) ft
->priv
;
156 /* zero-fill samples as needed */
157 while (p
->samplePtr
< p
->sampleTop
)
158 *(p
->samplePtr
)++ = 0;
160 gbuff
= p
->sampleTop
;
161 for (ch
=0; ch
<chans
; ch
++) {
165 gsp
= p
->samples
+ ch
;
166 for (i
=0; i
<BLOCKSIZE
; i
++) {
170 gsm_encode(p
->handle
[ch
], gbuff
, p
->frames
);
171 r
= lsx_writebuf(ft
, p
->frames
, FRAMESIZE
);
174 lsx_fail_errno(ft
,errno
,"write error");
178 p
->samplePtr
= p
->samples
;
180 return (SOX_SUCCESS
);
183 static size_t sox_gsmwrite(sox_format_t
* ft
, const sox_sample_t
*buf
, size_t samp
)
186 priv_t
*p
= (priv_t
*) ft
->priv
;
191 while ((p
->samplePtr
< p
->sampleTop
) && (done
< samp
))
193 SOX_SAMPLE_TO_SIGNED_16BIT(buf
[done
++], ft
->clips
);
195 if (p
->samplePtr
== p
->sampleTop
)
207 static int sox_gsmstopread(sox_format_t
* ft
)
209 priv_t
*p
= (priv_t
*) ft
->priv
;
212 for (ch
=0; ch
<p
->channels
; ch
++)
213 gsm_destroy(p
->handle
[ch
]);
217 return (SOX_SUCCESS
);
220 static int sox_gsmstopwrite(sox_format_t
* ft
)
223 priv_t
*p
= (priv_t
*) ft
->priv
;
225 if (p
->samplePtr
> p
->samples
)
232 return sox_gsmstopread(ft
); /* destroy handles and free buffers */
235 LSX_FORMAT_HANDLER(gsm
)
237 static char const * const names
[] = {"gsm", NULL
};
238 static sox_rate_t
const write_rates
[] = {8000, 0};
239 static unsigned const write_encodings
[] = {SOX_ENCODING_GSM
, 0, 0};
240 static sox_format_handler_t handler
= {SOX_LIB_VERSION_CODE
,
241 "GSM 06.10 (full-rate) lossy speech compression", names
, 0,
242 sox_gsmstartread
, sox_gsmread
, sox_gsmstopread
,
243 sox_gsmstartwrite
, sox_gsmwrite
, sox_gsmstopwrite
,
244 NULL
, write_encodings
, write_rates
, sizeof(priv_t
)