1 /* libSoX skeleton file format handler.
2 *
3 * Copyright 1999 Chris Bagwell And Sundry Contributors
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 <string.h>
23
24 /* Private data for SKEL file */
25 typedef struct {
26 size_t remaining_samples;
27 } priv_t;
28
29 /* Note that if any of your methods doesn't need to do anything, you
30 can instead use the relevant sox_*_nothing* method */
31
32 /*
33 * Do anything required before you start reading samples.
34 * Read file header.
35 * Find out sampling rate,
36 * size and encoding of samples,
37 * mono/stereo/quad.
38 */
startread(sox_format_t * ft)39 static int startread(sox_format_t * ft)
40 {
41 priv_t * sk = (priv_t *)ft->priv;
42 size_t samples_in_file;
43
44 /* If you need to seek around the input file. */
45 if (!ft->seekable) {
46 lsx_fail_errno(ft, SOX_EOF, "skel inputfile must be a file");
47 return SOX_EOF;
48 }
49
50 /*
51 * If your format is headerless and has fixed values for
52 * the following items, you can hard code them here (see cdr.c).
53 * If your format contains a header with format information
54 * then you should set it here.
55 */
56 ft->signal.rate = 44100; /* or 8000, 16000, 32000, 48000, ... */
57 ft->signal.channels = 1; /* or 2 or 3 ... */
58 ft->encoding.bits_per_sample = 8; /* or 16 ... */
59 ft->encoding.encoding = SOX_ENCODING_UNSIGNED; /* or SIGN2 ... */
60 sox_append_comment(&ft->oob.comments, "any comment in file header.");
61
62 /* If your format doesn't have a header then samples_in_file
63 * can be determined by the file size.
64 */
65 samples_in_file = lsx_filelength(ft) / (ft->encoding.bits_per_sample >> 3);
66
67 /* If you can detect the length of your file, record it here. */
68 ft->signal.length = samples_in_file;
69 sk->remaining_samples = samples_in_file;
70
71 return SOX_SUCCESS;
72 }
73
74 /*
75 * Read up to len samples of type sox_sample_t from file into buf[].
76 * Return number of samples read, or 0 if at end of file.
77 */
read_samples(sox_format_t * ft,sox_sample_t * buf,size_t len)78 static size_t read_samples(sox_format_t * ft, sox_sample_t *buf, size_t len)
79 {
80 priv_t * UNUSED sk = (priv_t *)ft->priv;
81 size_t done;
82 unsigned char sample;
83
84 for (done = 0; done < len; done++) {
85 if (lsx_eof(ft) || lsx_readb(ft, &sample)) /* no more samples */
86 break;
87 switch (ft->encoding.bits_per_sample) {
88 case 8:
89 switch (ft->encoding.encoding) {
90 case SOX_ENCODING_UNSIGNED:
91 *buf++ = SOX_UNSIGNED_8BIT_TO_SAMPLE(sample,);
92 break;
93 default:
94 lsx_fail("Undetected sample encoding in read!");
95 return 0;
96 }
97 break;
98 default:
99 lsx_fail("Undetected bad sample size in read!");
100 return 0;
101 }
102 }
103
104 return done;
105 }
106
107 /*
108 * Do anything required when you stop reading samples.
109 * Don't close input file!
110 */
stopread(sox_format_t UNUSED * ft)111 static int stopread(sox_format_t UNUSED * ft)
112 {
113 return SOX_SUCCESS;
114 }
115
startwrite(sox_format_t * ft)116 static int startwrite(sox_format_t * ft)
117 {
118 priv_t * UNUSED sk = (priv_t *)ft->priv;
119
120 /* If you have to seek around the output file. */
121 /* If header contains a length value then seeking will be
122 * required. Instead of failing, it's sometimes nice to
123 * just set the length to max value and not fail.
124 */
125 if (!ft->seekable) {
126 lsx_fail("Output .skel file must be a file, not a pipe");
127 return SOX_EOF;
128 }
129
130 if (ft->signal.rate != 44100)
131 lsx_fail("Output .skel file must have a sample rate of 44100Hz");
132
133 if (ft->encoding.bits_per_sample == 0) {
134 lsx_fail("Did not specify a size for .skel output file");
135 return SOX_EOF;
136 }
137
138 /* error check ft->encoding.encoding */
139 /* error check ft->signal.channels */
140
141 /* Write file header, if any */
142 /* Write comment field, if any */
143
144 return SOX_SUCCESS;
145
146 }
147
148 /*
149 * Write len samples of type sox_sample_t from buf[] to file.
150 * Return number of samples written.
151 */
write_samples(sox_format_t * ft,const sox_sample_t * buf,size_t len)152 static size_t write_samples(sox_format_t * ft, const sox_sample_t *buf, size_t len)
153 {
154 priv_t * sk = (priv_t *)ft->priv;
155 size_t done = 0;
156
157 (void)sk;
158 switch (ft->encoding.bits_per_sample) {
159 case 8:
160 switch (ft->encoding.encoding) {
161 SOX_SAMPLE_LOCALS;
162 case SOX_ENCODING_UNSIGNED:
163 while (done < len && lsx_writeb(ft, SOX_SAMPLE_TO_UNSIGNED_8BIT(*buf++, ft->clips)) == SOX_SUCCESS)
164 ++done;
165 break;
166 default:
167 lsx_fail("Undetected bad sample encoding in write!");
168 return 0;
169 }
170 break;
171 default:
172 lsx_fail("Undetected bad sample size in write!");
173 return 0;
174 }
175 return done;
176 }
177
stopwrite(sox_format_t UNUSED * ft)178 static int stopwrite(sox_format_t UNUSED * ft)
179 {
180 /* All samples are already written out. */
181 /* If file header needs fixing up, for example it needs the number
182 of samples in a field, seek back and write them here. */
183 return SOX_SUCCESS;
184 }
185
seek(sox_format_t UNUSED * ft,uint64_t UNUSED offset)186 static int seek(sox_format_t UNUSED * ft, uint64_t UNUSED offset)
187 {
188 /* Seek relative to current position. */
189 return SOX_SUCCESS;
190 }
191
LSX_FORMAT_HANDLER(skel)192 LSX_FORMAT_HANDLER(skel)
193 {
194 /* Format file suffixes */
195 static const char *names[] = {"skel",NULL };
196
197 /* Encoding types and sizes that this handler can write */
198 static const unsigned encodings[] = {
199 SOX_ENCODING_SIGN2, 16, 0,
200 SOX_ENCODING_UNSIGNED, 8, 0,
201 0};
202
203 /* Format descriptor
204 * If no specific processing is needed for any of
205 * the 7 functions, then the function above can be deleted
206 * and NULL used in place of the its name below.
207 */
208 static sox_format_handler_t handler = {
209 SOX_LIB_VERSION_CODE,
210 "My first SoX format!",
211 names, 0,
212 startread, read_samples, stopread,
213 startwrite, write_samples, stopwrite,
214 seek, encodings, NULL, sizeof(priv_t)
215 };
216
217 return &handler;
218 }
219