2 * sound.c (mar-2001 nzc)
10 #include "MEM_guardedalloc.h"
12 #include "BLI_blenlib.h"
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"
20 #include "AUD_C-API.h"
22 #include "BKE_utildefines.h"
23 #include "BKE_global.h"
25 #include "BKE_sound.h"
26 #include "BKE_context.h"
27 #include "BKE_library.h"
28 #include "BKE_packedFile.h"
37 int device, buffersize, success;
39 device = U.audiodevice;
40 buffersize = U.mixbufsize;
41 specs.channels = U.audiochannels;
42 specs.format = U.audioformat;
43 specs.rate = U.audiorate;
46 buffersize = AUD_DEFAULT_BUFFER_SIZE;
48 if(specs.rate < AUD_RATE_8000)
49 specs.rate = AUD_RATE_44100;
51 if(specs.format <= AUD_FORMAT_INVALID)
52 specs.format = AUD_FORMAT_S16;
54 if(specs.channels <= AUD_CHANNELS_INVALID)
55 specs.channels = AUD_CHANNELS_STEREO;
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);
61 success= AUD_init(AUD_SDL_DEVICE, specs, AUD_DEFAULT_BUFFER_SIZE*4);
64 AUD_init(AUD_NULL_DEVICE, specs, buffersize);
73 struct bSound* sound_new_file(struct Main *main, char* filename)
80 strcpy(str, filename);
81 BLI_convertstringcode(str, G.sce);
83 len = strlen(filename);
84 while(len > 0 && filename[len-1] != '/' && filename[len-1] != '\\')
87 sound = alloc_libblock(&main->sound, ID_SO, filename+len);
88 strcpy(sound->name, filename);
89 sound->type = SOUND_TYPE_FILE;
95 free_libblock(&main->sound, sound);
102 // XXX unused currently
104 struct bSound* sound_new_buffer(struct bContext *C, struct bSound *source)
106 bSound* sound = NULL;
109 strcpy(name, "buf_");
110 strcpy(name + 4, source->id.name);
112 sound = alloc_libblock(&CTX_data_main(C)->sound, ID_SO, name);
114 sound->child_sound = source;
115 sound->type = SOUND_TYPE_BUFFER;
119 if(!sound->snd_sound)
121 free_libblock(&CTX_data_main(C)->sound, sound);
128 struct bSound* sound_new_limiter(struct bContext *C, struct bSound *source, float start, float end)
130 bSound* sound = NULL;
133 strcpy(name, "lim_");
134 strcpy(name + 4, source->id.name);
136 sound = alloc_libblock(&CTX_data_main(C)->sound, ID_SO, name);
138 sound->child_sound = source;
139 sound->start = start;
141 sound->type = SOUND_TYPE_LIMITER;
145 if(!sound->snd_sound)
147 free_libblock(&CTX_data_main(C)->sound, sound);
155 void sound_delete(struct bContext *C, struct bSound* sound)
161 sound_unlink(C, sound);
163 free_libblock(&CTX_data_main(C)->sound, sound);
167 void sound_cache(struct bSound* sound, int ignore)
169 if(sound->cache && !ignore)
170 AUD_unload(sound->cache);
172 sound->cache = AUD_bufferSound(sound->snd_sound);
175 void sound_load(struct bSound* sound)
181 AUD_unload(sound->snd_sound);
182 sound->snd_sound = NULL;
187 case SOUND_TYPE_FILE:
189 char fullpath[FILE_MAX];
193 PackedFile* pf = sound->packedfile;
195 /* dont modify soundact->sound->name, only change a copy */
196 BLI_strncpy(fullpath, sound->name, sizeof(fullpath));
199 path = sound->id.lib->filename;
203 BLI_convertstringcode(fullpath, path);
205 /* but we need a packed file then */
207 sound->snd_sound = AUD_loadBuffer((unsigned char*) pf->data, pf->size);
208 /* or else load it from disk */
210 sound->snd_sound = AUD_load(fullpath);
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);
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);
230 void sound_free(struct bSound* sound)
232 if (sound->packedfile)
234 freePackedFile(sound->packedfile);
235 sound->packedfile = NULL;
240 AUD_unload(sound->snd_sound);
241 sound->snd_sound = NULL;
245 void sound_unlink(struct bContext *C, struct bSound* sound)
251 for(snd = CTX_data_main(C)->sound.first; snd; snd = snd->id.next)
253 if(snd->child_sound == sound)
255 snd->child_sound = NULL;
258 AUD_unload(sound->snd_sound);
259 snd->snd_sound = NULL;
262 sound_unlink(C, snd);
266 for(scene = CTX_data_main(C)->scene.first; scene; scene = scene->id.next)
268 for(handle = scene->sound_handles.first; handle; handle = handle->next)
270 if(handle->source == sound)
272 handle->source = NULL;
274 AUD_stop(handle->handle);
280 struct SoundHandle* sound_new_handle(struct Scene *scene, struct bSound* sound, int startframe, int endframe, int frameskip)
282 ListBase* handles = &scene->sound_handles;
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;
292 BLI_addtail(handles, handle);
297 void sound_delete_handle(struct Scene *scene, struct SoundHandle *handle)
303 AUD_stop(handle->handle);
305 BLI_freelinkN(&scene->sound_handles, handle);
308 void sound_stop_all(struct bContext *C)
312 for(handle = CTX_data_scene(C)->sound_handles.first; handle; handle = handle->next)
314 if(handle->state == AUD_STATUS_PLAYING)
316 AUD_pause(handle->handle);
317 handle->state = AUD_STATUS_PAUSED;
322 #define SOUND_PLAYBACK_LAMBDA 1.0
324 void sound_update_playing(struct bContext *C)
327 Scene* scene = CTX_data_scene(C);
334 for(handle = scene->sound_handles.first; handle; handle = handle->next)
336 if(cfra < handle->startframe || cfra >= handle->endframe || handle->mute)
338 if(handle->state == AUD_STATUS_PLAYING)
340 AUD_pause(handle->handle);
341 handle->state = AUD_STATUS_PAUSED;
348 if(handle->changed != handle->source->changed)
350 handle->changed = handle->source->changed;
352 if(handle->state != AUD_STATUS_INVALID)
354 AUD_stop(handle->handle);
355 handle->state = AUD_STATUS_INVALID;
360 if(handle->state != AUD_STATUS_PLAYING)
364 handle->state = AUD_getStatus(handle->handle);
365 if(handle->state != AUD_STATUS_PLAYING)
369 float diff = AUD_getPosition(handle->handle) - (cfra - handle->startframe) / fps;
370 // AUD_XXX float diff = AUD_getPosition(handle->handle) * fps - cfra + handle->startframe
373 if(diff > SOUND_PLAYBACK_LAMBDA)
374 // AUD_XXX if(diff > 5.0f)
384 if(handle->state == AUD_STATUS_INVALID)
386 if(handle->source && handle->source->snd_sound)
388 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);
389 handle->handle = AUD_play(limiter, 1);
392 handle->state = AUD_STATUS_PLAYING;
393 if(cfra == handle->startframe)
398 if(AUD_resume(handle->handle))
399 handle->state = AUD_STATUS_PLAYING;
401 handle->state = AUD_STATUS_INVALID;
405 AUD_seek(handle->handle, (cfra - handle->startframe) / fps);
412 void sound_scrub(struct bContext *C)
415 Scene* scene = CTX_data_scene(C);
419 if(scene->r.audio.flag & AUDIO_SCRUB && !CTX_wm_screen(C)->animtimer)
423 for(handle = scene->sound_handles.first; handle; handle = handle->next)
425 if(cfra >= handle->startframe && cfra < handle->endframe && !handle->mute)
427 if(handle->source && handle->source->snd_sound)
429 int frameskip = handle->frameskip + cfra - handle->startframe;
430 AUD_Sound* limiter = AUD_limitSound(handle->source->cache ? handle->source->cache : handle->source->snd_sound, frameskip / fps, (frameskip + 1)/fps);
431 AUD_play(limiter, 0);
441 AUD_Device* sound_mixdown(struct Scene *scene, AUD_Specs specs, int start, int end)
443 AUD_Device* mixdown = AUD_openReadDevice(specs);
446 AUD_Sound *limiter, *delayer;
451 for(handle = scene->sound_handles.first; handle; handle = handle->next)
453 if(start < handle->endframe && end > handle->startframe && !handle->mute && handle->source && handle->source->snd_sound)
455 frameskip = handle->frameskip;
456 s = handle->startframe - start;
457 e = handle->frameskip + AUD_MIN(handle->endframe, end) - handle->startframe;
465 limiter = AUD_limitSound(handle->source->snd_sound, frameskip / fps, e / fps);
466 delayer = AUD_delaySound(limiter, s / fps);
468 AUD_playDevice(mixdown, delayer);