Bayonne 3 - API
 All Classes Namespaces Files Functions Variables Typedefs Macros
audiofile.cpp
Go to the documentation of this file.
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>
21 #include <bayonne.h>
22 
23 #if defined(__GNUC__)
24 #define _PACKED
25 #elif !defined(__hpux) && !defined(_AIX)
26 #define _PACKED
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 
36 using namespace BAYONNE_NAMESPACE;
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 
109 AudioCodec *AudioFile::getCodec(void)
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 {
134  if(info.order == __BIG_ENDIAN) {
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 {
146  if(info.order == __BIG_ENDIAN)
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) {
157  if(info.order == __BIG_ENDIAN)
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) {
171  if(info.order == __BIG_ENDIAN)
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;
330  info.order = __LITTLE_ENDIAN;
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)
350  info.order = __LITTLE_ENDIAN;
351  if(info.order == __LITTLE_ENDIAN)
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)
545  info.order = __BIG_ENDIAN;
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:
756  info.order = __LITTLE_ENDIAN;
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;
773  info.order = __LITTLE_ENDIAN;
774  }
775 
776  if(!strncmp((char *)filehdr, "RIFX", 4)) {
777  info.order = __BIG_ENDIAN;
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;
809  info.order = __BIG_ENDIAN;
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
Definition: bayonne.h:25
#define __LITTLE_ENDIAN
Definition: audiofile.cpp:30
GNU Bayonne library namespace.
#define __BIG_ENDIAN
Definition: audiofile.cpp:31