"Fossies" - the Fresh Open Source Software Archive 
Member "xorriso-1.5.4/libburn/libdax_audioxtr.c" (30 Jan 2021, 10081 Bytes) of package /linux/misc/xorriso-1.5.4.pl02.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "libdax_audioxtr.c" see the
Fossies "Dox" file reference documentation and the last
Fossies "Diffs" side-by-side code changes report:
1.5.2_vs_1.5.4.
1
2 /* libdax_audioxtr
3 Audio track data extraction facility of libdax and libburn.
4 Copyright (C) 2006 Thomas Schmitt <scdbackup@gmx.net>, provided under GPLv2+
5 */
6
7 #ifdef HAVE_CONFIG_H
8 #include "../config.h"
9 #endif
10
11 #include <stdio.h>
12 #include <sys/types.h>
13 #include <sys/stat.h>
14 #include <fcntl.h>
15 #include <unistd.h>
16 #include <string.h>
17 #include <stdlib.h>
18 #include <errno.h>
19
20 /* ts B41126 : O_BINARY is needed for Cygwin but undefined elsewhere */
21 #ifndef O_BINARY
22 #define O_BINARY 0
23 #endif
24
25 #include "libdax_msgs.h"
26 extern struct libdax_msgs *libdax_messenger;
27
28
29 /* Only this single source module is entitled to do this */
30 #define LIBDAX_AUDIOXTR_H_INTERNAL 1
31
32 /* All clients of the extraction facility must do this or include libburn.h */
33 #define LIBDAX_AUDIOXTR_H_PUBLIC 1
34 #include "libdax_audioxtr.h"
35
36
37 int libdax_audioxtr_new(struct libdax_audioxtr **xtr, char *path, int flag)
38 {
39 int ret= -1;
40 struct libdax_audioxtr *o;
41
42 o= *xtr= (struct libdax_audioxtr *) calloc(1, sizeof(struct libdax_audioxtr));
43 if(o==NULL)
44 return(-1);
45 strncpy(o->path,path,LIBDAX_AUDIOXTR_STRLEN-1);
46 o->path[LIBDAX_AUDIOXTR_STRLEN-1]= 0;
47 o->fd= -1;
48 strcpy(o->fmt,"unidentified");
49 o->fmt_info[0]= 0;
50 o->data_size= 0;
51 o->extract_count= 0;
52
53 o->num_channels= 0;
54 o->sample_rate= 0;
55 o->bits_per_sample= 0;
56 o->msb_first= 0;
57
58 o->wav_data_location= 44;
59 o->wav_subchunk2_size= 0;
60
61 o->au_data_location= 0;
62 o->au_data_size= 0xffffffff;
63
64 ret= libdax_audioxtr_open(o,0);
65 if(ret<=0)
66 {ret= -2*(ret<0); goto failure;}
67
68 return(1);
69 failure:
70 libdax_audioxtr_destroy(xtr,0);
71 return(ret);
72 }
73
74
75 int libdax_audioxtr_destroy(struct libdax_audioxtr **xtr, int flag)
76 {
77 struct libdax_audioxtr *o;
78
79 o= *xtr;
80 if(o==NULL)
81 return(0);
82 if(o->fd>=0 && strcmp(o->path,"-")!=0)
83 close(o->fd);
84 free((char *) o);
85 *xtr= NULL;
86 return(1);
87 }
88
89
90 static int libdax_audioxtr_open(struct libdax_audioxtr *o, int flag)
91 {
92 int ret;
93 char msg[LIBDAX_AUDIOXTR_STRLEN+80];
94
95 if(strcmp(o->path,"-")==0)
96 o->fd= 0;
97 else
98 o->fd= open(o->path, O_RDONLY | O_BINARY);
99 if(o->fd<0) {
100 sprintf(msg,"Cannot open audio source file : %s",o->path);
101 libdax_msgs_submit(libdax_messenger,-1,0x00020200,
102 LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
103 msg, errno, 0);
104 return(-1);
105 }
106 ret= libdax_audioxtr_identify(o,0);
107 if(ret<=0) {
108 sprintf(msg,"Audio source file has unsuitable format : %s",o->path);
109 libdax_msgs_submit(libdax_messenger,-1,0x00020201,
110 LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
111 msg, 0, 0);
112 return(0);
113 }
114 ret= libdax_audioxtr_init_reading(o,0);
115 if(ret<=0) {
116 sprintf(msg,"Failed to prepare reading of audio data : %s",o->path);
117 libdax_msgs_submit(libdax_messenger,-1,0x00020202,
118 LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
119 msg, 0, 0);
120 return(0);
121 }
122 return(1);
123 }
124
125 /* @param flag: bit0= sequential file, skip by reading data
126 */
127 static int libdax_audioxtr_skip(struct libdax_audioxtr *o,
128 off_t *old_pos,
129 off_t pos, int flag)
130 {
131 int ret;
132 size_t to_read;
133 static char buf[256]; /* Thread safe because the content does not matter */
134
135 if((flag & 1) || o->fd == 0) { /* stdin */
136 while(pos - *old_pos > 0) {
137 to_read= pos - *old_pos;
138 if(to_read > sizeof(buf))
139 to_read= sizeof(buf);
140 ret= read(o->fd, buf, to_read);
141 if(ret < (int) to_read)
142 return(0);
143 *old_pos+= to_read;
144 }
145 } else {
146 ret= lseek(o->fd, pos, SEEK_SET);
147 if(ret == -1)
148 return(0);
149 *old_pos= pos;
150 }
151 return(1);
152 }
153
154 static int libdax_audioxtr_identify_wav(struct libdax_audioxtr *o, int flag)
155 {
156 int ret, fmt_seen= 0, data_seen= 0;
157 off_t pos= 0, old_pos= 0, riff_end= 0;
158 char buf[16];
159 unsigned char *ubuf;
160
161 /* check whether this is a MS WAVE file .wav */
162 /* info used: http://ccrma.stanford.edu/courses/422/projects/WaveFormat/
163 https://en.wikipedia.org/wiki/WAV
164 see summary in: doc/waveformat.txt
165 */
166 ubuf= (unsigned char *) buf;
167
168 /* Look for ChunkID "RIFF" , tolerate other known chunks */
169 while(1) {
170 ret= libdax_audioxtr_skip(o, &old_pos, pos, 0);
171 if(ret <= 0)
172 return(0);
173 ret= read(o->fd, buf, 8);
174 if(ret < 8)
175 return(0);
176 old_pos+= 8;
177 pos= old_pos + libdax_audioxtr_to_int(o, ubuf + 4, 4, 0);
178 if(pos > 0xffffffff || pos - old_pos < 4) /* Too large or no Format word */
179 return(0);
180 if(strncmp(buf, "RIFF", 4) == 0)
181 break;
182 /* Wikipedia mentions these known ChunkId values */
183 if(strncmp(buf, "INFO", 4) == 0 ||
184 strncmp(buf, "CSET", 4) == 0 ||
185 strncmp(buf, "JUNK", 4) == 0 ||
186 strncmp(buf, "PAD ", 4) == 0)
187 continue;
188 return(0);
189 }
190
191 /* Read RIFF Format header */
192 ret= read(o->fd, buf, 4);
193 if(ret < 4)
194 return(0);
195 old_pos+= 4;
196 if(strncmp(buf, "WAVE", 4) != 0) /* Format */
197 return(0);
198 riff_end= pos;
199
200 /* Look for SubchunkID "fmt " and "data" */
201 pos= old_pos;
202 while(old_pos < riff_end) {
203 ret= libdax_audioxtr_skip(o, &old_pos, pos, 0);
204 if(ret <= 0)
205 return(0);
206 ret= read(o->fd, buf, 8);
207 if(ret < 8)
208 return(0);
209 old_pos= pos + 8;
210 pos= old_pos + libdax_audioxtr_to_int(o, ubuf + 4, 4, 0); /* SubchunkSize */
211
212 if(strncmp(buf,"fmt ", 4) == 0) {
213 if(pos - old_pos < 16)
214 return(0);
215 ret= read(o->fd, buf, 16);
216 if(ret < 16)
217 return(0);
218 old_pos+= 16;
219 if(buf[0]!=1 || buf[1]!=0) /* AudioFormat (1 = Linear quantization) */
220 return(0);
221 o->msb_first= 0;
222 o->num_channels= libdax_audioxtr_to_int(o, ubuf + 2 , 2, 0);
223 o->sample_rate= libdax_audioxtr_to_int(o, ubuf + 4, 4, 0);
224 o->bits_per_sample= libdax_audioxtr_to_int(o, ubuf + 14, 2, 0);
225 sprintf(o->fmt_info,
226 ".wav , num_channels=%d , sample_rate=%d , bits_per_sample=%d",
227 o->num_channels, o->sample_rate, o->bits_per_sample);
228 fmt_seen= 1;
229
230 } else if(strncmp(buf,"data", 4) == 0) {
231 o->wav_data_location= old_pos;
232 o->wav_subchunk2_size= pos - old_pos;
233 o->data_size= o->wav_subchunk2_size;
234 data_seen= 1;
235 }
236 if(fmt_seen && data_seen) {
237 strcpy(o->fmt,".wav");
238 return(1);
239 }
240 }
241 return(0);
242 }
243
244
245 static int libdax_audioxtr_identify_au(struct libdax_audioxtr *o, int flag)
246 {
247 int ret,encoding;
248 char buf[24];
249
250 /* Check whether this is a Sun Audio, .au file */
251 /* info used: http://ccrma.stanford.edu/courses/422/projects/WaveFormat/ */
252
253 if(o->fd!=0) {
254 ret= lseek(o->fd,0,SEEK_SET);
255 if(ret==-1)
256 return(0);
257 }
258 ret= read(o->fd, buf, 24);
259 if(ret<24)
260 return(0);
261
262 if(strncmp(buf,".snd",4)!=0)
263 return(0);
264 strcpy(o->fmt,".au");
265 o->msb_first= 1;
266 o->au_data_location= libdax_audioxtr_to_int(o,(unsigned char *)buf+4,4,1);
267 o->au_data_size= libdax_audioxtr_to_int(o,(unsigned char *)buf+8,4,1);
268 encoding= libdax_audioxtr_to_int(o,(unsigned char *)buf+12,4,1);
269 if(encoding==2)
270 o->bits_per_sample= 8;
271 else if(encoding==3)
272 o->bits_per_sample= 16;
273 else if(encoding==4)
274 o->bits_per_sample= 24;
275 else if(encoding==5)
276 o->bits_per_sample= 32;
277 else
278 o->bits_per_sample= -encoding;
279 o->sample_rate= libdax_audioxtr_to_int(o,(unsigned char *)buf+16,4,1);
280 o->num_channels= libdax_audioxtr_to_int(o,(unsigned char *)buf+20,4,1);
281 if(o->au_data_size!=0xffffffff)
282 o->data_size= o->au_data_size;
283 else
284 o->data_size= 0;
285 sprintf(o->fmt_info,
286 ".au , num_channels=%d , sample_rate=%d , bits_per_sample=%d",
287 o->num_channels,o->sample_rate,o->bits_per_sample);
288 return(o->bits_per_sample>0); /* Audio format must be linear PCM */
289 }
290
291
292 static int libdax_audioxtr_identify(struct libdax_audioxtr *o, int flag)
293 {
294 int ret;
295
296 ret= libdax_audioxtr_identify_wav(o, 0);
297 if(ret!=0)
298 return(ret);
299 if(o->fd==0) /* cannot rewind stdin */
300 return(0);
301 ret= libdax_audioxtr_identify_au(o, 0);
302 if(ret!=0)
303 return(ret);
304 return(0);
305 }
306
307
308 /* @param flag bit0=msb_first */
309 static unsigned libdax_audioxtr_to_int(struct libdax_audioxtr *o,
310 unsigned char *bytes, int len, int flag)
311 {
312 unsigned int ret= 0;
313 int i;
314
315 if(flag&1)
316 for(i= 0; i<len; i++)
317 ret= ret*256+bytes[i];
318 else
319 for(i= len-1; i>=0; i--)
320 ret= ret*256+bytes[i];
321 return(ret);
322 }
323
324
325 static int libdax_audioxtr_init_reading(struct libdax_audioxtr *o, int flag)
326 {
327 int ret;
328
329
330 /* currently this only works for MS WAVE files .wav and Sun .au*/;
331 if(o->fd==0) /* stdin: hope no read came after libdax_audioxtr_identify() */
332 return(1);
333
334 o->extract_count= 0;
335 if(strcmp(o->fmt,".wav")==0)
336 ret= lseek(o->fd, o->wav_data_location, SEEK_SET);
337 else if(strcmp(o->fmt,".au")==0)
338 ret= lseek(o->fd,o->au_data_location,SEEK_SET);
339 else
340 ret= -1;
341 if(ret==-1)
342 return(0);
343
344 return(1);
345 }
346
347
348 int libdax_audioxtr_get_id(struct libdax_audioxtr *o,
349 char **fmt, char **fmt_info,
350 int *num_channels, int *sample_rate, int *bits_per_sample,
351 int *msb_first, int flag)
352 {
353 *fmt= o->fmt;
354 *fmt_info= o->fmt_info;
355 *num_channels= o->num_channels;
356 *sample_rate= o->sample_rate;
357 *bits_per_sample= o->bits_per_sample;
358 *msb_first= o->msb_first;
359 return(1);
360 }
361
362
363 int libdax_audioxtr_get_size(struct libdax_audioxtr *o, off_t *size, int flag)
364 {
365 *size= o->data_size;
366 return(1);
367 }
368
369
370 int libdax_audioxtr_read(struct libdax_audioxtr *o,
371 char buffer[], int buffer_size, int flag)
372 {
373 int ret;
374
375 if(buffer_size<=0 || o->fd<0)
376 return(-2);
377 if(o->data_size>0 && !(flag&1))
378 if(buffer_size > o->data_size - o->extract_count)
379 buffer_size= o->data_size - o->extract_count;
380 if(buffer_size<=0)
381 return(0);
382 ret= read(o->fd,buffer,buffer_size);
383 if(ret>0)
384 o->extract_count+= ret;
385 return(ret);
386 }
387
388
389 int libdax_audioxtr_detach_fd(struct libdax_audioxtr *o, int *fd, int flag)
390 {
391 if(o->fd<0)
392 return(-1);
393 if(strcmp(o->fmt,".wav")!=0 && strcmp(o->fmt,".au")!=0)
394 return(0);
395 if(flag&1) {
396 *fd= o->fd;
397 } else {
398 *fd= dup(o->fd);
399 if(*fd>=0 && strcmp(o->path,"-")!=0)
400 close(o->fd);
401 }
402 if(*fd>=0) {
403 o->fd= -1;
404 return(1);
405 }
406 return(-1);
407 }
408