1 /* libSoX lpc-10 format.
2  *
3  * Copyright 2007 Reuben Thomas <rrt@sc3d.org>
4  *
5  * This library is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU Lesser General Public License as published by
7  * the Free Software Foundation; either version 2.1 of the License, or (at
8  * your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with this library; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
18  */
19 
20 #include "sox_i.h"
21 
22 #include <lpc10.h>
23 
24 /* Private data */
25 typedef struct {
26   struct lpc10_encoder_state *encst;
27   float speech[LPC10_SAMPLES_PER_FRAME];
28   unsigned samples;
29   struct lpc10_decoder_state *decst;
30 } priv_t;
31 
32 /*
33   Write the bits in bits[0] through bits[len-1] to file f, in "packed"
34   format.
35 
36   bits is expected to be an array of len integer values, where each
37   integer is 0 to represent a 0 bit, and any other value represents a
38   1 bit. This bit string is written to the file f in the form of
39   several 8 bit characters. If len is not a multiple of 8, then the
40   last character is padded with 0 bits -- the padding is in the least
41   significant bits of the last byte. The 8 bit characters are "filled"
42   in order from most significant bit to least significant.
43 */
write_bits(sox_format_t * ft,INT32 * bits,int len)44 static void write_bits(sox_format_t * ft, INT32 *bits, int len)
45 {
46   int i;
47   uint8_t mask; /* The next bit position within the variable "data" to
48                    place the next bit. */
49   uint8_t data; /* The contents of the next byte to place in the
50                    output. */
51 
52   /* Fill in the array bits.
53    * The first compressed output bit will be the most significant
54    * bit of the byte, so initialize mask to 0x80.  The next byte of
55    * compressed data is initially 0, and the desired bits will be
56    * turned on below.
57    */
58   mask = 0x80;
59   data = 0;
60 
61   for (i = 0; i < len; i++) {
62     /* Turn on the next bit of output data, if necessary. */
63     if (bits[i]) {
64       data |= mask;
65     }
66     /*
67      * If the byte data is full, determined by mask becoming 0,
68      * then write the byte to the output file, and reinitialize
69      * data and mask for the next output byte.  Also add the byte
70      * if (i == len-1), because if len is not a multiple of 8,
71      * then mask won't yet be 0.  */
72     mask >>= 1;
73     if ((mask == 0) || (i == len-1)) {
74       lsx_writeb(ft, data);
75       data = 0;
76       mask = 0x80;
77     }
78   }
79 }
80 
81 /*
82   Read bits from file f into bits[0] through bits[len-1], in "packed"
83   format.
84 
85   Read ceiling(len/8) characters from file f, if that many are
86   available to read, otherwise read to the end of the file. The first
87   character's 8 bits, in order from MSB to LSB, are used to fill
88   bits[0] through bits[7]. The second character's bits are used to
89   fill bits[8] through bits[15], and so on. If ceiling(len/8)
90   characters are available to read, and len is not a multiple of 8,
91   then some of the least significant bits of the last character read
92   are completely ignored. Every entry of bits[] that is modified is
93   changed to either a 0 or a 1.
94 
95   The number of bits successfully read is returned, and is always in
96   the range 0 to len, inclusive. If it is less than len, it will
97   always be a multiple of 8.
98 */
read_bits(sox_format_t * ft,INT32 * bits,int len)99 static int read_bits(sox_format_t * ft, INT32 *bits, int len)
100 {
101   int i;
102   uint8_t c = 0;
103 
104   /* Unpack the array bits into coded_frame. */
105   for (i = 0; i < len; i++) {
106     if (i % 8 == 0) {
107       lsx_read_b_buf(ft, &c, (size_t) 1);
108       if (lsx_eof(ft)) {
109         return (i);
110       }
111     }
112     if (c & (0x80 >> (i & 7))) {
113       bits[i] = 1;
114     } else {
115       bits[i] = 0;
116     }
117   }
118   return (len);
119 }
120 
startread(sox_format_t * ft)121 static int startread(sox_format_t * ft)
122 {
123   priv_t * lpc = (priv_t *)ft->priv;
124 
125   if ((lpc->decst = create_lpc10_decoder_state()) == NULL) {
126     fprintf(stderr, "lpc10 could not allocate decoder state");
127     return SOX_EOF;
128   }
129   lpc->samples = LPC10_SAMPLES_PER_FRAME;
130   return lsx_check_read_params(ft, 1, 8000., SOX_ENCODING_LPC10, 0, (uint64_t)0, sox_false);
131 }
132 
startwrite(sox_format_t * ft)133 static int startwrite(sox_format_t * ft)
134 {
135   priv_t * lpc = (priv_t *)ft->priv;
136 
137   if ((lpc->encst = create_lpc10_encoder_state()) == NULL) {
138     fprintf(stderr, "lpc10 could not allocate encoder state");
139     return SOX_EOF;
140   }
141   lpc->samples = 0;
142 
143   return SOX_SUCCESS;
144 }
145 
read_samples(sox_format_t * ft,sox_sample_t * buf,size_t len)146 static size_t read_samples(sox_format_t * ft, sox_sample_t *buf, size_t len)
147 {
148   priv_t * lpc = (priv_t *)ft->priv;
149   size_t nread = 0;
150 
151   while (nread < len) {
152     SOX_SAMPLE_LOCALS;
153     /* Read more data if buffer is empty */
154     if (lpc->samples == LPC10_SAMPLES_PER_FRAME) {
155       INT32 bits[LPC10_BITS_IN_COMPRESSED_FRAME];
156 
157       if (read_bits(ft, bits, LPC10_BITS_IN_COMPRESSED_FRAME) !=
158           LPC10_BITS_IN_COMPRESSED_FRAME)
159         break;
160       lpc10_decode(bits, lpc->speech, lpc->decst);
161       lpc->samples = 0;
162     }
163 
164     while (nread < len && lpc->samples < LPC10_SAMPLES_PER_FRAME)
165       buf[nread++] = SOX_FLOAT_32BIT_TO_SAMPLE(lpc->speech[lpc->samples++], ft->clips);
166   }
167 
168   return nread;
169 }
170 
write_samples(sox_format_t * ft,const sox_sample_t * buf,size_t len)171 static size_t write_samples(sox_format_t * ft, const sox_sample_t *buf, size_t len)
172 {
173   priv_t * lpc = (priv_t *)ft->priv;
174   size_t nwritten = 0;
175 
176   while (len > 0) {
177     while (len > 0 && lpc->samples < LPC10_SAMPLES_PER_FRAME) {
178       SOX_SAMPLE_LOCALS;
179       lpc->speech[lpc->samples++] = SOX_SAMPLE_TO_FLOAT_32BIT(buf[nwritten++], ft->clips);
180       len--;
181     }
182 
183     if (lpc->samples == LPC10_SAMPLES_PER_FRAME) {
184       INT32 bits[LPC10_BITS_IN_COMPRESSED_FRAME];
185 
186       lpc10_encode(lpc->speech, bits, lpc->encst);
187       write_bits(ft, bits, LPC10_BITS_IN_COMPRESSED_FRAME);
188       lpc->samples = 0;
189     }
190   }
191 
192   return nwritten;
193 }
194 
stopread(sox_format_t * ft)195 static int stopread(sox_format_t * ft)
196 {
197   priv_t * lpc = (priv_t *)ft->priv;
198 
199   free(lpc->decst);
200 
201   return SOX_SUCCESS;
202 }
203 
stopwrite(sox_format_t * ft)204 static int stopwrite(sox_format_t * ft)
205 {
206   priv_t * lpc = (priv_t *)ft->priv;
207 
208   free(lpc->encst);
209 
210   return SOX_SUCCESS;
211 }
212 
LSX_FORMAT_HANDLER(lpc10)213 LSX_FORMAT_HANDLER(lpc10)
214 {
215   static char const * const names[] = {"lpc10", "lpc", NULL};
216   static sox_rate_t   const write_rates[] = {8000, 0};
217   static unsigned     const write_encodings[] = {SOX_ENCODING_LPC10, 0, 0};
218   static sox_format_handler_t handler = {SOX_LIB_VERSION_CODE,
219     "Low bandwidth, robotic sounding speech compression", names, SOX_FILE_MONO,
220     startread, read_samples, stopread,
221     startwrite, write_samples, stopwrite,
222     NULL, write_encodings, write_rates, sizeof(priv_t)
223   };
224   return &handler;
225 }
226