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