Changed default audio device from SDL to OpenAL after a discussion in IRC, we're...
[blender.git] / source / blender / blenkernel / intern / sound.c
1 /**
2  * sound.c (mar-2001 nzc)
3  *
4  * $Id$
5  */
6
7 #include <string.h>
8 #include <stdlib.h>
9
10 #include "MEM_guardedalloc.h"
11
12 #include "BLI_blenlib.h"
13
14 #include "DNA_scene_types.h"
15 #include "DNA_sound_types.h"
16 #include "DNA_packedFile_types.h"
17 #include "DNA_screen_types.h"
18 #include "DNA_userdef_types.h"
19
20 #include "AUD_C-API.h"
21
22 #include "BKE_utildefines.h"
23 #include "BKE_global.h"
24 #include "BKE_main.h"
25 #include "BKE_sound.h"
26 #include "BKE_context.h"
27 #include "BKE_library.h"
28 #include "BKE_packedFile.h"
29
30 #ifdef HAVE_CONFIG_H
31 #include <config.h>
32 #endif
33
34 void sound_init()
35 {
36         AUD_Specs specs;
37         int device, buffersize;
38
39         device = U.audiodevice;
40         buffersize = U.mixbufsize;
41         specs.channels = U.audiochannels;
42         specs.format = U.audioformat;
43         specs.rate = U.audiorate;
44
45         if(buffersize < 128)
46                 buffersize = AUD_DEFAULT_BUFFER_SIZE;
47
48         if(specs.rate < AUD_RATE_8000)
49                 specs.rate = AUD_RATE_44100;
50
51         if(specs.format <= AUD_FORMAT_INVALID)
52                 specs.format = AUD_FORMAT_S16;
53
54         if(specs.channels <= AUD_CHANNELS_INVALID)
55                 specs.channels = AUD_CHANNELS_STEREO;
56
57         if(!AUD_init(device, specs, buffersize))
58                 AUD_init(AUD_NULL_DEVICE, specs, buffersize);
59 }
60
61 void sound_exit()
62 {
63         AUD_exit();
64 }
65
66 struct bSound* sound_new_file(struct Main *main, char* filename)
67 {
68         bSound* sound = NULL;
69
70         char str[FILE_MAX];
71         int len;
72
73         strcpy(str, filename);
74         BLI_convertstringcode(str, main->name);
75
76         len = strlen(filename);
77         while(len > 0 && filename[len-1] != '/' && filename[len-1] != '\\')
78                 len--;
79
80         sound = alloc_libblock(&main->sound, ID_SO, filename+len);
81         strcpy(sound->name, filename);
82         sound->type = SOUND_TYPE_FILE;
83
84         sound_load(main, sound);
85
86         if(!sound->snd_sound)
87         {
88                 free_libblock(&main->sound, sound);
89                 sound = NULL;
90         }
91
92         return sound;
93 }
94
95 // XXX unused currently
96 #if 0
97 struct bSound* sound_new_buffer(struct bContext *C, struct bSound *source)
98 {
99         bSound* sound = NULL;
100
101         char name[25];
102         strcpy(name, "buf_");
103         strcpy(name + 4, source->id.name);
104
105         sound = alloc_libblock(&CTX_data_main(C)->sound, ID_SO, name);
106
107         sound->child_sound = source;
108         sound->type = SOUND_TYPE_BUFFER;
109
110         sound_load(CTX_data_main(C), sound);
111
112         if(!sound->snd_sound)
113         {
114                 free_libblock(&CTX_data_main(C)->sound, sound);
115                 sound = NULL;
116         }
117
118         return sound;
119 }
120
121 struct bSound* sound_new_limiter(struct bContext *C, struct bSound *source, float start, float end)
122 {
123         bSound* sound = NULL;
124
125         char name[25];
126         strcpy(name, "lim_");
127         strcpy(name + 4, source->id.name);
128
129         sound = alloc_libblock(&CTX_data_main(C)->sound, ID_SO, name);
130
131         sound->child_sound = source;
132         sound->start = start;
133         sound->end = end;
134         sound->type = SOUND_TYPE_LIMITER;
135
136         sound_load(CTX_data_main(C), sound);
137
138         if(!sound->snd_sound)
139         {
140                 free_libblock(&CTX_data_main(C)->sound, sound);
141                 sound = NULL;
142         }
143
144         return sound;
145 }
146 #endif
147
148 void sound_delete(struct bContext *C, struct bSound* sound)
149 {
150         if(sound)
151         {
152                 sound_free(sound);
153
154                 sound_unlink(C, sound);
155
156                 free_libblock(&CTX_data_main(C)->sound, sound);
157         }
158 }
159
160 void sound_cache(struct bSound* sound, int ignore)
161 {
162         if(sound->cache && !ignore)
163                 AUD_unload(sound->cache);
164
165         sound->cache = AUD_bufferSound(sound->snd_sound);
166 }
167
168 void sound_load(struct Main *main, struct bSound* sound)
169 {
170         if(sound)
171         {
172                 if(sound->snd_sound)
173                 {
174                         AUD_unload(sound->snd_sound);
175                         sound->snd_sound = NULL;
176                 }
177
178                 switch(sound->type)
179                 {
180                 case SOUND_TYPE_FILE:
181                 {
182                         char fullpath[FILE_MAX];
183                         char *path;
184
185                         /* load sound */
186                         PackedFile* pf = sound->packedfile;
187
188                         /* dont modify soundact->sound->name, only change a copy */
189                         BLI_strncpy(fullpath, sound->name, sizeof(fullpath));
190
191                         if(sound->id.lib)
192                                 path = sound->id.lib->filename;
193                         else
194                                 path = main ? main->name : NULL;
195
196                         BLI_convertstringcode(fullpath, path);
197
198                         /* but we need a packed file then */
199                         if (pf)
200                                 sound->snd_sound = AUD_loadBuffer((unsigned char*) pf->data, pf->size);
201                         /* or else load it from disk */
202                         else
203                                 sound->snd_sound = AUD_load(fullpath);
204                         break;
205                 }
206                 case SOUND_TYPE_BUFFER:
207                         if(sound->child_sound && sound->child_sound->snd_sound)
208                                 sound->snd_sound = AUD_bufferSound(sound->child_sound->snd_sound);
209                         break;
210                 case SOUND_TYPE_LIMITER:
211                         if(sound->child_sound && sound->child_sound->snd_sound)
212                                 sound->snd_sound = AUD_limitSound(sound->child_sound, sound->start, sound->end);
213                         break;
214                 }
215
216                 if(sound->cache)
217                 {
218
219                 }
220         }
221 }
222
223 void sound_free(struct bSound* sound)
224 {
225         if (sound->packedfile)
226         {
227                 freePackedFile(sound->packedfile);
228                 sound->packedfile = NULL;
229         }
230
231         if(sound->snd_sound)
232         {
233                 AUD_unload(sound->snd_sound);
234                 sound->snd_sound = NULL;
235         }
236 }
237
238 void sound_unlink(struct bContext *C, struct bSound* sound)
239 {
240         bSound *snd;
241         Scene *scene;
242         SoundHandle *handle;
243
244         for(snd = CTX_data_main(C)->sound.first; snd; snd = snd->id.next)
245         {
246                 if(snd->child_sound == sound)
247                 {
248                         snd->child_sound = NULL;
249                         if(snd->snd_sound)
250                         {
251                                 AUD_unload(sound->snd_sound);
252                                 snd->snd_sound = NULL;
253                         }
254
255                         sound_unlink(C, snd);
256                 }
257         }
258
259         for(scene = CTX_data_main(C)->scene.first; scene; scene = scene->id.next)
260         {
261                 for(handle = scene->sound_handles.first; handle; handle = handle->next)
262                 {
263                         if(handle->source == sound)
264                         {
265                                 handle->source = NULL;
266                                 if(handle->handle)
267                                         AUD_stop(handle->handle);
268                         }
269                 }
270         }
271 }
272
273 struct SoundHandle* sound_new_handle(struct Scene *scene, struct bSound* sound, int startframe, int endframe, int frameskip)
274 {
275         ListBase* handles = &scene->sound_handles;
276
277         SoundHandle* handle = MEM_callocN(sizeof(SoundHandle), "sound_handle");
278         handle->source = sound;
279         handle->startframe = startframe;
280         handle->endframe = endframe;
281         handle->frameskip = frameskip;
282         handle->state = AUD_STATUS_INVALID;
283         handle->volume = 1.0f;
284
285         BLI_addtail(handles, handle);
286
287         return handle;
288 }
289
290 void sound_delete_handle(struct Scene *scene, struct SoundHandle *handle)
291 {
292         if(handle == NULL)
293                 return;
294
295         if(handle->handle)
296                 AUD_stop(handle->handle);
297
298         BLI_freelinkN(&scene->sound_handles, handle);
299 }
300
301 void sound_stop_all(struct bContext *C)
302 {
303         SoundHandle *handle;
304
305         for(handle = CTX_data_scene(C)->sound_handles.first; handle; handle = handle->next)
306         {
307                 if(handle->state == AUD_STATUS_PLAYING)
308                 {
309                         AUD_pause(handle->handle);
310                         handle->state = AUD_STATUS_PAUSED;
311                 }
312         }
313 }
314
315 void sound_update_playing(struct bContext *C)
316 {
317         SoundHandle *handle;
318         Scene* scene = CTX_data_scene(C);
319         int cfra = CFRA;
320         float fps = FPS;
321         int action;
322
323         AUD_lock();
324
325         for(handle = scene->sound_handles.first; handle; handle = handle->next)
326         {
327                 if(cfra < handle->startframe || cfra >= handle->endframe || handle->mute)
328                 {
329                         if(handle->state == AUD_STATUS_PLAYING)
330                         {
331                                 AUD_pause(handle->handle);
332                                 handle->state = AUD_STATUS_PAUSED;
333                         }
334                 }
335                 else
336                 {
337                         action = 0;
338
339                         if(handle->changed != handle->source->changed)
340                         {
341                                 handle->changed = handle->source->changed;
342                                 action = 3;
343                                 if(handle->state != AUD_STATUS_INVALID)
344                                 {
345                                         AUD_stop(handle->handle);
346                                         handle->state = AUD_STATUS_INVALID;
347                                 }
348                         }
349                         else
350                         {
351                                 if(handle->state != AUD_STATUS_PLAYING)
352                                         action = 3;
353                                 else
354                                 {
355                                         handle->state = AUD_getStatus(handle->handle);
356                                         if(handle->state != AUD_STATUS_PLAYING)
357                                                 action = 3;
358                                         else
359                                         {
360                                                 float diff = AUD_getPosition(handle->handle) * fps - cfra + handle->startframe;
361                                                 if(diff < 0.0)
362                                                         diff = -diff;
363                                                 if(diff > 1.0f)
364                                                 {
365                                                         action = 2;
366                                                 }
367                                         }
368                                 }
369                         }
370
371                         if(action & 1)
372                         {
373                                 if(handle->state == AUD_STATUS_INVALID)
374                                 {
375                                         if(handle->source && handle->source->snd_sound)
376                                         {
377                                                 AUD_Sound* limiter = AUD_limitSound(handle->source->cache ? handle->source->cache : handle->source->snd_sound, handle->frameskip / fps, (handle->frameskip + handle->endframe - handle->startframe)/fps);
378                                                 handle->handle = AUD_play(limiter, 1);
379                                                 AUD_unload(limiter);
380                                                 if(handle->handle)
381                                                         handle->state = AUD_STATUS_PLAYING;
382                                                 if(cfra == handle->startframe)
383                                                         action &= ~2;
384                                         }
385                                 }
386                                 else
387                                         if(AUD_resume(handle->handle))
388                                                 handle->state = AUD_STATUS_PLAYING;
389                                         else
390                                                 handle->state = AUD_STATUS_INVALID;
391                         }
392
393                         if(action & 2)
394                                 AUD_seek(handle->handle, (cfra - handle->startframe) / fps);
395                 }
396         }
397
398         AUD_unlock();
399 }
400
401 void sound_scrub(struct bContext *C)
402 {
403         SoundHandle *handle;
404         Scene* scene = CTX_data_scene(C);
405         int cfra = CFRA;
406         float fps = FPS;
407
408         if(scene->r.audio.flag & AUDIO_SCRUB && !CTX_wm_screen(C)->animtimer)
409         {
410                 AUD_lock();
411
412                 for(handle = scene->sound_handles.first; handle; handle = handle->next)
413                 {
414                         if(cfra >= handle->startframe && cfra < handle->endframe && !handle->mute)
415                         {
416                                 if(handle->source && handle->source->snd_sound)
417                                 {
418                                         int frameskip = handle->frameskip + cfra - handle->startframe;
419                                         AUD_Sound* limiter = AUD_limitSound(handle->source->cache ? handle->source->cache : handle->source->snd_sound, frameskip / fps, (frameskip + 1)/fps);
420                                         AUD_play(limiter, 0);
421                                         AUD_unload(limiter);
422                                 }
423                         }
424                 }
425
426                 AUD_unlock();
427         }
428 }
429
430 AUD_Device* sound_mixdown(struct Scene *scene, AUD_Specs specs, int start, int end)
431 {
432         AUD_Device* mixdown = AUD_openReadDevice(specs);
433         SoundHandle *handle;
434         float fps = FPS;
435         AUD_Sound *limiter, *delayer;
436         int frameskip, s, e;
437
438         end++;
439
440         for(handle = scene->sound_handles.first; handle; handle = handle->next)
441         {
442                 if(start < handle->endframe && end > handle->startframe && !handle->mute && handle->source && handle->source->snd_sound)
443                 {
444                         frameskip = handle->frameskip;
445                         s = handle->startframe - start;
446                         e = handle->frameskip + AUD_MIN(handle->endframe, end) - handle->startframe;
447
448                         if(s < 0)
449                         {
450                                 frameskip -= s;
451                                 s = 0;
452                         }
453
454                         limiter = AUD_limitSound(handle->source->snd_sound, frameskip / fps, e / fps);
455                         delayer = AUD_delaySound(limiter, s / fps);
456
457                         AUD_playDevice(mixdown, delayer);
458
459                         AUD_unload(delayer);
460                         AUD_unload(limiter);
461                 }
462         }
463
464         return mixdown;
465 }