Mercurial > fife-parpg
comparison ext/openal-soft/Alc/wave.c @ 0:4a0efb7baf70
* Datasets becomes the new trunk and retires after that :-)
author | mvbarracuda@33b003aa-7bff-0310-803a-e67f0ece8222 |
---|---|
date | Sun, 29 Jun 2008 18:44:17 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4a0efb7baf70 |
---|---|
1 /** | |
2 * OpenAL cross platform audio library | |
3 * Copyright (C) 1999-2007 by authors. | |
4 * This library is free software; you can redistribute it and/or | |
5 * modify it under the terms of the GNU Library General Public | |
6 * License as published by the Free Software Foundation; either | |
7 * version 2 of the License, or (at your option) any later version. | |
8 * | |
9 * This library is distributed in the hope that it will be useful, | |
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
12 * Library General Public License for more details. | |
13 * | |
14 * You should have received a copy of the GNU Library General Public | |
15 * License along with this library; if not, write to the | |
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
17 * Boston, MA 02111-1307, USA. | |
18 * Or go to http://www.gnu.org/copyleft/lgpl.html | |
19 */ | |
20 | |
21 #include "config.h" | |
22 | |
23 #include <stdlib.h> | |
24 #include <stdio.h> | |
25 #include <memory.h> | |
26 #include "alMain.h" | |
27 #include "AL/al.h" | |
28 #include "AL/alc.h" | |
29 | |
30 | |
31 typedef struct { | |
32 FILE *f; | |
33 long DataStart; | |
34 | |
35 ALvoid *buffer; | |
36 ALuint size; | |
37 | |
38 int killNow; | |
39 ALvoid *thread; | |
40 } wave_data; | |
41 | |
42 | |
43 static ALCchar *waveDevice; | |
44 | |
45 | |
46 static ALuint WaveProc(ALvoid *ptr) | |
47 { | |
48 ALCdevice *pDevice = (ALCdevice*)ptr; | |
49 wave_data *data = (wave_data*)pDevice->ExtraData; | |
50 ALuint frameSize; | |
51 ALuint now, last; | |
52 size_t WriteCnt; | |
53 ALuint avail; | |
54 union { | |
55 short s; | |
56 char b[sizeof(short)]; | |
57 } uSB; | |
58 | |
59 uSB.s = 1; | |
60 frameSize = aluBytesFromFormat(pDevice->Format) * | |
61 aluChannelsFromFormat(pDevice->Format); | |
62 | |
63 last = timeGetTime(); | |
64 while(!data->killNow) | |
65 { | |
66 now = timeGetTime(); | |
67 | |
68 avail = (now-last) * pDevice->Frequency / 1000; | |
69 if(avail < pDevice->UpdateSize/4) | |
70 { | |
71 Sleep(1); | |
72 continue; | |
73 } | |
74 | |
75 while(avail > 0) | |
76 { | |
77 SuspendContext(NULL); | |
78 WriteCnt = min(data->size, avail); | |
79 aluMixData(pDevice->Context, data->buffer, WriteCnt * frameSize, | |
80 pDevice->Format); | |
81 ProcessContext(NULL); | |
82 | |
83 if(uSB.b[0] != 1 && aluBytesFromFormat(pDevice->Format) > 1) | |
84 { | |
85 ALubyte *bytes = data->buffer; | |
86 ALuint i; | |
87 | |
88 for(i = 0;i < WriteCnt*frameSize;i++) | |
89 fputc(bytes[i^1], data->f); | |
90 } | |
91 else | |
92 fwrite(data->buffer, frameSize, WriteCnt, data->f); | |
93 if(ferror(data->f)) | |
94 { | |
95 AL_PRINT("Error writing to file\n"); | |
96 data->killNow = 1; | |
97 break; | |
98 } | |
99 | |
100 avail -= WriteCnt; | |
101 } | |
102 last = now; | |
103 } | |
104 | |
105 return 0; | |
106 } | |
107 | |
108 static ALCboolean wave_open_playback(ALCdevice *device, const ALCchar *deviceName) | |
109 { | |
110 wave_data *data; | |
111 ALuint channels; | |
112 ALuint bits; | |
113 const char *fname; | |
114 int i; | |
115 | |
116 fname = GetConfigValue("wave", "file", ""); | |
117 if(!fname[0]) | |
118 return ALC_FALSE; | |
119 | |
120 if(deviceName) | |
121 { | |
122 if(strcmp(deviceName, waveDevice) != 0) | |
123 return ALC_FALSE; | |
124 device->szDeviceName = waveDevice; | |
125 } | |
126 else | |
127 device->szDeviceName = waveDevice; | |
128 | |
129 data = (wave_data*)calloc(1, sizeof(wave_data)); | |
130 | |
131 data->f = fopen(fname, "wb"); | |
132 if(!data->f) | |
133 { | |
134 free(data); | |
135 AL_PRINT("Could not open file '%s': %s\n", fname, strerror(errno)); | |
136 return ALC_FALSE; | |
137 } | |
138 | |
139 bits = aluBytesFromFormat(device->Format) * 8; | |
140 channels = aluChannelsFromFormat(device->Format); | |
141 switch(bits) | |
142 { | |
143 case 8: | |
144 case 16: | |
145 if(channels == 0) | |
146 { | |
147 AL_PRINT("Unknown format?! %x\n", device->Format); | |
148 fclose(data->f); | |
149 free(data); | |
150 return ALC_FALSE; | |
151 } | |
152 break; | |
153 | |
154 default: | |
155 AL_PRINT("Unknown format?! %x\n", device->Format); | |
156 fclose(data->f); | |
157 free(data); | |
158 return ALC_FALSE; | |
159 } | |
160 | |
161 fprintf(data->f, "RIFF"); | |
162 fputc(0, data->f); // 'RIFF' header len; filled in at close | |
163 fputc(0, data->f); | |
164 fputc(0, data->f); | |
165 fputc(0, data->f); | |
166 | |
167 fprintf(data->f, "WAVE"); | |
168 | |
169 fprintf(data->f, "fmt "); | |
170 fputc(16, data->f); // 'fmt ' header len; 16 bytes for PCM | |
171 fputc(0, data->f); | |
172 fputc(0, data->f); | |
173 fputc(0, data->f); | |
174 // 16-bit val, format type id (PCM: 1) | |
175 fputc(1, data->f); | |
176 fputc(0, data->f); | |
177 // 16-bit val, channel count | |
178 fputc(channels&0xff, data->f); | |
179 fputc((channels>>8)&0xff, data->f); | |
180 // 32-bit val, frequency | |
181 fputc(device->Frequency&0xff, data->f); | |
182 fputc((device->Frequency>>8)&0xff, data->f); | |
183 fputc((device->Frequency>>16)&0xff, data->f); | |
184 fputc((device->Frequency>>24)&0xff, data->f); | |
185 // 32-bit val, bytes per second | |
186 i = device->Frequency * channels * bits / 8; | |
187 fputc(i&0xff, data->f); | |
188 fputc((i>>8)&0xff, data->f); | |
189 fputc((i>>16)&0xff, data->f); | |
190 fputc((i>>24)&0xff, data->f); | |
191 // 16-bit val, frame size | |
192 i = channels * bits / 8; | |
193 fputc(i&0xff, data->f); | |
194 fputc((i>>8)&0xff, data->f); | |
195 // 16-bit val, bits per sample | |
196 fputc(bits&0xff, data->f); | |
197 fputc((bits>>8)&0xff, data->f); | |
198 | |
199 fprintf(data->f, "data"); | |
200 fputc(0, data->f); // 'data' header len; filled in at close | |
201 fputc(0, data->f); | |
202 fputc(0, data->f); | |
203 fputc(0, data->f); | |
204 | |
205 if(ferror(data->f)) | |
206 { | |
207 AL_PRINT("Error writing header: %s\n", strerror(errno)); | |
208 fclose(data->f); | |
209 free(data); | |
210 return ALC_FALSE; | |
211 } | |
212 | |
213 data->DataStart = ftell(data->f); | |
214 | |
215 device->UpdateSize = max(device->UpdateSize, 2048); | |
216 | |
217 data->size = device->UpdateSize; | |
218 data->buffer = malloc(data->size * channels * bits / 8); | |
219 if(!data->buffer) | |
220 { | |
221 AL_PRINT("buffer malloc failed\n"); | |
222 fclose(data->f); | |
223 free(data); | |
224 return ALC_FALSE; | |
225 } | |
226 | |
227 device->ExtraData = data; | |
228 data->thread = StartThread(WaveProc, device); | |
229 if(data->thread == NULL) | |
230 { | |
231 device->ExtraData = NULL; | |
232 fclose(data->f); | |
233 free(data->buffer); | |
234 free(data); | |
235 return ALC_FALSE; | |
236 } | |
237 | |
238 return ALC_TRUE; | |
239 } | |
240 | |
241 static void wave_close_playback(ALCdevice *device) | |
242 { | |
243 wave_data *data = (wave_data*)device->ExtraData; | |
244 ALuint dataLen; | |
245 long size; | |
246 | |
247 data->killNow = 1; | |
248 StopThread(data->thread); | |
249 | |
250 size = ftell(data->f); | |
251 if(size > 0) | |
252 { | |
253 dataLen = size - data->DataStart; | |
254 if(fseek(data->f, data->DataStart-4, SEEK_SET) == 0) | |
255 { | |
256 fputc(dataLen&0xff, data->f); // 'data' header len | |
257 fputc((dataLen>>8)&0xff, data->f); | |
258 fputc((dataLen>>16)&0xff, data->f); | |
259 fputc((dataLen>>24)&0xff, data->f); | |
260 } | |
261 if(fseek(data->f, 4, SEEK_SET) == 0) | |
262 { | |
263 size -= 8; | |
264 fputc(size&0xff, data->f); // 'WAVE' header len | |
265 fputc((size>>8)&0xff, data->f); | |
266 fputc((size>>16)&0xff, data->f); | |
267 fputc((size>>24)&0xff, data->f); | |
268 } | |
269 } | |
270 | |
271 fclose(data->f); | |
272 free(data->buffer); | |
273 free(data); | |
274 device->ExtraData = NULL; | |
275 } | |
276 | |
277 | |
278 static ALCboolean wave_open_capture(ALCdevice *pDevice, const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei SampleSize) | |
279 { | |
280 (void)pDevice; | |
281 (void)deviceName; | |
282 (void)frequency; | |
283 (void)format; | |
284 (void)SampleSize; | |
285 return ALC_FALSE; | |
286 } | |
287 | |
288 static void wave_close_capture(ALCdevice *pDevice) | |
289 { | |
290 (void)pDevice; | |
291 } | |
292 | |
293 static void wave_start_capture(ALCdevice *pDevice) | |
294 { | |
295 (void)pDevice; | |
296 } | |
297 | |
298 static void wave_stop_capture(ALCdevice *pDevice) | |
299 { | |
300 (void)pDevice; | |
301 } | |
302 | |
303 static void wave_capture_samples(ALCdevice *pDevice, ALCvoid *pBuffer, ALCuint lSamples) | |
304 { | |
305 (void)pDevice; | |
306 (void)pBuffer; | |
307 (void)lSamples; | |
308 } | |
309 | |
310 static ALCuint wave_available_samples(ALCdevice *pDevice) | |
311 { | |
312 (void)pDevice; | |
313 return 0; | |
314 } | |
315 | |
316 | |
317 BackendFuncs wave_funcs = { | |
318 wave_open_playback, | |
319 wave_close_playback, | |
320 wave_open_capture, | |
321 wave_close_capture, | |
322 wave_start_capture, | |
323 wave_stop_capture, | |
324 wave_capture_samples, | |
325 wave_available_samples | |
326 }; | |
327 | |
328 void alc_wave_init(BackendFuncs *func_list) | |
329 { | |
330 *func_list = wave_funcs; | |
331 | |
332 waveDevice = AppendDeviceList("Wave File Writer"); | |
333 AppendAllDeviceList(waveDevice); | |
334 } |