Bayonne 3 - API
 All Classes Namespaces Files Functions Variables Typedefs Macros
audiotool.cpp
Go to the documentation of this file.
1 //
3 // This file is part of GNU ccAudio2.
4 //
5 // GNU ccAudio2 is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU Lesser General Public License as published
7 // by the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
9 //``
10 // GNU ccAudio2 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 Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public License
16 // along with GNU ccAudio2. If not, see <http://www.gnu.org/licenses/>.
17 
18 #include <bayonne.h>
19 #include <config.h>
20 
21 using namespace BAYONNE_NAMESPACE;
22 using namespace UCOMMON_NAMESPACE;
23 
24 #ifdef HAVE_ENDIAN_H
25 #include <endian.h>
26 #endif
27 
28 #if !defined(__BIG_ENDIAN)
29 #define __LITTLE_ENDIAN 1234
30 #define __BIG_ENDIAN 4321
31 #define __PDP_ENDIAN 3412
32 #define __BYTE_ORDER __LITTLE_ENDIAN
33 #endif
34 
35 static const char *delfile = NULL;
36 static shell::stringopt encopt('e', "--encoding", _TEXT("audio encoding"), "name", NULL);
37 static shell::numericopt framing('f', "--framing", _TEXT("audio framing"), "msec", 20);
38 static shell::numericopt pad('p', "--padding", _TEXT("padding frames"), "count", 0);
39 static shell::numericopt rateopt('r', "--rate", _TEXT("audio rate"), "samples per second", 0);
40 static shell::numericopt silent('s', "--silence", _TEXT("silence level"), "level", 0);
41 static shell::flagopt helpflag('h',"--help", _TEXT("display this list"));
42 static shell::flagopt althelp('?', NULL, NULL);
43 static shell::stringopt lang('L', "--lang", _TEXT("specify language"), "language", "C");
44 static shell::stringopt prefix('P', "--prefix", _TEXT("specify alternate prefix path"), "path", NULL);
45 static shell::stringopt suffix('S', "--suffix", _TEXT("audio extension"), ".ext", ".au");
46 static shell::stringopt voice('V', "--voice", _TEXT("specify voice library"), "name", "default");
47 static shell::stringopt phrasebook('B', "--phrasebook", _TEXT("specify phrasebook directory"), "path", NULL);
48 static Env::pathinfo_t rules;
49 
50 class AudioBuild : public AudioStream
51 {
52 private:
53  char pathbuf[256];
54  char **list;
55  const char *getContinuation(void);
56 
57 public:
58  AudioBuild();
59  void open(char **argv);
60 
61  static void copyDirect(AudioStream &input, AudioStream &output);
62  static void copyConvert(AudioStream &input, AudioStream &output);
63 };
64 
65 class PacketStream : public AudioStream
66 {
67 private:
68  char pathbuf[256];
69  char **list;
70  const char *getContinuation(void);
71 
72 public:
73  PacketStream();
74  void open(char **argv);
75 };
76 
78 {
79  list = NULL;
80 }
81 
82 void PacketStream::open(char **argv)
83 {
84  const char *out = Env::path(rules, *(argv++), pathbuf, sizeof(pathbuf));
85  if(out)
86  AudioStream::open(out, modeRead, 10);
87  if(is_open())
88  list = argv;
89 }
90 
91 const char *PacketStream::getContinuation(void)
92 {
93  if(!list)
94  return NULL;
95 
96  return Env::path(rules, *(list++), pathbuf, sizeof(pathbuf));
97 }
98 
99 
101 {
102  list = NULL;
103 }
104 
105 void AudioBuild::open(char **argv)
106 {
107  const char *out = Env::path(rules, *(argv++), pathbuf, sizeof(pathbuf));
108  if(out)
109  AudioStream::open(out, modeRead, 10);
110  if(is_open())
111  list = argv;
112 }
113 
114 const char *AudioBuild::getContinuation(void)
115 {
116  if(!list)
117  return NULL;
118 
119  return Env::path(rules, *(list++), pathbuf, sizeof(pathbuf));
120 }
121 
123 {
124  unsigned long samples, copied;
125  linear_t buffer, source;
126  unsigned pages;
127  info_t from, to;
128  bool mono = true;
129  Audio::resample *resampler = NULL;
130  linear_t resample = NULL;
131 
132  input.getInfo(from);
133  output.getInfo(to);
134 
135  if(is_stereo(from.encoding) || is_stereo(to.encoding))
136  mono = false;
137 
138  samples = input.getCount();
139 
140 
141  if(mono)
142  buffer = new Audio::sample_t[samples];
143  else
144  buffer = new Audio::sample_t[samples * 2];
145 
146  source = buffer;
147 
148  if(from.rate != to.rate) {
149  resampler = new Audio::resample((Audio::rate_t)from.rate, (Audio::rate_t)to.rate);
150  resample = new Audio::sample_t[resampler->estimate(samples)];
151  source = resample;
152  }
153 
154  for(;;)
155  {
156  if(mono)
157  pages = input.getMono(buffer, 1);
158  else
159  pages = input.getStereo(buffer, 1);
160 
161  if(!pages)
162  break;
163 
164  if(resampler)
165  copied = resampler->process(buffer, resample, samples);
166  else
167  copied = samples;
168 
169  if(mono)
170  output.bufMono(source, copied); // used to set npages
171  else
172  output.bufStereo(source, copied); // used to set npages
173 
174  // if(!npages)
175  // break;
176  }
177 
178  delete[] buffer;
179 
180  if(resampler)
181  delete resampler;
182 
183  if(resample)
184  delete[] resample;
185 }
186 
188 {
189  unsigned bufsize;
190  encoded_t buffer;
191  info_t from, to;
192 // bool endian = false;
193  ssize_t status = 1;
194 
195  input.getInfo(from);
196  output.getInfo(to);
197 
198 // if(to.order && from.order && to.order != from.order && is_linear(from.encoding))
199 // endian = true;
200 
201  bufsize = from.framesize;
202  buffer = new unsigned char[bufsize];
203 
204  while(status > 0) {
205  status = input.getNative(buffer, bufsize);
206  if(status < 1)
207  break;
208 
209  status = output.putNative(buffer, status);
210  }
211 
212  delete[] buffer;
213 }
214 
215 static void stop(void)
216 {
217  if(delfile) {
218  remove(delfile);
219  delfile = NULL;
220  }
221 }
222 
223 static void codecs(void)
224 {
225  linked_pointer<AudioCodec> cp = AudioCodec::begin();
226 
227  while(is(cp)) {
228  printf("%s - %s\n", cp->getName(), cp->getDescription());
229  cp.next();
230  }
231  exit(0);
232 }
233 
234 static void version(void)
235 {
236  printf("%s\n", VERSION);
237  exit(0);
238 }
239 
240 static void showendian(void)
241 {
243  printf("%s\n", _TEXT("big"));
244  else
245  printf("%s\n", _TEXT("little"));
246  exit(0);
247 }
248 
249 static const char *fname(const char *cp)
250 {
251  const char *fn = strrchr(cp, '/');
252  if(!fn)
253  fn = strrchr(cp, '\\');
254  if(fn)
255  return ++fn;
256  return cp;
257 }
258 
259 static void rewrite(const char *source, char *target, size_t max)
260 {
261  char *fn;
262  char buffer[256];
263 
264 #ifdef WIN32
265  char *ext;
266  snprintf(buffer, sizeof(buffer), "%s", source);
267  while(NULL != (fn = strchr(buffer, '\\')))
268  *fn = '/';
269 
270  fn = strrchr(buffer, '/');
271  if(fn) {
272  *(fn++) = 0;
273  ext = strrchr(fn, '.');
274  if(ext)
275  *ext = 0;
276  snprintf(target, max, "%s/%s.tmp", buffer, fn);
277  }
278  else {
279  ext = strrchr(buffer, '.');
280  if(ext)
281  *ext = 0;
282  snprintf(target, max, "%s.tmp", buffer);
283  }
284 #else
285  snprintf(buffer, sizeof(buffer), "%s", source);
286  fn = strrchr(buffer, '/');
287  if(fn) {
288  *(fn++) = 0;
289  snprintf(target, max, "%s/.tmp.%s", buffer, fn);
290  }
291  else
292  snprintf(target, max, ".tmp.%s", source);
293 #endif
294 }
295 
296 static void chart(char **argv)
297 {
298  AudioFile file;
299  Audio::info_t info;
300  AudioCodec *codec = NULL;
301  Audio::level_t silence = (Audio::level_t)*silent;
302  unsigned char *buffer;
303  short max, current;
304  unsigned long sum;
305  unsigned long count;
306  char pathbuf[256];
307 
308  if(!*argv) {
309  shell::errexit(2, "*** audiotool: -chart: %s\n",
310  _TEXT("missing arguments"));
311  }
312 
313  while(*argv) {
314  const char *out = Env::path(rules, *argv, pathbuf, sizeof(pathbuf));
315  if(!out || !fsys::isfile(out)) {
316  printf("%s: %s\n",
317  fname(*(argv++)), _TEXT("invalid"));
318  continue;
319  }
320  if(fsys::access(out, R_OK)) {
321  printf("%s: %s\n",
322  fname(*(argv++)), _TEXT("inaccessable"));
323  continue;
324  }
325  file.open(out, Audio::modeRead, *framing);
326  file.getInfo(info);
327  if(!Audio::is_linear(info.encoding))
328  codec = AudioCodec::get(info);
329  if(!Audio::is_linear(info.encoding) && !codec) {
330  printf("%s: %s\n",
331  fname(*(argv++)), _TEXT("cannot load codec"));
332  continue;
333  }
334 
335  printf("%s: ", fname(*(argv++)));
336  buffer = new unsigned char[info.framesize];
337 
338  max = 0;
339  sum = 0;
340  count = 0;
341 
342  // autochart for silence value
343 
344  while(!silence) {
345  if(file.getBuffer(buffer, info.framesize) < (int)info.framesize)
346  break;
347  ++count;
348  if(codec)
349  sum += codec->impulse(buffer, info.framecount);
350  else
351  sum += Audio::impulse(info, buffer, info.framecount);
352  }
353 
354  if(!silence && count)
355  silence = (Audio::level_t)(((sum / count) * 2) / 3);
356 
357  max = 0;
358  sum = 0;
359  count = 0;
360 
361  file.setPosition(0);
362 
363  for(;;) {
364  if(file.getBuffer(buffer, info.framesize) < (int)info.framesize)
365  break;
366  ++count;
367  if(codec) {
368  current = codec->peak(buffer, info.framecount);
369  if(current > max)
370  max = current;
371  sum += codec->impulse(buffer, info.framecount);
372  if(codec->is_silent(silence, buffer, info.framecount)) {
373  if(codec->peak(buffer, info.framecount) >= silence)
374  printf("^");
375  else
376  printf(".");
377  }
378  else
379  printf("+");
380  fflush(stdout);
381  continue;
382  }
383 
384  current = Audio::peak(info, buffer, info.framecount);
385  if(current > max)
386  max = current;
387 
388  sum += Audio::impulse(info, buffer, info.framecount);
389  if(Audio::impulse(info, buffer, info.framecount) < silence) {
390  if(Audio::peak(info, buffer, info.framecount) >= silence)
391  printf("^");
392  else
393  printf(".");
394  }
395  else
396  printf("+");
397  fflush(stdout);
398  }
399  printf("\n");
400  if(count)
401  printf("%s = %d, %s = %ld, %s = %d\n",
402  _TEXT("silence threashold"), silence,
403  _TEXT("avg frame energy"), (sum / count),
404  _TEXT("peak level"), max);
405 
406  if(buffer)
407  delete[] buffer;
408 
409 
410  if(codec)
411  AudioCodec::release(codec);
412 
413  codec = NULL;
414  buffer = NULL;
415 
416  file.close();
417  }
418  exit(0);
419 }
420 
421 static void info(char **argv)
422 {
423  AudioFile au;
424  Audio::Info info;
425  const char *fn;
426  unsigned long end;
427  unsigned long minutes, seconds, subsec, scale;
428  char pathbuf[256];
429 
430  while(*argv) {
431  const char *out = Env::path(rules, *argv, pathbuf, sizeof(pathbuf));
432  if(!out || !fsys::isfile(out)) {
433  printf("audiotool: %s: %s\n",
434  fname(*(argv++)), _TEXT("invalid"));
435  continue;
436  }
437  if(fsys::access(out, R_OK)) {
438  printf("audiotool: %s: %s\n",
439  fname(*(argv++)), _TEXT("inaccessable"));
440  continue;
441  }
442  au.open(out, Audio::modeInfo, *framing);
443  au.getInfo(info);
444  au.setPosition();
445  end = au.getPosition();
446  printf("%s\n", fname(*(argv++)));
447  fn = Audio::getMIME(info);
448  if(!fn)
449  switch(info.format) {
450  case Audio::raw:
451  fn = "raw audio";
452  break;
453  case Audio::snd:
454  fn = "sun audio";
455  break;
456  case Audio::riff:
457  fn = "riff";
458  break;
459  case Audio::wave:
460  fn = "ms wave";
461  break;
462  }
463 
464 
465  if(fn)
466  printf(" %s: %s\n", _TEXT("Format"), fn);
467  else
468  printf(" %s: %s\n", _TEXT("Format"), _TEXT("unknown"));
469 
470  printf(" %s: %s\n", _TEXT("Encoding"), Audio::getName(info.encoding));
471  if(Audio::is_stereo(info.encoding))
472  printf(" %s: 2\n", _TEXT("Channels"));
473  else
474  printf(" %s: 1\n", _TEXT("Channels"));
475  if(info.framing)
476  printf(" %s: %ldms\n", _TEXT("Frame Size"), info.framing);
477  if(Audio::is_linear(info.encoding)) {
478  if(info.order == __BIG_ENDIAN)
479  printf(" %s: %s\n", _TEXT("Byte Order"), _TEXT("big"));
480  else if(info.order == __LITTLE_ENDIAN)
481  printf(" %s: %s\n", _TEXT("Byte Order"), _TEXT("little"));
482  else
483  printf(" %s: %s\n", _TEXT("Byte Order"), _TEXT("native"));
484  }
485  printf(" %s: %ld\n", _TEXT("Sample Rate"), info.rate);
486  printf(" %s: %ld\n", _TEXT("Bit Rate"), info.bitrate);
487  printf(" %s: %ld\n", _TEXT("Samples"), end);
488 
489  scale = info.rate / 1000;
490 
491  subsec = (end % info.rate) / scale;
492 
493  end /= info.rate;
494  seconds = end % 60;
495  end /= 60;
496  minutes = end % 60;
497  end /= 60;
498  printf(" %s %02ld:%02ld:%02ld.%03ld\n",
499  _TEXT("Duration"), end, minutes, seconds, subsec);
500 
501  if(info.headersize)
502  printf(" %s: %u, %s=%u, %s=%u\n",
503  _TEXT("Computed Frame Size"),
504  info.framesize - info.headersize - info.padding,
505  _TEXT("header"), info.headersize,
506  _TEXT("padding"), info.padding);;
507 
508  au.close();
509  }
510  exit(0);
511 }
512 
513 static void strip(char **argv)
514 {
515  AudioFile file, tmp;
516  Audio::info_t info;
517  AudioCodec *codec = NULL;
518  short silence = (short)(*silent);
519  int rtn;
520  unsigned char *buffer;
521  Audio::level_t max, current;
522  unsigned long sum;
523  unsigned long count;
524  char target[256];
525  char source[256];
526 
527  if(!*argv) {
528  shell::errexit(2, "*** audiotool: -strip: %s\n",
529  _TEXT("missing arguments"));
530  }
531 
532  while(*argv) {
533  const char *out = Env::path(rules, *argv, source, sizeof(source));
534  if(!out || !fsys::isfile(out)) {
535  printf("%s: %s\n",
536  *(argv++), _TEXT("invalid"));
537  continue;
538  }
539  if(fsys::access(out, R_OK)) {
540  printf("%s: %s\n",
541  *(argv++), _TEXT("inaccessable"));
542  continue;
543  }
544  rewrite(out, target, sizeof(target));
545  delfile = target;
546  file.open(out, Audio::modeRead, *framing);
547  file.getInfo(info);
548  if(!Audio::is_linear(info.encoding))
549  codec = AudioCodec::get(info);
550  if(!Audio::is_linear(info.encoding) && !codec) {
551  printf("%s: %s\n",
552  *(argv++), _TEXT("cannot load codec"));
553  continue;
554  }
555 
556  buffer = new unsigned char[info.framesize];
557 
558  max = 0;
559  sum = 0;
560  count = 0;
561 
562  // compute silence value
563 
564  while(!silence) {
565  rtn = file.getBuffer(buffer, info.framesize);
566  if(rtn < (int)info.framesize)
567  break;
568  ++count;
569  if(codec)
570  sum += codec->impulse(buffer, info.framecount);
571  else
572  sum += Audio::impulse(info, buffer, info.framecount);
573  }
574 
575  if(!silence && count)
576  silence = (Audio::level_t)(((sum / count) * 2) / 3);
577 
578  max = 0;
579  sum = 0;
580  count = 0;
581 
582  file.setPosition(0);
583 
584 
585  tmp.create(target, info);
586  if(!tmp.is_open()) {
587  printf("%s: %s\n",
588  *(argv++), _TEXT("cannot rewrite"));
589  continue;
590  }
591 
592  for(;;)
593  {
594  rtn = file.getBuffer(buffer, info.framesize);
595  if(rtn < (int)info.framesize)
596  break;
597  ++count;
598  if(codec) {
599  if(codec->is_silent(silence, buffer, info.framecount)) {
600  if(codec->peak(buffer, info.framecount) >= silence)
601  tmp.putBuffer(buffer, info.framesize);
602  }
603  else
604  tmp.putBuffer(buffer, info.framesize);
605  continue;
606  }
607 
608  current = Audio::peak(info, buffer, info.framecount);
609  if(current > max)
610  max = current;
611 
612  sum += Audio::impulse(info, buffer, info.framecount);
613  if(Audio::impulse(info, buffer, info.framecount) < silence) {
614  if(Audio::peak(info, buffer, info.framecount) >= silence)
615  tmp.putBuffer(buffer, info.framecount);
616  }
617  else
618  tmp.putBuffer(buffer, info.framecount);
619  }
620  if(buffer)
621  delete[] buffer;
622 
623  if(codec)
624  AudioCodec::release(codec);
625 
626  codec = NULL;
627  buffer = NULL;
628 
629  file.close();
630  tmp.close();
631 
632  rtn = rename(target, out);
633  remove(target);
634  delfile = NULL;
635 
636  if(rtn)
637  printf("%s: %s\n",
638  *argv, _TEXT("could not be replaced"));
639 
640  ++argv;
641  }
642  exit(0);
643 }
644 
645 static void trim(char **argv)
646 {
647  AudioFile file, tmp;
648  unsigned long first = 0, last = 0, total = 0, padding = *pad;
649  Audio::info_t info;
650  AudioCodec *codec = NULL;
651  Audio::level_t silence = (Audio::level_t)(*silent);
652  int rtn;
653  unsigned char *buffer;
654  Audio::linear_t samples = NULL;
655  unsigned long sum;
656  unsigned long count;
657  char target[256];
658  char source[256];
659  bool use = false;
660 
661  if(!*argv) {
662  shell::errexit(2, "*** audiotool: -trim: %s\n",
663  _TEXT("missing arguments"));
664  exit(-1);
665  }
666 
667  while(*argv) {
668  const char *out = Env::path(rules, *argv, source, sizeof(source));
669  if(!out || !fsys::isfile(out)) {
670  printf("%s: %s\n",
671  *(argv++), _TEXT("invalid"));
672  continue;
673  }
674  if(fsys::access(out, R_OK)) {
675  printf("%s: %s\n",
676  *(argv++), _TEXT("inaccessable"));
677  continue;
678  }
679  rewrite(out, target, sizeof(target));
680  delfile = target;
681  file.open(out, Audio::modeRead, *framing);
682  file.getInfo(info);
683  if(!Audio::is_linear(info.encoding))
684  codec = AudioCodec::get(info);
685  if(!Audio::is_linear(info.encoding) && !codec) {
686  printf("%s: %s\n",
687  *(argv++), _TEXT("cannot load codec"));
688  continue;
689  }
690 
691  buffer = new unsigned char[info.framesize];
692 
693  sum = 0;
694  count = 0;
695 
696  // compute silence value
697 
698  while(!silence) {
699  rtn = file.getBuffer(buffer, info.framesize);
700  if(rtn < (int)info.framesize)
701  break;
702  ++count;
703  if(codec)
704  sum += codec->impulse(buffer, info.framecount);
705  else
706  sum += Audio::impulse(info, buffer, info.framecount);
707  }
708 
709  if(!silence && count)
710  silence = (Audio::level_t)(((sum / count) * 2) / 3);
711 
712  sum = 0;
713  count = 0;
714 
715  file.setPosition(0);
716 
717  for(;;)
718  {
719  rtn = file.getBuffer(buffer, info.framesize);
720  if(rtn < (int)info.framesize)
721  break;
722 
723  ++total;
724  if(codec) {
725  if(codec->is_silent(silence, buffer, info.framecount)) {
726  use = false;
727  if(codec->peak(buffer, info.framecount) >= silence)
728  use = true;
729  }
730  else
731  use = true;
732  }
733  if(use && !first)
734  first = total;
735  if(use)
736  last = total;
737  }
738 
739  if(!last || !first) {
740  printf("%s: %s\n",
741  *(argv++), _TEXT("all silent, skipping"));
742  continue;
743  }
744 
745  --first;
746  total = last - first;
747  file.setPosition(first * info.framecount);
748 
749  tmp.create(target, info);
750  if(!tmp.is_open()) {
751  printf("%s: %s\n",
752  *(argv++), _TEXT("cannot rewrite"));
753  continue;
754  }
755 
756  while(total--) {
757  rtn = file.getBuffer(buffer, info.framesize);
758  if(rtn < (int)info.framesize)
759  break;
760  tmp.putBuffer(buffer, info.framesize);
761  }
762 
763  if(padding) {
764  if(!codec)
765  memset(buffer, 0, info.framesize);
766  else if(Audio::is_stereo(info.encoding))
767  {
768  samples = new Audio::sample_t[info.framecount * 2];
769  memset(samples, 0, info.framecount * 2);
770  codec->encode(samples, buffer, info.framecount);
771  }
772  else {
773  samples = new Audio::sample_t[info.framecount];
774  memset(samples, 0, info.framecount);
775  codec->encode(samples, buffer, info.framecount);
776  }
777  }
778 
779  while(padding--) {
780  rtn = tmp.putBuffer(buffer, info.framesize);
781  }
782 
783  if(samples)
784  delete[] samples;
785 
786  if(buffer)
787  delete[] buffer;
788 
789  if(codec)
790  AudioCodec::release(codec);
791 
792  codec = NULL;
793  buffer = NULL;
794 
795  file.close();
796  tmp.close();
797 
798  rtn = rename(target, out);
799  remove(target);
800  delfile = NULL;
801 
802  if(rtn)
803  printf("%s: %s\n",
804  *argv, _TEXT("could not be replaced"));
805 
806  ++argv;
807  }
808  exit(0);
809 }
810 
811 static void size(char **argv)
812 {
813  char *fn = *(argv++);
814  AudioFile file;
815  Audio::info_t info;
816  unsigned long pos;
817  char pathbuf[256];
818 
819  if(!fn) {
820  shell::errexit(2, "*** audiotool: -size: %s\n",
821  _TEXT("no file specified"));
822  }
823 
824  const char *out = Env::path(rules, fn, pathbuf, sizeof(pathbuf));
825  if(out)
826  file.open(out, Audio::modeRead);
827  if(!file.is_open()) {
828  shell::errexit(3, "*** audiotool: %s: %s\n",
829  fname(fn), _TEXT("cannot access"));
830  }
831  file.getInfo(info);
832  file.setPosition();
833  pos = file.getPosition();
834  pos /= info.rate;
835  printf("%ld\n", pos);
836  exit(0);
837 }
838 
839 static void packetdump(char **argv)
840 {
841  PacketStream packetfile;
842  const char *path = *argv;
843  Audio::encoded_t buffer;
844  Audio::info_t info;
845  ssize_t count;
846 
847  packetfile.open(argv);
848 
849  if(!packetfile.is_open()) {
850  shell::errexit(2, "*** audiotool: %s: %s\n",
851  fname(path), _TEXT("cannot access"));
852  }
853 
854  if(!packetfile.is_streamable()) {
855  shell::errexit(2, "*** audiotool: %s: %s\n",
856  fname(path), _TEXT("missing codec needed"));
857  }
858 
859  packetfile.getInfo(info);
860 
861  buffer = new unsigned char[Audio::maxFramesize(info)];
862 
863  while((count = packetfile.getPacket(buffer)) > 0)
864  printf("-- %ld\n", (long)count);
865 
866  delete[] buffer;
867  packetfile.close();
868  exit(0);
869 }
870 
871 static void note(char **argv)
872 {
873  char *fn = *(argv++);
874  char *ann = NULL;
875  AudioFile file, tmp;
876  Audio::info_t info;
877  char target[256];
878  char source[256];
879  unsigned char buffer[4096];
880  int rtn;
881 
882  if(!fn) {
883  shell::errexit(2, "*** audiotool: -notation: %s\n",
884  _TEXT("no file specified"));
885  }
886 
887  ann = *argv;
888 
889  const char *out = Env::path(rules, fn, source, sizeof(source));
890  if(out)
891  file.open(out, Audio::modeRead);
892  if(!file.is_open()) {
893  shell::errexit(4, "*** audiotool: %s: %s\n:",
894  fname(fn), _TEXT("cannot access"));
895  }
896  file.getInfo(info);
897  if(info.annotation && !ann)
898  printf("%s\n", info.annotation);
899  if(!ann)
900  exit(0);
901  rewrite(out, target, sizeof(target));
902  info.annotation = ann;
903  delfile = target;
904  remove(target);
905  tmp.create(target, info);
906  if(!tmp.is_open()) {
907  shell::errexit(5, "*** audiotool: %s: %s\n",
908  fname(target), _TEXT("unable to create"));
909  }
910  for(;;) {
911  rtn = file.getBuffer(buffer, sizeof(buffer));
912  if(!rtn)
913  break;
914  if(rtn < 0) {
915  remove(target);
916  shell::errexit(6, "*** audiotool: %s: %s\n",
917  fname(fn), _TEXT("read failed"));
918  }
919  rtn = tmp.putBuffer(buffer, rtn);
920  if(rtn < 1) {
921  remove(target);
922  shell::errexit(6, "*** audiotool: %s: %s\n",
923  fname(fn), _TEXT("write failed"));
924  }
925  }
926  file.close();
927  tmp.close();
928  rtn = rename(target, out);
929  remove(target);
930  delfile = NULL;
931  if(rtn) {
932  shell::errexit(6, "*** audiotool: %s: %s\n",
933  fname(fn), _TEXT("could not replace"));
934  }
935 
936  exit(0);
937 }
938 
939 static void build(char **argv)
940 {
941  AudioBuild input;
942  AudioStream output;
943  Audio::info_t info, make;
944  const char *target;
945  const char *encoding = *encopt;
946  Audio::rate_t rate = (Audio::rate_t)(*rateopt);
947  char pathbuf[256];
948 
949  if(!*argv) {
950  shell::errexit(2, "*** audiotool: -build: %s\n",
951  _TEXT("missing arguments"));
952  }
953 
954  if(*argv && **argv == '-') {
955  shell::errexit(2, "*** auditool: -build: %s: %s\n",
956  *argv, _TEXT("unknown option"));
957  }
958 
959  if(*argv) {
960  target = Env::path(rules, *(argv++), pathbuf, sizeof(pathbuf));
961 
962  if(!target) {
963  shell::errexit(4, "*** audiotool: -build: %s\n",
964  _TEXT("no files specified"));
965  }
966  }
967 
968  if(!*argv) {
969  shell::errexit(4, "*** audiotool: -build: %s\n",
970  _TEXT("no files specified"));
971  }
972 
973  input.open(argv);
974  if(!input.is_open()) {
975  shell::errexit(4, "*** audiotool: %s: %s\n",
976  *argv, _TEXT("cannot access"));
977  }
978  input.getInfo(info);
979  input.getInfo(make);
980  remove(target);
981  if(encoding)
982  make.encoding = Audio::getEncoding(encoding);
983 
984  if(rate != Audio::rateUnknown)
985  make.setRate(rate);
986 
987  output.create(target, make, 10);
988  if(!output.is_open()) {
989  shell::errexit(5, "*** audiotool: %s: %s\n",
990  target, _TEXT("cannot create"));
991  }
992  output.getInfo(make);
993 
994  if(make.encoding == info.encoding && make.rate == info.rate)
995  AudioBuild::copyDirect(input, output);
996  else {
997  if(!input.is_streamable()) {
998  remove(target);
999  shell::errexit(6, "*** audiotool: %s: %s\n",
1000  *argv, _TEXT("cannot load codec"));
1001  }
1002  if(!output.is_streamable()) {
1003  remove(target);
1004  shell::errexit(6, "*** audiotool: %s: %s\n",
1005  target, _TEXT("cannot load codec"));
1006  }
1007  AudioBuild::copyConvert(input, output);
1008  }
1009  input.close();
1010  output.close();
1011  exit(0);
1012 }
1013 
1014 static void append(char **argv)
1015 {
1016  AudioBuild input;
1017  AudioStream output;
1018  Audio::Info info, make;
1019  const char *target;
1020  char *option;
1021  char *offset = NULL;
1022  char pathbuf[256];
1023 
1024 retry:
1025  option = *argv;
1026 
1027  if(eq("--", option)) {
1028  ++argv;
1029  goto skip;
1030  }
1031 
1032  if(eq("--", option, 2))
1033  ++option;
1034 
1035  if(eq(option, "-offset=", 8)) {
1036  offset = option + 8;
1037  ++argv;
1038  goto retry;
1039  }
1040 
1041  if(eq(option, "-offset")) {
1042  ++argv;
1043  if(!*argv) {
1044  shell::errexit(3, "*** audiotool: -append: -offset: %s\n",
1045  _TEXT("missing argument"));
1046  exit(-1);
1047  }
1048  offset = *(argv++);
1049  goto retry;
1050  }
1051 
1052 skip:
1053  if(*argv && **argv == '-') {
1054  shell::errexit(2, "*** auditool: -append: %s: %s\n",
1055  *argv, _TEXT("unknown option"));
1056  }
1057 
1058  if(*argv) {
1059  target = Env::path(rules, *(argv++), pathbuf, sizeof(pathbuf));
1060 
1061  if(!target) {
1062  shell::errexit(4, "*** audiotool: -build: %s\n",
1063  _TEXT("no files specified"));
1064  }
1065  }
1066 
1067  if(!*argv) {
1068  shell::errexit(4, "*** audiotool: -append: %s\n",
1069  _TEXT("no files specified"));
1070  }
1071 
1072  input.open(argv);
1073  if(!input.is_open()) {
1074  shell::errexit(4, "*** audiotool: %s: %s\n",
1075  *argv, _TEXT("cannot access"));
1076  }
1077  input.getInfo(info);
1078  output.open(target, Audio::modeWrite, 10);
1079  if(!output.is_open()) {
1080  shell::errexit(4, "*** audiotool: %s: %s\n",
1081  target, _TEXT("cannot access"));
1082  }
1083  output.getInfo(make);
1084 
1085  if(offset)
1086  output.setPosition(atol(offset));
1087  else
1088  output.setPosition();
1089 
1090  if(make.encoding == info.encoding)
1091  AudioBuild::copyDirect(input, output);
1092  else {
1093  if(!input.is_streamable()) {
1094  shell::errexit(6, "*** audiotool: %s: %s\n",
1095  *argv, _TEXT("cannot load codec"));
1096  }
1097  if(!output.is_streamable()) {
1098  shell::errexit(6, "*** audiotool: %s: %s\n",
1099  target, _TEXT("cannot load codec"));
1100  }
1101  AudioBuild::copyConvert(input, output);
1102  }
1103  input.close();
1104  output.close();
1105  exit(0);
1106 }
1107 
1108 PROGRAM_MAIN(argc, argv)
1109 {
1110  shell::bind("audiotool");
1111  shell args(argc, argv);
1112 
1113  Env::tool(&args);
1114 
1115  rules.voices = *voice;
1116 
1117  if(is(prefix))
1118  Env::set("prefix", *prefix);
1119 
1120  if(is(phrasebook))
1121  Env::set("voices", *phrasebook);
1122 
1123  if(is(suffix))
1124  Env::set("extension", *suffix);
1125 
1126  if(is(lang))
1127  rules.book = Phrasebook::find(*lang);
1128  else
1129  rules.book = Phrasebook::find(NULL);
1130 
1131  if(is(helpflag) || is(althelp)) {
1132  printf("%s\n", _TEXT("Usage: audiotool [options] command arguments..."));
1133  printf("%s\n\n", _TEXT("Audio tool and audio file operations"));
1134  printf("%s\n", _TEXT("Options:"));
1135  shell::help();
1136  printf("\n%s\n", _TEXT("Report bugs to dyfet@gnu.org"));
1137  PROGRAM_EXIT(0);
1138  }
1139 
1140  if(!args())
1141  shell::errexit(1, "*** audiotool: %s\n",
1142  _TEXT("no command specified"));
1143 
1144  const char *cp = args[0];
1145 
1146  argv = args.argv();
1147  ++argv;
1148 
1149  shell::exiting(stop);
1150 
1151  if(eq(cp, "version"))
1152  version();
1153  else if(eq(cp, "endian"))
1154  showendian();
1155  else if(eq(cp, "build"))
1156  build(argv);
1157  else if(eq(cp, "append"))
1158  append(argv);
1159  else if(eq(cp, "chart"))
1160  chart(argv);
1161  else if(eq(cp, "info"))
1162  info(argv);
1163  else if(eq(cp, "note") || eq(cp, "annotate") || eq(cp, "notation"))
1164  note(argv);
1165  else if(eq(cp, "packets") || eq(cp, "dump") || eq(cp, "packetdump"))
1166  packetdump(argv);
1167  else if(eq(cp, "strip"))
1168  strip(argv);
1169  else if(eq(cp, "trim"))
1170  trim(argv);
1171  else if(eq(cp, "size"))
1172  size(argv);
1173  else if(eq(cp, "codecs"))
1174  codecs();
1175 
1176  shell::errexit(2, "*** audiotool: %s: %s\n",
1177  cp, _TEXT("unknown option"));
1178  PROGRAM_EXIT(0);
1179 }
#define __BIG_ENDIAN
Definition: audiotool.cpp:30
void open(char **argv)
Definition: audiotool.cpp:105
static void copyConvert(AudioStream &input, AudioStream &output)
Definition: audiotool.cpp:122
void open(char **argv)
Definition: audiotool.cpp:82
#define BAYONNE_NAMESPACE
Definition: bayonne.h:25
#define __BYTE_ORDER
Definition: audiotool.cpp:32
static void copyDirect(AudioStream &input, AudioStream &output)
Definition: audiotool.cpp:187
PROGRAM_MAIN(argc, argv)
Definition: audiotool.cpp:1108
GNU Bayonne library namespace.
#define __LITTLE_ENDIAN
Definition: audiotool.cpp:29