1 /* Signal Processing - Wave File Functions
2
3 * Copyright (C) 1998 J.A. Bezemer
4 *
5 * Licensed under the terms of the GNU General Public License.
6 * ABSOLUTELY NO WARRANTY.
7 * See the file `COPYING' in this directory.
8 */
9
10 #include "signpr_wav.h"
11 #include "fmtheaders.h"
12 #include "errorwindow.h"
13 #include "signpr_general.h"
14 #include <string.h>
15 #include <stdio.h>
16 #include <unistd.h>
17 #include <sys/stat.h>
18 #include <sys/types.h>
19 #include <fcntl.h>
20 #include "endian.h"
21
22 /* ----- SOURCE & READING -------------------------------------------------- */
23
24 FILE *sourcefile;
25 int num_read_samples_buffered = 0;
26 sample_t readsamplebuffer[44100];
27
28 int
openwavsource(char * filename)29 openwavsource (char *filename)
30 /* returns 0: failure (error_window has been displayed), 1: success.
31 More or less adapted from bplay.c, with stdio-patch by Axel Kohlmeyer
32 */
33 {
34 int count;
35 char hd_buf[20];
36 wavhead wavhd;
37
38 if ((sourcefile = fopen (filename, "rb")) == NULL)
39 {
40 error_window ("The source file could not be opened.");
41 return 0;
42 }
43
44 count = fread (hd_buf, 1, 20, sourcefile);
45 if (count < 20)
46 {
47 fclose (sourcefile);
48 error_window ("The source file could not be read, or is too short.");
49 return 0;
50 }
51
52 if (strstr (hd_buf, "RIFF") == NULL)
53 {
54 fclose (sourcefile);
55 error_window ("The source file is not a .wav file, and can not be \
56 processed.");
57 return 0;
58 }
59
60 memcpy ((void *) &wavhd, (void *) hd_buf, 20);
61 count = fread (((char *) &wavhd) + 20, 1, sizeof (wavhd) - 20, sourcefile);
62
63 if (count < sizeof (wavhd) - 20)
64 {
65 fclose (sourcefile);
66 error_window ("The source file is too short. Probably it is not \
67 a .wav sound file.");
68 return 0;
69 }
70
71 #ifdef SWAP_ENDIAN
72 wavhd.format = SwapTwoBytes (wavhd.format);
73 wavhd.sample_fq = SwapFourBytes (wavhd.sample_fq);
74 wavhd.bit_p_spl = SwapTwoBytes (wavhd.bit_p_spl);
75 wavhd.modus = SwapTwoBytes (wavhd.modus);
76 #endif
77
78 if (wavhd.format != 1)
79 {
80 fclose (sourcefile);
81 error_window ("The source file is a .wav file with unknown format, \
82 and can not be processed.");
83 return 0;
84 }
85
86 if (wavhd.sample_fq != 44100)
87 {
88 fclose (sourcefile);
89 error_window ("The source file is not sampled at 44100 Hz, and can \
90 not be processed.");
91 return 0;
92 }
93
94 if (wavhd.bit_p_spl != 16)
95 {
96 fclose (sourcefile);
97 error_window ("The source file does not have 16 bit samples, and \
98 can not be processed.");
99 return 0;
100 }
101
102 if (wavhd.modus != 2)
103 {
104 fclose (sourcefile);
105 error_window ("The source file is not stereo, and can not be \
106 processed.");
107 return 0;
108 }
109
110 /* Well, everything seems to be OK */
111 num_read_samples_buffered = 0;
112 return 1;
113 }
114
115 void
closewavsource()116 closewavsource ()
117 {
118 fclose (sourcefile);
119 num_read_samples_buffered = 0;
120 }
121
122 int
seeksamplesource(long samplenumber)123 seeksamplesource (long samplenumber)
124 /* returns 0: failure, 1: success */
125 {
126 struct stat buf;
127
128 /* throw away buffer on fseek */
129 num_read_samples_buffered = 0;
130
131 if (fstat (fileno (sourcefile), &buf))
132 return 0;
133
134 if (sizeof (wavhead) + 2 * 2 * samplenumber >= buf.st_size)
135 return 0;
136
137 if (fseek (sourcefile, sizeof (wavhead) + 2 * 2 * samplenumber, SEEK_SET) > -1)
138 return 1;
139 else
140 return 0;
141 }
142
143 sample_t
readsamplesource()144 readsamplesource ()
145 {
146 /* millions of calls to fread sure slow things down.... buffer it a little */
147 static int i;
148
149 if (i >= num_read_samples_buffered)
150 {
151 num_read_samples_buffered = fread(readsamplebuffer, 4, sizeof(readsamplebuffer)/4, sourcefile);
152 i = 0;
153 if (!num_read_samples_buffered)
154 {
155 /* reading after end of file - this just happens when using
156 pre-read buffers! */
157 readsamplebuffer[0].left = 0;
158 readsamplebuffer[0].right = 0;
159 return readsamplebuffer[0];
160 }
161 }
162
163 #ifdef SWAP_ENDIAN
164 SWAPSAMPLEREF (readsamplebuffer+i);
165 #endif
166 return readsamplebuffer[i++];
167 }
168
169
170 /* ----- DESTINATION & WRITING --------------------------------------------- */
171
172 FILE *destfile;
173 int destfileispipe; /* remember open() - - -> close() */
174 int num_write_samples_buffered = 0;
175 sample_t writesamplebuffer[44100];
176
177 int
openwavdest(char * filename,long bcount)178 openwavdest (char *filename, long bcount)
179 /* returns 0: failure (error_window has NOT been displayed), 1: success.
180 bcount must be 4 * number_of_samples !
181 Adapted from bplay.c
182 */
183 {
184 wavhead header;
185 char *riff = "RIFF";
186 char *wave = "WAVE";
187 char *fmt = "fmt ";
188 char *data = "data";
189
190 if (*filename == '|')
191 {
192 destfileispipe = 1; /* remember for closing */
193 if ((destfile = popen (filename + 1, "w")) == NULL)
194 return 0;
195 }
196 else
197 {
198 destfileispipe = 0;
199 if ((destfile = fopen (filename, "wb")) == NULL)
200 return 0;
201 }
202
203
204 memcpy (&(header.main_chunk), riff, 4);
205 header.length = sizeof (wavhead) - 8 + bcount;
206 memcpy (&(header.chunk_type), wave, 4);
207
208 memcpy (&(header.sub_chunk), fmt, 4);
209 header.sc_len = 16;
210 header.format = 1;
211 header.modus = /*stereo */ 1 + 1;
212 header.sample_fq = /*speed */ 44100;
213 header.byte_p_sec = /*((bits > 8)? 2:1)*(stereo+1)*speed */ 2 * 2 * 44100;
214 header.byte_p_spl = /*(bits > 8)? 2:1 */ 4; /* stereo & 16 bit..? */
215 header.bit_p_spl = /*bits */ 16; /* stereo doesn't count here? */
216
217 memcpy (&(header.data_chunk), data, 4);
218 header.data_length = bcount;
219
220 #ifdef SWAP_ENDIAN
221 header.length = SwapFourBytes (header.length);
222 header.sc_len = SwapFourBytes (header.sc_len);
223 header.format = SwapTwoBytes (header.format);
224 header.modus = SwapTwoBytes (header.modus);
225 header.sample_fq = SwapFourBytes (header.sample_fq);
226 header.byte_p_sec = SwapFourBytes (header.byte_p_sec);
227 header.byte_p_spl = SwapTwoBytes (header.byte_p_spl);
228 header.bit_p_spl = SwapTwoBytes (header.bit_p_spl);
229 header.data_length = SwapFourBytes (header.data_length);
230 #endif
231
232 fwrite (&header, sizeof (header), 1, destfile);
233
234 num_write_samples_buffered = 0; /* just in case */
235 return 1;
236 }
237
flushwritebuffer()238 void flushwritebuffer()
239 {
240 fwrite(writesamplebuffer, 4 * num_write_samples_buffered, 1, destfile);
241 num_write_samples_buffered = 0;
242 }
243
244 void
closewavdest()245 closewavdest ()
246 {
247 flushwritebuffer();
248 if (destfileispipe)
249 pclose (destfile);
250 else
251 fclose (destfile);
252 }
253
254 void
writesampledest(sample_t sample)255 writesampledest (sample_t sample)
256 {
257
258 #ifdef SWAP_ENDIAN
259 SWAPSAMPLEREF(&sample);
260 #endif
261 if (num_write_samples_buffered == (sizeof (writesamplebuffer) / 4))
262 flushwritebuffer();
263 writesamplebuffer[num_write_samples_buffered++] = sample;
264 }
265