1 #include "config.h"
2
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <unistd.h>
7 #include <fcntl.h>
8 #include <errno.h>
9 #include <curses.h>
10 #include <signal.h>
11 #include <inttypes.h>
12 #include <sys/time.h>
13 #include <sys/signal.h>
14 #include <sys/ioctl.h>
15 #include <sys/types.h>
16 #ifdef HAVE_SOUNDCARD_H
17 # include <soundcard.h>
18 #endif
19 #ifdef HAVE_SYS_SOUNDCARD_H
20 # include <sys/soundcard.h>
21 #endif
22
23 /* -------------------------------------------------------------------- */
24
25 static void
26 tty_raw(void)
27 {
28 initscr();
29 cbreak();
30 noecho();
31 keypad(stdscr,1);
32 refresh();
33 }
34
35 static void
36 tty_restore(void)
37 {
38 endwin();
39 }
40
41 /* -------------------------------------------------------------------- */
42
43 static int sound_fd;
44 static int sound_rcount;
45 static unsigned int sound_blksize;
46 static int16_t *sound_buffer;
47 static int maxl,maxr;
48 static int secl,secr;
49 static int *histl,*histr,histn,histi;
50 static float peak_seconds = 1.5;
51 static char *audio_dev = "/dev/dsp";
52
53 static int
54 sound_open(int rate)
55 {
56 int frag,afmt,channels,trigger,srate;
57
58 if (-1 == (sound_fd = open(audio_dev, O_RDONLY))) {
59 fprintf(stderr,"open %s: %s\n",audio_dev,strerror(errno));
60 exit(1);
61 }
62
63 frag = 0x7fff000d; /* 8k */
64 if (-1 == ioctl(sound_fd, SNDCTL_DSP_SETFRAGMENT, &frag))
65 perror("ioctl SNDCTL_DSP_SETFRAGMENT");
66
67 /* format */
68 afmt = AFMT_S16_LE;
69 if (-1 == ioctl(sound_fd, SNDCTL_DSP_SETFMT, &afmt)) {
70 perror("ioctl SNDCTL_DSP_SETFMT");
71 exit(1);
72 }
73 if (afmt != AFMT_S16_LE) {
74 fprintf(stderr,"can't set sound format to 16 bit (le)\n");
75 exit(1);
76 }
77
78 /* channels */
79 channels = 2;
80 if (-1 == ioctl(sound_fd, SNDCTL_DSP_CHANNELS, &channels)) {
81 perror("ioctl SNDCTL_DSP_CHANNELS");
82 exit(1);
83 }
84 if (channels != 2) {
85 fprintf(stderr,"can't record in stereo\n");
86 exit(1);
87 }
88
89 /* rate */
90 srate = rate;
91 if (-1 == ioctl(sound_fd, SNDCTL_DSP_SPEED, &srate)) {
92 perror("ioctl SNDCTL_DSP_SPEED");
93 exit(1);
94 }
95 /* accept +/- 1% */
96 if (srate < rate * 99 / 100 ||
97 srate > rate * 101 / 100) {
98 fprintf(stderr,"can't set sample rate to %d (got %d)\n",
99 rate,srate);
100 exit(1);
101 }
102
103 /* get block size */
104 if (-1 == ioctl(sound_fd, SNDCTL_DSP_GETBLKSIZE, &sound_blksize)) {
105 perror("ioctl SNDCTL_DSP_GETBLKSIZE");
106 exit(1);
107 }
108 if (0 == sound_blksize)
109 sound_blksize = 4096;
110 sound_buffer = malloc(sound_blksize);
111
112 /* peak level history */
113 histn = peak_seconds * rate * 4 / sound_blksize;
114 histl = malloc(histn * sizeof(int));
115 histr = malloc(histn * sizeof(int));
116 memset(histl,0,histn * sizeof(int));
117 memset(histr,0,histn * sizeof(int));
118
119 /* trigger record */
120 trigger = ~PCM_ENABLE_INPUT;
121 ioctl(sound_fd,SNDCTL_DSP_SETTRIGGER,&trigger);
122 trigger = PCM_ENABLE_INPUT;
123 ioctl(sound_fd,SNDCTL_DSP_SETTRIGGER,&trigger);
124
125 return sound_fd;
126 }
127
128 static int
129 sound_read(void)
130 {
131 unsigned int have;
132 int i,rc;
133 int16_t *v;
134
135 /* read */
136 for (have = 0;have < sound_blksize;) {
137 rc = read(sound_fd,sound_buffer+have,sound_blksize-have);
138 switch (rc) {
139 case -1:
140 if (EINTR != errno) {
141 perror("read sound");
142 exit(1);
143 }
144 break;
145 case 0:
146 fprintf(stderr,"Huh? got 0 bytes from sound device?\n");
147 exit(1);
148 default:
149 have += rc;
150
151 }
152 }
153
154 /* look for peaks */
155 maxl = 0;
156 maxr = 0;
157 for (i = sound_blksize>>2, v=sound_buffer; i > 0; i--) {
158 if (abs(*v) > maxl)
159 maxl = abs(*v);
160 v++;
161 if (abs(*v) > maxr)
162 maxr = abs(*v);
163 v++;
164 }
165
166 /* max for the last second */
167 histl[histi] = maxl;
168 histr[histi] = maxr;
169 histi++;
170 if (histn == histi)
171 histi = 0;
172
173 for (secl = 0, secr = 0, i = 0; i < histn; i++) {
174 if (secl < histl[i])
175 secl = histl[i];
176 if (secr < histr[i])
177 secr = histr[i];
178 }
179 sound_rcount++;
180 return 0;
181 }
182
183 /* -------------------------------------------------------------------- */
184
185 char *names[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_NAMES;
186 char *config_names[SOUND_MIXER_NRDEVICES][4];
187
188 static int mix;
189 static int dev = -1;
190 static int volume;
191 static char *mixer_dev = "/dev/mixer";
192
193 static int
194 mixer_open(char *filename, char *device)
195 {
196 int i, devmask;
197
198 if (-1 == (mix = open(filename,O_RDONLY))) {
199 fprintf(stderr,"open %s: %s\n",filename,strerror(errno));
200 exit(1);
201 }
202 if (-1 == ioctl(mix,MIXER_READ(SOUND_MIXER_DEVMASK),&devmask)) {
203 perror("mixer read devmask");
204 exit(1);
205 }
206 for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
207 if ((1<<i) & devmask && strcasecmp(names[i],device) == 0) {
208 if (-1 == ioctl(mix,MIXER_READ(i),&volume)) {
209 perror("mixer read volume");
210 exit(1);
211 } else {
212 dev = i;
213 }
214 }
215 }
216 if (-1 == dev) {
217 fprintf(stderr,"mixer: havn't found device '%s'\nmixer: available: ",device);
218 for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
219 if ((1<<i) & devmask)
220 fprintf(stderr," '%s'",names[i]);
221 fprintf(stderr,"\n");
222 exit(1);
223 }
224 return (-1 != dev) ? 0 : -1;
225 }
226
227 static void
228 mixer_close(void)
229 {
230 close(mix);
231 dev = -1;
232 }
233
234 static int
235 mixer_get_volume(void)
236 {
237 return (-1 == dev) ? -1 : (volume & 0x7f);
238 }
239
240 static int
241 mixer_set_volume(int val)
242 {
243 if (-1 == dev)
244 return -1;
245 val &= 0x7f;
246 volume = val | (val << 8);;
247 if (-1 == ioctl(mix,MIXER_WRITE(dev),&volume)) {
248 perror("mixer write volume");
249 return -1;
250 }
251 return 0;
252 }
253
254 /* ---------------------------------------------------------------------- */
255 /* *.wav I/O stolen from cdda2wav */
256
257 /* Copyright (C) by Heiko Eissfeldt */
258
259 typedef uint8_t BYTE;
260 typedef uint16_t WORD;
261 typedef uint32_t DWORD;
262 typedef uint32_t FOURCC; /* a four character code */
263
264 /* flags for 'wFormatTag' field of WAVEFORMAT */
265 #define WAVE_FORMAT_PCM 1
266
267 /* MMIO macros */
268 #define mmioFOURCC(ch0, ch1, ch2, ch3) \
269 ((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | \
270 ((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24))
271
272 #define FOURCC_RIFF mmioFOURCC ('R', 'I', 'F', 'F')
273 #define FOURCC_LIST mmioFOURCC ('L', 'I', 'S', 'T')
274 #define FOURCC_WAVE mmioFOURCC ('W', 'A', 'V', 'E')
275 #define FOURCC_FMT mmioFOURCC ('f', 'm', 't', ' ')
276 #define FOURCC_DATA mmioFOURCC ('d', 'a', 't', 'a')
277
278 typedef struct CHUNKHDR {
279 FOURCC ckid; /* chunk ID */
280 DWORD dwSize; /* chunk size */
281 } CHUNKHDR;
282
283 /* simplified Header for standard WAV files */
284 typedef struct WAVEHDR {
285 CHUNKHDR chkRiff;
286 FOURCC fccWave;
287 CHUNKHDR chkFmt;
288 WORD wFormatTag; /* format type */
289 WORD nChannels; /* number of channels (i.e. mono, stereo, etc.) */
290 DWORD nSamplesPerSec; /* sample rate */
291 DWORD nAvgBytesPerSec; /* for buffer estimation */
292 WORD nBlockAlign; /* block size of data */
293 WORD wBitsPerSample;
294 CHUNKHDR chkData;
295 } WAVEHDR;
296
297 #define IS_STD_WAV_HEADER(waveHdr) ( \
298 waveHdr.chkRiff.ckid == FOURCC_RIFF && \
299 waveHdr.fccWave == FOURCC_WAVE && \
300 waveHdr.chkFmt.ckid == FOURCC_FMT && \
301 waveHdr.chkData.ckid == FOURCC_DATA && \
302 waveHdr.wFormatTag == WAVE_FORMAT_PCM)
303
304 #define cpu_to_le32(x) (x)
305 #define cpu_to_le16(x) (x)
306 #define le32_to_cpu(x) (x)
307 #define le16_to_cpu(x) (x)
308
309 /* -------------------------------------------------------------------- */
310
311 static WAVEHDR fileheader;
312 static size_t wav_size;
313 static size_t done_size;
314
315 static void
316 wav_init_header(int rate)
317 {
318 /* stolen from cdda2wav */
319 int nBitsPerSample = 16;
320 int channels = 2;
321
322 unsigned long nBlockAlign = channels * ((nBitsPerSample + 7) / 8);
323 unsigned long nAvgBytesPerSec = nBlockAlign * rate;
324 unsigned long temp = /* data length */ 0 +
325 sizeof(WAVEHDR) - sizeof(CHUNKHDR);
326
327 fileheader.chkRiff.ckid = cpu_to_le32(FOURCC_RIFF);
328 fileheader.fccWave = cpu_to_le32(FOURCC_WAVE);
329 fileheader.chkFmt.ckid = cpu_to_le32(FOURCC_FMT);
330 fileheader.chkFmt.dwSize = cpu_to_le32(16);
331 fileheader.wFormatTag = cpu_to_le16(WAVE_FORMAT_PCM);
332 fileheader.nChannels = cpu_to_le16(channels);
333 fileheader.nSamplesPerSec = cpu_to_le32(rate);
334 fileheader.nAvgBytesPerSec = cpu_to_le32(nAvgBytesPerSec);
335 fileheader.nBlockAlign = cpu_to_le16(nBlockAlign);
336 fileheader.wBitsPerSample = cpu_to_le16(nBitsPerSample);
337 fileheader.chkData.ckid = cpu_to_le32(FOURCC_DATA);
338 fileheader.chkRiff.dwSize = cpu_to_le32(temp);
339 fileheader.chkData.dwSize = cpu_to_le32(0 /* data length */);
340 }
341
342 static void
343 wav_start_write(int fd,int rate)
344 {
345 wav_init_header(rate);
346 lseek(fd,0,SEEK_SET);
347 write(fd,&fileheader,sizeof(WAVEHDR));
348 wav_size = 0;
349 }
350
351 static int
352 wav_write_audio(int fd, void *data, int len)
353 {
354 int rc;
355
356 rc = write(fd,data,len);
357 if (len == rc) {
358 wav_size += len;
359 return 0;
360 } else
361 return -1;
362 }
363
364 static void
365 wav_stop_write(int fd)
366 {
367 unsigned long temp = wav_size + sizeof(WAVEHDR) - sizeof(CHUNKHDR);
368
369 fileheader.chkRiff.dwSize = cpu_to_le32(temp);
370 fileheader.chkData.dwSize = cpu_to_le32(wav_size);
371 lseek(fd,0,SEEK_SET);
372 write(fd,&fileheader,sizeof(WAVEHDR));
373 done_size += wav_size;
374 }
375
376 /* -------------------------------------------------------------------- */
377
378 static char full[] =
379 "##################################################"
380 "##################################################"
381 "##################################################"
382 "##################################################";
383
384 static char empty[] =
385 "--------------------------------------------------"
386 "--------------------------------------------------"
387 "--------------------------------------------------"
388 "--------------------------------------------------";
389
390 static char blank[] =
391 " "
392 " "
393 " "
394 " ";
395
396 static char alive[] = "-\\|/";
397 //static char alive[] = ".oOo";
398 #define ALIVE(count) alive[count % (sizeof(alive)/sizeof(alive[0])-1)]
399
400 static void
401 print_bar(int line, char *name, int val1, int val2, int max)
402 {
403 int total,len;
404
405 total = COLS-16;
406 len = val1*total/max;
407
408 mvprintw(line,0,"%-6s: %5d ",name,(val2 != -1) ? val2 : val1);
409 printw("%*.*s",len,len,full);
410 printw("%*.*s",total-len,total-len,empty);
411 if (val2 != -1)
412 mvprintw(line,14+val2*total/max,"|");
413 }
414
415 /* -------------------------------------------------------------------- */
416
417 enum MODE {
418 NCURSES = 1,
419 CONSOLE = 2,
420 };
421 enum MODE mode = NCURSES;
422 int stop,verbose;
423 char *filename = "record";
424 int rate = 44100;
425
426 static void
427 ctrlc(int signal)
428 {
429 if (verbose)
430 fprintf(stderr,"\n%s - exiting\n",
431 sys_siglist[signal]);
432 stop = 1;
433 }
434
435 static int
436 record_start(char *outfile, int *nr)
437 {
438 int wav;
439
440 do {
441 sprintf(outfile,"%s%03d.wav",filename,(*nr)++);
442 wav = open(outfile, O_WRONLY | O_EXCL | O_CREAT, 0666);
443 } while ((-1 == wav) && (EEXIST == errno));
444 if (-1 == wav) {
445 perror("open");
446 exit(1);
447 }
448 wav_start_write(wav,rate);
449 return wav;
450 }
451
452 static void
453 record_stop(int fd)
454 {
455 wav_stop_write(fd);
456 close(fd);
457 switch (mode) {
458 case CONSOLE:
459 if (verbose)
460 printf("\n");
461 break;
462 case NCURSES:
463 mvprintw(3,0,"%*.*s",COLS-1,COLS-1,blank);
464 break;
465 }
466 }
467
468 static size_t
469 parse_size(const char *arg)
470 {
471 int value;
472 char mul[4];
473 off_t retval = -1;
474
475 if (2 != sscanf(arg,"%d%3s",&value,mul))
476 return 0;
477 if (0 == strcasecmp(mul,"g") ||
478 0 == strcasecmp(mul,"gb"))
479 retval = (off_t)value * 1024 * 1024 * 1024;
480 if (0 == strcasecmp(mul,"m") ||
481 0 == strcasecmp(mul,"mb"))
482 retval = (off_t)value * 1024 * 1024;
483 if (0 == strcasecmp(mul,"k") ||
484 0 == strcasecmp(mul,"kb"))
485 retval = (off_t)value * 1024;
486 return retval;
487 }
488
489 static char*
490 str_mb(off_t value)
491 {
492 static char buf[32];
493
494 if (value > (1 << 30)) {
495 value = (value * 10) >> 30;
496 sprintf(buf,"%d.%d GB",(int)(value/10),(int)(value%10));
497 return buf;
498 }
499 if (value > (1 << 20)) {
500 value = (value * 10) >> 20;
501 sprintf(buf,"%d.%d MB",(int)(value/10),(int)(value%10));
502 return buf;
503 }
504 value >>= 10;
505 sprintf(buf,"%3d kB",(int)value);
506 return buf;
507 }
508
509 /* -------------------------------------------------------------------- */
510
511 char *progname;
512 char *input = "line";
513 char *str_maxsize = "2GB";
514 int level_trigger;
515
516 static void
517 usage(FILE *fp)
518 {
519 fprintf(fp,
520 "\n"
521 "%s records sound in CD-Quality (44100/16bit/stereo).\n"
522 "It has a nice ascii-art input-level meter. It is a\n"
523 "interactive curses application. You'll need a fast\n"
524 "terminal, don't try this on a 9600 bps vt100...\n"
525 "\n"
526 "%s has several options:\n"
527 " -h this text\n"
528 " -o file output file basename [%s], a number and the .wav\n"
529 " extention are added by %s.\n"
530 " -i ctrl mixer control [%s]. This should be the one\n"
531 " where you can adjust the record level for\n"
532 " your audio source, \"line\", \"mic\" and \"igain\"\n"
533 " are good candidates.\n"
534 " -m dev set mixer device [%s]\n"
535 " -d dev set dsp device [%s]\n"
536 " -r rate set sample rate [%d]\n"
537 " -p sec peak seconds [%.1f]\n"
538 "\n"
539 "for non-interactive usage only:\n"
540 " -c enable console (non-interactive) mode\n"
541 " -v be verbose (show progress)\n"
542 " -t mm:ss limit the time to record. By default it records\n"
543 " until stopped by a signal (^C)\n"
544 " -s size set max file size [%s]. You have to give number\n"
545 " and unit without space inbetween, i.e. \"100mb\".\n"
546 " -n num limit amount of files recorded, quits when\n"
547 " reached.\n"
548 " -l signal level triggered recording.\n"
549 " -L level same as above + specify trigger level [%d]\n"
550 "\n",
551 progname,progname,filename,progname,
552 input,mixer_dev,audio_dev,
553 rate,peak_seconds,str_maxsize,
554 level_trigger ? level_trigger : 1000);
555 }
556
557 int
558 main(int argc, char *argv[])
559 {
560 int c,key,vol,delay,auto_adjust;
561 int record,nr,wav=0;
562 char *outfile;
563 fd_set s;
564 int sec,maxhour,maxmin,maxsec;
565 int maxfiles = 0;
566 size_t maxsize;
567
568 /* init some vars */
569 progname = strrchr(argv[0],'/');
570 progname = progname ? progname+1 : argv[0];
571 maxsec = 0;
572 delay = 0;
573 auto_adjust = 1;
574 record = 0;
575 nr = 0;
576
577 /* parse options */
578 for (;;) {
579 if (-1 == (c = getopt(argc, argv, "vhlci:o:d:m:r:t:s:L:p:n:")))
580 break;
581 switch (c) {
582 case 'v':
583 verbose = 1;
584 break;
585 case 'l':
586 level_trigger = 1000;
587 break;
588 case 'L':
589 level_trigger = atoi(optarg);
590 break;
591 case 'i':
592 input = optarg;
593 break;
594 case 'o':
595 filename = optarg;
596 break;
597 case 'd':
598 audio_dev = optarg;
599 break;
600 case 'm':
601 mixer_dev = optarg;
602 break;
603 case 'c':
604 mode = CONSOLE;
605 break;
606 case 'r':
607 rate = atoi(optarg);
608 break;
609 case 'p':
610 peak_seconds = atof(optarg);
611 break;
612 case 't':
613 if (3 != sscanf(optarg,"%d:%d:%d",&maxhour,&maxmin,&maxsec)) {
614 maxhour = 0;
615 if (2 != sscanf(optarg,"%d:%d",&maxmin,&maxsec)) {
616 fprintf(stderr,"time parse error\n");
617 exit(1);
618 }
619 }
620 maxsec += maxmin * 60;
621 maxsec += maxhour * 60 * 60;
622 break;
623 case 's':
624 str_maxsize = optarg;
625 break;
626 case 'n':
627 maxfiles = atoi(optarg);
628 break;
629 case 'h':
630 usage(stdout);
631 exit(0);
632 default:
633 usage(stderr);
634 exit(1);
635 }
636 }
637 maxsize = parse_size(str_maxsize);
638 if (0 == maxsize) {
639 fprintf(stderr,"maxsize parse error [%s]\n",str_maxsize);
640 exit(1);
641 }
642
643 mixer_open(mixer_dev,input);
644 sound_open(rate);
645 outfile = malloc(strlen(filename)+16);
646
647 if (mode == NCURSES) {
648 tty_raw();
649 atexit(tty_restore);
650 }
651
652 signal(SIGINT,ctrlc);
653 signal(SIGQUIT,ctrlc);
654 signal(SIGTERM,ctrlc);
655 signal(SIGHUP,ctrlc);
656
657 if (mode == NCURSES) {
658 mvprintw( 5,0,"record to %s*.wav",filename);
659 mvprintw( 7,0,"left/right adjust mixer level for \"%s\"",input);
660 mvprintw( 8,0,"space starts/stops recording");
661 /* line 9 is printed later */
662 mvprintw(10,0," auto-adjust reduces the record level on overruns");
663 mvprintw(11,0,"'N' next file (same as space twice, but without break)");
664 mvprintw(12,0,"'Q' quit");
665 mvprintw(LINES-3,0,"--");
666 mvprintw(LINES-2,0,"(c) 1999-2003 Gerd Knorr <kraxel@bytesex.org>");
667
668 for (;!stop;) {
669 refresh();
670 FD_ZERO(&s);
671 FD_SET(0,&s);
672 FD_SET(sound_fd,&s);
673 if (-1 == select(sound_fd+1,&s,NULL,NULL,NULL)) {
674 if (EINTR == errno)
675 continue;
676 perror("select");
677 break;
678 }
679
680 if (FD_ISSET(sound_fd,&s)) {
681 /* sound */
682 if (-1 == sound_read())
683 break;
684 if (delay)
685 delay--;
686 if (auto_adjust && (0 == delay) &&
687 (maxl >= 32767 || maxr >= 32767)) {
688 /* auto-adjust */
689 vol = mixer_get_volume();
690 vol--;
691 if (vol < 0)
692 vol = 0;
693 mixer_set_volume(vol);
694 delay = 3;
695 }
696 print_bar(0,input,mixer_get_volume(),-1,100);
697 print_bar(1,"left",maxl,secl,32768);
698 print_bar(2,"right",maxr,secr,32768);
699 mvprintw(9,0,"'A' toggle auto-adjust [%s] ",
700 auto_adjust ? "on" : "off");
701 if (record) {
702 wav_write_audio(wav,sound_buffer,sound_blksize);
703 sec = wav_size / (rate*4);
704 mvprintw(3,0,"%s: %3d:%02d (%s) ",outfile,
705 sec/60,sec%60,str_mb(wav_size));
706 } else {
707 mvprintw(3,0,"%c",ALIVE(sound_rcount));
708 }
709 }
710
711 if (FD_ISSET(0,&s)) {
712 /* tty in */
713 switch (key = getch()) {
714 case 'Q':
715 case 'q':
716 stop = 1;
717 break;
718 case 'A':
719 case 'a':
720 auto_adjust = !auto_adjust;
721 break;
722 case 'N':
723 case 'n':
724 if (record) {
725 record_stop(wav);
726 wav = record_start(outfile,&nr);
727 }
728 break;
729 case ' ':
730 if (!filename)
731 break;
732 if (!record) {
733 /* start */
734 wav = record_start(outfile,&nr);
735 record=1;
736 auto_adjust=0;
737 } else {
738 /* stop */
739 record_stop(wav);
740 record=0;
741 }
742 break;
743 case KEY_RIGHT:
744 vol = mixer_get_volume();
745 vol++;
746 if (vol > 100)
747 vol = 100;
748 mixer_set_volume(vol);
749 break;
750 case KEY_LEFT:
751 vol = mixer_get_volume();
752 vol--;
753 if (vol < 0)
754 vol = 0;
755 mixer_set_volume(vol);
756 break;
757 }
758 }
759 }
760 }
761
762 if (mode == CONSOLE) {
763 if (!level_trigger) {
764 wav = record_start(outfile,&nr);
765 record=1;
766 }
767
768 for (;!stop;) {
769 if (-1 == sound_read())
770 break;
771 if (level_trigger) {
772 if (!record &&
773 (maxl > level_trigger ||
774 maxr > level_trigger)) {
775 wav = record_start(outfile,&nr);
776 record=1;
777 }
778 if (record &&
779 secl < level_trigger &&
780 secr < level_trigger) {
781 record_stop(wav);
782 record=0;
783 if (maxfiles && nr == maxfiles)
784 break;
785 }
786 }
787 if (!record) {
788 printf("waiting for signal %c [%d/%d]... \r",
789 ALIVE(sound_rcount), maxl,maxr);
790 fflush(stdout);
791 continue;
792 }
793
794 sec = (done_size + wav_size) / (rate*4);
795 if (maxsec && sec >= maxsec)
796 break;
797 if (wav_size + sound_blksize + sizeof(WAVEHDR) > maxsize) {
798 record_stop(wav);
799 wav = record_start(outfile,&nr);
800 }
801 wav_write_audio(wav,sound_buffer,sound_blksize);
802 if (verbose) {
803 int total = 10;
804 int len = (maxl+maxr)*total/32768/2;
805 printf("|%*.*s%*.*s| %s %d:%02d",
806 len,len,full, total-len,total-len,empty,
807 outfile,sec/60,sec%60);
808 if (maxsec)
809 printf("/%d:%02d",maxsec/60,maxsec%60);
810 printf(" (%s",str_mb(wav_size));
811 if (done_size)
812 printf(", %s total",str_mb(done_size + wav_size));
813 printf(") \r");
814 fflush(stdout);
815 }
816 }
817 }
818
819 if (record)
820 record_stop(wav);
821 mixer_close();
822 exit(0);
823 }
824
|
This page was automatically generated by the
LXR engine.
|