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 */
7
8 /*
9 * GSM 06.10 courtesy Communications and Operating Systems Research Group,
10 * Technische Universitaet Berlin
11 *
12 * Source code and more information on this format can be obtained from
13 * http://www.quut.com/gsm/
14 *
15 * Written 26 Jan 1995 by Andrew Pam
16 * Portions Copyright (c) 1995 Serious Cybernetics
17 *
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).
21 *
22 * Nov. 26, 1999 - Stan Brooks (stabro@megsinet.com)
23 * Rewritten to support multiple channels
24 */
25
26 #include "sox_i.h"
27
28 #ifdef HAVE_GSM_GSM_H
29 #include <gsm/gsm.h>
30 #else
31 #include <gsm.h>
32 #endif
33
34 #include <errno.h>
35
36 #define MAXCHANS 16
37
38 /* sizeof(gsm_frame) */
39 #define FRAMESIZE (size_t)33
40 /* samples per gsm_frame */
41 #define BLOCKSIZE 160
42
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;
52
gsmstart_rw(sox_format_t * ft,int w)53 static int gsmstart_rw(sox_format_t * ft, int w)
54 {
55 priv_t *p = (priv_t *) ft->priv;
56 unsigned ch;
57
58 ft->encoding.encoding = SOX_ENCODING_GSM;
59 if (!ft->signal.rate)
60 ft->signal.rate = 8000;
61
62 if (ft->signal.channels == 0)
63 ft->signal.channels = 1;
64
65 p->channels = ft->signal.channels;
66 if (p->channels > MAXCHANS || p->channels <= 0)
67 {
68 lsx_fail_errno(ft,SOX_EFMT,"gsm: channels(%d) must be in 1-16", ft->signal.channels);
69 return(SOX_EOF);
70 }
71
72 for (ch=0; ch<p->channels; ch++) {
73 p->handle[ch] = gsm_create();
74 if (!p->handle[ch])
75 {
76 lsx_fail_errno(ft,errno,"unable to create GSM stream");
77 return (SOX_EOF);
78 }
79 }
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);
85 }
86
sox_gsmstartread(sox_format_t * ft)87 static int sox_gsmstartread(sox_format_t * ft)
88 {
89 return gsmstart_rw(ft,0);
90 }
91
sox_gsmstartwrite(sox_format_t * ft)92 static int sox_gsmstartwrite(sox_format_t * ft)
93 {
94 return gsmstart_rw(ft,1);
95 }
96
97 /*
98 * Read up to len samples from file.
99 * Convert to signed longs.
100 * Place in buf[].
101 * Return number of samples read.
102 */
103
sox_gsmread(sox_format_t * ft,sox_sample_t * buf,size_t samp)104 static size_t sox_gsmread(sox_format_t * ft, sox_sample_t *buf, size_t samp)
105 {
106 size_t done = 0, r;
107 int ch, chans;
108 gsm_signal *gbuff;
109 priv_t *p = (priv_t *) ft->priv;
110
111 chans = p->channels;
112
113 while (done < samp)
114 {
115 while (p->samplePtr < p->sampleTop && done < samp)
116 buf[done++] =
117 SOX_SIGNED_16BIT_TO_SAMPLE(*(p->samplePtr)++,);
118
119 if (done>=samp) break;
120
121 r = lsx_readbuf(ft, p->frames, p->channels * FRAMESIZE);
122 if (r != p->channels * FRAMESIZE)
123 break;
124
125 p->samplePtr = p->samples;
126 for (ch=0; ch<chans; ch++) {
127 int i;
128 gsm_signal *gsp;
129
130 gbuff = p->sampleTop;
131 if (gsm_decode(p->handle[ch], p->frames + ch*FRAMESIZE, gbuff) < 0)
132 {
133 lsx_fail_errno(ft,errno,"error during GSM decode");
134 return (0);
135 }
136
137 gsp = p->samples + ch;
138 for (i=0; i<BLOCKSIZE; i++) {
139 *gsp = *gbuff++;
140 gsp += chans;
141 }
142 }
143 }
144
145 return done;
146 }
147
gsmflush(sox_format_t * ft)148 static int gsmflush(sox_format_t * ft)
149 {
150 int r, ch, chans;
151 gsm_signal *gbuff;
152 priv_t *p = (priv_t *) ft->priv;
153
154 chans = p->channels;
155
156 /* zero-fill samples as needed */
157 while (p->samplePtr < p->sampleTop)
158 *(p->samplePtr)++ = 0;
159
160 gbuff = p->sampleTop;
161 for (ch=0; ch<chans; ch++) {
162 int i;
163 gsm_signal *gsp;
164
165 gsp = p->samples + ch;
166 for (i=0; i<BLOCKSIZE; i++) {
167 gbuff[i] = *gsp;
168 gsp += chans;
169 }
170 gsm_encode(p->handle[ch], gbuff, p->frames);
171 r = lsx_writebuf(ft, p->frames, FRAMESIZE);
172 if (r != FRAMESIZE)
173 {
174 lsx_fail_errno(ft,errno,"write error");
175 return(SOX_EOF);
176 }
177 }
178 p->samplePtr = p->samples;
179
180 return (SOX_SUCCESS);
181 }
182
sox_gsmwrite(sox_format_t * ft,const sox_sample_t * buf,size_t samp)183 static size_t sox_gsmwrite(sox_format_t * ft, const sox_sample_t *buf, size_t samp)
184 {
185 size_t done = 0;
186 priv_t *p = (priv_t *) ft->priv;
187
188 while (done < samp)
189 {
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);
194
195 if (p->samplePtr == p->sampleTop)
196 {
197 if(gsmflush(ft))
198 {
199 return 0;
200 }
201 }
202 }
203
204 return done;
205 }
206
sox_gsmstopread(sox_format_t * ft)207 static int sox_gsmstopread(sox_format_t * ft)
208 {
209 priv_t *p = (priv_t *) ft->priv;
210 unsigned ch;
211
212 for (ch=0; ch<p->channels; ch++)
213 gsm_destroy(p->handle[ch]);
214
215 free(p->samples);
216 free(p->frames);
217 return (SOX_SUCCESS);
218 }
219
sox_gsmstopwrite(sox_format_t * ft)220 static int sox_gsmstopwrite(sox_format_t * ft)
221 {
222 int rc;
223 priv_t *p = (priv_t *) ft->priv;
224
225 if (p->samplePtr > p->samples)
226 {
227 rc = gsmflush(ft);
228 if (rc)
229 return rc;
230 }
231
232 return sox_gsmstopread(ft); /* destroy handles and free buffers */
233 }
234
LSX_FORMAT_HANDLER(gsm)235 LSX_FORMAT_HANDLER(gsm)
236 {
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)
245 };
246 return &handler;
247 }
248