📄 aplay.c
字号:
if (hwparams.format == SND_PCM_FORMAT_FLOAT_LE) f.format = LE_SHORT(WAV_FMT_IEEE_FLOAT); else f.format = LE_SHORT(WAV_FMT_PCM); f.channels = LE_SHORT(hwparams.channels); f.sample_fq = LE_INT(hwparams.rate);#if 0 tmp2 = (samplesize == 8) ? 1 : 2; f.byte_p_spl = LE_SHORT(tmp2); tmp = dsp_speed * hwparams.channels * (u_int) tmp2;#else tmp2 = hwparams.channels * snd_pcm_format_physical_width(hwparams.format) / 8; f.byte_p_spl = LE_SHORT(tmp2); tmp = (u_int) tmp2 * hwparams.rate;#endif f.byte_p_sec = LE_INT(tmp); f.bit_p_spl = LE_SHORT(bits); cd.type = WAV_DATA; cd.length = LE_INT(cnt); if (write(fd, &h, sizeof(WaveHeader)) != sizeof(WaveHeader) || write(fd, &cf, sizeof(WaveChunkHeader)) != sizeof(WaveChunkHeader) || write(fd, &f, sizeof(WaveFmtBody)) != sizeof(WaveFmtBody) || write(fd, &cd, sizeof(WaveChunkHeader)) != sizeof(WaveChunkHeader)) { error(_("write error")); exit(EXIT_FAILURE); }}/* write a Au-header */static void begin_au(int fd, size_t cnt){ AuHeader ah; ah.magic = AU_MAGIC; ah.hdr_size = BE_INT(24); ah.data_size = BE_INT(cnt); switch ((unsigned long) hwparams.format) { case SND_PCM_FORMAT_MU_LAW: ah.encoding = BE_INT(AU_FMT_ULAW); break; case SND_PCM_FORMAT_U8: ah.encoding = BE_INT(AU_FMT_LIN8); break; case SND_PCM_FORMAT_S16_BE: ah.encoding = BE_INT(AU_FMT_LIN16); break; default: error(_("Sparc Audio doesn't support %s format..."), snd_pcm_format_name(hwparams.format)); exit(EXIT_FAILURE); } ah.sample_rate = BE_INT(hwparams.rate); ah.channels = BE_INT(hwparams.channels); if (write(fd, &ah, sizeof(AuHeader)) != sizeof(AuHeader)) { error(_("write error")); exit(EXIT_FAILURE); }}/* closing .VOC */static void end_voc(int fd){ off64_t length_seek; VocBlockType bt; size_t cnt; char dummy = 0; /* Write a Terminator */ if (write(fd, &dummy, 1) != 1) { error(_("write error")); exit(EXIT_FAILURE); } length_seek = sizeof(VocHeader); if (hwparams.channels > 1) length_seek += sizeof(VocBlockType) + sizeof(VocExtBlock); bt.type = 1; cnt = fdcount; cnt += sizeof(VocVoiceData); /* Channel_data block follows */ if (cnt > 0x00ffffff) cnt = 0x00ffffff; bt.datalen = (u_char) (cnt & 0xFF); bt.datalen_m = (u_char) ((cnt & 0xFF00) >> 8); bt.datalen_h = (u_char) ((cnt & 0xFF0000) >> 16); if (lseek64(fd, length_seek, SEEK_SET) == length_seek) write(fd, &bt, sizeof(VocBlockType)); if (fd != 1) close(fd);}static void end_wave(int fd){ /* only close output */ WaveChunkHeader cd; off64_t length_seek; off64_t filelen; u_int rifflen; length_seek = sizeof(WaveHeader) + sizeof(WaveChunkHeader) + sizeof(WaveFmtBody); cd.type = WAV_DATA; cd.length = fdcount > 0x7fffffff ? LE_INT(0x7fffffff) : LE_INT(fdcount); filelen = fdcount + 2*sizeof(WaveChunkHeader) + sizeof(WaveFmtBody) + 4; rifflen = filelen > 0x7fffffff ? LE_INT(0x7fffffff) : LE_INT(filelen); if (lseek64(fd, 4, SEEK_SET) == 4) write(fd, &rifflen, 4); if (lseek64(fd, length_seek, SEEK_SET) == length_seek) write(fd, &cd, sizeof(WaveChunkHeader)); if (fd != 1) close(fd);}static void end_au(int fd){ /* only close output */ AuHeader ah; off64_t length_seek; length_seek = (char *)&ah.data_size - (char *)&ah; ah.data_size = fdcount > 0xffffffff ? 0xffffffff : BE_INT(fdcount); if (lseek64(fd, length_seek, SEEK_SET) == length_seek) write(fd, &ah.data_size, sizeof(ah.data_size)); if (fd != 1) close(fd);}static void header(int rtype, char *name){ if (!quiet_mode) { if (! name) name = (stream == SND_PCM_STREAM_PLAYBACK) ? "stdout" : "stdin"; fprintf(stderr, "%s %s '%s' : ", (stream == SND_PCM_STREAM_PLAYBACK) ? _("Playing") : _("Recording"), gettext(fmt_rec_table[rtype].what), name); fprintf(stderr, "%s, ", snd_pcm_format_description(hwparams.format)); fprintf(stderr, _("Rate %d Hz, "), hwparams.rate); if (hwparams.channels == 1) fprintf(stderr, _("Mono")); else if (hwparams.channels == 2) fprintf(stderr, _("Stereo")); else fprintf(stderr, _("Channels %i"), hwparams.channels); fprintf(stderr, "\n"); }}/* playing raw data */static void playback_go(int fd, size_t loaded, off64_t count, int rtype, char *name){ int l, r; off64_t written = 0; off64_t c; header(rtype, name); set_params(); while (loaded > chunk_bytes && written < count) { if (pcm_write(audiobuf + written, chunk_size) <= 0) return; written += chunk_bytes; loaded -= chunk_bytes; } if (written > 0 && loaded > 0) memmove(audiobuf, audiobuf + written, loaded); l = loaded; while (written < count) { do { c = count - written; if (c > chunk_bytes) c = chunk_bytes; c -= l; if (c == 0) break; r = safe_read(fd, audiobuf + l, c); if (r < 0) { perror(name); exit(EXIT_FAILURE); } fdcount += r; if (r == 0) break; l += r; } while ((size_t)l < chunk_bytes); l = l * 8 / bits_per_frame; r = pcm_write(audiobuf, l); if (r != l) break; r = r * bits_per_frame / 8; written += r; l = 0; } snd_pcm_nonblock(handle, 0); snd_pcm_drain(handle); snd_pcm_nonblock(handle, nonblock);}/* * let's play or capture it (capture_type says VOC/WAVE/raw) */static void playback(char *name){ int ofs; size_t dta; ssize_t dtawave; pbrec_count = LLONG_MAX; fdcount = 0; if (!name || !strcmp(name, "-")) { fd = fileno(stdin); name = "stdin"; } else { if ((fd = open64(name, O_RDONLY, 0)) == -1) { perror(name); exit(EXIT_FAILURE); } } /* read the file header */ dta = sizeof(AuHeader); if ((size_t)safe_read(fd, audiobuf, dta) != dta) { error(_("read error")); exit(EXIT_FAILURE); } if (test_au(fd, audiobuf) >= 0) { rhwparams.format = hwparams.format; pbrec_count = calc_count(); playback_go(fd, 0, pbrec_count, FORMAT_AU, name); goto __end; } dta = sizeof(VocHeader); if ((size_t)safe_read(fd, audiobuf + sizeof(AuHeader), dta - sizeof(AuHeader)) != dta - sizeof(AuHeader)) { error(_("read error")); exit(EXIT_FAILURE); } if ((ofs = test_vocfile(audiobuf)) >= 0) { pbrec_count = calc_count(); voc_play(fd, ofs, name); goto __end; } /* read bytes for WAVE-header */ if ((dtawave = test_wavefile(fd, audiobuf, dta)) >= 0) { pbrec_count = calc_count(); playback_go(fd, dtawave, pbrec_count, FORMAT_WAVE, name); } else { /* should be raw data */ init_raw_data(); pbrec_count = calc_count(); playback_go(fd, dta, pbrec_count, FORMAT_RAW, name); } __end: if (fd != 0) close(fd);}static int new_capture_file(char *name, char *namebuf, size_t namelen, int filecount){ /* get a copy of the original filename */ char *s; char buf[PATH_MAX+1]; strncpy(buf, name, sizeof(buf)); /* separate extension from filename */ s = buf + strlen(buf); while (s > buf && *s != '.' && *s != '/') --s; if (*s == '.') *s++ = 0; else if (*s == '/') s = buf + strlen(buf); /* upon first jump to this if block rename the first file */ if (filecount == 1) { if (*s) snprintf(namebuf, namelen, "%s-01.%s", buf, s); else snprintf(namebuf, namelen, "%s-01", buf); remove(namebuf); rename(name, namebuf); filecount = 2; } /* name of the current file */ if (*s) snprintf(namebuf, namelen, "%s-%02i.%s", buf, filecount, s); else snprintf(namebuf, namelen, "%s-%02i", buf, filecount); return filecount;}static void capture(char *orig_name){ int tostdout=0; /* boolean which describes output stream */ int filecount=0; /* number of files written */ char *name = orig_name; /* current filename */ char namebuf[PATH_MAX+1]; off64_t count, rest; /* number of bytes to capture */ /* get number of bytes to capture */ count = calc_count(); if (count == 0) count = LLONG_MAX; /* WAVE-file should be even (I'm not sure), but wasting one byte isn't a problem (this can only be in 8 bit mono) */ if (count < LLONG_MAX) count += count % 2; else count -= count % 2; /* display verbose output to console */ header(file_type, name); /* setup sound hardware */ set_params(); /* write to stdout? */ if (!name || !strcmp(name, "-")) { fd = fileno(stdout); name = "stdout"; tostdout=1; if (count > fmt_rec_table[file_type].max_filesize) count = fmt_rec_table[file_type].max_filesize; } do { /* open a file to write */ if(!tostdout) { /* upon the second file we start the numbering scheme */ if (filecount) { filecount = new_capture_file(orig_name, namebuf, sizeof(namebuf), filecount); name = namebuf; } /* open a new file */ remove(name); if ((fd = open64(name, O_WRONLY | O_CREAT, 0644)) == -1) { perror(name); exit(EXIT_FAILURE); } filecount++; } rest = count; if (rest > fmt_rec_table[file_type].max_filesize) rest = fmt_rec_table[file_type].max_filesize; /* setup sample header */ if (fmt_rec_table[file_type].start) fmt_rec_table[file_type].start(fd, rest); /* capture */ fdcount = 0; while (rest > 0) { size_t c = (rest <= (off64_t)chunk_bytes) ? (size_t)rest : chunk_bytes; size_t f = c * 8 / bits_per_frame; if (pcm_read(audiobuf, f) != f) break; if (write(fd, audiobuf, c) != c) { perror(name); exit(EXIT_FAILURE); } count -= c; rest -= c; fdcount += c; } /* finish sample container */ if (fmt_rec_table[file_type].end && !tostdout) { fmt_rec_table[file_type].end(fd); fd = -1; } /* repeat the loop when format is raw without timelimit or * requested counts of data are recorded */ } while ((file_type == FORMAT_RAW && !timelimit) || count > 0);}static void playbackv_go(int* fds, unsigned int channels, size_t loaded, off64_t count, int rtype, char **names){ int r; size_t vsize; unsigned int channel; u_char *bufs[channels]; header(rtype, names[0]); set_params(); vsize = chunk_bytes / channels; // Not yet implemented assert(loaded == 0); for (channel = 0; channel < channels; ++channel) bufs[channel] = audiobuf + vsize * channel; while (count > 0) { size_t c = 0; size_t expected = count / channels; if (expected > vsize) expected = vsize; do { r = safe_read(fds[0], bufs[0], expected); if (r < 0) { perror(names[channel]); exit(EXIT_FAILURE); } for (channel = 1; channel < channels; ++channel) { if (safe_read(fds[channel], bufs[channel], r) != r) { perror(names[channel]); exit(EXIT_FAILURE); } } if (r == 0) break; c += r; } while (c < expected); c = c * 8 / bits_per_sample; r = pcm_writev(bufs, channels, c); if ((size_t)r != c) break; r = r * bits_per_frame / 8; count -= r; } snd_pcm_nonblock(handle, 0); snd_pcm_drain(handle); snd_pcm_nonblock(handle, nonblock);}static void capturev_go(int* fds, unsigned int channels, off64_t count, int rtype, char **names){ size_t c; ssize_t r; unsigned int channel; size_t vsize; u_char *bufs[channels]; header(rtype, names[0]); set_params(); vsize = chunk_bytes / channels; for (channel = 0; channel < channels; ++channel) bufs[channel] = audiobuf + vsize * channel; while (count > 0) { size_t rv; c = count; if (c > chunk_bytes) c = chunk_bytes; c = c * 8 / bits_per_frame; if ((size_t)(r = pcm_readv(bufs, channels, c)) != c) break; rv = r * bits_per_sample / 8; for (channel = 0; channel < channels; ++channel) { if ((size_t)write(fds[channel], bufs[channel], rv) != rv) { perror(names[channel]); exit(EXIT_FAILURE); } } r = r * bits_per_frame / 8; count -= r; fdcount += r; }}static void playbackv(char **names, unsigned int count){ int ret = 0; unsigned int channel; unsigned int channels = rhwparams.channels; int alloced = 0; int fds[channels]; for (channel = 0; channel < channels; ++channel) fds[channel] = -1; if (count == 1 && channels > 1) { size_t len = strlen(names[0]); char format[1024]; memcpy(format, names[0], len); strcpy(format + len, ".%d"); len += 4; names = malloc(sizeof(*names) * channels); for (channel = 0; channel < channels; ++channel) { names[channel] = malloc(len); sprintf(nam
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -