delete bundled libgsm
[sox.git] / src / gsm.c
blob0277d0c0f81e14cd142fe848d5ba9d343b668c9f
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.
6 */
8 /*
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
26 #include "sox_i.h"
28 #ifdef HAVE_GSM_GSM_H
29 #include <gsm/gsm.h>
30 #else
31 #include <gsm.h>
32 #endif
34 #include <errno.h>
36 #define MAXCHANS 16
38 /* sizeof(gsm_frame) */
39 #define FRAMESIZE (size_t)33
40 /* samples per gsm_frame */
41 #define BLOCKSIZE 160
43 /* Private data */
44 typedef struct {
45 unsigned channels;
46 gsm_signal *samples;
47 gsm_signal *samplePtr;
48 gsm_signal *sampleTop;
49 gsm_byte *frames;
50 gsm handle[MAXCHANS];
51 } priv_t;
53 static int gsmstart_rw(sox_format_t * ft, int w)
55 priv_t *p = (priv_t *) ft->priv;
56 unsigned ch;
58 ft->encoding.encoding = SOX_ENCODING_GSM;
59 if (!ft->signal.rate)
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);
69 return(SOX_EOF);
72 for (ch=0; ch<p->channels; ch++) {
73 p->handle[ch] = gsm_create();
74 if (!p->handle[ch])
76 lsx_fail_errno(ft,errno,"unable to create GSM stream");
77 return (SOX_EOF);
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;
84 return (SOX_SUCCESS);
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.
100 * Place in buf[].
101 * Return number of samples read.
104 static size_t sox_gsmread(sox_format_t * ft, sox_sample_t *buf, size_t samp)
106 size_t done = 0, r;
107 int ch, chans;
108 gsm_signal *gbuff;
109 priv_t *p = (priv_t *) ft->priv;
111 chans = p->channels;
113 while (done < samp)
115 while (p->samplePtr < p->sampleTop && done < samp)
116 buf[done++] =
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)
123 break;
125 p->samplePtr = p->samples;
126 for (ch=0; ch<chans; ch++) {
127 int i;
128 gsm_signal *gsp;
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");
134 return (0);
137 gsp = p->samples + ch;
138 for (i=0; i<BLOCKSIZE; i++) {
139 *gsp = *gbuff++;
140 gsp += chans;
145 return done;
148 static int gsmflush(sox_format_t * ft)
150 int r, ch, chans;
151 gsm_signal *gbuff;
152 priv_t *p = (priv_t *) ft->priv;
154 chans = p->channels;
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++) {
162 int i;
163 gsm_signal *gsp;
165 gsp = p->samples + ch;
166 for (i=0; i<BLOCKSIZE; i++) {
167 gbuff[i] = *gsp;
168 gsp += chans;
170 gsm_encode(p->handle[ch], gbuff, p->frames);
171 r = lsx_writebuf(ft, p->frames, FRAMESIZE);
172 if (r != FRAMESIZE)
174 lsx_fail_errno(ft,errno,"write error");
175 return(SOX_EOF);
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)
185 size_t done = 0;
186 priv_t *p = (priv_t *) ft->priv;
188 while (done < samp)
190 SOX_SAMPLE_LOCALS;
191 while ((p->samplePtr < p->sampleTop) && (done < samp))
192 *(p->samplePtr)++ =
193 SOX_SAMPLE_TO_SIGNED_16BIT(buf[done++], ft->clips);
195 if (p->samplePtr == p->sampleTop)
197 if(gsmflush(ft))
199 return 0;
204 return done;
207 static int sox_gsmstopread(sox_format_t * ft)
209 priv_t *p = (priv_t *) ft->priv;
210 unsigned ch;
212 for (ch=0; ch<p->channels; ch++)
213 gsm_destroy(p->handle[ch]);
215 free(p->samples);
216 free(p->frames);
217 return (SOX_SUCCESS);
220 static int sox_gsmstopwrite(sox_format_t * ft)
222 int rc;
223 priv_t *p = (priv_t *) ft->priv;
225 if (p->samplePtr > p->samples)
227 rc = gsmflush(ft);
228 if (rc)
229 return rc;
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)
246 return &handler;