10#include <condition_variable>
30#define DNA_DEPRECATED_ALLOW
44# include <AUD_Handle.h>
45# include <AUD_Sequence.h>
46# include <AUD_Sound.h>
47# include <AUD_Special.h>
73 std::optional<Library *> ,
81 sound_dst->
handle =
nullptr;
82 sound_dst->
cache =
nullptr;
89 sound_dst->
ipo =
nullptr;
140 function_callback(
id, &key, &sound->
waveform, 0, user_data);
188 sound->
cache =
nullptr;
238static char **audio_device_names =
nullptr;
270 STRNCPY(filepath_abs, filepath);
298 STRNCPY(filepath_abs, filepath);
332 AUD_Sound_free(sound->
handle);
338 AUD_Sound_free(sound->
cache);
339 sound->
cache =
nullptr;
352 const char *force_device =
nullptr;
355 const char *device_name =
nullptr;
356 AUD_DeviceSpecs initialized_specs;
359 AUD_Device *sound_device =
nullptr;
361 std::mutex sound_device_mutex;
363 bool need_exit =
false;
364 bool use_delayed_close =
true;
365 std::thread delayed_close_thread;
366 std::condition_variable delayed_close_cv;
368 int num_device_users = 0;
369 std::chrono::time_point<std::chrono::steady_clock> last_user_disconnect_time_point;
375static void sound_device_close_no_lock()
379 AUD_exit(
g_state.sound_device);
380 g_state.sound_device =
nullptr;
384static void sound_device_open_no_lock(AUD_DeviceSpecs requested_specs)
390 g_state.sound_device = AUD_init(
391 g_state.device_name, requested_specs,
g_state.buffer_size,
"Blender");
393 g_state.sound_device = AUD_init(
"None", requested_specs,
g_state.buffer_size,
"Blender");
396 g_state.initialized_specs.channels = AUD_Device_getChannels(
g_state.sound_device);
397 g_state.initialized_specs.rate = AUD_Device_getRate(
g_state.sound_device);
398 g_state.initialized_specs.format = AUD_Device_getFormat(
g_state.sound_device);
401static void sound_device_use_begin()
409 sound_device_open_no_lock(
g_state.initialized_specs);
412static void sound_device_use_end_after(
const std::chrono::milliseconds after_ms)
415 if (
g_state.num_device_users == 0) {
416 g_state.last_user_disconnect_time_point = std::chrono::steady_clock::now() + after_ms;
417 g_state.delayed_close_cv.notify_one();
421static void sound_device_use_end()
423 sound_device_use_end_after(std::chrono::milliseconds(0));
429static bool sound_use_close_thread()
434 if (__builtin_available(macOS 15.2, *)) {
443static void delayed_close_thread_run()
445 constexpr std::chrono::milliseconds device_close_delay{30000};
450 if (!
g_state.use_delayed_close) {
458 if (
g_state.num_device_users == 0) {
459 if (
g_state.sound_device ==
nullptr) {
464 g_state.delayed_close_cv.wait_until(
465 lock,
g_state.last_user_disconnect_time_point + device_close_delay);
481 if (!
g_state.use_delayed_close) {
488 CLOG_INFO(&
LOG, 3,
"Device is not open, nothing to do");
492 CLOG_INFO(&
LOG, 3,
"Checking last device usage and timestamp");
494 if (
g_state.num_device_users) {
499 const std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now();
500 if ((now -
g_state.last_user_disconnect_time_point) >= device_close_delay) {
501 sound_device_close_no_lock();
505 CLOG_INFO(&
LOG, 3,
"Delayed device close thread finished");
510static void sound_sync_callback(
void *
data,
int mode,
float time)
527 if (sound_use_close_thread()) {
528 CLOG_INFO(&
LOG, 2,
"Using delayed device close thread");
529 g_state.delayed_close_thread = std::thread(delayed_close_thread_run);
536 sound_device_close_no_lock();
546 if (
g_state.delayed_close_thread.joinable()) {
547 g_state.delayed_close_cv.notify_one();
548 g_state.delayed_close_thread.join();
552 sound_device_close_no_lock();
555 if (audio_device_names !=
nullptr) {
557 for (
i = 0; audio_device_names[
i];
i++) {
558 free(audio_device_names[
i]);
560 free(audio_device_names);
561 audio_device_names =
nullptr;
569 sound_device_close_no_lock();
571 AUD_DeviceSpecs requested_specs;
572 requested_specs.channels = AUD_Channels(
U.audiochannels);
573 requested_specs.format = AUD_SampleFormat(
U.audioformat);
574 requested_specs.rate =
U.audiorate;
576 if (
g_state.force_device ==
nullptr) {
578 g_state.device_name = names[0];
581 for (
int i = 0; names[
i];
i++) {
582 if (
i ==
U.audiodevice) {
591 g_state.buffer_size =
U.mixbufsize < 128 ? 1024 :
U.mixbufsize;
593 if (requested_specs.rate < AUD_RATE_8000) {
594 requested_specs.rate = AUD_RATE_48000;
597 if (requested_specs.format <= AUD_FORMAT_INVALID) {
598 requested_specs.format = AUD_FORMAT_S16;
601 if (requested_specs.channels <= AUD_CHANNELS_INVALID) {
602 requested_specs.channels = AUD_CHANNELS_STEREO;
606 sound_device_open_no_lock(requested_specs);
620 g_state.use_delayed_close =
false;
621 AUD_setSynchronizerCallback(sound_sync_callback, bmain);
624 g_state.use_delayed_close =
true;
625 sound_device_close_no_lock();
633 AUD_setSynchronizerCallback(sound_sync_callback, bmain);
648 sound->child_sound = source;
649 sound->type = SOUND_TYPE_BUFFER;
651 sound_load(bmain, sound);
656bSound *BKE_sound_new_limiter(
Main *bmain,
bSound *source,
float start,
float end)
665 sound->child_sound = source;
666 sound->start = start;
668 sound->type = SOUND_TYPE_LIMITER;
670 sound_load(bmain, sound);
681 AUD_Sound_free(sound->
cache);
696 AUD_Sound_free(sound->
cache);
697 sound->
cache =
nullptr;
702static void sound_load_audio(
Main *bmain,
bSound *sound,
bool free_waveform)
706 AUD_Sound_free(sound->
cache);
707 sound->
cache =
nullptr;
711 AUD_Sound_free(sound->
handle);
722 switch (sound->type) {
723 case SOUND_TYPE_FILE:
741 sound->
handle = AUD_Sound_file(fullpath);
748 case SOUND_TYPE_BUFFER:
749 if (sound->child_sound && sound->child_sound->
handle) {
750 sound->
handle = AUD_bufferSound(sound->child_sound->
handle);
753 case SOUND_TYPE_LIMITER:
754 if (sound->child_sound && sound->child_sound->
handle) {
755 sound->
handle = AUD_limitSound(sound->child_sound, sound->start, sound->end);
761 void *handle = AUD_Sound_rechannel(sound->
handle, AUD_CHANNELS_MONO);
762 AUD_Sound_free(sound->
handle);
781 sound_load_audio(bmain, sound,
true);
784AUD_Device *BKE_sound_mixdown(
const Scene *scene, AUD_DeviceSpecs specs,
int start,
float volume)
787 return AUD_openMixdownDevice(
788 specs, scene->
sound_scene, volume, AUD_RESAMPLE_QUALITY_MEDIUM, start /
FPS);
834 g_state.sound_device_mutex.lock();
835 if (
g_state.sound_device ==
nullptr) {
838 AUD_Device_lock(
g_state.sound_device);
843 g_state.sound_device_mutex.unlock();
844 if (
g_state.sound_device ==
nullptr) {
847 AUD_Device_unlock(
g_state.sound_device);
889 Scene *scene,
Strip *sequence,
int startframe,
int endframe,
int frameskip)
892 if (sequence->
scene && scene != sequence->
scene) {
893 const double fps =
FPS;
914 Scene *scene,
Strip *sequence,
int startframe,
int endframe,
int frameskip)
918 if (sequence->
sound ==
nullptr) {
922 const double fps =
FPS;
925 if (offset_time >= 0.0f) {
928 startframe / fps + offset_time,
955 AUD_SequenceEntry_setMuted(handle, mute);
966 const double fps =
FPS;
967 const double offset_time = audio_offset - frameskip / fps;
968 if (offset_time >= 0.0f) {
969 AUD_SequenceEntry_move(handle, startframe / fps + offset_time, endframe / fps, 0.0f);
972 AUD_SequenceEntry_move(handle, startframe / fps, endframe / fps, -offset_time);
980 double offset_time = 0.0f;
981 if (sequence->
sound !=
nullptr) {
1002#ifdef WITH_AUDASPACE
1003 AUD_SequenceEntry_setSound(handle, sound_handle);
1009#ifdef WITH_AUDASPACE
1027 const char animated)
1029 AUD_SequenceEntry_setAnimationData(handle, AUD_AP_VOLUME, frame, &volume, animated);
1035 const char animated)
1037 AUD_SequenceEntry_setAnimationData(handle, AUD_AP_PITCH, frame, &pitch, animated);
1045 frame_start =
max_ii(0, frame_start);
1046 frame_end =
max_ii(0, frame_end);
1047 AUD_SequenceEntry_setConstantRangeAnimationData(
1048 handle, AUD_AP_PITCH, frame_start, frame_end, &pitch);
1054 const char animated)
1056 AUD_SequenceEntry_setAnimationData(handle, AUD_AP_PANNING, frame, &pan, animated);
1061 BLI_assert_msg(0,
"is not supposed to be used, is weird function.");
1065 for (scene =
static_cast<Scene *
>(
main->scenes.first); scene;
1073static void sound_start_play_scene(
Scene *scene)
1092 sound_device_use_begin();
1098 AUD_Device_lock(
g_state.sound_device);
1115 if (status == AUD_STATUS_INVALID) {
1116 sound_start_play_scene(scene);
1119 AUD_Device_unlock(
g_state.sound_device);
1124 if (status != AUD_STATUS_PLAYING) {
1127 AUD_seekSynchronizer(cur_time);
1133 AUD_playSynchronizer();
1136 AUD_Device_unlock(
g_state.sound_device);
1147 AUD_stopSynchronizer();
1150 sound_device_use_end();
1156 bool animation_playing =
false;
1158 screen =
static_cast<bScreen *
>(screen->id.next))
1160 if (screen->animtimer) {
1161 animation_playing =
true;
1168 if (do_audio_scrub) {
1170 sound_device_use_begin();
1172 else if (
g_state.sound_device ==
nullptr) {
1178 AUD_Device_lock(
g_state.sound_device);
1182 if (status == AUD_STATUS_INVALID) {
1183 sound_start_play_scene(scene);
1186 AUD_Device_unlock(
g_state.sound_device);
1187 if (do_audio_scrub) {
1188 sound_device_use_end();
1196 const double one_frame = 1.0 /
FPS +
1197 (
U.audiorate > 0 ?
U.mixbufsize / double(
U.audiorate) : 0.0);
1200 if (do_audio_scrub) {
1215 sound_device_use_end_after(std::chrono::milliseconds(
int(one_frame * 1000)));
1217 else if (status == AUD_STATUS_PLAYING) {
1222 AUD_seekSynchronizer(cur_time);
1226 AUD_Device_unlock(
g_state.sound_device);
1234 if (
G.is_rendering) {
1240 return AUD_getSynchronizerPosition();
1253 if (waveform->
data) {
1267 bool need_close_audio_handles =
false;
1270 sound_load_audio(bmain, sound,
true);
1271 need_close_audio_handles =
true;
1277 if (info.length > 0) {
1282 short stop_i16 = *
stop;
1283 waveform->
length = AUD_readSound(
1285 *
stop = stop_i16 != 0;
1292 waveform->
data =
nullptr;
1297 if (waveform->
data) {
1314 if (need_close_audio_handles) {
1319static void sound_update_base(
Scene *scene,
Object *
object,
void *new_set)
1339 if (speaker->
sound) {
1340 AUD_SequenceEntry_move(strip->speaker_handle,
double(strip->start) /
FPS,
FLT_MAX, 0);
1343 AUD_Sequence_remove(scene->
sound_scene, strip->speaker_handle);
1344 strip->speaker_handle =
nullptr;
1348 if (speaker->
sound) {
1349 strip->speaker_handle = AUD_Sequence_add(scene->
sound_scene,
1351 double(strip->start) /
FPS,
1354 AUD_SequenceEntry_setRelative(strip->speaker_handle, 0);
1358 if (strip->speaker_handle) {
1361 AUD_SequenceEntry_setVolumeMaximum(strip->speaker_handle, speaker->
volume_max);
1362 AUD_SequenceEntry_setVolumeMinimum(strip->speaker_handle, speaker->
volume_min);
1363 AUD_SequenceEntry_setDistanceMaximum(strip->speaker_handle, speaker->
distance_max);
1364 AUD_SequenceEntry_setDistanceReference(strip->speaker_handle, speaker->
distance_reference);
1365 AUD_SequenceEntry_setAttenuation(strip->speaker_handle, speaker->
attenuation);
1366 AUD_SequenceEntry_setConeAngleOuter(strip->speaker_handle, speaker->
cone_angle_outer);
1367 AUD_SequenceEntry_setConeAngleInner(strip->speaker_handle, speaker->
cone_angle_inner);
1368 AUD_SequenceEntry_setConeVolumeOuter(strip->speaker_handle, speaker->
cone_volume_outer);
1372 AUD_SequenceEntry_setAnimationData(
1373 strip->speaker_handle, AUD_AP_LOCATION, scene->
r.
cfra, location, 1);
1374 AUD_SequenceEntry_setAnimationData(
1375 strip->speaker_handle, AUD_AP_ORIENTATION, scene->
r.
cfra, quat, 1);
1376 AUD_SequenceEntry_setAnimationData(
1377 strip->speaker_handle, AUD_AP_VOLUME, scene->
r.
cfra, &speaker->
volume, 1);
1378 AUD_SequenceEntry_setAnimationData(
1379 strip->speaker_handle, AUD_AP_PITCH, scene->
r.
cfra, &speaker->
pitch, 1);
1381 AUD_SequenceEntry_setMuted(strip->speaker_handle, mute);
1403 sound_update_base(scene,
object, new_set);
1415 AUD_Sequence_setAnimationData(scene->
sound_scene, AUD_AP_LOCATION, scene->
r.
cfra, location, 1);
1416 AUD_Sequence_setAnimationData(scene->
sound_scene, AUD_AP_ORIENTATION, scene->
r.
cfra, quat, 1);
1425 return ((
bSound *)sound)->playback_handle;
1443 if (audio_device_names ==
nullptr) {
1444 audio_device_names = AUD_getDeviceNames();
1447 return audio_device_names;
1450static bool sound_info_from_playback_handle(
void *playback_handle,
SoundInfo *sound_info)
1452 if (playback_handle ==
nullptr) {
1455 AUD_SoundInfo info = AUD_getInfo(playback_handle);
1465 return sound_info_from_playback_handle(sound->
playback_handle, sound_info);
1470 sound_load_audio(
main, sound,
false);
1477 const char *filepath,
1484 AUD_StreamInfo *stream_infos;
1487 STRNCPY(filepath_abs, filepath);
1490 sound = AUD_Sound_file(filepath_abs);
1495 stream_count = AUD_Sound_getFileStreams(sound, &stream_infos);
1497 AUD_Sound_free(sound);
1499 if (!stream_infos) {
1503 if ((stream < 0) || (stream >= stream_count)) {
1508 sound_info->
start = stream_infos[stream].start;
1509 sound_info->
duration = stream_infos[stream].duration;
1620 static char *names[1] = {
nullptr};
1659 sound->
cache =
nullptr;
1665 if (sound->
cache !=
nullptr) {
1673#if defined(WITH_AUDASPACE)
1685 if (
G.is_rendering) {
1688#ifdef WITH_AUDASPACE
1689 AUD_Device_lock(
g_state.sound_device);
1700 AUD_Device_unlock(
g_state.sound_device);
void * AUD_getSet(void *set)
void AUD_addSet(void *set, void *entry)
void AUD_destroySet(void *set)
char AUD_removeSet(void *set, void *entry)
bool BKE_bpath_foreach_path_fixed_process(BPathForeachPathData *bpath_data, char *path, size_t path_maxncpy)
@ BKE_BPATH_FOREACH_PATH_SKIP_PACKED
@ IDTYPE_FLAGS_APPEND_IS_REUSABLE
@ IDTYPE_FLAGS_NO_ANIMDATA
void(*)(ID *id, const IDCacheKey *cache_key, void **cache_p, uint flags, void *user_data) IDTypeForeachCacheFunctionCallback
void * BKE_libblock_alloc(Main *bmain, short type, const char *name, int flag) ATTR_WARN_UNUSED_RESULT
void BKE_id_blend_write(BlendWriter *writer, ID *id)
LibraryForeachIDFlag BKE_lib_query_foreachid_process_flags_get(const LibraryForeachIDData *data)
@ 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()
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
void(* SoundJackSyncCallback)(struct Main *bmain, int mode, double time)
#define BLI_assert_msg(a, msg)
void BLI_kdtree_nd_ free(KDTree *tree)
#define LISTBASE_FOREACH(type, var, list)
MINLINE int max_ii(int a, int b)
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
char * STRNCPY(char(&dst)[N], const char *src)
#define BLI_string_join(...)
pthread_spinlock_t SpinLock
void BLI_spin_init(SpinLock *spin)
void BLI_spin_unlock(SpinLock *spin)
void BLI_spin_lock(SpinLock *spin)
void BLI_spin_end(SpinLock *spin)
#define UNUSED_VARS_NDEBUG(...)
bool BLO_read_data_is_undo(BlendDataReader *reader)
#define BLO_write_id_struct(writer, struct_name, id_address, id)
bool BLO_write_is_undo(BlendWriter *writer)
#define BLT_I18NCONTEXT_ID_SOUND
#define CLOG_INFO(clg_ref, level,...)
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_TAG_COPIED_ON_EVAL_FINAL_RESULT
Object is a sort of wrapper for general info.
@ SOUND_TAGS_WAVEFORM_LOADING
@ SOUND_TAGS_WAVEFORM_NO_RELOAD
Read Guarded memory(de)allocation.
void BKE_sound_jack_sync_callback_set(SoundJackSyncCallback callback)
void BKE_sound_refresh_callback_bmain(Main *)
void BKE_sound_ensure_scene(Scene *scene)
BLI_INLINE void sound_verify_evaluated_id(const ID *id)
double BKE_sound_sync_scene(Scene *)
void * BKE_sound_add_scene_sound_defaults(Scene *, Strip *)
void BKE_sound_destroy_scene(Scene *)
char ** BKE_sound_get_device_names()
void BKE_sound_init(Main *)
static void sound_free_audio(bSound *sound)
void BKE_sound_load(Main *, bSound *)
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_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_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_move_scene_sound_defaults(Scene *, Strip *)
void * BKE_sound_scene_add_scene_sound_defaults(Scene *, Strip *)
void BKE_sound_remove_scene_sound(Scene *, void *)
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 *)
void * BKE_sound_scene_add_scene_sound(Scene *, Strip *, int, int, int)
bool BKE_sound_info_get(Main *, bSound *, SoundInfo *)
static void sound_foreach_id(ID *id, LibraryForeachIDData *data)
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_add_scene_sound(Scene *, Strip *, int, int, int)
void BKE_sound_set_scene_sound_pitch_at_frame(void *, int, float, char)
void BKE_sound_create_scene(Scene *)
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_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)
BMesh const char void * data
BPy_StructRNA * depsgraph
#define pf(_x, _i)
Prefetch 64.
float length(VecOp< float, D >) RET
static GPUSelectNextState g_state
#define ID_BLEND_PATH(_bmain, _id)
#define ID_IS_OVERRIDE_LIBRARY(_id)
void * MEM_mallocN(size_t len, const char *str)
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
void MEM_freeN(void *vmemh)
int time_right_handle_frame_get(const Scene *scene, const Strip *strip)
void sound_update_length(Main *bmain, Scene *scene)
int time_left_handle_frame_get(const Scene *, const Strip *strip)
void sound_update(Scene *scene, bSound *sound)
VecBase< float, 3 > float3
unsigned int id_session_uid
void * sound_scrub_handle
struct SoundInfo::@044326216360345075252245153320322143020002364111 specs
struct PackedFile * packedfile
struct PackedFile * newpackedfile
static void sound_jack_sync_callback(Main *bmain, int mode, double time)