1 // Copyright (C) 2008-2011 David Sugar, Tycho Softworks.
2 //
3 // This file is part of GNU Bayonne.
4 //
5 // GNU Bayonne is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // GNU Bayonne is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with GNU Bayonne. If not, see <http://www.gnu.org/licenses/>.
17
18 #include <config.h>
19 #include <ucommon/ucommon.h>
20 #include <ucommon/export.h>
22
23 #if defined(__GNUC__)
24 #define _PACKED
25 #elif !defined(__hpux) && !defined(_AIX)
27 #endif
28
29 #if !defined(__BIG_ENDIAN)
30 #define __LITTLE_ENDIAN 1234
31 #define __BIG_ENDIAN 4321
32 #define __PDP_ENDIAN 3412
33 #define __BYTE_ORDER __LITTLE_ENDIAN
34 #endif
35
37 using namespace UCOMMON_NAMESPACE;
38
39 AudioFile::AudioFile(const char *name, unsigned long sample)
40 {
41 pathname = NULL;
42 initialize();
43 AudioFile::open(name);
44 if(!is_open())
45 return;
46 setPosition(sample);
47 }
48
49 AudioFile::AudioFile(const char *name, info_t& inf, unsigned long samples)
50 {
51 info = inf;
52 pathname = NULL;
53 initialize();
54 AudioFile::create(name, inf);
55 if(!is_open())
56 return;
57 setMinimum(samples);
58 }
59
60 AudioFile::AudioFile()
61 {
62 pathname = NULL;
63 initialize();
64 }
65
66 AudioFile::~AudioFile()
67 {
68 AudioFile::close();
69 AudioFile::clear();
70 }
71
72 ssize_t AudioFile::read(void *buffer, size_t request)
73 {
74 ssize_t result = fs.read(buffer, request);
75 if(result > 0)
76 pos += result;
77 if(pos > eof)
78 eof = pos;
79 return result;
80 }
81
82 ssize_t AudioFile::write(void *buffer, size_t request)
83 {
84 ssize_t result = fs.write(buffer, request);
85 if(result > 0)
86 pos += result;
87 if(pos > eof)
88 eof = pos;
89 return result;
90 }
91
92 ssize_t AudioFile::peek(void *buffer, size_t request)
93 {
94 ssize_t result = fs.read(buffer, request);
95 if(result > 0)
96 fs.seek(pos);
97 return result;
98 }
99
100 bool AudioFile::seek(size_t offset)
101 {
102 if(!fs.seek(offset)) {
103 pos = offset;
104 return true;
105 }
106 return false;
107 }
108
110 {
111 encoding_t e = getEncoding();
112 switch(e) {
113 case alawAudio:
114 return AudioCodec::get(e, "g.711");
115 case mulawAudio:
116 return AudioCodec::get(e, "g.711");
117 case g721ADPCM:
118 case okiADPCM:
119 case voxADPCM:
120 return AudioCodec::get(e, "g.721");
121 case g722_7bit:
122 case g722_6bit:
123 return AudioCodec::get(e, "g.722");
124 case g723_3bit:
125 case g723_5bit:
126 return AudioCodec::get(e, "g.723");
127 default:
128 return NULL;
129 }
130 }
131
132 void AudioFile::setShort(unsigned char *data, unsigned short val)
133 {
135 data[0] = val / 256;
136 data[1] = val % 256;
137 }
138 else {
139 data[1] = val / 256;
140 data[0] = val % 256;
141 }
142 }
143
144 unsigned short AudioFile::getShort(unsigned char *data) const
145 {
147 return data[0] * 256 + data[1];
148 else
149 return data[1] * 256 + data[0];
150 }
151
152 void AudioFile::setLong(unsigned char *data, unsigned long val)
153 {
154 int i = 4;
155
156 while(i-- > 0) {
158 data[i] = (unsigned char)(val & 0xff);
159 else
160 data[3 - i] = (unsigned char)(val & 0xff);
161 val /= 256;
162 }
163 }
164
165 unsigned long AudioFile::getLong(unsigned char * data) const
166 {
167 int i = 4;
168 unsigned long val =0;
169
170 while(i-- > 0) {
172 val = (val << 8) | data[3 - i];
173 else
174 val = (val << 8) | data[i];
175 }
176 return val;
177 }
178
179 ssize_t AudioFile::putNative(encoded_t data, size_t bytes)
180 {
181 if(!is(fs))
182 return 0;
183
184 swapEncoded(info, data, bytes);
185 return putBuffer(data, bytes);
186 }
187
188 ssize_t AudioFile::getNative(encoded_t data, size_t bytes)
189 {
190 ssize_t result = 0;
191
192 if(is(fs))
193 result = getBuffer(data, bytes);
194
195 if(result < 1)
196 return result;
197
198 swapEncoded(info, data, result);
199 return result;
200 }
201
202 void AudioFile::create(const char *name, info_t& myinfo, timeout_t framing)
203 {
204 int pcm = 0;
205 unsigned char aufile[24];
206 unsigned char riffhdr[40];
207 const char *ext = strrchr(name, '/');
208 pos = 0l;
209
210 if(!ext)
211 ext = strrchr(name, '\\');
212
213 if(!ext)
214 ext = strrchr(name, ':');
215
216 if(!ext)
217 ext = strrchr(name, '.');
218 else
219 ext = strrchr(ext, '.');
220
221 if(!ext)
222 ext = ".none";
223
224 mode = modeWrite;
225 fs.create(name, fsys::ACCESS_STREAM, 0660);
226 if(!is(fs))
227 return;
228
229 memset(riffhdr, 0, sizeof(riffhdr));
230 info = myinfo;
231 info.annotation = NULL;
232 pathname = new char[strlen(name) + 1];
233 strcpy(pathname, name);
234 if(myinfo.annotation) {
235 info.annotation = new char[strlen(myinfo.annotation) + 1];
236 strcpy(info.annotation, myinfo.annotation);
237 }
238
239 if(!stricmp(ext, ".raw") || !stricmp(ext, ".bin")) {
240 info.format = raw;
241 if(info.encoding == unknownEncoding)
242 info.encoding = pcm16Mono;
243 }
244 else if(!stricmp(ext, ".au") || !stricmp(ext, ".snd"))
245 {
246 info.order = 0;
247 info.format = snd;
248 }
249 else if(!stricmp(ext, ".wav") || !stricmp(ext, ".wave"))
250 {
251 info.order = 0;
252 info.format = wave;
253 }
254 else if(!stricmp(ext, ".ul") || !stricmp(ext, ".ulaw") || !stricmp(ext, ".mulaw"))
255 {
256 info.encoding = mulawAudio;
257 info.format = raw;
258 info.order = 0;
259 info.rate = 8000;
260 }
261 else if(!stricmp(ext, ".al") || !stricmp(ext, ".alaw"))
262 {
263 info.encoding = alawAudio;
264 info.format = raw;
265 info.order = 0;
266 info.rate = 8000;
267 }
268 else if(!stricmp(ext, ".sw") || !stricmp(ext, ".pcm"))
269 {
270 info.encoding = pcm16Mono;
271 info.format = raw;
272 info.order = 0;
273 }
274 else if(!stricmp(ext, ".vox"))
275 {
276 info.encoding = voxADPCM;
277 info.format = raw;
278 info.order = 0;
279 info.rate = 6000;
280 }
281 else if(!stricmp(ext, ".gsm"))
282 {
283 info.encoding = gsmVoice;
284 info.format = raw;
285 info.order = 0;
286 info.rate = 8000;
287 info.framecount = 160;
288 info.framesize = 33;
289 info.bitrate = 13200;
290 }
291 else if(!stricmp(ext, ".adpcm") || !stricmp(ext, ".a32"))
292 {
293 info.encoding = g721ADPCM;
294 info.format = raw;
295 info.order = 0;
296 info.rate = 8000;
297 }
298 else if(!stricmp(ext, ".a24"))
299 {
300 info.encoding = g723_3bit;
301 info.format = raw;
302 info.order = 0;
303 info.rate = 8000;
304 }
305 else if(!stricmp(ext, ".a16"))
306 {
307 info.encoding = g723_2bit;
308 info.format = raw;
309 info.order = 0;
310 info.order = 8000;
311 }
312 else if(!stricmp(ext, ".sx"))
313 {
314 info.encoding = sx96Voice;
315 info.format = raw;
316 info.order = 0;
317 info.rate = 8000;
318 }
319 else if(!stricmp(ext, ".a40"))
320 {
321 info.encoding = g723_5bit;
322 info.format = raw;
323 info.order = 0;
324 info.rate = 8000;
325 }
326 else if(!stricmp(ext, ".cda"))
327 {
328 info.encoding = cdaStereo;
329 info.format = raw;
331 info.rate = 44100;
332 }
333
334 switch(info.format) {
335 case wave:
336 case riff:
337 /*
338 * RIFF header
339 *
340 * 12 bytes
341 *
342 * 0-3: RIFF magic "RIFF" (0x52 49 46 46)
343 *
344 * 4-7: RIFF header chunk size
345 * (4 + (8 + subchunk 1 size) + (8 + subchunk 2 size))
346 *
347 * 8-11: WAVE RIFF type magic "WAVE" (0x57 41 56 45)
348 */
349 if(!info.order)
352 strncpy((char *)riffhdr, "RIFF", 4);
353 else
354 strncpy((char *)riffhdr, "RIFX", 4);
355 if(!info.rate)
356 info.rate = Audio::getRate(info.encoding);
357 if(!info.rate)
358 info.rate = rate8khz;
359
360 header = 0;
361
362 memset(riffhdr + 4, 0xff, 4);
363 strncpy((char *)riffhdr + 8, "WAVE", 4);
364 if(write(riffhdr, 12) != 12) {
365 AudioFile::close();
366 return;
367 }
368
369 /*
370 * Subchunk 1: WAVE metadata
371 *
372 * Length: 24+
373 *
374 * (offset from start of subchunk 1) startoffset-endoffset
375 *
376 * (0) 12-15: WAVE metadata magic "fmt " (0x 66 6d 74 20)
377 *
378 * (4) 16-19: subchunk 1 size minus 8. 0x10 for PCM.
379 *
380 * (8) 20-21: Audio format code. 0x01 for linear PCM.
381 * More codes here:
382 * http://www.goice.co.jp/member/mo/formats/wav.html
383 *
384 * (10) 22-23: Number of channels. Mono = 0x01,
385 * Stereo = 0x02.
386 *
387 * (12) 24-27: Sample rate in samples per second. (8000,
388 * 44100, etc)
389 *
390 * (16) 28-31: Bytes per second = SampleRate *
391 * NumChannels * (BitsPerSample / 8)
392 *
393 * (20) 32-33: Block align (the number of bytes for
394 * one multi-channel sample) = Numchannels *
395 * (BitsPerSample / 8)
396 *
397 * (22) 34-35: Bits per single-channel sample. 8 bits
398 * per channel sample = 0x8, 16 bits per channel
399 * sample = 0x10
400 *
401 * (24) 36-37: Size of extra PCM parameters for
402 * non-PCM formats. If a PCM format code is
403 * specified, this doesn't exist.
404 *
405 * Subchunk 3: Optional 'fact' subchunk for non-PCM formats
406 * (26) 38-41: WAVE metadata magic 'fact' (0x 66 61 63 74)
407 *
408 * (30) 42-45: Length of 'fact' subchunk, not
409 * including this field and the fact
410 * identification field (usually 4)
411 *
412 * (34) 46-49: ??? sndrec32.exe outputs 0x 00 00 00 00
413 * here. See
414 * http://www.health.uottawa.ca/biomech/csb/ARCHIVES/riff-for.txt
415 *
416 */
417
418 memset(riffhdr, 0, sizeof(riffhdr));
419 strncpy((char *)riffhdr, "fmt ", 4);
420 // FIXME A bunch of the following only works for PCM
421 // and mulaw/alaw, so you'll probably have to fix it
422 // if you want to use one of the other formats.
423 if(info.encoding < cdaStereo)
424 setLong(riffhdr + 4, 18);
425 else
426 setLong(riffhdr + 4, 16);
427
428 setShort(riffhdr + 8, 0x01); // default in case invalid encoding specified
429 if(is_mono(info.encoding))
430 setShort(riffhdr + 10, 1);
431 else
432 setShort(riffhdr + 10, 2);
433 setLong(riffhdr + 12, info.rate);
434 setLong(riffhdr + 16, (unsigned long)toBytes(info, info.rate));
435 setShort(riffhdr + 20, (snd16_t)toBytes(info, 1));
436 setShort(riffhdr + 22, 0);
437
438 switch(info.encoding) {
439 case pcm8Mono:
440 case pcm8Stereo:
441 setShort(riffhdr + 22, 8);
442 pcm = 1;
443 break;
444 case pcm16Mono:
445 case pcm16Stereo:
446 case cdaMono:
447 case cdaStereo:
448 setShort(riffhdr + 22, 16);
449 pcm = 1;
450 break;
451 case pcm32Mono:
452 case pcm32Stereo:
453 setShort(riffhdr + 22, 32);
454 pcm = 1;
455 break;
456 case alawAudio:
457 setShort(riffhdr + 8, 6);
458 setShort(riffhdr + 22, 8);
459 break;
460 case mulawAudio:
461 setShort(riffhdr + 8, 7);
462 setShort(riffhdr + 22, 8);
463 break;
464
465 // FIXME I'm pretty sure these are supposed to
466 // be writing to offset 22 instead of 24...
467 case okiADPCM:
468 setShort(riffhdr + 8, 0x10);
469 setShort(riffhdr + 24, 4);
470 break;
471 case voxADPCM:
472 setShort(riffhdr + 8, 0x17);
473 setShort(riffhdr + 24, 4);
474 break;
475 case g721ADPCM:
476 setShort(riffhdr + 8, 0x40);
477 setShort(riffhdr + 24, 4);
478 break;
479 case g722Audio:
480 setShort(riffhdr + 8, 0x64);
481 setShort(riffhdr + 24, 8);
482 break;
483 case gsmVoice:
484 case msgsmVoice:
485 setShort(riffhdr + 8, 0x31);
486 setShort(riffhdr + 24, 260);
487 break;
488 case g723_3bit:
489 setShort(riffhdr + 8, 0x14);
490 setShort(riffhdr + 24, 3);
491 break;
492 case g723_5bit:
493 setShort(riffhdr + 8, 0x14);
494 setShort(riffhdr + 24, 5);
495 case unknownEncoding:
496 default:
497 break;
498 }
499
500 if(pcm == 0) {
501 setShort(riffhdr + 24, 0);
502 strncpy((char *)(riffhdr + 26), "fact", 4);
503 setLong(riffhdr + 30, 4);
504 setLong(riffhdr + 34, 0);
505 if(write(riffhdr, 38) != 38) {
506 AudioFile::close();
507 return;
508 }
509 }
510 else {
511 if(write(riffhdr, 24) != 24) {
512 AudioFile::close();
513 return;
514 }
515 }
516
517 /*
518 * Subchunk 2: data subchunk
519 *
520 * Length: 8+
521 *
522 * (0) 36-39: data subchunk magic "data" (0x 64 61 74 61)
523 *
524 * (4) 40-43: subchunk 2 size =
525 * NumSamples * NumChannels * (BitsPerSample / 8)
526 * Note that this does not include the size of this
527 * field and the previous one.
528 *
529 * (8) 44+: Samples
530 */
531
532 memset(riffhdr, 0, sizeof(riffhdr));
533 strncpy((char *)riffhdr, "data", 4);
534 memset(riffhdr + 4, 0xff, 4);
535 if(write(riffhdr, 8) != 8) {
536 AudioFile::close();
537 return;
538 }
539
540 header = getAbsolutePosition();
541 break;
542
543 case snd:
544 // if(!info.order)
546
547 if(!info.rate)
548 info.rate = Audio::getRate(info.encoding);
549 if(!info.rate)
550 info.rate = rate8khz;
551
552 strncpy((char *)aufile, ".snd", 4);
553 if(info.annotation)
554 setLong(aufile + 4, 24 + (unsigned long)strlen(info.annotation) + 1);
555 else
556 setLong(aufile + 4, 24);
557 header = getLong(aufile + 4);
558 setLong(aufile + 8, ~0l);
559 switch(info.encoding) {
560 case pcm8Stereo:
561 case pcm8Mono:
562 setLong(aufile + 12, 2);
563 break;
564 case pcm16Stereo:
565 case pcm16Mono:
566 case cdaStereo:
567 case cdaMono:
568 setLong(aufile + 12, 3);
569 break;
570 case pcm32Stereo:
571 case pcm32Mono:
572 setLong(aufile + 12, 5);
573 break;
574 case g721ADPCM:
575 setLong(aufile + 12, 23);
576 break;
577 case g722Audio:
578 case g722_7bit:
579 case g722_6bit:
580 setLong(aufile + 12, 24);
581 break;
582 case g723_3bit:
583 setLong(aufile + 12, 25);
584 break;
585 case g723_5bit:
586 setLong(aufile + 12, 26);
587 break;
588 case gsmVoice:
589 setLong(aufile + 12, 28);
590 break;
591 case alawAudio:
592 setLong(aufile + 12, 27);
593 break;
594 default:
595 setLong(aufile + 12, 1);
596 }
597 setLong(aufile + 16, info.rate);
598 if(is_mono(info.encoding))
599 setLong(aufile + 20, 1);
600 else
601 setLong(aufile + 20, 2);
602 if(write(aufile, 24) != 24) {
603 AudioFile::close();
604 return;
605 }
606 if(info.annotation)
607 write((unsigned char *)info.annotation, (unsigned long)strlen(info.annotation) + 1);
608 header = getAbsolutePosition();
609 break;
610 case raw:
611 break;
612 }
613 if(framing)
614 info.setFraming(framing);
615 else
616 info.set();
617 }
618
619 void AudioFile::getWaveFormat(int request)
620 {
621 unsigned char filehdr[24];
622 int bitsize;
623 int channels;
624
625 if(request > 24)
626 request = 24;
627
628 if(peek(filehdr, request) < 1) {
629 AudioFile::close();
630 return;
631 }
632 channels = getShort(filehdr + 2);
633 info.rate = getLong(filehdr + 4);
634
635 switch(getShort(filehdr)) {
636 case 1:
637 bitsize = getShort(filehdr + 14);
638 switch(bitsize) {
639 case 8:
640 if(channels > 1)
641 info.encoding = pcm8Stereo;
642 else
643 info.encoding = pcm8Mono;
644 break;
645 case 16:
646 if(info.rate == 44100) {
647 if(channels > 1)
648 info.encoding = cdaStereo;
649 else
650 info.encoding = cdaMono;
651 break;
652 }
653 if(channels > 1)
654 info.encoding = pcm16Stereo;
655 else
656 info.encoding = pcm16Mono;
657 break;
658 case 32:
659 if(channels > 1)
660 info.encoding = pcm32Stereo;
661 else
662 info.encoding = pcm32Mono;
663 break;
664 default:
665 info.encoding = unknownEncoding;
666 }
667 break;
668 case 6:
669 info.encoding = alawAudio;
670 break;
671 case 7:
672 info.encoding = mulawAudio;
673 break;
674 case 0x10:
675 info.encoding = okiADPCM;
676 break;
677 case 0x17:
678 info.encoding = voxADPCM;
679 break;
680 case 0x40:
681 info.encoding = g721ADPCM;
682 break;
683 case 0x65:
684 info.encoding = g722Audio;
685 break;
686 case 0x31:
687 info.encoding = msgsmVoice;
688 break;
689 case 0x14:
690 bitsize = getLong(filehdr + 8) * 8 / info.rate;
691 if(bitsize == 3)
692 info.encoding = g723_3bit;
693 else
694 info.encoding = g723_5bit;
695 break;
696 default:
697 info.encoding = unknownEncoding;
698 }
699 }
700
701 void AudioFile::open(const char *name, mode_t m, timeout_t framing)
702 {
703 unsigned char filehdr[24];
704 unsigned int count;
705 char *ext;
706 unsigned channels;
707 mode = m;
708 pos = 0;
709 fsys::access_t fm;
710 fsys::fileinfo_t ino;
711
712 switch(mode) {
713 case modeWrite:
714 fm = fsys::ACCESS_REWRITE;
715 break;
716 case modeAppend:
717 fm = fsys::ACCESS_APPEND;
718 break;
719 default:
720 fm = fsys::ACCESS_STREAM;
721 }
722
723 for(;;) {
724 fs.open(name, fm);
725 if(is(fs))
726 break;
727
728 fsys::fileinfo(name, &ino);
729 eof = ino.st_size;
730
731 if(mode == modeReadAny || mode == modeReadOne)
732 name = getContinuation();
733 else
734 name = NULL;
735 }
736
737 if(!name)
738 return;
739
740 pathname = new char[strlen(name) + 1];
741 strcpy(pathname, name);
742 header = 0l;
743
744 info.framesize = 0;
745 info.framecount = 0;
746 info.encoding = mulawAudio;
747 info.format = raw;
748 info.order = 0;
749 ext = strrchr(pathname, '.');
750 if(!ext)
751 goto done;
752
753 info.encoding = Audio::getEncoding(ext);
754 switch(info.encoding) {
755 case cdaStereo:
757 break;
758 case unknownEncoding:
759 info.encoding = mulawAudio;
760 default:
761 break;
762 }
763
764 strcpy((char *)filehdr, ".xxx");
765
766 if(peek(filehdr, 24) < 1) {
767 AudioFile::close();
768 return;
769 }
770
771 if(!strncmp((char *)filehdr, "RIFF", 4)) {
772 info.format = riff;
774 }
775
776 if(!strncmp((char *)filehdr, "RIFX", 4)) {
778 info.format = riff;
779 }
780
781 if(!strncmp((char *)filehdr + 8, "WAVE", 4) && info.format == riff) {
782 header = 12;
783 for(;;)
784 {
785 if(!seek(header)) {
786 AudioFile::close();
787 return;
788 }
789 if(peek(filehdr, 8) < 1) {
790 AudioFile::close();
791 return;
792 }
793 header += 8;
794 if(!strncmp((char *)filehdr, "data", 4))
795 break;
796
797 count = getLong(filehdr + 4);
798 header += count;
799 if(!strncmp((char *)filehdr, "fmt ", 4))
800 getWaveFormat(count);
801
802 }
803 seek(header);
804 goto done;
805 }
806
807 if(!strncmp((char *)filehdr, ".snd", 4)) {
808 info.format = snd;
810 header = getLong(filehdr + 4);
811 info.rate = getLong(filehdr + 16);
812 channels = getLong(filehdr + 20);
813
814 switch(getLong(filehdr + 12)) {
815 case 2:
816 if(channels > 1)
817 info.encoding = pcm8Stereo;
818 else
819 info.encoding = pcm8Mono;
820 break;
821 case 3:
822 if(info.rate == 44100) {
823 if(channels > 1)
824 info.encoding = cdaStereo;
825 else
826 info.encoding = cdaMono;
827 break;
828 }
829 if(channels > 1)
830 info.encoding = pcm16Stereo;
831 else
832 info.encoding = pcm16Mono;
833 break;
834 case 5:
835 if(channels > 1)
836 info.encoding = pcm32Stereo;
837 else
838 info.encoding = pcm32Mono;
839 break;
840 case 23:
841 info.encoding = g721ADPCM;
842 break;
843 case 24:
844 info.encoding = g722Audio;
845 break;
846 case 25:
847 info.encoding = g723_3bit;
848 break;
849 case 26:
850 info.encoding = g723_5bit;
851 break;
852 case 27:
853 info.encoding = alawAudio;
854 break;
855 case 28:
856 info.encoding = gsmVoice;
857 break;
858 case 1:
859 info.encoding = mulawAudio;
860 break;
861 default:
862 info.encoding = unknownEncoding;
863 }
864 if(header > 24) {
865 info.annotation = new char[header - 24];
866 seek(24);
867 read((unsigned char *)info.annotation, header - 24);
868 }
869 goto done;
870 }
871
872 seek(0);
873
874 done:
875 info.headersize = 0;
876 if(framing)
877 info.setFraming(framing);
878 else
879 info.set();
880
881 if(mode == modeFeed) {
882 fsys::fileinfo_t ino;
883 fsys::fileinfo(name, &ino);
884 iolimit = ino.st_size;
885 }
886 }
887
888 void AudioFile::close(void)
889 {
890 unsigned char buf[58];
891
892 if(!is(fs))
893 return;
894
895 if(mode != modeWrite) {
896 fs.close();
897 clear();
898 return;
899 }
900
901 if(!seek(0)) {
902 fs.close();
903 clear();
904 return;
905 }
906
907 if(-1 == peek(buf, 58)) {
908 fs.close();
909 clear();
910 return;
911 }
912
913 switch(info.format) {
914 case riff:
915 case wave:
916 // RIFF header
917 setLong(buf + 4, eof - 8);
918
919 // If it's a non-PCM datatype, the offsets are a bit
920 // different for subchunk 2.
921 switch(info.encoding) {
922 case cdaStereo:
923 case cdaMono:
924 case pcm8Stereo:
925 case pcm8Mono:
926 case pcm16Stereo:
927 case pcm16Mono:
928 case pcm32Stereo:
929 case pcm32Mono:
930 setLong(buf + 40, eof - header);
931 break;
932 default:
933 setLong(buf + 54, eof - header);
934 }
935
936 write(buf, 58);
937 break;
938 case snd:
939 setLong(buf + 8, eof - header);
940 write(buf, 12);
941 break;
942 default:
943 break;
944 }
945 fs.close();
946 clear();
947 }
948
949 void AudioFile::clear(void)
950 {
951 if(pathname) {
952 if(pathname)
953 delete[] pathname;
954 pathname = NULL;
955 }
956 if(info.annotation) {
957 if(info.annotation)
958 delete[] info.annotation;
959 info.annotation = NULL;
960 }
961 minimum = 0l;
962 iolimit = 0l;
963 pos = eof = 0l;
964 }
965
966 void AudioFile::initialize(void)
967 {
968 pos = eof = 0l;
969 minimum = 0l;
970 pathname = NULL;
971 info.annotation = NULL;
972 header = 0l;
973 iolimit = 0l;
974 mode = modeInfo;
975 fs.close();
976 }
977
978 int AudioFile::getSamples(void *addr, unsigned request)
979 {
980 const char *fname;
981 unsigned char *caddr = (unsigned char *)addr;
982 ssize_t count, bytes;
983
984 if(!request)
985 request = info.framecount;
986
987 for(;;)
988 {
989 bytes = (int)toBytes(info, request);
990 if(bytes < 1)
991 return EINVAL;
992 count = read(caddr, bytes);
993 if(count == bytes)
994 return 0;
995
996 if(count < 0)
997 return fs.err();
998
999 if(count > 0) {
1000 caddr += count;
1001 count = request - toSamples(info.encoding, count);
1002 }
1003 else
1004 count = request;
1005
1006 if(mode == modeFeed) {
1007 setPosition(0);
1008 request = count;
1009 continue;
1010 }
1011
1012 retry:
1013 if(mode == modeReadOne)
1014 fname = NULL;
1015 else
1016 fname = getContinuation();
1017
1018 if(!fname)
1019 break;
1020
1021 AudioFile::close();
1022 AudioFile::open(fname, modeRead);
1023 if(!is(fs)) {
1024 if(mode == modeReadAny)
1025 goto retry;
1026 break;
1027 }
1028
1029 request = count;
1030 }
1031 if(count)
1032 Audio::fill(caddr, count, info.encoding);
1033 return EPIPE;
1034 }
1035
1036 int AudioFile::putSamples(void *addr, unsigned samples)
1037 {
1038 int count;
1039 int bytes;
1040
1041 if(!samples)
1042 samples = info.framecount;
1043
1044 bytes = (int)toBytes(info, samples);
1045 if(bytes < 1)
1046 return EINVAL;
1047
1048 count = write((unsigned char *)addr, bytes);
1049 if(count == bytes)
1050 return 0;
1051 else if(count < 1)
1052 return fs.err();
1053 else
1054 return EPIPE;
1055 }
1056
1057 ssize_t AudioFile::putBuffer(encoded_t addr, size_t len)
1058 {
1059 ssize_t count;
1060 unsigned long curpos;
1061
1062 if(!len)
1063 len = info.framesize;
1064
1065 curpos = (unsigned long)toBytes(info, getPosition());
1066 if(curpos >= iolimit && mode == modeFeed) {
1067 curpos = 0;
1068 setPosition(0);
1069 }
1070
1071 if (iolimit && ((curpos + len) > iolimit))
1072 len = iolimit - curpos;
1073
1074 if (len <= 0)
1075 return 0;
1076
1077 count = write((unsigned char *)addr, (unsigned)len);
1078 if(count == (ssize_t)len)
1079 return count;
1080 if(count < 1)
1081 return count;
1082 else
1083 return count;
1084 }
1085
1086 ssize_t AudioFile::getBuffer(encoded_t addr, size_t bytes)
1087 {
1088 info_t prior;
1089 const char *fname;
1090 ssize_t count;
1091 unsigned long curpos, xfer = 0;
1092
1093 if(!bytes)
1094 bytes = info.framesize;
1095
1096 curpos = (unsigned long)toBytes(info, getPosition());
1097 if(curpos >= iolimit && mode == modeFeed) {
1098 curpos = 0;
1099 setPosition(0);
1100 }
1101 if (iolimit && ((curpos + bytes) > iolimit))
1102 bytes = iolimit - curpos;
1103 if (bytes < 0)
1104 bytes = 0;
1105
1106 getInfo(prior);
1107
1108 for(;;)
1109 {
1110 count = read(addr, (unsigned)bytes);
1111 if(count < 0) {
1112 if(!xfer)
1113 return count;
1114 return xfer;
1115 }
1116 xfer += count;
1117 if(count == (ssize_t)bytes)
1118 return xfer;
1119 if(mode == modeFeed) {
1120 setPosition(0l);
1121 goto cont;
1122 }
1123
1124 retry:
1125 if(mode == modeReadOne)
1126 fname = NULL;
1127 else
1128 fname = getContinuation();
1129
1130 if(!fname)
1131 return xfer;
1132 AudioFile::close();
1133 AudioFile::open(fname, modeRead, info.framing);
1134 if(!is(fs)) {
1135 if(mode == modeReadAny)
1136 goto retry;
1137 return xfer;
1138 }
1139
1140 if(prior.encoding != info.encoding) {
1141 AudioFile::close();
1142 return xfer;
1143 }
1144 cont:
1145 bytes -= count;
1146 addr += count;
1147 }
1148 }
1149
1150
1151 int AudioFile::setPosition(unsigned long samples)
1152 {
1153 size_t offset;
1154 fsys::fileinfo_t ino;
1155
1156 if(!is(fs))
1157 return EBADF;
1158
1159 fs.fileinfo(&ino);
1160
1161 if(samples == (unsigned long)~0l)
1162 return seek(ino.st_size);
1163
1164 offset = header + toBytes(info, samples);
1165 if(offset > (size_t)ino.st_size)
1166 offset = ino.st_size;
1167
1168 return seek(offset);
1169 }
1170
1171 unsigned long AudioFile::getPosition(void)
1172 {
1173 if(!is(fs) || !pos)
1174 return 0;
1175
1176 return toSamples(info, (pos - header));
1177 }
1178
1179 int AudioFile::setMinimum(unsigned long samples)
1180 {
1181 if(!is(fs))
1182 return EBADF;
1183 minimum = samples;
1184 return 0;
1185 }
1186
1187
1188
1189 const char *AudioFile::getContinuation(void)
1190 {
1191 return NULL;
1192 }
#define BAYONNE_NAMESPACE
GNU Bayonne library namespace.