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