diff options
Diffstat (limited to 'snd/convert.c')
-rw-r--r-- | snd/convert.c | 247 |
1 files changed, 247 insertions, 0 deletions
diff --git a/snd/convert.c b/snd/convert.c new file mode 100644 index 0000000..85c839c --- /dev/null +++ b/snd/convert.c @@ -0,0 +1,247 @@ +/* Standard includes */ + +#include "stdlib.h" +#include "string.h" +#include "stdio.h" + +/* snd includes */ + +#include "snd.h" + +/* set the length of buffers to be even multiple of Audio_... + * to avoid fractional filling of + * audio output buffers + */ +#define MAXLEN MAX_FILE_BUF_LEN + +char *header_string[] = { "none", "AIFF", "IRCAM", "NeXT", "Wave" }; + +char *header_to_string(long header) +{ + if (header < 0 || header > 4) return "InvalidData"; + else return header_string[header]; +} + +void snd_print_info(snd_type snd) +{ + if (snd->device == SND_DEVICE_AUDIO) { + if (snd->write_flag == SND_READ) { + printf("audio input"); + } else { + printf("audio output"); + } + } else if (snd->device == SND_DEVICE_MEM) { + if (snd->write_flag == SND_READ) { + printf("from memory buffer"); + } else { + printf("to memory buffer"); + } + } else { + printf("header %s", header_to_string(snd->u.file.header)); + } + printf(", channels %d, mode %s, bits %d, srate %g", + snd->format.channels, + snd_mode_to_string(snd->format.mode), + snd->format.bits, snd->format.srate); + if (snd->device == SND_DEVICE_MEM) { + if (snd->write_flag == SND_READ) { + printf("length %d\n", snd->u.mem.buffer_len); + } else { + printf("length %d\n", snd->u.mem.buffer_max); + } + } else if (snd->device == SND_DEVICE_FILE && + snd->write_flag == SND_READ) { + printf(", length %d\n", (snd->u.file.end_offset - + snd->u.file.byte_offset) / snd_bytes_per_frame(snd)); + } else printf("\n"); +} + + +int main(int argc, char *argv[]) +{ + char *fromfile = NULL; + char *tofile = NULL; + int i; + long flags = 0; + long frames; + long len; + long checksum = 0; + long count = 0; + + int format = SND_HEAD_AIFF; + int mode = SND_MODE_PCM; + int channels = 1; + int bits = 16; + double srate = 44100.0; + snd_node from_snd, to_snd; + char from_buf[MAXLEN]; + char to_buf[MAXLEN]; + long frames_from_len; + long frames_to_len; + long from_len = 0; + long to_len = 0; + + for (i = 1; i < argc; i++) { + if (*(argv[i]) != '-') { + if (!fromfile) fromfile = argv[i]; + else if (!tofile) tofile = argv[i]; + else { + printf("%s: don't know what to do with 3rd file\n", argv[i]); + return 1; + } + } else { + char *flag = argv[i] + 1; + if (*flag == '?') { + printf("convert -- sound file conversion utility\n\n"); + printf("usage: convert fromfile tofile -flag1 -flag2 ...\n"); + printf(" -fa -- AIFF file format\n"); + printf(" -fi -- IRCAM file format\n"); + printf(" -fn -- NeXT/Sun file format\n"); + printf(" -fw -- Wave file format\n"); + printf(" -ep -- PCM\n"); + printf(" -em -- u-Law\n"); + printf(" -ef -- float\n"); + printf(" -eu -- unsigned PCM\n"); + printf(" -b1 -- 8-bit\n"); + printf(" -b2 -- 16-bit\n"); + printf(" -b4 -- 32-bit\n"); + printf(" -c1 -- 1 channel, etc.\n"); + printf("use 'ada' to get audio input or output\n"); + } else if (*flag == 'f') { + switch (flag[1]) { + case 'a': format = SND_HEAD_AIFF; break; + case 'i': format = SND_HEAD_IRCAM; break; + case 'n': format = SND_HEAD_NEXT; break; + case 'w': format = SND_HEAD_WAVE; break; + default: printf("flag %s ignored\n", argv[i]); break; + } + } else if (*flag == 'e') { + switch (flag[1]) { + case 'p': mode = SND_MODE_PCM; break; + case 'm': mode = SND_MODE_ULAW; break; + case 'f': mode = SND_MODE_FLOAT; break; + case 'u': mode = SND_MODE_UPCM; break; + default: printf("flag %s ignored\n", argv[i]); break; + } + } else if (*flag == 'b') { + switch (flag[1]) { + case '1': bits = 8; break; + case '2': bits = 16; break; + case '4': bits = 32; break; + default: printf("flag %s ignored\n", argv[i]); break; + } + } else if (*flag == 'r') { + switch (flag[1]) { + case '4': srate = 44100.0; break; + case '2': srate = 22050.0; break; + case '1': srate = 11025.0; break; + case '8': srate = 8000.0; break; + default: printf("flag %s ignored\n", argv[i]); break; + } + } else if (*flag == 'c') { + channels = atoi(flag+1); + if (channels < 1 || channels > 16) { + channels = 1; + printf("flag %s ignored, using 1 channel\n", + argv[i]); + } + } + } + } + if (!tofile) { + printf("2 files not found, use -? for help\n"); + return 1; + } + + from_snd.device = SND_DEVICE_FILE; + from_snd.write_flag = SND_READ; + from_snd.u.file.byte_offset = 0; + from_snd.format.channels = channels; + from_snd.format.mode = mode; + from_snd.format.bits = bits; + from_snd.format.srate = srate; + + if (strcmp(fromfile, "ada") == 0) { + from_snd.device = SND_DEVICE_AUDIO; + from_snd.u.audio.protocol = SND_COMPUTEAHEAD; + from_snd.u.audio.latency = 1.0; + from_snd.u.audio.granularity = 0.1; + strcpy(from_snd.u.file.filename, ""); + } else { + strcpy(from_snd.u.file.filename, fromfile); + } + if (snd_open(&from_snd, &flags) != SND_SUCCESS) { + printf("error opening %s for input\n", fromfile); + exit(1); + } + printf("Opened %s for input: ", from_snd.u.file.filename); + snd_print_info(&from_snd); + + to_snd.device = SND_DEVICE_FILE; + to_snd.write_flag = SND_WRITE; + to_snd.format.channels = channels; + to_snd.format.mode = mode; + to_snd.format.bits = bits; + to_snd.format.srate = from_snd.format.srate; + to_snd.u.file.header = format; /* header format, e.g. AIFF */ + if (to_snd.u.file.header == SND_HEAD_WAVE && to_snd.format.mode == SND_MODE_PCM && + to_snd.format.bits == 8) to_snd.format.mode = SND_MODE_UPCM; + if (strcmp(tofile, "ada") == 0) { + to_snd.device = SND_DEVICE_AUDIO; + to_snd.u.audio.protocol = SND_COMPUTEAHEAD; + to_snd.u.audio.latency = 0.0; + to_snd.u.audio.granularity = 0.1; + strcpy(to_snd.u.audio.interfacename, ""); + strcpy(to_snd.u.audio.devicename, ""); + } else { + strcpy(to_snd.u.file.filename, tofile); + } + if (snd_open(&to_snd, &flags) != SND_SUCCESS) { + printf("error opening %s for output\n", tofile); + exit(1); + } + printf("Opened %s for output: ", to_snd.u.file.filename); + snd_print_info(&to_snd); + + /* figure out how much to convert on each iteration */ + + /* first, compute how many frames could fit in each buffer */ + from_len = MAXLEN / snd_bytes_per_frame(&from_snd); + to_len = MAXLEN / snd_bytes_per_frame(&to_snd); + + /* then compute the minimum of the two frame counts */ + frames = min(from_len, to_len); + + while (1) { + /* then convert back from frame counts to byte counts: */ + while ((frames_from_len = snd_poll(&from_snd)) <=0); + frames_from_len = min(frames_from_len, frames); + while ((frames_to_len = snd_poll(&to_snd)) <= 0); + frames_to_len = min(frames_to_len, frames); + len = min(frames_to_len, frames_from_len); + len = snd_read(&from_snd, from_buf, len); + if (((from_snd.device == SND_DEVICE_AUDIO) && + (count > from_snd.format.srate * 10)) || (!len)) { + break; + } + for (i = 0; i < len * snd_bytes_per_frame(&from_snd); i++) { + checksum += from_buf[i]; + count++; + } + len = snd_convert(&to_snd, to_buf, &from_snd, from_buf, len); + len = snd_write(&to_snd, to_buf, len); + printf("#"); + fflush(stdout); + } + snd_close(&from_snd); + if (to_snd.device == SND_DEVICE_AUDIO) { + while (snd_flush(&to_snd) != SND_SUCCESS) ; + } + snd_close(&to_snd); + + printf("Read %ld frames, checksum = %ld\n", count, checksum); + exit(0); +} + + + |