Blender V4.3
blenkernel/intern/sound.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include <cstdlib>
10#include <cstring>
11#include <optional>
12
13#include "MEM_guardedalloc.h"
14
15#include "BLI_blenlib.h"
16#include "BLI_iterator.h"
17#include "BLI_math_rotation.h"
18#include "BLI_threads.h"
19
20#include "BLT_translation.hh"
21
22/* Allow using deprecated functionality for .blend file I/O. */
23#define DNA_DEPRECATED_ALLOW
24
25#include "DNA_anim_types.h"
26#include "DNA_object_types.h"
28#include "DNA_scene_types.h"
29#include "DNA_screen_types.h"
30#include "DNA_sequence_types.h"
31#include "DNA_sound_types.h"
32#include "DNA_speaker_types.h"
34
35#ifdef WITH_AUDASPACE
37# include <AUD_Handle.h>
38# include <AUD_Sequence.h>
39# include <AUD_Sound.h>
40# include <AUD_Special.h>
41#endif
42
43#include "BKE_bpath.hh"
44#include "BKE_global.hh"
45#include "BKE_idtype.hh"
46#include "BKE_lib_id.hh"
47#include "BKE_lib_query.hh"
48#include "BKE_main.hh"
49#include "BKE_packedFile.hh"
50#include "BKE_sound.h"
51
52#include "DEG_depsgraph.hh"
54
55#include "BLO_read_write.hh"
56
57#include "SEQ_sound.hh"
58#include "SEQ_time.hh"
59
60static void sound_free_audio(bSound *sound);
61
62static void sound_copy_data(Main * /*bmain*/,
63 std::optional<Library *> /*owner_library*/,
64 ID *id_dst,
65 const ID *id_src,
66 const int /*flag*/)
67{
68 bSound *sound_dst = (bSound *)id_dst;
69 const bSound *sound_src = (const bSound *)id_src;
70
71 sound_dst->handle = nullptr;
72 sound_dst->cache = nullptr;
73 sound_dst->waveform = nullptr;
74 sound_dst->playback_handle = nullptr;
75 sound_dst->spinlock = MEM_mallocN(sizeof(SpinLock), "sound_spinlock");
76 BLI_spin_init(static_cast<SpinLock *>(sound_dst->spinlock));
77
78 /* Just to be sure, should not have any value actually after reading time. */
79 sound_dst->ipo = nullptr;
80 sound_dst->newpackedfile = nullptr;
81
82 if (sound_src->packedfile != nullptr) {
83 sound_dst->packedfile = BKE_packedfile_duplicate(sound_src->packedfile);
84 }
85
86 BKE_sound_reset_runtime(sound_dst);
87}
88
89static void sound_free_data(ID *id)
90{
91 bSound *sound = (bSound *)id;
92
93 /* No animation-data here. */
94
95 if (sound->packedfile) {
97 sound->packedfile = nullptr;
98 }
99
100 sound_free_audio(sound);
102
103 if (sound->spinlock) {
104 BLI_spin_end(static_cast<SpinLock *>(sound->spinlock));
105 MEM_freeN(sound->spinlock);
106 sound->spinlock = nullptr;
107 }
108}
109
111{
112 bSound *sound = reinterpret_cast<bSound *>(id);
114
117 }
118}
119
120static void sound_foreach_cache(ID *id,
121 IDTypeForeachCacheFunctionCallback function_callback,
122 void *user_data)
123{
124 bSound *sound = (bSound *)id;
125 IDCacheKey key{};
126 key.id_session_uid = id->session_uid;
127 key.identifier = offsetof(bSound, waveform);
128
129 function_callback(id, &key, &sound->waveform, 0, user_data);
130}
131
132static void sound_foreach_path(ID *id, BPathForeachPathData *bpath_data)
133{
134 bSound *sound = (bSound *)id;
135 if (sound->packedfile != nullptr && (bpath_data->flag & BKE_BPATH_FOREACH_PATH_SKIP_PACKED) != 0)
136 {
137 return;
138 }
139
140 /* FIXME: This does not check for empty path... */
141 BKE_bpath_foreach_path_fixed_process(bpath_data, sound->filepath, sizeof(sound->filepath));
142}
143
144static void sound_blend_write(BlendWriter *writer, ID *id, const void *id_address)
145{
146 bSound *sound = (bSound *)id;
147 const bool is_undo = BLO_write_is_undo(writer);
148
149 /* Clean up, important in undo case to reduce false detection of changed datablocks. */
150 sound->tags = 0;
151 sound->handle = nullptr;
152 sound->playback_handle = nullptr;
153 sound->spinlock = nullptr;
154
155 /* Do not store packed files in case this is a library override ID. */
156 if (ID_IS_OVERRIDE_LIBRARY(sound) && !is_undo) {
157 sound->packedfile = nullptr;
158 }
159
160 /* write LibData */
161 BLO_write_id_struct(writer, bSound, id_address, &sound->id);
162 BKE_id_blend_write(writer, &sound->id);
163
165}
166
167static void sound_blend_read_data(BlendDataReader *reader, ID *id)
168{
169 bSound *sound = (bSound *)id;
170 sound->tags = 0;
171 sound->handle = nullptr;
172 sound->playback_handle = nullptr;
173
174 /* versioning stuff, if there was a cache, then we enable caching: */
175 if (sound->cache) {
176 sound->flags |= SOUND_FLAGS_CACHING;
177 sound->cache = nullptr;
178 }
179
180 if (BLO_read_data_is_undo(reader)) {
182 }
183
184 sound->spinlock = MEM_mallocN(sizeof(SpinLock), "sound_spinlock");
185 BLI_spin_init(static_cast<SpinLock *>(sound->spinlock));
186
187 /* clear waveform loading flag */
188 sound->tags &= ~SOUND_TAGS_WAVEFORM_LOADING;
189
190 BKE_packedfile_blend_read(reader, &sound->packedfile, sound->filepath);
191 BKE_packedfile_blend_read(reader, &sound->newpackedfile, sound->filepath);
192}
193
195 /*id_code*/ ID_SO,
196 /*id_filter*/ FILTER_ID_SO,
197 /*dependencies_id_types*/ 0,
198 /*main_listbase_index*/ INDEX_ID_SO,
199 /*struct_size*/ sizeof(bSound),
200 /*name*/ "Sound",
201 /*name_plural*/ N_("sounds"),
202 /*translation_context*/ BLT_I18NCONTEXT_ID_SOUND,
204 /*asset_type_info*/ nullptr,
205
206 /* A fuzzy case, think NULLified content is OK here... */
207 /*init_data*/ nullptr,
208 /*copy_data*/ sound_copy_data,
209 /*free_data*/ sound_free_data,
210 /*make_local*/ nullptr,
211 /*foreach_id*/ sound_foreach_id,
212 /*foreach_cache*/ sound_foreach_cache,
213 /*foreach_path*/ sound_foreach_path,
214 /*owner_pointer_get*/ nullptr,
215
216 /*blend_write*/ sound_blend_write,
217 /*blend_read_data*/ sound_blend_read_data,
218 /*blend_read_after_liblink*/ nullptr,
219
220 /*blend_read_undo_preserve*/ nullptr,
221
222 /*lib_override_apply_post*/ nullptr,
223};
224
225#ifdef WITH_AUDASPACE
226/* evil globals ;-) */
227static char **audio_device_names = nullptr;
228#endif
229
231{
233 /* This is a bit tricky and not quite reliable, but good enough check.
234 *
235 * We don't want audio system handles to be allocated on an original data-blocks, and only want
236 * them to be allocated on a data-blocks which are result of dependency graph evaluation.
237 *
238 * Data-blocks which are covered by a copy-on-evaluation system of dependency graph will have
239 * ID_TAG_COPIED_ON_EVAL tag set on them. But if some of data-blocks during its evaluation
240 * decides to re-allocate its nested one (for example, object evaluation could re-allocate mesh
241 * when evaluating modifier stack). Such data-blocks will have
242 * ID_TAG_COPIED_ON_EVAL_FINAL_RESULT tag set on them.
243 *
244 * Additionally, we also allow data-blocks outside of main database. Those can not be "original"
245 * and could be used as a temporary evaluated result during operations like baking.
246 *
247 * NOTE: We consider ID evaluated if ANY of those flags is set. We do NOT require ALL of them.
248 */
249 BLI_assert(id->tag &
251}
252
253bSound *BKE_sound_new_file(Main *bmain, const char *filepath)
254{
255 bSound *sound;
256 const char *blendfile_path = BKE_main_blendfile_path(bmain);
257 char filepath_abs[FILE_MAX];
258
259 STRNCPY(filepath_abs, filepath);
260 BLI_path_abs(filepath_abs, blendfile_path);
261
262 sound = static_cast<bSound *>(BKE_libblock_alloc(bmain, ID_SO, BLI_path_basename(filepath), 0));
263 STRNCPY(sound->filepath, filepath);
264 // sound->type = SOUND_TYPE_FILE; /* UNUSED. */
265
266 /* Extract sound specs for bSound */
267 SoundInfo info;
268 bool success = BKE_sound_info_get(bmain, sound, &info);
269 if (success) {
270 sound->samplerate = info.specs.samplerate;
271 sound->audio_channels = info.specs.channels;
272 }
273
274 sound->spinlock = MEM_mallocN(sizeof(SpinLock), "sound_spinlock");
275 BLI_spin_init(static_cast<SpinLock *>(sound->spinlock));
276
278
279 return sound;
280}
281
282bSound *BKE_sound_new_file_exists_ex(Main *bmain, const char *filepath, bool *r_exists)
283{
284 bSound *sound;
285 char filepath_abs[FILE_MAX], filepath_test[FILE_MAX];
286
287 STRNCPY(filepath_abs, filepath);
288 BLI_path_abs(filepath_abs, BKE_main_blendfile_path(bmain));
289
290 /* first search an identical filepath */
291 for (sound = static_cast<bSound *>(bmain->sounds.first); sound;
292 sound = static_cast<bSound *>(sound->id.next))
293 {
294 STRNCPY(filepath_test, sound->filepath);
295 BLI_path_abs(filepath_test, ID_BLEND_PATH(bmain, &sound->id));
296
297 if (BLI_path_cmp(filepath_test, filepath_abs) == 0) {
298 id_us_plus(&sound->id); /* officially should not, it doesn't link here! */
299 if (r_exists) {
300 *r_exists = true;
301 }
302 return sound;
303 }
304 }
305
306 if (r_exists) {
307 *r_exists = false;
308 }
309 return BKE_sound_new_file(bmain, filepath);
310}
311
312bSound *BKE_sound_new_file_exists(Main *bmain, const char *filepath)
313{
314 return BKE_sound_new_file_exists_ex(bmain, filepath, nullptr);
315}
316
317static void sound_free_audio(bSound *sound)
318{
319#ifdef WITH_AUDASPACE
320 if (sound->handle) {
321 AUD_Sound_free(sound->handle);
322 sound->handle = nullptr;
323 sound->playback_handle = nullptr;
324 }
325
326 if (sound->cache) {
327 AUD_Sound_free(sound->cache);
328 sound->cache = nullptr;
329 }
330#else
331 UNUSED_VARS(sound);
332#endif /* WITH_AUDASPACE */
333}
334
335#ifdef WITH_AUDASPACE
336
337static const char *force_device = nullptr;
338
339# ifdef WITH_JACK
341
342static void sound_sync_callback(void *data, int mode, float time)
343{
344 if (sound_jack_sync_callback == nullptr) {
345 return;
346 }
347 Main *bmain = (Main *)data;
348 sound_jack_sync_callback(bmain, mode, time);
349}
350# endif
351
352void BKE_sound_force_device(const char *device)
353{
354 force_device = device;
355}
356
358{
359 AUD_initOnce();
360 atexit(BKE_sound_exit_once);
361}
362
363static AUD_Device *sound_device = nullptr;
364
366{
367 return sound_device;
368}
369
370void BKE_sound_init(Main *bmain)
371{
372 /* Make sure no instance of the sound system is running, otherwise we get leaks. */
374
375 AUD_DeviceSpecs specs;
376 int device, buffersize;
377 const char *device_name;
378
379 device = U.audiodevice;
380 buffersize = U.mixbufsize;
381 specs.channels = AUD_Channels(U.audiochannels);
382 specs.format = AUD_SampleFormat(U.audioformat);
383 specs.rate = U.audiorate;
384
385 if (force_device == nullptr) {
386 int i;
387 char **names = BKE_sound_get_device_names();
388 device_name = names[0];
389
390 /* make sure device is within the bounds of the array */
391 for (i = 0; names[i]; i++) {
392 if (i == device) {
393 device_name = names[i];
394 }
395 }
396 }
397 else {
398 device_name = force_device;
399 }
400
401 if (buffersize < 128) {
402 buffersize = 1024;
403 }
404
405 if (specs.rate < AUD_RATE_8000) {
406 specs.rate = AUD_RATE_48000;
407 }
408
409 if (specs.format <= AUD_FORMAT_INVALID) {
410 specs.format = AUD_FORMAT_S16;
411 }
412
413 if (specs.channels <= AUD_CHANNELS_INVALID) {
414 specs.channels = AUD_CHANNELS_STEREO;
415 }
416
417 if (!(sound_device = AUD_init(device_name, specs, buffersize, "Blender"))) {
418 sound_device = AUD_init("None", specs, buffersize, "Blender");
419 }
420
421 BKE_sound_init_main(bmain);
422}
423
424void BKE_sound_init_main(Main *bmain)
425{
426# ifdef WITH_JACK
427 if (sound_device) {
428 AUD_setSynchronizerCallback(sound_sync_callback, bmain);
429 }
430# else
431 UNUSED_VARS(bmain);
432# endif
433}
434
435void BKE_sound_exit()
436{
437 AUD_exit(sound_device);
438 sound_device = nullptr;
439}
440
442{
443 AUD_exit(sound_device);
444 sound_device = nullptr;
445 AUD_exitOnce();
446
447 if (audio_device_names != nullptr) {
448 int i;
449 for (i = 0; audio_device_names[i]; i++) {
450 free(audio_device_names[i]);
451 }
452 free(audio_device_names);
453 audio_device_names = nullptr;
454 }
455}
456
457/* XXX unused currently */
458# if 0
459bSound *BKE_sound_new_buffer(Main *bmain, bSound *source)
460{
461 bSound *sound = nullptr;
462
463 char name[MAX_ID_NAME + 5];
464 BLI_string_join(name, sizeof(name), "buf_", source->id.name);
465
466 sound = BKE_libblock_alloc(bmain, ID_SO, name);
467
468 sound->child_sound = source;
469 sound->type = SOUND_TYPE_BUFFER;
470
471 sound_load(bmain, sound);
472
473 return sound;
474}
475
476bSound *BKE_sound_new_limiter(Main *bmain, bSound *source, float start, float end)
477{
478 bSound *sound = nullptr;
479
480 char name[MAX_ID_NAME + 5];
481 BLI_string_join(name, sizeof(name), "lim_", source->id.name);
482
483 sound = BKE_libblock_alloc(bmain, ID_SO, name);
484
485 sound->child_sound = source;
486 sound->start = start;
487 sound->end = end;
488 sound->type = SOUND_TYPE_LIMITER;
489
490 sound_load(bmain, sound);
491
492 return sound;
493}
494# endif
495
496void BKE_sound_cache(bSound *sound)
497{
499
500 if (sound->cache) {
501 AUD_Sound_free(sound->cache);
502 }
503
504 sound->cache = AUD_Sound_cache(sound->handle);
505 if (sound->cache) {
506 sound->playback_handle = sound->cache;
507 }
508 else {
509 sound->playback_handle = sound->handle;
510 }
511}
512
514{
515 if (sound->cache) {
516 AUD_Sound_free(sound->cache);
517 sound->cache = nullptr;
518 sound->playback_handle = sound->handle;
519 }
520}
521
522static void sound_load_audio(Main *bmain, bSound *sound, bool free_waveform)
523{
524
525 if (sound->cache) {
526 AUD_Sound_free(sound->cache);
527 sound->cache = nullptr;
528 }
529
530 if (sound->handle) {
531 AUD_Sound_free(sound->handle);
532 sound->handle = nullptr;
533 sound->playback_handle = nullptr;
534 }
535
536 if (free_waveform) {
538 }
539
540/* XXX unused currently */
541# if 0
542 switch (sound->type) {
543 case SOUND_TYPE_FILE:
544# endif
545 {
546 char fullpath[FILE_MAX];
547
548 /* load sound */
549 PackedFile *pf = sound->packedfile;
550
551 /* Don't modify `sound->filepath`, only change a copy. */
552 STRNCPY(fullpath, sound->filepath);
553 BLI_path_abs(fullpath, ID_BLEND_PATH(bmain, &sound->id));
554
555 /* but we need a packed file then */
556 if (pf) {
557 sound->handle = AUD_Sound_bufferFile((uchar *)pf->data, pf->size);
558 }
559 else {
560 /* or else load it from disk */
561 sound->handle = AUD_Sound_file(fullpath);
562 }
563 }
564/* XXX unused currently */
565# if 0
566 break;
567 }
568 case SOUND_TYPE_BUFFER:
569 if (sound->child_sound && sound->child_sound->handle) {
570 sound->handle = AUD_bufferSound(sound->child_sound->handle);
571 }
572 break;
573 case SOUND_TYPE_LIMITER:
574 if (sound->child_sound && sound->child_sound->handle) {
575 sound->handle = AUD_limitSound(sound->child_sound, sound->start, sound->end);
576 }
577 break;
578}
579# endif
580 if (sound->flags & SOUND_FLAGS_MONO) {
581 void *handle = AUD_Sound_rechannel(sound->handle, AUD_CHANNELS_MONO);
582 AUD_Sound_free(sound->handle);
583 sound->handle = handle;
584 }
585
586 if (sound->flags & SOUND_FLAGS_CACHING) {
587 sound->cache = AUD_Sound_cache(sound->handle);
588 }
589
590 if (sound->cache) {
591 sound->playback_handle = sound->cache;
592 }
593 else {
594 sound->playback_handle = sound->handle;
595 }
596}
597
598void BKE_sound_load(Main *bmain, bSound *sound)
599{
601 sound_load_audio(bmain, sound, true);
602}
603
604AUD_Device *BKE_sound_mixdown(const Scene *scene, AUD_DeviceSpecs specs, int start, float volume)
605{
606 sound_verify_evaluated_id(&scene->id);
607 return AUD_openMixdownDevice(
608 specs, scene->sound_scene, volume, AUD_RESAMPLE_QUALITY_MEDIUM, start / FPS);
609}
610
611void BKE_sound_create_scene(Scene *scene)
612{
613 sound_verify_evaluated_id(&scene->id);
614
615 /* should be done in version patch, but this gets called before */
616 if (scene->r.frs_sec_base == 0) {
617 scene->r.frs_sec_base = 1;
618 }
619
620 scene->sound_scene = AUD_Sequence_create(FPS, scene->audio.flag & AUDIO_MUTE);
621 AUD_Sequence_setSpeedOfSound(scene->sound_scene, scene->audio.speed_of_sound);
622 AUD_Sequence_setDopplerFactor(scene->sound_scene, scene->audio.doppler_factor);
623 AUD_Sequence_setDistanceModel(scene->sound_scene,
624 AUD_DistanceModel(scene->audio.distance_model));
625 scene->playback_handle = nullptr;
626 scene->sound_scrub_handle = nullptr;
627 scene->speaker_handles = nullptr;
628}
629
631{
632 if (scene->playback_handle) {
633 AUD_Handle_stop(scene->playback_handle);
634 }
635 if (scene->sound_scrub_handle) {
636 AUD_Handle_stop(scene->sound_scrub_handle);
637 }
638 if (scene->speaker_handles) {
639 void *handle;
640
641 while ((handle = AUD_getSet(scene->speaker_handles))) {
642 AUD_Sequence_remove(scene->sound_scene, handle);
643 }
644
645 AUD_destroySet(scene->speaker_handles);
646 }
647 if (scene->sound_scene) {
648 AUD_Sequence_free(scene->sound_scene);
649 }
650}
651
652void BKE_sound_lock()
653{
654 AUD_Device_lock(sound_device);
655}
656
657void BKE_sound_unlock()
658{
659 AUD_Device_unlock(sound_device);
660}
661
663{
664 sound_verify_evaluated_id(&scene->id);
665
666 if (scene->sound_scene) {
667 AUD_Specs specs;
668
669 specs.channels = AUD_Device_getChannels(sound_device);
670 specs.rate = AUD_Device_getRate(sound_device);
671
672 AUD_Sequence_setSpecs(scene->sound_scene, specs);
673 }
674}
675
676void BKE_sound_mute_scene(Scene *scene, int muted)
677{
678 sound_verify_evaluated_id(&scene->id);
679 if (scene->sound_scene) {
680 AUD_Sequence_setMuted(scene->sound_scene, muted);
681 }
682}
683
684void BKE_sound_update_fps(Main *bmain, Scene *scene)
685{
686 sound_verify_evaluated_id(&scene->id);
687
688 if (scene->sound_scene) {
689 AUD_Sequence_setFPS(scene->sound_scene, FPS);
690 }
691
692 SEQ_sound_update_length(bmain, scene);
693}
694
696{
697 sound_verify_evaluated_id(&scene->id);
698
699 AUD_Sequence_setSpeedOfSound(scene->sound_scene, scene->audio.speed_of_sound);
700 AUD_Sequence_setDopplerFactor(scene->sound_scene, scene->audio.doppler_factor);
701 AUD_Sequence_setDistanceModel(scene->sound_scene,
702 AUD_DistanceModel(scene->audio.distance_model));
703}
704
706 Scene *scene, Sequence *sequence, int startframe, int endframe, int frameskip)
707{
708 sound_verify_evaluated_id(&scene->id);
709 if (sequence->scene && scene != sequence->scene) {
710 const double fps = FPS;
711 return AUD_Sequence_add(scene->sound_scene,
712 sequence->scene->sound_scene,
713 startframe / fps,
714 endframe / fps,
715 frameskip / fps);
716 }
717 return nullptr;
718}
719
721{
723 sequence,
724 SEQ_time_left_handle_frame_get(scene, sequence),
725 SEQ_time_right_handle_frame_get(scene, sequence),
726 sequence->startofs + sequence->anim_startofs);
727}
728
730 Scene *scene, Sequence *sequence, int startframe, int endframe, int frameskip)
731{
732 sound_verify_evaluated_id(&scene->id);
733 /* Happens when sequence's sound data-block was removed. */
734 if (sequence->sound == nullptr) {
735 return nullptr;
736 }
738 const double fps = FPS;
739 const double offset_time = sequence->sound->offset_time + sequence->sound_offset -
740 frameskip / fps;
741 if (offset_time >= 0.0f) {
742 return AUD_Sequence_add(scene->sound_scene,
743 sequence->sound->playback_handle,
744 startframe / fps + offset_time,
745 endframe / fps,
746 0.0f);
747 }
748 return AUD_Sequence_add(scene->sound_scene,
749 sequence->sound->playback_handle,
750 startframe / fps,
751 endframe / fps,
752 -offset_time);
753}
754
756{
757 return BKE_sound_add_scene_sound(scene,
758 sequence,
759 SEQ_time_left_handle_frame_get(scene, sequence),
760 SEQ_time_right_handle_frame_get(scene, sequence),
761 sequence->startofs + sequence->anim_startofs);
762}
763
764void BKE_sound_remove_scene_sound(Scene *scene, void *handle)
765{
766 AUD_Sequence_remove(scene->sound_scene, handle);
767}
768
769void BKE_sound_mute_scene_sound(void *handle, bool mute)
770{
771 AUD_SequenceEntry_setMuted(handle, mute);
772}
773
774void BKE_sound_move_scene_sound(const Scene *scene,
775 void *handle,
776 int startframe,
777 int endframe,
778 int frameskip,
779 double audio_offset)
780{
781 sound_verify_evaluated_id(&scene->id);
782 const double fps = FPS;
783 const double offset_time = audio_offset - frameskip / fps;
784 if (offset_time >= 0.0f) {
785 AUD_SequenceEntry_move(handle, startframe / fps + offset_time, endframe / fps, 0.0f);
786 }
787 else {
788 AUD_SequenceEntry_move(handle, startframe / fps, endframe / fps, -offset_time);
789 }
790}
791
793{
794 sound_verify_evaluated_id(&scene->id);
795 if (sequence->scene_sound) {
796 double offset_time = 0.0f;
797 if (sequence->sound != nullptr) {
798 offset_time = sequence->sound->offset_time + sequence->sound_offset;
799 }
801 sequence->scene_sound,
802 SEQ_time_left_handle_frame_get(scene, sequence),
803 SEQ_time_right_handle_frame_get(scene, sequence),
804 sequence->startofs + sequence->anim_startofs,
805 offset_time);
806 }
807}
808
809void BKE_sound_update_scene_sound(void *handle, bSound *sound)
810{
811 AUD_SequenceEntry_setSound(handle, sound->playback_handle);
812}
813
814#endif /* WITH_AUDASPACE */
815
816void BKE_sound_update_sequence_handle(void *handle, void *sound_handle)
817{
818#ifdef WITH_AUDASPACE
819 AUD_SequenceEntry_setSound(handle, sound_handle);
820#else
821 UNUSED_VARS(handle, sound_handle);
822#endif
823}
824
825#ifdef WITH_AUDASPACE
826
827void BKE_sound_set_scene_volume(Scene *scene, float volume)
828{
829 sound_verify_evaluated_id(&scene->id);
830 if (scene->sound_scene == nullptr) {
831 return;
832 }
833 AUD_Sequence_setAnimationData(scene->sound_scene,
834 AUD_AP_VOLUME,
835 scene->r.cfra,
836 &volume,
837 (scene->audio.flag & AUDIO_VOLUME_ANIMATED) != 0);
838}
839
841 const int frame,
842 float volume,
843 const char animated)
844{
845 AUD_SequenceEntry_setAnimationData(handle, AUD_AP_VOLUME, frame, &volume, animated);
846}
847
849 const int frame,
850 float pitch,
851 const char animated)
852{
853 AUD_SequenceEntry_setAnimationData(handle, AUD_AP_PITCH, frame, &pitch, animated);
854}
855
857 int frame_start,
858 int frame_end,
859 float pitch)
860{
861 frame_start = max_ii(0, frame_start);
862 frame_end = max_ii(0, frame_end);
863 AUD_SequenceEntry_setConstantRangeAnimationData(
864 handle, AUD_AP_PITCH, frame_start, frame_end, &pitch);
865}
866
868 const int frame,
869 float pan,
870 const char animated)
871{
872 AUD_SequenceEntry_setAnimationData(handle, AUD_AP_PANNING, frame, &pan, animated);
873}
874
876{
877 BLI_assert_msg(0, "is not supposed to be used, is weird function.");
878
879 Scene *scene;
880
881 for (scene = static_cast<Scene *>(main->scenes.first); scene;
882 scene = static_cast<Scene *>(scene->id.next))
883 {
884 SEQ_sound_update(scene, sound);
885 }
886}
887
888static void sound_start_play_scene(Scene *scene)
889{
890 sound_verify_evaluated_id(&scene->id);
891
892 if (scene->playback_handle) {
893 AUD_Handle_stop(scene->playback_handle);
894 }
895
897
898 if ((scene->playback_handle = AUD_Device_play(sound_device, scene->sound_scene, 1))) {
899 AUD_Handle_setLoopCount(scene->playback_handle, -1);
900 }
901}
902
903static double get_cur_time(Scene *scene)
904{
905 /* We divide by the current framelen to take into account time remapping.
906 * Otherwise we will get the wrong starting time which will break A/V sync.
907 * See #74111 for further details. */
908 return FRA2TIME((scene->r.cfra + scene->r.subframe) / double(scene->r.framelen));
909}
910
911void BKE_sound_play_scene(Scene *scene)
912{
913 sound_verify_evaluated_id(&scene->id);
914
915 AUD_Status status;
916 const double cur_time = get_cur_time(scene);
917
918 AUD_Device_lock(sound_device);
919
920 status = scene->playback_handle ? AUD_Handle_getStatus(scene->playback_handle) :
921 AUD_STATUS_INVALID;
922
923 if (status == AUD_STATUS_INVALID) {
924 sound_start_play_scene(scene);
925
926 if (!scene->playback_handle) {
927 AUD_Device_unlock(sound_device);
928 return;
929 }
930 }
931
932 if (status != AUD_STATUS_PLAYING) {
933 AUD_Handle_setPosition(scene->playback_handle, cur_time);
934 AUD_Handle_resume(scene->playback_handle);
935 }
936
937 if (scene->audio.flag & AUDIO_SYNC) {
938 AUD_playSynchronizer();
939 }
940
941 AUD_Device_unlock(sound_device);
942}
943
944void BKE_sound_stop_scene(Scene *scene)
945{
946 if (scene->playback_handle) {
947 AUD_Handle_pause(scene->playback_handle);
948
949 if (scene->audio.flag & AUDIO_SYNC) {
950 AUD_stopSynchronizer();
951 }
952 }
953}
954
955void BKE_sound_seek_scene(Main *bmain, Scene *scene)
956{
957 sound_verify_evaluated_id(&scene->id);
958
959 AUD_Status status;
960 bScreen *screen;
961 int animation_playing;
962
963 const double one_frame = 1.0 / FPS +
964 (U.audiorate > 0 ? U.mixbufsize / double(U.audiorate) : 0.0);
965 const double cur_time = FRA2TIME(scene->r.cfra);
966
967 AUD_Device_lock(sound_device);
968
969 status = scene->playback_handle ? AUD_Handle_getStatus(scene->playback_handle) :
970 AUD_STATUS_INVALID;
971
972 if (status == AUD_STATUS_INVALID) {
973 sound_start_play_scene(scene);
974
975 if (!scene->playback_handle) {
976 AUD_Device_unlock(sound_device);
977 return;
978 }
979
980 AUD_Handle_pause(scene->playback_handle);
981 }
982
983 animation_playing = 0;
984 for (screen = static_cast<bScreen *>(bmain->screens.first); screen;
985 screen = static_cast<bScreen *>(screen->id.next))
986 {
987 if (screen->animtimer) {
988 animation_playing = 1;
989 break;
990 }
991 }
992
993 if (scene->audio.flag & AUDIO_SCRUB && !animation_playing) {
994 AUD_Handle_setPosition(scene->playback_handle, cur_time);
995 if (scene->audio.flag & AUDIO_SYNC) {
996 AUD_seekSynchronizer(scene->playback_handle, cur_time);
997 }
998 AUD_Handle_resume(scene->playback_handle);
999 if (scene->sound_scrub_handle &&
1000 AUD_Handle_getStatus(scene->sound_scrub_handle) != AUD_STATUS_INVALID)
1001 {
1002 AUD_Handle_setPosition(scene->sound_scrub_handle, 0);
1003 }
1004 else {
1005 if (scene->sound_scrub_handle) {
1006 AUD_Handle_stop(scene->sound_scrub_handle);
1007 }
1008 scene->sound_scrub_handle = AUD_pauseAfter(scene->playback_handle, one_frame);
1009 }
1010 }
1011 else {
1012 if (scene->audio.flag & AUDIO_SYNC) {
1013 AUD_seekSynchronizer(scene->playback_handle, cur_time);
1014 }
1015 else {
1016 if (status == AUD_STATUS_PLAYING) {
1017 AUD_Handle_setPosition(scene->playback_handle, cur_time);
1018 }
1019 }
1020 }
1021
1022 AUD_Device_unlock(sound_device);
1023}
1024
1025double BKE_sound_sync_scene(Scene *scene)
1026{
1027 sound_verify_evaluated_id(&scene->id);
1028
1029 /* Ugly: Blender doesn't like it when the animation is played back during rendering */
1030 if (G.is_rendering) {
1031 return NAN_FLT;
1032 }
1033
1034 if (scene->playback_handle) {
1035 if (scene->audio.flag & AUDIO_SYNC) {
1036 return AUD_getSynchronizerPosition(scene->playback_handle);
1037 }
1038
1039 return AUD_Handle_getPosition(scene->playback_handle);
1040 }
1041 return NAN_FLT;
1042}
1043
1045{
1046 sound_verify_evaluated_id(&scene->id);
1047
1048 /* Ugly: Blender doesn't like it when the animation is played back during rendering */
1049 if (G.is_rendering) {
1050 return -1;
1051 }
1052
1053 /* In case of a "None" audio device, we have no playback information. */
1054 if (AUD_Device_getRate(sound_device) == AUD_RATE_INVALID) {
1055 return -1;
1056 }
1057
1058 if (scene->audio.flag & AUDIO_SYNC) {
1059 return AUD_isSynchronizerPlaying();
1060 }
1061
1062 return -1;
1063}
1064
1066{
1067 if ((sound->tags & SOUND_TAGS_WAVEFORM_NO_RELOAD) == 0) {
1068 SoundWaveform *waveform = static_cast<SoundWaveform *>(sound->waveform);
1069 if (waveform) {
1070 if (waveform->data) {
1071 MEM_freeN(waveform->data);
1072 }
1073 MEM_freeN(waveform);
1074 }
1075
1076 sound->waveform = nullptr;
1077 }
1078 /* This tag is only valid once. */
1079 sound->tags &= ~SOUND_TAGS_WAVEFORM_NO_RELOAD;
1080}
1081
1082void BKE_sound_read_waveform(Main *bmain, bSound *sound, bool *stop)
1083{
1084 bool need_close_audio_handles = false;
1085 if (sound->playback_handle == nullptr) {
1086 /* TODO(sergey): Make it fully independent audio handle. */
1087 sound_load_audio(bmain, sound, true);
1088 need_close_audio_handles = true;
1089 }
1090
1091 AUD_SoundInfo info = AUD_getInfo(sound->playback_handle);
1092 SoundWaveform *waveform = static_cast<SoundWaveform *>(
1093 MEM_mallocN(sizeof(SoundWaveform), "SoundWaveform"));
1094
1095 if (info.length > 0) {
1096 int length = info.length * SOUND_WAVE_SAMPLES_PER_SECOND;
1097
1098 waveform->data = static_cast<float *>(
1099 MEM_mallocN(sizeof(float[3]) * length, "SoundWaveform.samples"));
1100 /* Ideally this would take a boolean argument. */
1101 short stop_i16 = *stop;
1102 waveform->length = AUD_readSound(
1103 sound->playback_handle, waveform->data, length, SOUND_WAVE_SAMPLES_PER_SECOND, &stop_i16);
1104 *stop = stop_i16 != 0;
1105 }
1106 else {
1107 /* Create an empty waveform here if the sound couldn't be
1108 * read. This indicates that reading the waveform is "done",
1109 * whereas just setting sound->waveform to nullptr causes other
1110 * code to think the waveform still needs to be created. */
1111 waveform->data = nullptr;
1112 waveform->length = 0;
1113 }
1114
1115 if (*stop) {
1116 if (waveform->data) {
1117 MEM_freeN(waveform->data);
1118 }
1119 MEM_freeN(waveform);
1120 BLI_spin_lock(static_cast<SpinLock *>(sound->spinlock));
1121 sound->tags &= ~SOUND_TAGS_WAVEFORM_LOADING;
1122 BLI_spin_unlock(static_cast<SpinLock *>(sound->spinlock));
1123 return;
1124 }
1125
1127
1128 BLI_spin_lock(static_cast<SpinLock *>(sound->spinlock));
1129 sound->waveform = waveform;
1130 sound->tags &= ~SOUND_TAGS_WAVEFORM_LOADING;
1131 BLI_spin_unlock(static_cast<SpinLock *>(sound->spinlock));
1132
1133 if (need_close_audio_handles) {
1134 sound_free_audio(sound);
1135 }
1136}
1137
1138static void sound_update_base(Scene *scene, Object *object, void *new_set)
1139{
1140 Speaker *speaker;
1141 float quat[4];
1142
1143 sound_verify_evaluated_id(&scene->id);
1144 sound_verify_evaluated_id(&object->id);
1145
1146 if ((object->type != OB_SPEAKER) || !object->adt) {
1147 return;
1148 }
1149
1150 LISTBASE_FOREACH (NlaTrack *, track, &object->adt->nla_tracks) {
1151 LISTBASE_FOREACH (NlaStrip *, strip, &track->strips) {
1152 if (strip->type != NLASTRIP_TYPE_SOUND) {
1153 continue;
1154 }
1155 speaker = (Speaker *)object->data;
1156
1157 if (AUD_removeSet(scene->speaker_handles, strip->speaker_handle)) {
1158 if (speaker->sound) {
1159 AUD_SequenceEntry_move(strip->speaker_handle, double(strip->start) / FPS, FLT_MAX, 0);
1160 }
1161 else {
1162 AUD_Sequence_remove(scene->sound_scene, strip->speaker_handle);
1163 strip->speaker_handle = nullptr;
1164 }
1165 }
1166 else {
1167 if (speaker->sound) {
1168 strip->speaker_handle = AUD_Sequence_add(scene->sound_scene,
1169 speaker->sound->playback_handle,
1170 double(strip->start) / FPS,
1171 FLT_MAX,
1172 0);
1173 AUD_SequenceEntry_setRelative(strip->speaker_handle, 0);
1174 }
1175 }
1176
1177 if (strip->speaker_handle) {
1178 const bool mute = ((strip->flag & NLASTRIP_FLAG_MUTED) || (speaker->flag & SPK_MUTED));
1179 AUD_addSet(new_set, strip->speaker_handle);
1180 AUD_SequenceEntry_setVolumeMaximum(strip->speaker_handle, speaker->volume_max);
1181 AUD_SequenceEntry_setVolumeMinimum(strip->speaker_handle, speaker->volume_min);
1182 AUD_SequenceEntry_setDistanceMaximum(strip->speaker_handle, speaker->distance_max);
1183 AUD_SequenceEntry_setDistanceReference(strip->speaker_handle, speaker->distance_reference);
1184 AUD_SequenceEntry_setAttenuation(strip->speaker_handle, speaker->attenuation);
1185 AUD_SequenceEntry_setConeAngleOuter(strip->speaker_handle, speaker->cone_angle_outer);
1186 AUD_SequenceEntry_setConeAngleInner(strip->speaker_handle, speaker->cone_angle_inner);
1187 AUD_SequenceEntry_setConeVolumeOuter(strip->speaker_handle, speaker->cone_volume_outer);
1188
1189 mat4_to_quat(quat, object->object_to_world().ptr());
1190 blender::float3 location = object->object_to_world().location();
1191 AUD_SequenceEntry_setAnimationData(
1192 strip->speaker_handle, AUD_AP_LOCATION, scene->r.cfra, location, 1);
1193 AUD_SequenceEntry_setAnimationData(
1194 strip->speaker_handle, AUD_AP_ORIENTATION, scene->r.cfra, quat, 1);
1195 AUD_SequenceEntry_setAnimationData(
1196 strip->speaker_handle, AUD_AP_VOLUME, scene->r.cfra, &speaker->volume, 1);
1197 AUD_SequenceEntry_setAnimationData(
1198 strip->speaker_handle, AUD_AP_PITCH, scene->r.cfra, &speaker->pitch, 1);
1199 AUD_SequenceEntry_setSound(strip->speaker_handle, speaker->sound->playback_handle);
1200 AUD_SequenceEntry_setMuted(strip->speaker_handle, mute);
1201 }
1202 }
1203 }
1204}
1205
1206void BKE_sound_update_scene(Depsgraph *depsgraph, Scene *scene)
1207{
1208 sound_verify_evaluated_id(&scene->id);
1209
1210 void *new_set = AUD_createSet();
1211 void *handle;
1212 float quat[4];
1213
1214 /* cheap test to skip looping over all objects (no speakers is a common case) */
1216 DEGObjectIterSettings deg_iter_settings = {nullptr};
1217 deg_iter_settings.depsgraph = depsgraph;
1218 deg_iter_settings.flags = DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY |
1221 DEG_OBJECT_ITER_BEGIN (&deg_iter_settings, object) {
1222 sound_update_base(scene, object, new_set);
1223 }
1225 }
1226
1227 while ((handle = AUD_getSet(scene->speaker_handles))) {
1228 AUD_Sequence_remove(scene->sound_scene, handle);
1229 }
1230
1231 if (scene->camera) {
1232 mat4_to_quat(quat, scene->camera->object_to_world().ptr());
1233 blender::float3 location = scene->camera->object_to_world().location();
1234 AUD_Sequence_setAnimationData(scene->sound_scene, AUD_AP_LOCATION, scene->r.cfra, location, 1);
1235 AUD_Sequence_setAnimationData(scene->sound_scene, AUD_AP_ORIENTATION, scene->r.cfra, quat, 1);
1236 }
1237
1238 AUD_destroySet(scene->speaker_handles);
1239 scene->speaker_handles = new_set;
1240}
1241
1242void *BKE_sound_get_factory(void *sound)
1243{
1244 return ((bSound *)sound)->playback_handle;
1245}
1246
1247float BKE_sound_get_length(Main *bmain, bSound *sound)
1248{
1249 if (sound->playback_handle != nullptr) {
1250 AUD_SoundInfo info = AUD_getInfo(sound->playback_handle);
1251 return info.length;
1252 }
1253 SoundInfo info;
1254 if (!BKE_sound_info_get(bmain, sound, &info)) {
1255 return 0.0f;
1256 }
1257 return info.length;
1258}
1259
1261{
1262 if (audio_device_names == nullptr) {
1263 audio_device_names = AUD_getDeviceNames();
1264 }
1265
1266 return audio_device_names;
1267}
1268
1269static bool sound_info_from_playback_handle(void *playback_handle, SoundInfo *sound_info)
1270{
1271 if (playback_handle == nullptr) {
1272 return false;
1273 }
1274 AUD_SoundInfo info = AUD_getInfo(playback_handle);
1275 sound_info->specs.channels = (eSoundChannels)info.specs.channels;
1276 sound_info->length = info.length;
1277 sound_info->specs.samplerate = info.specs.rate;
1278 return true;
1279}
1280
1281bool BKE_sound_info_get(Main *main, bSound *sound, SoundInfo *sound_info)
1282{
1283 if (sound->playback_handle != nullptr) {
1284 return sound_info_from_playback_handle(sound->playback_handle, sound_info);
1285 }
1286 /* TODO(sergey): Make it fully independent audio handle. */
1287 /* Don't free waveforms during non-destructive queries.
1288 * This causes unnecessary recalculation - see #69921 */
1289 sound_load_audio(main, sound, false);
1290 const bool result = sound_info_from_playback_handle(sound->playback_handle, sound_info);
1291 sound_free_audio(sound);
1292 return result;
1293}
1294
1296 const char *filepath,
1297 int stream,
1298 SoundStreamInfo *sound_info)
1299{
1300 const char *blendfile_path = BKE_main_blendfile_path(main);
1301 char filepath_abs[FILE_MAX];
1302 AUD_Sound *sound;
1303 AUD_StreamInfo *stream_infos;
1304 int stream_count;
1305
1306 STRNCPY(filepath_abs, filepath);
1307 BLI_path_abs(filepath_abs, blendfile_path);
1308
1309 sound = AUD_Sound_file(filepath_abs);
1310 if (!sound) {
1311 return false;
1312 }
1313
1314 stream_count = AUD_Sound_getFileStreams(sound, &stream_infos);
1315
1316 AUD_Sound_free(sound);
1317
1318 if (!stream_infos) {
1319 return false;
1320 }
1321
1322 if ((stream < 0) || (stream >= stream_count)) {
1323 free(stream_infos);
1324 return false;
1325 }
1326
1327 sound_info->start = stream_infos[stream].start;
1328 sound_info->duration = stream_infos[stream].duration;
1329
1330 free(stream_infos);
1331
1332 return true;
1333}
1334
1335#else /* WITH_AUDASPACE */
1336
1337# include "BLI_utildefines.h"
1338
1339void BKE_sound_force_device(const char * /*device*/) {}
1341void BKE_sound_init(Main * /*bmain*/) {}
1344void BKE_sound_cache(bSound * /*sound*/) {}
1345void BKE_sound_delete_cache(bSound * /*sound*/) {}
1346void BKE_sound_load(Main * /*bmain*/, bSound * /*sound*/) {}
1347void BKE_sound_create_scene(Scene * /*scene*/) {}
1348void BKE_sound_destroy_scene(Scene * /*scene*/) {}
1352void BKE_sound_mute_scene(Scene * /*scene*/, int /*muted*/) {}
1354 Sequence * /*sequence*/,
1355 int /*startframe*/,
1356 int /*endframe*/,
1357 int /*frameskip*/)
1358{
1359 return nullptr;
1360}
1362{
1363 return nullptr;
1364}
1366 Sequence * /*sequence*/,
1367 int /*startframe*/,
1368 int /*endframe*/,
1369 int /*frameskip*/)
1370{
1371 return nullptr;
1372}
1373void *BKE_sound_add_scene_sound_defaults(Scene * /*scene*/, Sequence * /*sequence*/)
1374{
1375 return nullptr;
1376}
1377void BKE_sound_remove_scene_sound(Scene * /*scene*/, void * /*handle*/) {}
1378void BKE_sound_mute_scene_sound(void * /*handle*/, bool /*mute*/) {}
1379void BKE_sound_move_scene_sound(const Scene * /*scene*/,
1380 void * /*handle*/,
1381 int /*startframe*/,
1382 int /*endframe*/,
1383 int /*frameskip*/,
1384 double /*audio_offset*/)
1385{
1386}
1387void BKE_sound_move_scene_sound_defaults(Scene * /*scene*/, Sequence * /*sequence*/) {}
1388void BKE_sound_play_scene(Scene * /*scene*/) {}
1389void BKE_sound_stop_scene(Scene * /*scene*/) {}
1390void BKE_sound_seek_scene(Main * /*bmain*/, Scene * /*scene*/) {}
1391double BKE_sound_sync_scene(Scene * /*scene*/)
1392{
1393 return NAN_FLT;
1394}
1396{
1397 return -1;
1398}
1400 bSound *sound,
1401 /* NOLINTNEXTLINE: readability-non-const-parameter. */
1402 bool *stop)
1403{
1404 UNUSED_VARS(sound, stop, bmain);
1405}
1406void BKE_sound_init_main(Main * /*bmain*/) {}
1407void BKE_sound_update_sequencer(Main * /*main*/, bSound * /*sound*/) {}
1408void BKE_sound_update_scene(Depsgraph * /*depsgraph*/, Scene * /*scene*/) {}
1409void BKE_sound_update_scene_sound(void * /*handle*/, bSound * /*sound*/) {}
1411void BKE_sound_update_fps(Main * /*bmain*/, Scene * /*scene*/) {}
1413 int /*frame*/,
1414 float /*volume*/,
1415 char /*animated*/)
1416{
1417}
1419 int /*frame*/,
1420 float /*pan*/,
1421 char /*animated*/)
1422{
1423}
1424void BKE_sound_set_scene_volume(Scene * /*scene*/, float /*volume*/) {}
1426 int /*frame*/,
1427 float /*pitch*/,
1428 char /*animated*/)
1429{
1430}
1432 int /*frame_start*/,
1433 int /*frame_end*/,
1434 float /*pitch*/)
1435{
1436}
1437float BKE_sound_get_length(Main * /*bmain*/, bSound * /*sound*/)
1438{
1439 return 0;
1440}
1442{
1443 static char *names[1] = {nullptr};
1444 return names;
1445}
1446
1448
1449bool BKE_sound_info_get(Main * /*main*/, bSound * /*sound*/, SoundInfo * /*sound_info*/)
1450{
1451 return false;
1452}
1453
1455 const char * /*filepath*/,
1456 int /*stream*/,
1457 SoundStreamInfo * /*sound_info*/)
1458{
1459 return false;
1460}
1461
1462#endif /* WITH_AUDASPACE */
1463
1465{
1466 scene->sound_scene = nullptr;
1467 scene->playback_handle = nullptr;
1468 scene->sound_scrub_handle = nullptr;
1469 scene->speaker_handles = nullptr;
1470}
1471
1473{
1474 if (scene->sound_scene != nullptr) {
1475 return;
1476 }
1478}
1479
1481{
1482 sound->cache = nullptr;
1483 sound->playback_handle = nullptr;
1484}
1485
1487{
1488 if (sound->cache != nullptr) {
1489 return;
1490 }
1491 BKE_sound_load(bmain, sound);
1492}
1493
1495{
1496#if defined(WITH_AUDASPACE) && defined(WITH_JACK)
1498#else
1500#endif
1501}
1502
1503void BKE_sound_jack_scene_update(Scene *scene, int mode, double time)
1504{
1505 sound_verify_evaluated_id(&scene->id);
1506
1507 /* Ugly: Blender doesn't like it when the animation is played back during rendering. */
1508 if (G.is_rendering) {
1509 return;
1510 }
1511
1512 if (mode) {
1513 BKE_sound_play_scene(scene);
1514 }
1515 else {
1516 BKE_sound_stop_scene(scene);
1517 }
1518#ifdef WITH_AUDASPACE
1519 if (scene->playback_handle != nullptr) {
1520 AUD_Handle_setPosition(scene->playback_handle, time);
1521 }
1522#else
1523 UNUSED_VARS(time);
1524#endif
1525}
1526
1527void BKE_sound_evaluate(Depsgraph *depsgraph, Main *bmain, bSound *sound)
1528{
1529 DEG_debug_print_eval(depsgraph, __func__, sound->id.name, sound);
1530 if (sound->id.recalc & ID_RECALC_SOURCE) {
1531 /* Sequencer checks this flag to see if the strip sound is to be updated from the Audaspace
1532 * side. */
1533 sound->id.recalc |= ID_RECALC_AUDIO;
1534 }
1535
1536 if (sound->id.recalc & ID_RECALC_AUDIO) {
1537 BKE_sound_load(bmain, sound);
1538 return;
1539 }
1540 BKE_sound_ensure_loaded(bmain, sound);
1541}
void * AUD_createSet()
Definition AUD_Set.cpp:13
void * AUD_getSet(void *set)
Definition AUD_Set.cpp:38
void AUD_addSet(void *set, void *entry)
Definition AUD_Set.cpp:31
void AUD_destroySet(void *set)
Definition AUD_Set.cpp:18
char AUD_removeSet(void *set, void *entry)
Definition AUD_Set.cpp:23
bool BKE_bpath_foreach_path_fixed_process(BPathForeachPathData *bpath_data, char *path, size_t path_maxncpy)
Definition bpath.cc:123
@ BKE_BPATH_FOREACH_PATH_SKIP_PACKED
Definition BKE_bpath.hh:37
@ IDTYPE_FLAGS_APPEND_IS_REUSABLE
Definition BKE_idtype.hh:39
@ IDTYPE_FLAGS_NO_ANIMDATA
Definition BKE_idtype.hh:41
void(*)(ID *id, const IDCacheKey *cache_key, void **cache_p, uint flags, void *user_data) IDTypeForeachCacheFunctionCallback
Definition BKE_idtype.hh:98
void * BKE_libblock_alloc(Main *bmain, short type, const char *name, int flag) ATTR_WARN_UNUSED_RESULT
Definition lib_id.cc:1415
void id_us_plus(ID *id)
Definition lib_id.cc:351
void BKE_id_blend_write(BlendWriter *writer, ID *id)
Definition lib_id.cc:2560
@ IDWALK_CB_USER
int BKE_lib_query_foreachid_process_flags_get(const LibraryForeachIDData *data)
Definition lib_query.cc:120
@ IDWALK_DO_DEPRECATED_POINTERS
#define BKE_LIB_FOREACHID_PROCESS_ID_NOCHECK(data_, id_, cb_flag_)
const char * BKE_main_blendfile_path(const Main *bmain) ATTR_NONNULL()
Definition main.cc:832
PackedFile * BKE_packedfile_duplicate(const PackedFile *pf_src)
void BKE_packedfile_free(PackedFile *pf)
void BKE_packedfile_blend_write(BlendWriter *writer, const PackedFile *pf)
void BKE_packedfile_blend_read(BlendDataReader *reader, PackedFile **pf_p, blender::StringRefNull filepath)
void * BKE_sound_get_factory(void *sound)
#define SOUND_WAVE_SAMPLES_PER_SECOND
Definition BKE_sound.h:14
void(* SoundJackSyncCallback)(struct Main *bmain, int mode, double time)
Definition BKE_sound.h:197
void * BKE_sound_get_device(void)
eSoundChannels
Definition BKE_sound.h:68
#define BLI_assert(a)
Definition BLI_assert.h:50
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:57
#define BLI_INLINE
void BLI_kdtree_nd_ free(KDTree *tree)
#define LISTBASE_FOREACH(type, var, list)
MINLINE int max_ii(int a, int b)
#define NAN_FLT
void mat4_to_quat(float q[4], const float mat[4][4])
bool BLI_path_abs(char path[FILE_MAX], const char *basepath) ATTR_NONNULL(1
void void void const char * BLI_path_basename(const char *path) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT
#define FILE_MAX
#define BLI_path_cmp
#define STRNCPY(dst, src)
Definition BLI_string.h:593
#define BLI_string_join(...)
unsigned char uchar
pthread_spinlock_t SpinLock
void BLI_spin_init(SpinLock *spin)
Definition threads.cc:391
void BLI_spin_unlock(SpinLock *spin)
Definition threads.cc:430
void BLI_spin_lock(SpinLock *spin)
Definition threads.cc:405
void BLI_spin_end(SpinLock *spin)
Definition threads.cc:445
#define UNUSED_VARS(...)
#define UNUSED_VARS_NDEBUG(...)
bool BLO_read_data_is_undo(BlendDataReader *reader)
Definition readfile.cc:5135
#define BLO_write_id_struct(writer, struct_name, id_address, id)
bool BLO_write_is_undo(BlendWriter *writer)
#define BLT_I18NCONTEXT_ID_SOUND
typedef double(DMatrix)[4][4]
void DEG_debug_print_eval(Depsgraph *depsgraph, const char *function_name, const char *object_name, const void *object_address)
#define DEG_OBJECT_ITER_BEGIN(settings_, instance_)
#define DEG_OBJECT_ITER_END
bool DEG_id_type_any_exists(const Depsgraph *depsgraph, short id_type)
@ DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY
@ DEG_ITER_OBJECT_FLAG_LINKED_INDIRECTLY
@ DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET
@ ID_RECALC_AUDIO
Definition DNA_ID.h:1099
@ ID_RECALC_SOURCE
Definition DNA_ID.h:1110
#define FILTER_ID_SO
Definition DNA_ID.h:1186
#define MAX_ID_NAME
Definition DNA_ID.h:377
#define ID_BLEND_PATH(_bmain, _id)
Definition DNA_ID.h:647
@ ID_TAG_COPIED_ON_EVAL
Definition DNA_ID.h:964
@ ID_TAG_COPIED_ON_EVAL_FINAL_RESULT
Definition DNA_ID.h:974
@ ID_TAG_NO_MAIN
Definition DNA_ID.h:945
@ INDEX_ID_SO
Definition DNA_ID.h:1270
#define ID_IS_OVERRIDE_LIBRARY(_id)
Definition DNA_ID.h:683
@ ID_SO
@ ID_SPK
@ NLASTRIP_FLAG_MUTED
@ NLASTRIP_TYPE_SOUND
Object is a sort of wrapper for general info.
@ OB_SPEAKER
#define FPS
@ AUDIO_MUTE
@ AUDIO_VOLUME_ANIMATED
@ AUDIO_SCRUB
@ AUDIO_SYNC
#define FRA2TIME(a)
struct bSound bSound
@ SOUND_FLAGS_MONO
@ SOUND_FLAGS_CACHING
@ SOUND_TAGS_WAVEFORM_NO_RELOAD
@ SPK_MUTED
Read Guarded memory(de)allocation.
void BKE_sound_jack_sync_callback_set(SoundJackSyncCallback callback)
void BKE_sound_ensure_scene(Scene *scene)
BLI_INLINE void sound_verify_evaluated_id(const ID *id)
void BKE_sound_exit()
double BKE_sound_sync_scene(Scene *)
void BKE_sound_destroy_scene(Scene *)
char ** BKE_sound_get_device_names()
void BKE_sound_init(Main *)
static void sound_free_audio(bSound *sound)
int BKE_sound_scene_playing(Scene *)
void BKE_sound_lock()
void BKE_sound_load(Main *, bSound *)
void BKE_sound_move_scene_sound_defaults(Scene *, Sequence *)
void BKE_sound_update_sequencer(Main *, bSound *)
static void sound_free_data(ID *id)
static void sound_blend_read_data(BlendDataReader *reader, ID *id)
void BKE_sound_mute_scene_sound(void *, bool)
void BKE_sound_seek_scene(Main *, Scene *)
void * BKE_sound_add_scene_sound(Scene *, Sequence *, int, int, int)
void BKE_sound_init_main(Main *)
void BKE_sound_play_scene(Scene *)
void BKE_sound_force_device(const char *)
void BKE_sound_jack_scene_update(Scene *scene, int mode, double time)
void BKE_sound_update_scene(Depsgraph *, Scene *)
bSound * BKE_sound_new_file_exists_ex(Main *bmain, const char *filepath, bool *r_exists)
static void sound_blend_write(BlendWriter *writer, ID *id, const void *id_address)
void BKE_sound_mute_scene(Scene *, int)
void * BKE_sound_scene_add_scene_sound(Scene *, Sequence *, int, int, int)
void BKE_sound_exit_once()
bSound * BKE_sound_new_file(Main *bmain, const char *filepath)
void BKE_sound_update_fps(Main *, Scene *)
void BKE_sound_delete_cache(bSound *)
static void sound_foreach_path(ID *id, BPathForeachPathData *bpath_data)
void BKE_sound_remove_scene_sound(Scene *, void *)
void * BKE_sound_add_scene_sound_defaults(Scene *, Sequence *)
void BKE_sound_reset_runtime(bSound *sound)
bool BKE_sound_stream_info_get(Main *, const char *, int, SoundStreamInfo *)
float BKE_sound_get_length(Main *, bSound *)
bool BKE_sound_info_get(Main *, bSound *, SoundInfo *)
static void sound_foreach_id(ID *id, LibraryForeachIDData *data)
void * BKE_sound_scene_add_scene_sound_defaults(Scene *, Sequence *)
void BKE_sound_set_scene_sound_pan_at_frame(void *, int, float, char)
static void sound_copy_data(Main *, std::optional< Library * >, ID *id_dst, const ID *id_src, const int)
void BKE_sound_init_once()
void BKE_sound_set_scene_sound_pitch_at_frame(void *, int, float, char)
void BKE_sound_create_scene(Scene *)
IDTypeInfo IDType_ID_SO
void BKE_sound_update_scene_sound(void *, bSound *)
void BKE_sound_free_waveform(bSound *)
void BKE_sound_set_scene_sound_pitch_constant_range(void *, int, int, float)
static void sound_foreach_cache(ID *id, IDTypeForeachCacheFunctionCallback function_callback, void *user_data)
void BKE_sound_set_scene_volume(Scene *, float)
bSound * BKE_sound_new_file_exists(Main *bmain, const char *filepath)
void BKE_sound_reset_scene_runtime(Scene *scene)
void BKE_sound_update_sequence_handle(void *handle, void *sound_handle)
void BKE_sound_stop_scene(Scene *)
void BKE_sound_reset_scene_specs(Scene *)
void BKE_sound_evaluate(Depsgraph *depsgraph, Main *bmain, bSound *sound)
void BKE_sound_move_scene_sound(const Scene *, void *, int, int, int, double)
void BKE_sound_read_waveform(Main *bmain, bSound *sound, bool *stop)
void BKE_sound_unlock()
void BKE_sound_cache(bSound *)
void BKE_sound_update_scene_listener(Scene *)
void BKE_sound_ensure_loaded(Main *bmain, bSound *sound)
void BKE_sound_set_scene_sound_volume_at_frame(void *, int, float, char)
unsigned int U
Definition btGjkEpa3.h:78
const Depsgraph * depsgraph
DEGForeachIDComponentCallback callback
#define offsetof(t, d)
#define pf(_x, _i)
Prefetch 64.
Definition gim_memory.h:48
void *(* MEM_mallocN)(size_t len, const char *str)
Definition mallocn.cc:44
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
#define G(x, y, z)
int main()
void SEQ_sound_update(Scene *scene, bSound *sound)
void SEQ_sound_update_length(Main *bmain, Scene *scene)
#define FLT_MAX
Definition stdcycles.h:14
int SEQ_time_left_handle_frame_get(const Scene *, const Sequence *seq)
int SEQ_time_right_handle_frame_get(const Scene *scene, const Sequence *seq)
eBPathForeachFlag flag
Definition BKE_bpath.hh:88
unsigned int id_session_uid
Definition BKE_idtype.hh:69
Definition DNA_ID.h:413
unsigned int recalc
Definition DNA_ID.h:437
void * next
Definition DNA_ID.h:416
char name[66]
Definition DNA_ID.h:425
void * first
ListBase sounds
Definition BKE_main.hh:230
ListBase screens
Definition BKE_main.hh:225
ListBase strips
void * sound_scene
struct Scene * scene
struct bSound * sound
int samplerate
Definition BKE_sound.h:83
eSoundChannels channels
Definition BKE_sound.h:82
struct SoundInfo::@58 specs
float length
Definition BKE_sound.h:85
double duration
Definition BKE_sound.h:89
float * data
Definition BKE_sound.h:28
float cone_angle_outer
float distance_reference
float cone_volume_outer
float distance_max
float attenuation
struct bSound * sound
float cone_angle_inner
void * playback_handle
struct PackedFile * packedfile
struct PackedFile * newpackedfile
char filepath[1024]
void * handle
struct Ipo * ipo
void * cache
void * spinlock
void * waveform
int audio_channels
short flags
double offset_time
#define N_(msgid)
static void sound_jack_sync_callback(Main *bmain, int mode, double time)
uint8_t flag
Definition wm_window.cc:138