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