📄 unixinput.c
字号:
/* * unixinput.c -- input sound samples * * Copyright (C) 1996 * Thomas Sailer (sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *//* ---------------------------------------------------------------------- */#include "multimon.h"#include <stdio.h>#include <stdarg.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>#include <errno.h>#include <string.h>#include <sys/wait.h>#include <stdlib.h>#ifdef SUN_AUDIO#include <sys/audioio.h>#include <stropts.h>#include <sys/conf.h>#else /* SUN_AUDIO */#include <sys/soundcard.h>#include <sys/ioctl.h>#endif /* SUN_AUDIO *//* ---------------------------------------------------------------------- */static const char *allowed_types[] = { "raw", "aiff", "au", "hcom", "sf", "voc", "cdr", "dat", "smp", "wav", "maud", "vwe", NULL};/* ---------------------------------------------------------------------- */static const struct demod_param *dem[] = { ALL_DEMOD };#define NUMDEMOD (sizeof(dem)/sizeof(dem[0]))static struct demod_state dem_st[NUMDEMOD];static unsigned int dem_mask[(NUMDEMOD+31)/32];#define MASK_SET(n) dem_mask[(n)>>5] |= 1<<((n)&0x1f)#define MASK_RESET(n) dem_mask[(n)>>5] &= ~(1<<((n)&0x1f))#define MASK_ISSET(n) (dem_mask[(n)>>5] & 1<<((n)&0x1f))/* ---------------------------------------------------------------------- */static int verbose_level = 0;/* ---------------------------------------------------------------------- */void verbprintf(int verb_level, const char *fmt, ...){ va_list args; va_start(args, fmt); if (verb_level <= verbose_level) vfprintf(stdout, fmt, args); va_end(args);}/* ---------------------------------------------------------------------- */static void process_buffer(float *buf, unsigned int len){ int i; for (i = 0; i < NUMDEMOD; i++) if (MASK_ISSET(i) && dem[i]->demod) dem[i]->demod(dem_st+i, buf, len);}/* ---------------------------------------------------------------------- */#ifdef SUN_AUDIOstatic void input_sound(unsigned int sample_rate, unsigned int overlap, const char *ifname){ audio_info_t audioinfo; audio_info_t audioinfo2; audio_device_t audiodev; int fd; short buffer[8192]; float fbuf[16384]; unsigned int fbuf_cnt = 0; int i; short *sp; if ((fd = open(ifname ? ifname : "/dev/audio", O_RDONLY)) < 0) { perror("open"); exit (10); } if (ioctl(fd, AUDIO_GETDEV, &audiodev) == -1) { perror("ioctl: AUDIO_GETDEV"); exit (10); } AUDIO_INITINFO(&audioinfo); audioinfo.record.sample_rate = sample_rate; audioinfo.record.channels = 1; audioinfo.record.precision = 16; audioinfo.record.encoding = AUDIO_ENCODING_LINEAR; /*audioinfo.record.gain = 0x20; audioinfo.record.port = AUDIO_LINE_IN; audioinfo.monitor_gain = 0;*/ if (ioctl(fd, AUDIO_SETINFO, &audioinfo) == -1) { perror("ioctl: AUDIO_SETINFO"); exit (10); } if (ioctl(fd, I_FLUSH, FLUSHR) == -1) { perror("ioctl: I_FLUSH"); exit (10); } if (ioctl(fd, AUDIO_GETINFO, &audioinfo2) == -1) { perror("ioctl: AUDIO_GETINFO"); exit (10); } fprintf(stdout, "Audio device: name %s, ver %s, config %s, " "sampling rate %d\n", audiodev.name, audiodev.version, audiodev.config, audioinfo.record.sample_rate); for (;;) { i = read(fd, sp = buffer, sizeof(buffer)); if (i < 0 && errno != EAGAIN) { perror("read"); exit(4); } if (!i) break; if (i > 0) { for (; i >= sizeof(buffer[0]); i -= sizeof(buffer[0]), sp++) fbuf[fbuf_cnt++] = (*sp) * (1.0/32768.0); if (i) fprintf(stderr, "warning: noninteger number of samples read\n"); if (fbuf_cnt > overlap) { process_buffer(fbuf, fbuf_cnt-overlap); memmove(fbuf, fbuf+fbuf_cnt-overlap, overlap*sizeof(fbuf[0])); fbuf_cnt = overlap; } } } close(fd);}#else /* SUN_AUDIO *//* ---------------------------------------------------------------------- */static void input_sound(unsigned int sample_rate, unsigned int overlap, const char *ifname){ int sndparam; int fd; union { short s[8192]; unsigned char b[8192]; } b; float fbuf[16384]; unsigned int fbuf_cnt = 0; int i; short *sp; unsigned char *bp; int fmt = 0; if ((fd = open(ifname ? ifname : "/dev/dsp", O_RDONLY)) < 0) { perror("open"); exit (10); } sndparam = AFMT_S16_LE; /* we want 16 bits/sample signed */ /* little endian; works only on little endian systems! */ if (ioctl(fd, SNDCTL_DSP_SETFMT, &sndparam) == -1) { perror("ioctl: SNDCTL_DSP_SETFMT"); exit (10); } if (sndparam != AFMT_S16_LE) { fmt = 1; sndparam = AFMT_U8; if (ioctl(fd, SNDCTL_DSP_SETFMT, &sndparam) == -1) { perror("ioctl: SNDCTL_DSP_SETFMT"); exit (10); } if (sndparam != AFMT_U8) { perror("ioctl: SNDCTL_DSP_SETFMT"); exit (10); } } sndparam = 0; /* we want only 1 channel */ if (ioctl(fd, SNDCTL_DSP_STEREO, &sndparam) == -1) { perror("ioctl: SNDCTL_DSP_STEREO"); exit (10); } if (sndparam != 0) { fprintf(stderr, "soundif: Error, cannot set the channel " "number to 1\n"); exit (10); } sndparam = sample_rate; if (ioctl(fd, SNDCTL_DSP_SPEED, &sndparam) == -1) { perror("ioctl: SNDCTL_DSP_SPEED"); exit (10); } if ((10*abs(sndparam-sample_rate)) > sample_rate) { perror("ioctl: SNDCTL_DSP_SPEED"); exit (10); } if (sndparam != sample_rate) { fprintf(stderr, "Warning: Sampling rate is %u, " "requested %u\n", sndparam, sample_rate); }#if 0 sndparam = 4; if (ioctl(fd, SOUND_PCM_SUBDIVIDE, &sndparam) == -1) { perror("ioctl: SOUND_PCM_SUBDIVIDE"); } if (sndparam != 4) { perror("ioctl: SOUND_PCM_SUBDIVIDE"); }#endif for (;;) { if (fmt) { i = read(fd, bp = b.b, sizeof(b.b)); if (i < 0 && errno != EAGAIN) { perror("read"); exit(4); } if (!i) break; if (i > 0) { for (; i >= sizeof(b.b[0]); i -= sizeof(b.b[0]), sp++) fbuf[fbuf_cnt++] = ((int)(*bp)-0x80) * (1.0/128.0); if (i) fprintf(stderr, "warning: noninteger number of samples read\n"); if (fbuf_cnt > overlap) { process_buffer(fbuf, fbuf_cnt-overlap); memmove(fbuf, fbuf+fbuf_cnt-overlap, overlap*sizeof(fbuf[0])); fbuf_cnt = overlap; } } } else { i = read(fd, sp = b.s, sizeof(b.s)); if (i < 0 && errno != EAGAIN) { perror("read"); exit(4); } if (!i) break; if (i > 0) { for (; i >= sizeof(b.s[0]); i -= sizeof(b.s[0]), sp++) fbuf[fbuf_cnt++] = (*sp) * (1.0/32768.0); if (i) fprintf(stderr, "warning: noninteger number of samples read\n"); if (fbuf_cnt > overlap) { process_buffer(fbuf, fbuf_cnt-overlap); memmove(fbuf, fbuf+fbuf_cnt-overlap, overlap*sizeof(fbuf[0])); fbuf_cnt = overlap; } } } } close(fd);}#endif /* SUN_AUDIO *//* ---------------------------------------------------------------------- */static void input_file(unsigned int sample_rate, unsigned int overlap, const char *fname, const char *type){ struct stat statbuf; int pipedes[2]; int pid = 0, soxstat; int fd; int i; short buffer[8192]; float fbuf[16384]; unsigned int fbuf_cnt = 0; short *sp; /* * if the input type is not raw, sox is started to convert the * samples to the requested format */ if (!type || !strcmp(type, "raw")) { if ((fd = open(fname, O_RDONLY)) < 0) { perror("open"); exit(10); } } else { if (stat(fname, &statbuf)) { perror("stat"); exit(10); } if (pipe(pipedes)) { perror("pipe"); exit(10); } if (!(pid = fork())) { char srate[8]; /* * child starts here... first set up filedescriptors, * then start sox... */ sprintf(srate, "%d", sample_rate); close(pipedes[0]); /* close reading pipe end */ close(1); /* close standard output */ if (dup2(pipedes[1], 1) < 0) perror("dup2"); close(pipedes[1]); /* close writing pipe end */ execlp("sox", "sox", "-t", type, fname, "-t", "raw", "-s", "-w", "-r", srate, "-", NULL); perror("execlp"); exit(10); } if (pid < 0) { perror("fork"); exit(10); } close(pipedes[1]); /* close writing pipe end */ fd = pipedes[0]; } /* * demodulate */ for (;;) { i = read(fd, sp = buffer, sizeof(buffer)); if (i < 0 && errno != EAGAIN) { perror("read"); exit(4); } if (!i) break; if (i > 0) { for (; i >= sizeof(buffer[0]); i -= sizeof(buffer[0]), sp++) fbuf[fbuf_cnt++] = (*sp) * (1.0/32768.0); if (i) fprintf(stderr, "warning: noninteger number of samples read\n"); if (fbuf_cnt > overlap) { process_buffer(fbuf, fbuf_cnt-overlap); memmove(fbuf, fbuf+fbuf_cnt-overlap, overlap*sizeof(fbuf[0])); fbuf_cnt = overlap; } } } close(fd); waitpid(pid, &soxstat, 0);}/* ---------------------------------------------------------------------- */static const char usage_str[] = "multimod\n""Demodulates many different radio transmission formats\n""(C) 1996 by Thomas Sailer HB9JNX/AE4WA\n"" -t <type> : input file type (any other type than raw requires sox)\n"" -a <demod> : add demodulator\n"" -s <demod> : subtract demodulator\n";int main(int argc, char *argv[]){ int c; int errflg = 0; int i; char **itype; int mask_first = 1; int sample_rate = -1; unsigned int overlap = 0; char *input_type = "hw"; fprintf(stdout, "multimod (C) 1996/1997 by Tom Sailer HB9JNX/AE4WA\n" "available demodulators:"); for (i = 0; i < NUMDEMOD; i++) fprintf(stdout, " %s", dem[i]->name); fprintf(stdout, "\n"); while ((c = getopt(argc, argv, "t:a:s:v:")) != EOF) { switch (c) { case '?': errflg++; break; case 'v': verbose_level = strtoul(optarg, 0, 0); break; case 't': for (itype = (char **)allowed_types; *itype; itype++) if (!strcmp(*itype, optarg)) { input_type = *itype; goto intypefound; } fprintf(stderr, "invalid input type \"%s\"\n" "allowed types: ", optarg); for (itype = (char **)allowed_types; *itype; itype++) fprintf(stderr, "%s ", *itype); fprintf(stderr, "\n"); errflg++; intypefound: break; case 'a': if (mask_first) memset(dem_mask, 0, sizeof(dem_mask)); mask_first = 0; for (i = 0; i < NUMDEMOD; i++) if (!strcasecmp(optarg, dem[i]->name)) { MASK_SET(i); break; } if (i >= NUMDEMOD) { fprintf(stderr, "invalid mode \"%s\"\n", optarg); errflg++; } break; case 's': if (mask_first) memset(dem_mask, 0xff, sizeof(dem_mask)); mask_first = 0; for (i = 0; i < NUMDEMOD; i++) if (!strcasecmp(optarg, dem[i]->name)) { MASK_RESET(i); break; } if (i >= NUMDEMOD) { fprintf(stderr, "invalid mode \"%s\"\n", optarg); errflg++; } break; } } if (errflg) { (void)fprintf(stderr, usage_str); exit(2); } if (mask_first) memset(dem_mask, 0xff, sizeof(dem_mask)); fprintf(stdout, "Enabled demodulators:"); for (i = 0; i < NUMDEMOD; i++) if (MASK_ISSET(i)) { fprintf(stdout, " %s", dem[i]->name); memset(dem_st+i, 0, sizeof(dem_st[i])); dem_st[i].dem_par = dem[i]; if (dem[i]->init) dem[i]->init(dem_st+i); if (sample_rate == -1) sample_rate = dem[i]->samplerate; else if (sample_rate != dem[i]->samplerate) { fprintf(stdout, "\n"); fprintf(stderr, "Error: Current sampling rate %d, " " demodulator \"%s\" requires %d\n", sample_rate, dem[i]->name, dem[i]->samplerate); exit(3); } if (dem[i]->overlap > overlap) overlap = dem[i]->overlap; } fprintf(stdout, "\n"); if (!strcmp(input_type, "hw")) { if ((argc - optind) >= 1) input_sound(sample_rate, overlap, argv[optind]); else input_sound(sample_rate, overlap, NULL); exit(0); } if ((argc - optind) < 1) { (void)fprintf(stderr, "no source files specified\n"); exit(4); } for (i = optind; i < argc; i++) input_file(sample_rate, overlap, argv[i], input_type); exit(0);}/* ---------------------------------------------------------------------- */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -