1 #ifndef lint
2 static char rcsid[] =
3     "$Id: encode_riff.c,v 1.10 1997/03/25 15:21:09 tommy Exp $";
4 #endif
5 
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <fcntl.h>
9 #include <string.h>
10 #include <unistd.h>
11 #include <signal.h>
12 #include <err.h>
13 #include <arpa/inet.h>
14 
15 #include <sys/soundcard.h>
16 
17 #include "play.h"
18 #include "encode_riff.h"
19 
check_riff(char * audio_file)20 riff_header_t *check_riff(char *audio_file)
21 {
22     int fd, stat;
23     static riff_header_t header;
24 
25     if ((fd = open(audio_file, O_RDONLY)) < 0) {
26 	warn("%s", audio_file);
27 	return (riff_header_t*)FAIL;
28     }
29     if (read(fd, &header, sizeof(header)) < 0) {
30 	warn("%s", audio_file);
31 	stat = NULL; goto checkfail;
32     }
33 
34     header.magic = htonl(header.magic);
35     if (header.magic == RIFF_MAGIC) {
36 	header.chunk_data = htonl(header.chunk_data);
37 	header.chunk_type = htonl(header.chunk_type);
38 	if (header.chunk_type != RIFF_TYPE) {
39 	    fprintf(stderr, "%s: missing \"WAVE\"\n", myname, audio_file);
40 	    stat = FAIL; goto checkfail;
41 	}
42 	header.chunk_format = htonl(header.chunk_format) >> 8;
43 	if ((header.chunk_format) != RIFF_FORMAT) {
44 	    fprintf(stderr, "%s: missing \"fmt\"\n",  audio_file);
45 	    stat = FAIL; goto checkfail;
46 	}
47 	return &header;
48     }
49     stat = NULL;
50 
51 checkfail:
52     close(fd);
53     return (riff_header_t*)stat;
54 }
55 
print_riff_header(riff_header_t * headp)56 void print_riff_header(riff_header_t *headp)
57 {
58     printf("       magic = %d\n", headp->magic);
59     printf("      length = %d\n", headp->length);
60     printf("  chunk_type = %d\n", headp->chunk_type);
61     printf("chunk_format = %x\n", headp->chunk_format);
62     printf("chunk_length = %d\n", headp->chunk_length);
63     printf("      format = %d\n", headp->format);
64     printf("    chanells = %d\n", headp->channels);
65     printf(" sample_rate = %d\n", headp->sample_rate);
66     printf("       speed = %d\n", headp->speed);
67     printf(" sample_size = %d\n", headp->sample_size);
68     printf("   precision = %d\n", headp->precision);
69     printf("  chunk_data = %d\n", headp->chunk_data);
70     printf(" data_length = %d\n", headp->data_length);
71 }
72 
play_riff(char * audio_file,riff_header_t * headerp,arg_params_t * params)73 int play_riff(char *audio_file, riff_header_t *headerp, arg_params_t *params)
74 {
75     char *bufp;
76     char *device;
77     int devfd, filefd;
78     int stat, len, buf_size, format = 0, data_length;
79 
80     if (!f_hasdsp) {
81 	fprintf(stderr, "%s: %s: needs DSP for play\n", myname, audio_file);
82 	return FAIL;
83     }
84     if (f_extra)
85 	print_riff_header(headerp);
86 
87     switch (headerp->precision) {
88     case 8:
89 	format = AFMT_U8;
90 	break;
91     case 16:
92 	format = AFMT_S16_LE;
93 	break;
94     default:
95 	break;
96     }
97 
98     if (params->device == NULL)
99 	device = DEV_DSP;
100     else
101 	device = params->device;
102 
103     if ((data_length = headerp->data_length) < 16)
104 	data_length = headerp->length - sizeof(riff_header_t);
105 
106     if ((devfd = open(device, O_WRONLY)) < 0)
107 	err(1, "%s", device);
108 
109     if (ioctl(devfd, SNDCTL_DSP_GETBLKSIZE, &buf_size) < 0) {
110 	warn("%s", device);
111 	stat = FAIL; goto failplay0;
112     }
113 #if 0
114     /* this (at least under fbsd) means that you want to set play format
115      * to headerp->sample_size which is a nonsense */
116     if (ioctl(devfd, SNDCTL_DSP_SAMPLESIZE, &headerp->sample_size) < 0) {
117 #endif
118     if (ioctl(devfd, SNDCTL_DSP_SAMPLESIZE, &format) < 0) {
119 	warn("%s", device);
120 	stat = FAIL; goto failplay0;
121     }
122     if (ioctl(devfd, SNDCTL_DSP_SPEED, &headerp->speed) < 0) {
123 	warn("%s", device);
124 	stat = FAIL; goto failplay0;
125     }
126     if (ioctl(devfd, SOUND_PCM_WRITE_RATE, &headerp->sample_rate) < 0) {
127 	warn("%s", device);
128 	stat = FAIL; goto failplay0;
129     }
130     if (headerp->channels > 1) {
131 	int ch = headerp->channels;
132 	if (ioctl(devfd, SNDCTL_DSP_STEREO, &ch) < 0) {
133 	    warn("%s", device);
134 	    stat = FAIL; goto failplay0;
135 	}
136     }
137     if (ioctl(devfd, SNDCTL_DSP_SYNC, NULL) < 0) {
138 	warn("%s", device);
139 	stat = FAIL; goto failplay0;
140     }
141 
142     if ((filefd = open(audio_file, O_RDONLY)) < 0) {
143 	warn("%s", audio_file);
144 	stat = FAIL; goto failplay0;
145     }
146     if ((bufp = (char*)malloc((size_t)buf_size)) == NULL) {
147 	warn("malloc");
148 	stat = FAIL; goto failplay1;
149     }
150     if ((stat = read(filefd, bufp, sizeof(riff_header_t))) < 0) {
151 	warn("%s", audio_file);
152 	stat = FAIL; goto failplay2;
153     }
154 
155     len = data_length;
156 
157     intr = FALSE;
158     signal(SIGINT, intr_play);
159 
160     while (len > 0) {
161 	if (intr)
162 	    break;
163 	if ((stat = read(filefd, bufp, buf_size)) < 0) {
164 	    warn("read");
165 	    stat = FAIL; goto failplay2;
166 	}
167 /*	printf("len = %10d, len = %10d\n", stat, len); */
168 	stat = (len < stat)? len : stat;
169 	if (write(devfd, bufp, stat) < 0) {
170 	    warn("write");
171 	    stat = FAIL; goto failplay2;
172 	}
173 	len -= stat;
174     }
175     stat = SUCCESS;
176 
177 failplay2:
178     free(bufp);
179 failplay1:
180     close(filefd);
181 failplay0:
182     close(devfd);
183 
184     return stat;
185 }
186