#ifndef lint static char rcsid[] = "$Id: encode_riff.c,v 1.10 1997/03/25 15:21:09 tommy Exp $"; #endif #include #include #include #include #include #include #include #include #include "play.h" #include "encode_riff.h" riff_header_t *check_riff(char *audio_file) { int fd, stat; static riff_header_t header; if ((fd = open(audio_file, O_RDONLY)) < 0) { warn("%s", audio_file); return (riff_header_t*)FAIL; } if (read(fd, &header, sizeof(header)) < 0) { warn("%s", audio_file); stat = NULL; goto checkfail; } header.magic = htonl(header.magic); if (header.magic == RIFF_MAGIC) { header.chunk_data = htonl(header.chunk_data); header.chunk_type = htonl(header.chunk_type); if (header.chunk_type != RIFF_TYPE) { fprintf(stderr, "%s: missing \"WAVE\"\n", myname, audio_file); stat = FAIL; goto checkfail; } header.chunk_format = htonl(header.chunk_format) >> 8; if ((header.chunk_format) != RIFF_FORMAT) { fprintf(stderr, "%s: missing \"fmt\"\n", audio_file); stat = FAIL; goto checkfail; } return &header; } stat = NULL; checkfail: close(fd); return (riff_header_t*)stat; } void print_riff_header(riff_header_t *headp) { printf(" magic = %d\n", headp->magic); printf(" length = %d\n", headp->length); printf(" chunk_type = %d\n", headp->chunk_type); printf("chunk_format = %x\n", headp->chunk_format); printf("chunk_length = %d\n", headp->chunk_length); printf(" format = %d\n", headp->format); printf(" chanells = %d\n", headp->channels); printf(" sample_rate = %d\n", headp->sample_rate); printf(" speed = %d\n", headp->speed); printf(" sample_size = %d\n", headp->sample_size); printf(" precision = %d\n", headp->precision); printf(" chunk_data = %d\n", headp->chunk_data); printf(" data_length = %d\n", headp->data_length); } int play_riff(char *audio_file, riff_header_t *headerp, arg_params_t *params) { char *bufp; char *device; int devfd, filefd; int stat, len, buf_size, format = 0, data_length; if (!f_hasdsp) { fprintf(stderr, "%s: %s: needs DSP for play\n", myname, audio_file); return FAIL; } if (f_extra) print_riff_header(headerp); switch (headerp->precision) { case 8: format = AFMT_U8; break; case 16: format = AFMT_S16_LE; break; default: break; } if (params->device == NULL) device = DEV_DSP; else device = params->device; if ((data_length = headerp->data_length) < 16) data_length = headerp->length - sizeof(riff_header_t); if ((devfd = open(device, O_WRONLY)) < 0) err(1, "%s", device); if (ioctl(devfd, SNDCTL_DSP_GETBLKSIZE, &buf_size) < 0) { warn("%s", device); stat = FAIL; goto failplay0; } #if 0 /* this (at least under fbsd) means that you want to set play format * to headerp->sample_size which is a nonsense */ if (ioctl(devfd, SNDCTL_DSP_SAMPLESIZE, &headerp->sample_size) < 0) { #endif if (ioctl(devfd, SNDCTL_DSP_SAMPLESIZE, &format) < 0) { warn("%s", device); stat = FAIL; goto failplay0; } if (ioctl(devfd, SNDCTL_DSP_SPEED, &headerp->speed) < 0) { warn("%s", device); stat = FAIL; goto failplay0; } if (ioctl(devfd, SOUND_PCM_WRITE_RATE, &headerp->sample_rate) < 0) { warn("%s", device); stat = FAIL; goto failplay0; } if (headerp->channels > 1) { int ch = headerp->channels; if (ioctl(devfd, SNDCTL_DSP_STEREO, &ch) < 0) { warn("%s", device); stat = FAIL; goto failplay0; } } if (ioctl(devfd, SNDCTL_DSP_SYNC, NULL) < 0) { warn("%s", device); stat = FAIL; goto failplay0; } if ((filefd = open(audio_file, O_RDONLY)) < 0) { warn("%s", audio_file); stat = FAIL; goto failplay0; } if ((bufp = (char*)malloc((size_t)buf_size)) == NULL) { warn("malloc"); stat = FAIL; goto failplay1; } if ((stat = read(filefd, bufp, sizeof(riff_header_t))) < 0) { warn("%s", audio_file); stat = FAIL; goto failplay2; } len = data_length; intr = FALSE; signal(SIGINT, intr_play); while (len > 0) { if (intr) break; if ((stat = read(filefd, bufp, buf_size)) < 0) { warn("read"); stat = FAIL; goto failplay2; } /* printf("len = %10d, len = %10d\n", stat, len); */ stat = (len < stat)? len : stat; if (write(devfd, bufp, stat) < 0) { warn("write"); stat = FAIL; goto failplay2; } len -= stat; } stat = SUCCESS; failplay2: free(bufp); failplay1: close(filefd); failplay0: close(devfd); return stat; }