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