Merge with -r 22620:23107.
[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 // XXX unused currently sound->type = SOUND_TYPE_FILE;
83
84         sound_load(main, sound);
85
86         if(!sound->handle)
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->handle)
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->handle)
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->handle);
166         sound->changed++;
167 }
168
169 void sound_delete_cache(struct bSound* sound)
170 {
171         if(sound->cache)
172         {
173                 AUD_unload(sound->cache);
174                 sound->cache = NULL;
175         }
176 }
177
178 void sound_load(struct Main *main, struct bSound* sound)
179 {
180         if(sound)
181         {
182                 if(sound->handle)
183                 {
184                         AUD_unload(sound->handle);
185                         sound->handle = NULL;
186                 }
187
188 // XXX unused currently
189 #if 0
190                 switch(sound->type)
191                 {
192                 case SOUND_TYPE_FILE:
193 #endif
194                 {
195                         char fullpath[FILE_MAX];
196                         char *path;
197
198                         /* load sound */
199                         PackedFile* pf = sound->packedfile;
200
201                         /* dont modify soundact->sound->name, only change a copy */
202                         BLI_strncpy(fullpath, sound->name, sizeof(fullpath));
203
204                         if(sound->id.lib)
205                                 path = sound->id.lib->filename;
206                         else
207                                 path = main ? main->name : G.sce;
208
209                         BLI_convertstringcode(fullpath, path);
210
211                         /* but we need a packed file then */
212                         if (pf)
213                                 sound->handle = AUD_loadBuffer((unsigned char*) pf->data, pf->size);
214                         /* or else load it from disk */
215                         else
216                                 sound->handle = AUD_load(fullpath);
217                 } // XXX
218 // XXX unused currently
219 #if 0
220                         break;
221                 }
222                 case SOUND_TYPE_BUFFER:
223                         if(sound->child_sound && sound->child_sound->handle)
224                                 sound->handle = AUD_bufferSound(sound->child_sound->handle);
225                         break;
226                 case SOUND_TYPE_LIMITER:
227                         if(sound->child_sound && sound->child_sound->handle)
228                                 sound->handle = AUD_limitSound(sound->child_sound, sound->start, sound->end);
229                         break;
230                 }
231 #endif
232                 sound->changed++;
233         }
234 }
235
236 void sound_free(struct bSound* sound)
237 {
238         if (sound->packedfile)
239         {
240                 freePackedFile(sound->packedfile);
241                 sound->packedfile = NULL;
242         }
243
244         if(sound->handle)
245         {
246                 AUD_unload(sound->handle);
247                 sound->handle = NULL;
248         }
249 }
250
251 void sound_unlink(struct bContext *C, struct bSound* sound)
252 {
253         Scene *scene;
254         SoundHandle *handle;
255
256 // XXX unused currently
257 #if 0
258         bSound *snd;
259         for(snd = CTX_data_main(C)->sound.first; snd; snd = snd->id.next)
260         {
261                 if(snd->child_sound == sound)
262                 {
263                         snd->child_sound = NULL;
264                         if(snd->handle)
265                         {
266                                 AUD_unload(sound->handle);
267                                 snd->handle = NULL;
268                         }
269
270                         sound_unlink(C, snd);
271                 }
272         }
273 #endif
274
275         for(scene = CTX_data_main(C)->scene.first; scene; scene = scene->id.next)
276         {
277                 for(handle = scene->sound_handles.first; handle; handle = handle->next)
278                 {
279                         if(handle->source == sound)
280                         {
281                                 handle->source = NULL;
282                                 if(handle->handle)
283                                         AUD_stop(handle->handle);
284                         }
285                 }
286         }
287 }
288
289 struct SoundHandle* sound_new_handle(struct Scene *scene, struct bSound* sound, int startframe, int endframe, int frameskip)
290 {
291         ListBase* handles = &scene->sound_handles;
292
293         SoundHandle* handle = MEM_callocN(sizeof(SoundHandle), "sound_handle");
294         handle->source = sound;
295         handle->startframe = startframe;
296         handle->endframe = endframe;
297         handle->frameskip = frameskip;
298         handle->state = AUD_STATUS_INVALID;
299         handle->volume = 1.0f;
300
301         BLI_addtail(handles, handle);
302
303         return handle;
304 }
305
306 void sound_delete_handle(struct Scene *scene, struct SoundHandle *handle)
307 {
308         if(handle == NULL)
309                 return;
310
311         if(handle->handle)
312                 AUD_stop(handle->handle);
313
314         BLI_freelinkN(&scene->sound_handles, handle);
315 }
316
317 void sound_stop_all(struct bContext *C)
318 {
319         SoundHandle *handle;
320
321         for(handle = CTX_data_scene(C)->sound_handles.first; handle; handle = handle->next)
322         {
323                 if(handle->state == AUD_STATUS_PLAYING)
324                 {
325                         AUD_pause(handle->handle);
326                         handle->state = AUD_STATUS_PAUSED;
327                 }
328         }
329 }
330
331 void sound_update_playing(struct bContext *C)
332 {
333         SoundHandle *handle;
334         Scene* scene = CTX_data_scene(C);
335         int cfra = CFRA;
336         float fps = FPS;
337         int action;
338
339         AUD_lock();
340
341         for(handle = scene->sound_handles.first; handle; handle = handle->next)
342         {
343                 if(cfra < handle->startframe || cfra >= handle->endframe || handle->mute)
344                 {
345                         if(handle->state == AUD_STATUS_PLAYING)
346                         {
347                                 AUD_pause(handle->handle);
348                                 handle->state = AUD_STATUS_PAUSED;
349                         }
350                 }
351                 else
352                 {
353                         action = 0;
354
355                         if(handle->changed != handle->source->changed)
356                         {
357                                 handle->changed = handle->source->changed;
358                                 action = 3;
359                                 if(handle->state != AUD_STATUS_INVALID)
360                                 {
361                                         AUD_stop(handle->handle);
362                                         handle->state = AUD_STATUS_INVALID;
363                                 }
364                         }
365                         else
366                         {
367                                 if(handle->state != AUD_STATUS_PLAYING)
368                                         action = 3;
369                                 else
370                                 {
371                                         handle->state = AUD_getStatus(handle->handle);
372                                         if(handle->state != AUD_STATUS_PLAYING)
373                                                 action = 3;
374                                         else
375                                         {
376                                                 float diff = AUD_getPosition(handle->handle) * fps - cfra + handle->startframe;
377                                                 if(diff < 0.0)
378                                                         diff = -diff;
379                                                 if(diff > FPS/2.0)
380                                                 {
381                                                         action = 2;
382                                                 }
383                                         }
384                                 }
385                         }
386
387                         if(action & 1)
388                         {
389                                 if(handle->state == AUD_STATUS_INVALID)
390                                 {
391                                         if(handle->source && handle->source->handle)
392                                         {
393                                                 AUD_Sound* limiter = AUD_limitSound(handle->source->cache ? handle->source->cache : handle->source->handle, handle->frameskip / fps, (handle->frameskip + handle->endframe - handle->startframe)/fps);
394                                                 handle->handle = AUD_play(limiter, 1);
395                                                 AUD_unload(limiter);
396                                                 if(handle->handle)
397                                                         handle->state = AUD_STATUS_PLAYING;
398                                                 if(cfra == handle->startframe)
399                                                         action &= ~2;
400                                         }
401                                 }
402                                 else
403                                         if(AUD_resume(handle->handle))
404                                                 handle->state = AUD_STATUS_PLAYING;
405                                         else
406                                                 handle->state = AUD_STATUS_INVALID;
407                         }
408
409                         if(action & 2)
410                                 AUD_seek(handle->handle, (cfra - handle->startframe) / fps);
411                 }
412         }
413
414         AUD_unlock();
415 }
416
417 void sound_scrub(struct bContext *C)
418 {
419         SoundHandle *handle;
420         Scene* scene = CTX_data_scene(C);
421         int cfra = CFRA;
422         float fps = FPS;
423
424         if(scene->r.audio.flag & AUDIO_SCRUB && !CTX_wm_screen(C)->animtimer)
425         {
426                 AUD_lock();
427
428                 for(handle = scene->sound_handles.first; handle; handle = handle->next)
429                 {
430                         if(cfra >= handle->startframe && cfra < handle->endframe && !handle->mute)
431                         {
432                                 if(handle->source && handle->source->handle)
433                                 {
434                                         int frameskip = handle->frameskip + cfra - handle->startframe;
435                                         AUD_Sound* limiter = AUD_limitSound(handle->source->cache ? handle->source->cache : handle->source->handle, frameskip / fps, (frameskip + 1)/fps);
436                                         AUD_play(limiter, 0);
437                                         AUD_unload(limiter);
438                                 }
439                         }
440                 }
441
442                 AUD_unlock();
443         }
444 }
445
446 AUD_Device* sound_mixdown(struct Scene *scene, AUD_Specs specs, int start, int end)
447 {
448         AUD_Device* mixdown = AUD_openReadDevice(specs);
449         SoundHandle *handle;
450         float fps = FPS;
451         AUD_Sound *limiter, *delayer;
452         int frameskip, s, e;
453
454         end++;
455
456         for(handle = scene->sound_handles.first; handle; handle = handle->next)
457         {
458                 if(start < handle->endframe && end > handle->startframe && !handle->mute && handle->source && handle->source->handle)
459                 {
460                         frameskip = handle->frameskip;
461                         s = handle->startframe - start;
462                         e = handle->frameskip + AUD_MIN(handle->endframe, end) - handle->startframe;
463
464                         if(s < 0)
465                         {
466                                 frameskip -= s;
467                                 s = 0;
468                         }
469
470                         limiter = AUD_limitSound(handle->source->handle, frameskip / fps, e / fps);
471                         delayer = AUD_delaySound(limiter, s / fps);
472
473                         AUD_playDevice(mixdown, delayer);
474
475                         AUD_unload(delayer);
476                         AUD_unload(limiter);
477                 }
478         }
479
480         return mixdown;
481 }