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