aiff: handle id3 tags
[sox.git] / src / lpc10.c
blob58e9c1185bc38692e4275b7cc744c7b230ce0d96
1 /* libSoX lpc-10 format.
3 * Copyright 2007 Reuben Thomas <rrt@sc3d.org>
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.
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.
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
20 #include "sox_i.h"
22 #include <lpc10.h>
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;
33 Write the bits in bits[0] through bits[len-1] to file f, in "packed"
34 format.
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.
44 static void write_bits(sox_format_t * ft, INT32 *bits, int len)
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. */
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.
58 mask = 0x80;
59 data = 0;
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;
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;
82 Read bits from file f into bits[0] through bits[len-1], in "packed"
83 format.
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.
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.
99 static int read_bits(sox_format_t * ft, INT32 *bits, int len)
101 int i;
102 uint8_t c = 0;
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);
112 if (c & (0x80 >> (i & 7))) {
113 bits[i] = 1;
114 } else {
115 bits[i] = 0;
118 return (len);
121 static int startread(sox_format_t * ft)
123 priv_t * lpc = (priv_t *)ft->priv;
125 if ((lpc->decst = create_lpc10_decoder_state()) == NULL) {
126 fprintf(stderr, "lpc10 could not allocate decoder state");
127 return SOX_EOF;
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);
133 static int startwrite(sox_format_t * ft)
135 priv_t * lpc = (priv_t *)ft->priv;
137 if ((lpc->encst = create_lpc10_encoder_state()) == NULL) {
138 fprintf(stderr, "lpc10 could not allocate encoder state");
139 return SOX_EOF;
141 lpc->samples = 0;
143 return SOX_SUCCESS;
146 static size_t read_samples(sox_format_t * ft, sox_sample_t *buf, size_t len)
148 priv_t * lpc = (priv_t *)ft->priv;
149 size_t nread = 0;
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];
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;
164 while (nread < len && lpc->samples < LPC10_SAMPLES_PER_FRAME)
165 buf[nread++] = SOX_FLOAT_32BIT_TO_SAMPLE(lpc->speech[lpc->samples++], ft->clips);
168 return nread;
171 static size_t write_samples(sox_format_t * ft, const sox_sample_t *buf, size_t len)
173 priv_t * lpc = (priv_t *)ft->priv;
174 size_t nwritten = 0;
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--;
183 if (lpc->samples == LPC10_SAMPLES_PER_FRAME) {
184 INT32 bits[LPC10_BITS_IN_COMPRESSED_FRAME];
186 lpc10_encode(lpc->speech, bits, lpc->encst);
187 write_bits(ft, bits, LPC10_BITS_IN_COMPRESSED_FRAME);
188 lpc->samples = 0;
192 return nwritten;
195 static int stopread(sox_format_t * ft)
197 priv_t * lpc = (priv_t *)ft->priv;
199 free(lpc->decst);
201 return SOX_SUCCESS;
204 static int stopwrite(sox_format_t * ft)
206 priv_t * lpc = (priv_t *)ft->priv;
208 free(lpc->encst);
210 return SOX_SUCCESS;
213 LSX_FORMAT_HANDLER(lpc10)
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)
224 return &handler;