mirror of
https://github.com/game-stop/veejay.git
synced 2026-06-16 04:31:23 +02:00
revise audio sync, audio beat, add break beat mode, improve auto fx / freeze mode, add/revise sync modes #399, udpate core components to faciliate new functionality
This commit is contained in:
@@ -477,8 +477,7 @@ static inline double vj_runtime_tempo_follow_correction(video_playback_setup *se
|
||||
return 1.0;
|
||||
|
||||
mode = atomic_load_int(&settings->audio_sync.mode);
|
||||
if(mode != VJ_AUDIO_SYNC_MODE_TEMPO_FOLLOW &&
|
||||
mode != VJ_AUDIO_SYNC_MODE_TEMPO_BRIDGE)
|
||||
if(mode != VJ_AUDIO_SYNC_MODE_TEMPO_FOLLOW)
|
||||
return 1.0;
|
||||
|
||||
if(!vj_audio_sync_is_enabled(&settings->audio_sync))
|
||||
@@ -510,13 +509,15 @@ static inline double vj_runtime_tempo_follow_correction(video_playback_setup *se
|
||||
return correction;
|
||||
}
|
||||
#endif
|
||||
static inline double vj_runtime_target_time_s(video_playback_setup *settings, long long frame)
|
||||
static inline double vj_runtime_effective_spvf(video_playback_setup *settings)
|
||||
{
|
||||
double epoch_s = atomic_load_double(&settings->fps_epoch_s);
|
||||
long long epoch_frame = atomic_load_long_long(&settings->fps_epoch_frame);
|
||||
double spvf = settings->spvf;
|
||||
double spvf;
|
||||
|
||||
if (spvf <= 0.0)
|
||||
if(!settings)
|
||||
return 1.0 / 25.0;
|
||||
|
||||
spvf = settings->spvf;
|
||||
if(spvf <= 0.0)
|
||||
spvf = 1.0 / 25.0;
|
||||
|
||||
#ifdef HAVE_JACK
|
||||
@@ -527,6 +528,18 @@ static inline double vj_runtime_target_time_s(video_playback_setup *settings, lo
|
||||
}
|
||||
#endif
|
||||
|
||||
if(spvf <= 0.0)
|
||||
spvf = 1.0 / 25.0;
|
||||
|
||||
return spvf;
|
||||
}
|
||||
|
||||
static inline double vj_runtime_target_time_s(video_playback_setup *settings, long long frame)
|
||||
{
|
||||
double epoch_s = atomic_load_double(&settings->fps_epoch_s);
|
||||
long long epoch_frame = atomic_load_long_long(&settings->fps_epoch_frame);
|
||||
double spvf = vj_runtime_effective_spvf(settings);
|
||||
|
||||
if (epoch_s <= 0.0) {
|
||||
double anchor = atomic_load_double(&settings->audio_start_offset);
|
||||
epoch_s = (anchor > 0.0) ? anchor : monotonic_now_s();
|
||||
@@ -561,19 +574,10 @@ static void vj_runtime_reanchor_clock(veejay_t *info,
|
||||
master_frame = atomic_load_long_long(&settings->master_frame_num);
|
||||
master_s = vj_runtime_master_clock_now_s(info, &using_audio_clock);
|
||||
|
||||
anchor_frame = requested_frame;
|
||||
if(using_audio_clock && master_frame >= 0)
|
||||
anchor_frame = master_frame;
|
||||
anchor_frame = (master_frame >= 0) ? master_frame : requested_frame;
|
||||
|
||||
atomic_store_double(&settings->fps_epoch_s, master_s);
|
||||
atomic_store_long_long(&settings->fps_epoch_frame, anchor_frame);
|
||||
|
||||
veejay_msg(VEEJAY_MSG_DEBUG,
|
||||
"[CLOCK] transport clock re-anchored at frame %lld requested=%lld reason=%s domain=%s",
|
||||
anchor_frame,
|
||||
requested_frame,
|
||||
reason ? reason : "transport-discontinuity",
|
||||
using_audio_clock ? "jack-audio" : "monotonic");
|
||||
}
|
||||
|
||||
static void vj_runtime_update_frame_fps(veejay_t *info, float fps)
|
||||
@@ -1612,6 +1616,32 @@ static inline void safe_join(pthread_t *t, const char *name)
|
||||
}
|
||||
}
|
||||
|
||||
static void veejay_wake_playback_waiters(veejay_t *info)
|
||||
{
|
||||
if (!info || !info->settings)
|
||||
return;
|
||||
|
||||
video_playback_setup *settings = (video_playback_setup*) info->settings;
|
||||
|
||||
atomic_store_int(&settings->first_audio_frame_ready, 1);
|
||||
atomic_store_int(&info->audio_running, 0);
|
||||
|
||||
#ifdef HAVE_JACK
|
||||
vj_audio_beat_request_stop(&settings->audio_beat);
|
||||
vj_audio_sync_request_stop(&settings->audio_sync);
|
||||
#endif
|
||||
|
||||
pthread_mutex_lock(&settings->mutex);
|
||||
pthread_cond_broadcast(&settings->producer_wait_cv);
|
||||
pthread_cond_broadcast(&settings->renderer_wait_cv);
|
||||
pthread_cond_broadcast(&settings->data_ready_cv);
|
||||
pthread_mutex_unlock(&settings->mutex);
|
||||
|
||||
pthread_mutex_lock(&settings->start_mutex);
|
||||
pthread_cond_broadcast(&settings->start_cond);
|
||||
pthread_mutex_unlock(&settings->start_mutex);
|
||||
}
|
||||
|
||||
void veejay_busy(veejay_t * info)
|
||||
{
|
||||
if (!info || !info->settings) {
|
||||
@@ -1621,10 +1651,8 @@ void veejay_busy(veejay_t * info)
|
||||
video_playback_setup *settings = (video_playback_setup*)(info->settings);
|
||||
|
||||
veejay_msg(VEEJAY_MSG_DEBUG, "Waiting for threads to finish...");
|
||||
#ifdef HAVE_JACK
|
||||
vj_audio_beat_request_stop(&settings->audio_beat);
|
||||
vj_audio_sync_request_stop(&settings->audio_sync);
|
||||
#endif
|
||||
veejay_change_state(info, LAVPLAY_STATE_STOP);
|
||||
veejay_wake_playback_waiters(info);
|
||||
|
||||
safe_join(&settings->renderer_thread, "Renderer");
|
||||
safe_join(&settings->producer_thread, "Producer");
|
||||
@@ -1639,7 +1667,8 @@ void veejay_busy(veejay_t * info)
|
||||
|
||||
void veejay_quit(veejay_t * info)
|
||||
{
|
||||
veejay_change_state(info, LAVPLAY_STATE_STOP);
|
||||
veejay_change_state(info, LAVPLAY_STATE_STOP);
|
||||
veejay_wake_playback_waiters(info);
|
||||
}
|
||||
|
||||
|
||||
@@ -1867,8 +1896,6 @@ void veejay_set_framerate( veejay_t *info , float fps )
|
||||
vj_audio_sync_set_track_align_video_fps(&settings->audio_sync,
|
||||
veejay_track_align_media_fps(info));
|
||||
#endif
|
||||
|
||||
veejay_msg(VEEJAY_MSG_INFO, "Playback engine is now playing at %.2f FPS", fps);
|
||||
}
|
||||
|
||||
|
||||
@@ -2397,6 +2424,22 @@ void veejay_stop_sampling(veejay_t * info)
|
||||
info->current_edit_list = info->edit_list;
|
||||
}
|
||||
|
||||
static int veejay_cond_wait_stop_poll(video_playback_setup *settings, pthread_cond_t *cv)
|
||||
{
|
||||
struct timespec ts;
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
ts.tv_nsec += 50000000L;
|
||||
if (ts.tv_nsec >= 1000000000L) {
|
||||
ts.tv_nsec -= 1000000000L;
|
||||
ts.tv_sec++;
|
||||
}
|
||||
|
||||
pthread_cond_timedwait(cv, &settings->mutex, &ts);
|
||||
|
||||
return atomic_load_int(&settings->state) == LAVPLAY_STATE_STOP;
|
||||
}
|
||||
|
||||
VJFrame *veejay_video_queue_reserve_buffer(veejay_t *info)
|
||||
{
|
||||
video_playback_setup *settings = info->settings;
|
||||
@@ -2416,7 +2459,10 @@ VJFrame *veejay_video_queue_reserve_buffer(veejay_t *info)
|
||||
pthread_mutex_unlock(&settings->mutex);
|
||||
return NULL;
|
||||
}
|
||||
pthread_cond_wait(&settings->producer_wait_cv, &settings->mutex);
|
||||
if (veejay_cond_wait_stop_poll(settings, &settings->producer_wait_cv)) {
|
||||
pthread_mutex_unlock(&settings->mutex);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
settings->states[idx] = BUFFER_RESERVED;
|
||||
@@ -2458,8 +2504,10 @@ VJFrame *veejay_video_queue_get_frame(veejay_t *info)
|
||||
pthread_mutex_unlock(&settings->mutex);
|
||||
return NULL;
|
||||
}
|
||||
// wait is here
|
||||
pthread_cond_wait(&settings->renderer_wait_cv, &settings->mutex);
|
||||
if (veejay_cond_wait_stop_poll(settings, &settings->renderer_wait_cv)) {
|
||||
pthread_mutex_unlock(&settings->mutex);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
settings->states[idx] = BUFFER_IN_RENDER;
|
||||
@@ -2673,7 +2721,13 @@ static char *veejay_pipe_append_audio_beat_status(veejay_t *info, char *ptr)
|
||||
ptr = vj_sprintf(ptr, ok ? AB_POS(snap.sample_rate) : 0); /* 53 */
|
||||
ptr = vj_sprintf(ptr, ok ? AB_POS(snap.hit_seq) : 0); /* 54 */
|
||||
ptr = vj_sprintf(ptr, audio_mute); /* 55 */
|
||||
ptr = vj_sprintf(ptr, record_audio_source);
|
||||
ptr = vj_sprintf(ptr, record_audio_source); /* 56 */
|
||||
{
|
||||
int action = ok ? vj_audio_beat_get_action(&info->settings->audio_beat) : 0;
|
||||
if(action < 0 || action > 4)
|
||||
action = 0;
|
||||
ptr = vj_sprintf(ptr, action); /* 57 */
|
||||
}
|
||||
#undef AB_POS
|
||||
#undef AB_AGE
|
||||
#undef AB_BPM10
|
||||
@@ -2697,7 +2751,8 @@ static char *veejay_pipe_append_audio_beat_status(veejay_t *info, char *ptr)
|
||||
ptr = vj_sprintf(ptr, 0); /* 53 sample_rate */
|
||||
ptr = vj_sprintf(ptr, 0); /* 54 hit_seq */
|
||||
ptr = vj_sprintf(ptr, 1); /* 55 muted */
|
||||
ptr = vj_sprintf(ptr, record_audio_source);
|
||||
ptr = vj_sprintf(ptr, record_audio_source); /* 56 */
|
||||
ptr = vj_sprintf(ptr, 0); /* 57 action */
|
||||
#endif
|
||||
|
||||
return ptr;
|
||||
@@ -2727,32 +2782,31 @@ static char *veejay_pipe_append_audio_sync_status(veejay_t *info, char *ptr)
|
||||
#define AS_CORR100(v_) \
|
||||
((int)((((v_) < 0.0) ? 0.0 : (((v_) > 9.999) ? 9.999 : (v_))) * 100.0) + 0.5)
|
||||
|
||||
ptr = vj_sprintf(ptr, ok ? snap.enabled : 0); /* 57 */
|
||||
ptr = vj_sprintf(ptr, ok ? snap.open : 0); /* 58 */
|
||||
ptr = vj_sprintf(ptr, ok ? snap.running : 0); /* 59 */
|
||||
ptr = vj_sprintf(ptr, ok ? snap.mode : 0); /* 60 */
|
||||
ptr = vj_sprintf(ptr, ok ? snap.source : 0); /* 61 */
|
||||
ptr = vj_sprintf(ptr, ok ? AS_POS(snap.channels) : 0); /* 62 */
|
||||
ptr = vj_sprintf(ptr, ok ? AS_POS(snap.sample_rate) : 0); /* 63 */
|
||||
ptr = vj_sprintf(ptr, ok ? AS_PCT(snap.level) : 0); /* 64 */
|
||||
ptr = vj_sprintf(ptr, ok ? AS_PCT(snap.transient) : 0); /* 65 */
|
||||
ptr = vj_sprintf(ptr, ok ? AS_BPM10(snap.bpm) : 0); /* 66 */
|
||||
ptr = vj_sprintf(ptr, ok ? AS_PCT(snap.beat_phase) : 0); /* 67 */
|
||||
ptr = vj_sprintf(ptr, ok ? AS_PCT(snap.confidence) : 0); /* 68 */
|
||||
ptr = vj_sprintf(ptr, ok ? (((snap.mode == VJ_AUDIO_SYNC_MODE_TEMPO_BRIDGE ||
|
||||
snap.mode == VJ_AUDIO_SYNC_MODE_MONITOR) && snap.open) ? 1 : 0) : 0); /* 69 external playback active */
|
||||
ptr = vj_sprintf(ptr, ok ? AS_RATIO1000(snap.bridge_ratio) : 1000); /* 70 */
|
||||
ptr = vj_sprintf(ptr, ok ? AS_CORR100(snap.bridge_correction) : 100); /* 71 */
|
||||
ptr = vj_sprintf(ptr, ok ? snap.target_mode : 0); /* 72 */
|
||||
ptr = vj_sprintf(ptr, ok ? AS_BPM10(snap.target_bpm) : 0); /* 73 */
|
||||
ptr = vj_sprintf(ptr, ok ? AS_PCT(snap.target_confidence) : 0); /* 74 */
|
||||
ptr = vj_sprintf(ptr, ok ? AS_POS(snap.max_correction_pct) : 0); /* 75 */
|
||||
ptr = vj_sprintf(ptr, ok ? AS_POS(snap.bridge_state) : 0); /* 76 */
|
||||
ptr = vj_sprintf(ptr, ok ? AS_POS(snap.track_align_locked) : 0); /* 77 */
|
||||
ptr = vj_sprintf(ptr, ok ? snap.track_align_offset_ms : 0); /* 78 */
|
||||
ptr = vj_sprintf(ptr, ok ? AS_POS(snap.track_align_confidence_pct) : 0); /* 79 */
|
||||
ptr = vj_sprintf(ptr, ok ? snap.track_align_correction_ppm : 0); /* 80 */
|
||||
ptr = vj_sprintf(ptr, ok ? AS_POS(snap.track_align_state) : 0); /* 81 */
|
||||
ptr = vj_sprintf(ptr, ok ? snap.enabled : 0); /* 58 */
|
||||
ptr = vj_sprintf(ptr, ok ? snap.open : 0); /* 59 */
|
||||
ptr = vj_sprintf(ptr, ok ? snap.running : 0); /* 60 */
|
||||
ptr = vj_sprintf(ptr, ok ? snap.mode : 0); /* 61 */
|
||||
ptr = vj_sprintf(ptr, ok ? snap.source : 0); /* 62 */
|
||||
ptr = vj_sprintf(ptr, ok ? AS_POS(snap.channels) : 0); /* 63 */
|
||||
ptr = vj_sprintf(ptr, ok ? AS_POS(snap.sample_rate) : 0); /* 64 */
|
||||
ptr = vj_sprintf(ptr, ok ? AS_PCT(snap.level) : 0); /* 65 */
|
||||
ptr = vj_sprintf(ptr, ok ? AS_PCT(snap.transient) : 0); /* 66 */
|
||||
ptr = vj_sprintf(ptr, ok ? AS_BPM10(snap.bpm) : 0); /* 67 */
|
||||
ptr = vj_sprintf(ptr, ok ? AS_PCT(snap.beat_phase) : 0); /* 68 */
|
||||
ptr = vj_sprintf(ptr, ok ? AS_PCT(snap.confidence) : 0); /* 69 */
|
||||
ptr = vj_sprintf(ptr, ok ? ((snap.mode != VJ_AUDIO_SYNC_MODE_TEMPO_FOLLOW && vj_audio_sync_mode_uses_external_playback(snap.mode) && snap.open) ? 1 : 0) : 0); /* 70 external playback active */
|
||||
ptr = vj_sprintf(ptr, ok ? AS_RATIO1000(snap.bridge_ratio) : 1000); /* 71 */
|
||||
ptr = vj_sprintf(ptr, ok ? AS_CORR100(snap.bridge_correction) : 100); /* 72 */
|
||||
ptr = vj_sprintf(ptr, ok ? snap.target_mode : 0); /* 73 */
|
||||
ptr = vj_sprintf(ptr, ok ? AS_BPM10(snap.target_bpm) : 0); /* 74 */
|
||||
ptr = vj_sprintf(ptr, ok ? AS_PCT(snap.target_confidence) : 0); /* 75 */
|
||||
ptr = vj_sprintf(ptr, ok ? AS_POS(snap.max_correction_pct) : 0); /* 76 */
|
||||
ptr = vj_sprintf(ptr, ok ? AS_POS(snap.bridge_state) : 0); /* 77 */
|
||||
ptr = vj_sprintf(ptr, ok ? AS_POS(snap.track_align_locked) : 0); /* 78 */
|
||||
ptr = vj_sprintf(ptr, ok ? snap.track_align_offset_ms : 0); /* 79 */
|
||||
ptr = vj_sprintf(ptr, ok ? AS_POS(snap.track_align_confidence_pct) : 0); /* 80 */
|
||||
ptr = vj_sprintf(ptr, ok ? snap.track_align_correction_ppm : 0); /* 81 */
|
||||
ptr = vj_sprintf(ptr, ok ? AS_POS(snap.track_align_state) : 0); /* 82 */
|
||||
|
||||
#undef AS_CORR100
|
||||
#undef AS_RATIO1000
|
||||
@@ -2819,21 +2873,21 @@ static char *veejay_pipe_append_chain_entry_status(veejay_t *info, char *ptr)
|
||||
else if(num_params > VJ_STATUS_CHAIN_ENTRY_PARAMETERS)
|
||||
num_params = VJ_STATUS_CHAIN_ENTRY_PARAMETERS;
|
||||
|
||||
ptr = vj_sprintf(ptr, effect_id); /* 82 */
|
||||
ptr = vj_sprintf(ptr, is_video); /* 83 */
|
||||
ptr = vj_sprintf(ptr, num_params); /* 84 */
|
||||
ptr = vj_sprintf(ptr, entry->kf_type); /* 85 */
|
||||
ptr = vj_sprintf(ptr, entry->kf_status); /* 86 */
|
||||
ptr = vj_sprintf(ptr, 0); /* 87 transition enabled */
|
||||
ptr = vj_sprintf(ptr, 0); /* 88 transition loop */
|
||||
ptr = vj_sprintf(ptr, entry->source_type); /* 89 */
|
||||
ptr = vj_sprintf(ptr, entry->channel); /* 90 */
|
||||
ptr = vj_sprintf(ptr, entry->e_flag); /* 91 */
|
||||
ptr = vj_sprintf(ptr, entry->beat_flag); /* 92 */
|
||||
ptr = vj_sprintf(ptr, entry->is_rendering); /* 93 */
|
||||
ptr = vj_sprintf(ptr, effect_id); /* 83 */
|
||||
ptr = vj_sprintf(ptr, is_video); /* 84 */
|
||||
ptr = vj_sprintf(ptr, num_params); /* 85 */
|
||||
ptr = vj_sprintf(ptr, entry->kf_type); /* 86 */
|
||||
ptr = vj_sprintf(ptr, entry->kf_status); /* 87 */
|
||||
ptr = vj_sprintf(ptr, 0); /* 88 transition enabled */
|
||||
ptr = vj_sprintf(ptr, 0); /* 89 transition loop */
|
||||
ptr = vj_sprintf(ptr, entry->source_type); /* 90 */
|
||||
ptr = vj_sprintf(ptr, entry->channel); /* 91 */
|
||||
ptr = vj_sprintf(ptr, entry->e_flag); /* 92 */
|
||||
ptr = vj_sprintf(ptr, entry->beat_flag); /* 93 */
|
||||
ptr = vj_sprintf(ptr, entry->is_rendering); /* 94 */
|
||||
|
||||
for(int i = 0; i < VJ_STATUS_CHAIN_ENTRY_PARAMETERS; i++)
|
||||
ptr = vj_sprintf(ptr, (i < num_params) ? entry->arg[i] : 0); /* 94..109 */
|
||||
ptr = vj_sprintf(ptr, (i < num_params) ? entry->arg[i] : 0); /* 95..110 */
|
||||
|
||||
return ptr;
|
||||
}
|
||||
@@ -2992,8 +3046,8 @@ static void veejay_pipe_write_status(veejay_t * info)
|
||||
{
|
||||
if(!status_packet_warned) {
|
||||
veejay_msg(VEEJAY_MSG_WARNING,
|
||||
"Status packet base mismatch: got %d fields, expected %d; padding fixed 110-token packet",
|
||||
base_tokens, VJ_STATUS_BASE_TOKENS);
|
||||
"Status packet base mismatch: got %d fields, expected %d; padding fixed %d-token packet",
|
||||
base_tokens, VJ_STATUS_BASE_TOKENS, VIMS_STATUS_TOKENS);
|
||||
status_packet_warned = 1;
|
||||
}
|
||||
|
||||
@@ -3200,6 +3254,10 @@ void veejay_handle_signal(int sig, siginfo_t *si, void *unused)
|
||||
case SIGINT:
|
||||
case SIGQUIT:
|
||||
veejay_change_state(info, LAVPLAY_STATE_STOP);
|
||||
if (info && info->settings) {
|
||||
atomic_store_int(&info->audio_running, 0);
|
||||
atomic_store_int(&info->settings->first_audio_frame_ready, 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case SIGSEGV:
|
||||
@@ -3614,7 +3672,7 @@ void *veejay_display_renderer_thread(void *arg)
|
||||
}
|
||||
|
||||
double audio_master = atomic_load_double(&settings->audio_master_s);
|
||||
double spvf = settings->spvf;
|
||||
double spvf = vj_runtime_effective_spvf(settings);
|
||||
double target_time_s = vj_runtime_target_time_s(settings, frame->frame_num);
|
||||
double delay_s = target_time_s - audio_master;
|
||||
|
||||
@@ -3723,11 +3781,14 @@ int veejay_open(veejay_t * info)
|
||||
int i;
|
||||
|
||||
pthread_mutex_init(&(settings->control_mutex), NULL);
|
||||
|
||||
pthread_mutex_init(&(settings->start_mutex), NULL);
|
||||
|
||||
pthread_mutex_init(&settings->mutex, NULL);
|
||||
pthread_cond_init(&settings->producer_wait_cv, NULL);
|
||||
pthread_cond_init(&settings->producer_wait_cv, &attr);
|
||||
pthread_cond_init(&settings->renderer_wait_cv, &attr);
|
||||
pthread_cond_init(&settings->data_ready_cv, &attr);
|
||||
pthread_cond_init(&settings->data_ready_cv, &attr);
|
||||
pthread_cond_init(&settings->start_cond, &attr);
|
||||
pthread_condattr_destroy(&attr);
|
||||
|
||||
settings->producer_index = 0;
|
||||
settings->renderer_index = 0;
|
||||
@@ -3804,15 +3865,7 @@ int veejay_close(veejay_t *info)
|
||||
int success = 1;
|
||||
|
||||
veejay_change_state_save(info, LAVPLAY_STATE_STOP);
|
||||
#ifdef HAVE_JACK
|
||||
vj_audio_beat_request_stop(&settings->audio_beat);
|
||||
vj_audio_sync_request_stop(&settings->audio_sync);
|
||||
#endif
|
||||
|
||||
pthread_mutex_lock(&settings->mutex);
|
||||
pthread_cond_broadcast(&settings->producer_wait_cv);
|
||||
pthread_cond_broadcast(&settings->renderer_wait_cv);
|
||||
pthread_mutex_unlock(&settings->mutex);
|
||||
veejay_wake_playback_waiters(info);
|
||||
|
||||
safe_join(&settings->renderer_thread, "Renderer");
|
||||
safe_join(&settings->producer_thread, "Producer");
|
||||
@@ -3824,8 +3877,12 @@ int veejay_close(veejay_t *info)
|
||||
#endif
|
||||
|
||||
pthread_mutex_destroy(&settings->mutex);
|
||||
pthread_mutex_destroy(&settings->control_mutex);
|
||||
pthread_mutex_destroy(&settings->start_mutex);
|
||||
pthread_cond_destroy(&settings->producer_wait_cv);
|
||||
pthread_cond_destroy(&settings->renderer_wait_cv);
|
||||
pthread_cond_destroy(&settings->data_ready_cv);
|
||||
pthread_cond_destroy(&settings->start_cond);
|
||||
|
||||
for (int i = 0; i < VIDEO_QUEUE_LEN; i++)
|
||||
if (settings->buffers[i]) veejay_free_frame_buffer(settings->buffers[i]);
|
||||
@@ -4746,7 +4803,7 @@ static inline double vj_audio_producer_pace_sleep_s(long client_rate,
|
||||
settings,
|
||||
budget);
|
||||
}
|
||||
static inline int vj_audio_is_external_jack_monitor_source(
|
||||
static inline int vj_audio_uses_external_audio_playback_source(
|
||||
video_playback_setup *settings,
|
||||
int audio_source,
|
||||
int sync_mode,
|
||||
@@ -4757,9 +4814,10 @@ static inline int vj_audio_is_external_jack_monitor_source(
|
||||
if(!settings || !sync_enabled)
|
||||
return 0;
|
||||
|
||||
if(sync_mode != VJ_AUDIO_SYNC_MODE_MONITOR &&
|
||||
sync_mode != VJ_AUDIO_SYNC_MODE_TEMPO_BRIDGE &&
|
||||
sync_mode != VJ_AUDIO_SYNC_MODE_TRACK_ALIGN)
|
||||
if(sync_mode == VJ_AUDIO_SYNC_MODE_TEMPO_FOLLOW)
|
||||
return 0;
|
||||
|
||||
if(!vj_audio_sync_mode_uses_external_playback(sync_mode))
|
||||
return 0;
|
||||
|
||||
source = atomic_load_int(&settings->audio_sync.source);
|
||||
@@ -4798,7 +4856,7 @@ static int vj_tempo_bridge_reverse_should_reanchor(
|
||||
if(!vj_audio_sync_is_enabled(&settings->audio_sync))
|
||||
return 0;
|
||||
|
||||
if(!vj_audio_is_external_jack_monitor_source(
|
||||
if(!vj_audio_uses_external_audio_playback_source(
|
||||
settings,
|
||||
atomic_load_int(&settings->record_audio_source),
|
||||
sync_mode,
|
||||
@@ -4896,7 +4954,7 @@ static inline int vj_audio_should_pace_direct_jack_monitor(
|
||||
if(!settings)
|
||||
return 0;
|
||||
|
||||
external_monitor = vj_audio_is_external_jack_monitor_source(
|
||||
external_monitor = vj_audio_uses_external_audio_playback_source(
|
||||
settings, audio_source, sync_mode, sync_enabled
|
||||
);
|
||||
|
||||
@@ -4907,7 +4965,10 @@ static inline int vj_audio_should_pace_direct_jack_monitor(
|
||||
mute = atomic_load_int(&settings->audio_mute);
|
||||
|
||||
external_tape = external_monitor && !mute &&
|
||||
(sync_mode == VJ_AUDIO_SYNC_MODE_TEMPO_BRIDGE || !neutral);
|
||||
vj_audio_sync_mode_uses_transport_driven_playback(sync_mode) &&
|
||||
(sync_mode == VJ_AUDIO_SYNC_MODE_TEMPO_BRIDGE ||
|
||||
sync_mode == VJ_AUDIO_SYNC_MODE_MONITOR_TRICKPLAY ||
|
||||
!neutral);
|
||||
|
||||
if(external_tape_source)
|
||||
*external_tape_source = external_tape;
|
||||
@@ -5380,7 +5441,7 @@ void *veejay_audio_producer_thread(void *arg)
|
||||
sfd_dbg
|
||||
);
|
||||
int external_monitor_audio =
|
||||
vj_audio_is_external_jack_monitor_source(
|
||||
vj_audio_uses_external_audio_playback_source(
|
||||
settings,
|
||||
audio_source_dbg,
|
||||
audio_sync_mode_dbg,
|
||||
@@ -5388,7 +5449,9 @@ void *veejay_audio_producer_thread(void *arg)
|
||||
);
|
||||
external_tape_source_dbg =
|
||||
external_monitor_audio &&
|
||||
vj_audio_sync_mode_uses_transport_driven_playback(audio_sync_mode_dbg) &&
|
||||
(audio_sync_mode_dbg == VJ_AUDIO_SYNC_MODE_TEMPO_BRIDGE ||
|
||||
audio_sync_mode_dbg == VJ_AUDIO_SYNC_MODE_MONITOR_TRICKPLAY ||
|
||||
!external_tape_neutral_dbg);
|
||||
int external_live_source_dbg =
|
||||
external_monitor_audio && !external_tape_source_dbg;
|
||||
@@ -5883,13 +5946,16 @@ void *veejay_audio_producer_thread(void *arg)
|
||||
|
||||
} else {
|
||||
#endif
|
||||
double spvf = settings->spvf;
|
||||
double spvf = vj_runtime_effective_spvf(settings);
|
||||
const double next_frame_target = vj_runtime_target_time_s(settings, (long long)(loop_count + 1));
|
||||
|
||||
double now = monotonic_now_s();
|
||||
double remaining_s = next_frame_target - now;
|
||||
|
||||
if (remaining_s > 0.0) {
|
||||
if (remaining_s > spvf)
|
||||
remaining_s = spvf;
|
||||
|
||||
usleep_hybrid((long long)(remaining_s * 1e6), settings);
|
||||
}
|
||||
|
||||
@@ -5993,7 +6059,8 @@ static void veejay_producer_thread_audio_startup(veejay_t *info)
|
||||
return;
|
||||
}
|
||||
|
||||
while (!atomic_load_int(&info->audio_running))
|
||||
while (!atomic_load_int(&info->audio_running) &&
|
||||
atomic_load_int(&settings->state) != LAVPLAY_STATE_STOP)
|
||||
usleep_accurate(200,settings);
|
||||
|
||||
}
|
||||
@@ -6060,9 +6127,9 @@ static void veejay_audio_sync_thread_startup(veejay_t *info)
|
||||
|
||||
static int veejay_audio_sync_mode_is_playback(int mode)
|
||||
{
|
||||
return mode == VJ_AUDIO_SYNC_MODE_TEMPO_BRIDGE ||
|
||||
mode == VJ_AUDIO_SYNC_MODE_TRACK_ALIGN ||
|
||||
mode == VJ_AUDIO_SYNC_MODE_MONITOR;
|
||||
if(mode == VJ_AUDIO_SYNC_MODE_TEMPO_FOLLOW)
|
||||
return 0;
|
||||
return vj_audio_sync_mode_uses_external_playback(mode);
|
||||
}
|
||||
|
||||
static int veejay_audio_threads_disabled(video_playback_setup *settings)
|
||||
@@ -6237,7 +6304,8 @@ int veejay_audio_sync_set_mode_control(veejay_t *info, int mode)
|
||||
|
||||
vj_audio_sync_set_mode(&settings->audio_sync, mode);
|
||||
if(mode == VJ_AUDIO_SYNC_MODE_TRACK_ALIGN ||
|
||||
mode == VJ_AUDIO_SYNC_MODE_TEMPO_FOLLOW)
|
||||
mode == VJ_AUDIO_SYNC_MODE_TEMPO_FOLLOW ||
|
||||
mode == VJ_AUDIO_SYNC_MODE_TEMPO_BRIDGE)
|
||||
vj_audio_sync_set_target_mode(&settings->audio_sync,
|
||||
VJ_AUDIO_SYNC_TARGET_CURRENT_CLIP);
|
||||
|
||||
@@ -6430,12 +6498,7 @@ static void veejay_audio_beat_prepare_sync_source(veejay_t *info)
|
||||
current_channels = atomic_load_int(&settings->audio_sync.input_channels_request);
|
||||
record_source = atomic_load_int(&settings->record_audio_source);
|
||||
|
||||
external_mode =
|
||||
(mode == VJ_AUDIO_SYNC_MODE_LIVE_EXTERNAL ||
|
||||
mode == VJ_AUDIO_SYNC_MODE_MONITOR ||
|
||||
mode == VJ_AUDIO_SYNC_MODE_TEMPO_BRIDGE ||
|
||||
mode == VJ_AUDIO_SYNC_MODE_TRACK_ALIGN ||
|
||||
mode == VJ_AUDIO_SYNC_MODE_TEMPO_FOLLOW);
|
||||
external_mode = vj_audio_sync_mode_is_audio_sync_family(mode);
|
||||
|
||||
use_push_source = 0;
|
||||
if(record_source == VJ_RECORD_AUDIO_SOURCE_ORIGINAL)
|
||||
@@ -6737,27 +6800,39 @@ static void *veejay_producer_thread_loop(void *ptr)
|
||||
sigaddset(&mask, SIGPIPE);
|
||||
pthread_sigmask(SIG_BLOCK, &mask, NULL);
|
||||
|
||||
while (atomic_load_int(&settings->warmup_active)) {
|
||||
while (atomic_load_int(&settings->warmup_active) &&
|
||||
atomic_load_int(&settings->state) != LAVPLAY_STATE_STOP) {
|
||||
usleep_accurate(100, settings);
|
||||
}
|
||||
|
||||
if (atomic_load_int(&settings->state) == LAVPLAY_STATE_STOP)
|
||||
pthread_exit(NULL);
|
||||
|
||||
atomic_store_long_long(&settings->current_frame_num, -1);
|
||||
atomic_store_int(&settings->audio_mode, AUDIO_MODE_SILENCE_FILL);
|
||||
|
||||
if(info->audio) {
|
||||
#ifdef HAVE_JACK
|
||||
veejay_msg(VEEJAY_MSG_DEBUG, "[PRODUCER] waiting for audio anchor");
|
||||
while (atomic_load_double(&settings->audio_start_offset) <= 0.0) {
|
||||
while (atomic_load_double(&settings->audio_start_offset) <= 0.0 &&
|
||||
atomic_load_int(&settings->state) != LAVPLAY_STATE_STOP) {
|
||||
usleep_accurate(100, settings);
|
||||
}
|
||||
|
||||
if (atomic_load_int(&settings->state) == LAVPLAY_STATE_STOP)
|
||||
pthread_exit(NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
veejay_msg(VEEJAY_MSG_DEBUG, "[PRODUCER] waiting for first audio frame ready");
|
||||
while (atomic_load_int(&settings->first_audio_frame_ready) == 0) {
|
||||
while (atomic_load_int(&settings->first_audio_frame_ready) == 0 &&
|
||||
atomic_load_int(&settings->state) != LAVPLAY_STATE_STOP) {
|
||||
usleep_accurate(100, settings);
|
||||
}
|
||||
|
||||
if (atomic_load_int(&settings->state) == LAVPLAY_STATE_STOP)
|
||||
pthread_exit(NULL);
|
||||
|
||||
veejay_msg(VEEJAY_MSG_DEBUG, "[PRODUCER] Wait for playback to reach anchor");
|
||||
|
||||
veejay_set_speed(info, 1, 0);
|
||||
@@ -6790,7 +6865,8 @@ static void *veejay_producer_thread_loop(void *ptr)
|
||||
int beat_action = vj_audio_beat_get_action(&settings->audio_beat);
|
||||
|
||||
if(beat_action == VJ_AUDIO_BEAT_ACTION_FREEZE ||
|
||||
beat_action == VJ_AUDIO_BEAT_ACTION_FREEZE_AND_AUTO_FX)
|
||||
beat_action == VJ_AUDIO_BEAT_ACTION_FREEZE_AND_AUTO_FX ||
|
||||
beat_action == VJ_AUDIO_BEAT_ACTION_BREAK_BEAT)
|
||||
{
|
||||
vj_audio_beat_consume(info, &settings->audio_beat);
|
||||
}
|
||||
@@ -7377,10 +7453,14 @@ int veejay_main(veejay_t *info)
|
||||
veejay_producer_thread_audio_startup(info);
|
||||
|
||||
|
||||
while (atomic_load_int(&settings->first_audio_frame_ready) == 0) {
|
||||
while (atomic_load_int(&settings->first_audio_frame_ready) == 0 &&
|
||||
atomic_load_int(&settings->state) != LAVPLAY_STATE_STOP) {
|
||||
usleep_accurate(5000, settings);
|
||||
}
|
||||
|
||||
if (atomic_load_int(&settings->state) == LAVPLAY_STATE_STOP)
|
||||
return 0;
|
||||
|
||||
Welcome(info);
|
||||
|
||||
return 1;
|
||||
@@ -7985,10 +8065,18 @@ int veejay_audio_sync_set_external_wav(veejay_t *info, const char *path, int loo
|
||||
mode > VJ_AUDIO_SYNC_MODE_MAX)
|
||||
{
|
||||
veejay_msg(VEEJAY_MSG_WARNING,
|
||||
"[AUDIO-SYNC][WAV] invalid mode=%d, forcing external-analysis(%d)",
|
||||
"[AUDIO-SYNC][WAV] invalid mode=%d, forcing clean monitor(%d)",
|
||||
mode,
|
||||
VJ_AUDIO_SYNC_MODE_LIVE_EXTERNAL);
|
||||
mode = VJ_AUDIO_SYNC_MODE_LIVE_EXTERNAL;
|
||||
VJ_AUDIO_SYNC_MODE_MONITOR);
|
||||
mode = VJ_AUDIO_SYNC_MODE_MONITOR;
|
||||
}
|
||||
|
||||
if(!vj_audio_sync_mode_supports_wav_master(mode)) {
|
||||
veejay_msg(VEEJAY_MSG_WARNING,
|
||||
"[AUDIO-SYNC][WAV] mode=%d does not support a WAV master, forcing clean monitor(%d)",
|
||||
mode,
|
||||
VJ_AUDIO_SYNC_MODE_MONITOR);
|
||||
mode = VJ_AUDIO_SYNC_MODE_MONITOR;
|
||||
}
|
||||
|
||||
loop = loop ? 1 : 0;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -24,21 +24,18 @@
|
||||
|
||||
#ifdef HAVE_JACK
|
||||
|
||||
/* Keep this public header independent from vj-lib.h and vj-audio-sync.h.
|
||||
* Only pointer types are used here, so forward declarations are enough.
|
||||
* The complete vj_audio_beat_shared_t and veejay_t definitions live in
|
||||
* vj-lib.h; vj_audio_sync_shared_t lives in vj-audio-sync.h.
|
||||
*/
|
||||
typedef struct vj_audio_beat_shared_t vj_audio_beat_shared_t;
|
||||
typedef struct vj_audio_sync_shared_t vj_audio_sync_shared_t;
|
||||
typedef struct veejay_t veejay_t;
|
||||
typedef struct sample_eff_t sample_eff_chain;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
VJ_AUDIO_BEAT_ACTION_NONE = 0,
|
||||
VJ_AUDIO_BEAT_ACTION_FREEZE = 1,
|
||||
VJ_AUDIO_BEAT_ACTION_AUTO_FX = 2,
|
||||
VJ_AUDIO_BEAT_ACTION_FREEZE_AND_AUTO_FX = 3
|
||||
VJ_AUDIO_BEAT_ACTION_FREEZE_AND_AUTO_FX = 3,
|
||||
VJ_AUDIO_BEAT_ACTION_BREAK_BEAT = 4
|
||||
} vj_audio_beat_action_t;
|
||||
|
||||
typedef enum
|
||||
@@ -131,6 +128,7 @@ typedef struct
|
||||
typedef int (*vj_audio_beat_get_fx_id_func)(void *ctx, int chain_pos);
|
||||
typedef int (*vj_audio_beat_get_fx_arg_func)(void *ctx, int chain_pos, int param_nr);
|
||||
typedef int (*vj_audio_beat_set_fx_arg_func)(void *ctx, int chain_pos, int param_nr, int value);
|
||||
typedef sample_eff_chain *(*vj_audio_beat_get_fx_entry_func)(void *ctx, int chain_pos);
|
||||
|
||||
void vj_audio_beat_init(vj_audio_beat_shared_t *s, int input_channels);
|
||||
void vj_audio_beat_bind_sync(vj_audio_beat_shared_t *s, vj_audio_sync_shared_t *sync);
|
||||
@@ -147,6 +145,9 @@ int vj_audio_beat_is_enabled(vj_audio_beat_shared_t *s);
|
||||
int vj_audio_beat_is_running(vj_audio_beat_shared_t *s);
|
||||
int vj_audio_beat_is_open(vj_audio_beat_shared_t *s);
|
||||
int vj_audio_beat_is_paused_by_beat(vj_audio_beat_shared_t *s);
|
||||
int vj_audio_beat_transport_is_internal(vj_audio_beat_shared_t *s);
|
||||
void vj_audio_beat_user_transport_override(veejay_t *v, vj_audio_beat_shared_t *s,
|
||||
int requested_speed);
|
||||
|
||||
void vj_audio_beat_set_freeze_ms(vj_audio_beat_shared_t *s, int ms);
|
||||
void vj_audio_beat_set_cooldown_ms(vj_audio_beat_shared_t *s, int ms);
|
||||
@@ -170,6 +171,23 @@ int vj_audio_beat_auto_apply_chain(
|
||||
vj_audio_beat_get_fx_arg_func get_arg,
|
||||
vj_audio_beat_set_fx_arg_func set_arg
|
||||
);
|
||||
int vj_audio_beat_auto_apply_chain_ex(
|
||||
vj_audio_beat_shared_t *s,
|
||||
void *ctx,
|
||||
int chain_len,
|
||||
vj_audio_beat_get_fx_id_func get_fx_id,
|
||||
vj_audio_beat_get_fx_arg_func get_arg,
|
||||
vj_audio_beat_set_fx_arg_func set_arg,
|
||||
vj_audio_beat_get_fx_entry_func get_entry
|
||||
);
|
||||
int vj_audio_beat_auto_modulate_args(
|
||||
vj_audio_beat_shared_t *s,
|
||||
sample_eff_chain *entry,
|
||||
int effect_id,
|
||||
int *args,
|
||||
int n_params,
|
||||
long long n_frame
|
||||
);
|
||||
|
||||
int vj_audio_beat_copy_record_audio(
|
||||
vj_audio_beat_shared_t *s,
|
||||
@@ -190,6 +208,12 @@ int vj_audio_beat_get_snapshot(vj_audio_beat_shared_t *s, vj_audio_beat_snapshot
|
||||
float vj_audio_beat_get_signal(vj_audio_beat_shared_t *s, int signal);
|
||||
int vj_audio_beat_map_signal(vj_audio_beat_shared_t *s, int signal, int min_value, int max_value, int invert);
|
||||
|
||||
int vj_audio_beat_disable_for_transport(veejay_t *v, vj_audio_beat_shared_t *s);
|
||||
int vj_audio_beat_release_transport(veejay_t *v, vj_audio_beat_shared_t *s);
|
||||
void vj_audio_beat_set_action_for_transport(veejay_t *v,
|
||||
vj_audio_beat_shared_t *s,
|
||||
int action);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -32,19 +32,52 @@
|
||||
|
||||
#define VJ_AUDIO_SYNC_ALIGN_FEATURES 4096
|
||||
|
||||
static inline int vj_audio_sync_mode_is_control_only(int mode)
|
||||
{
|
||||
return mode == VJ_AUDIO_SYNC_MODE_LIVE_EXTERNAL;
|
||||
}
|
||||
|
||||
static inline int vj_audio_sync_mode_is_tempo_follow(int mode)
|
||||
{
|
||||
return mode == VJ_AUDIO_SYNC_MODE_TEMPO_FOLLOW;
|
||||
}
|
||||
|
||||
#define VJ_AUDIO_SYNC_TRACK_STATE_IDLE 0
|
||||
#define VJ_AUDIO_SYNC_TRACK_STATE_WAIT_SOURCE 1
|
||||
#define VJ_AUDIO_SYNC_TRACK_STATE_WAIT_TARGET 2
|
||||
#define VJ_AUDIO_SYNC_TRACK_STATE_SEARCHING 3
|
||||
#define VJ_AUDIO_SYNC_TRACK_STATE_LOCKED 4
|
||||
#define VJ_AUDIO_SYNC_TRACK_STATE_HOLD 5
|
||||
#define VJ_AUDIO_SYNC_TRACK_STATE_FALLBACK 6
|
||||
static inline int vj_audio_sync_mode_is_clean_monitor(int mode)
|
||||
{
|
||||
return mode == VJ_AUDIO_SYNC_MODE_MONITOR;
|
||||
}
|
||||
|
||||
#ifndef VJ_AUDIO_SYNC_MODE_MAX
|
||||
#define VJ_AUDIO_SYNC_MODE_MAX VJ_AUDIO_SYNC_MODE_TEMPO_FOLLOW
|
||||
#endif
|
||||
static inline int vj_audio_sync_mode_is_trickplay_monitor(int mode)
|
||||
{
|
||||
return mode == VJ_AUDIO_SYNC_MODE_MONITOR_TRICKPLAY;
|
||||
}
|
||||
|
||||
static inline int vj_audio_sync_mode_uses_external_playback(int mode)
|
||||
{
|
||||
return mode == VJ_AUDIO_SYNC_MODE_MONITOR ||
|
||||
mode == VJ_AUDIO_SYNC_MODE_MONITOR_TRICKPLAY ||
|
||||
mode == VJ_AUDIO_SYNC_MODE_TEMPO_BRIDGE ||
|
||||
mode == VJ_AUDIO_SYNC_MODE_TRACK_ALIGN;
|
||||
}
|
||||
|
||||
static inline int vj_audio_sync_mode_uses_transport_driven_playback(int mode)
|
||||
{
|
||||
return mode == VJ_AUDIO_SYNC_MODE_MONITOR_TRICKPLAY ||
|
||||
mode == VJ_AUDIO_SYNC_MODE_TEMPO_BRIDGE ||
|
||||
mode == VJ_AUDIO_SYNC_MODE_TRACK_ALIGN;
|
||||
}
|
||||
|
||||
static inline int vj_audio_sync_mode_supports_wav_master(int mode)
|
||||
{
|
||||
return vj_audio_sync_mode_uses_external_playback(mode);
|
||||
}
|
||||
|
||||
static inline int vj_audio_sync_mode_is_audio_sync_family(int mode)
|
||||
{
|
||||
return mode == VJ_AUDIO_SYNC_MODE_LIVE_EXTERNAL ||
|
||||
mode == VJ_AUDIO_SYNC_MODE_TEMPO_FOLLOW ||
|
||||
vj_audio_sync_mode_uses_external_playback(mode);
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@@ -97,20 +130,12 @@ typedef struct
|
||||
int track_align_correction_ppm;
|
||||
int track_align_state;
|
||||
|
||||
/* Internal wide-search snap suggestion, consumed by the playback loop.
|
||||
* Not part of the public status token contract.
|
||||
*/
|
||||
int track_align_snap_pending;
|
||||
int track_align_snap_delta_frames;
|
||||
int track_align_snap_confidence_pct;
|
||||
} vj_audio_sync_snapshot_t;
|
||||
|
||||
|
||||
/* Full shared state is intentionally defined here because video_playback_setup
|
||||
* embeds vj_audio_sync_shared_t directly. Do not include vj-lib.h from the
|
||||
* audio synchronizer: modules that only need pointers can forward-declare this
|
||||
* typedef, while vj-lib.h includes this header to get the complete size.
|
||||
*/
|
||||
typedef struct vj_audio_sync_shared_t
|
||||
{
|
||||
volatile int initialized;
|
||||
@@ -186,10 +211,6 @@ typedef struct vj_audio_sync_shared_t
|
||||
long bridge_latch_updated_ms;
|
||||
volatile int bridge_state;
|
||||
|
||||
/* Tempo Bridge transport clock.
|
||||
* Keep BPM estimates latched and slow-moving so the audible read-head
|
||||
* behaves like a stable transport, not like a phase-chasing cassette motor.
|
||||
*/
|
||||
double bridge_source_bpm_latched;
|
||||
double bridge_target_bpm_latched;
|
||||
int bridge_bpm_latch_valid;
|
||||
@@ -201,10 +222,6 @@ typedef struct vj_audio_sync_shared_t
|
||||
int bridge_stretch_segment_len;
|
||||
int bridge_stretch_overlap;
|
||||
|
||||
/* Track Align / waveform sync feature rings.
|
||||
* Source = external master track; target = current clip/original audio.
|
||||
* Features are low-rate onset/envelope values, updated by capture/push paths.
|
||||
*/
|
||||
float align_source_feat[VJ_AUDIO_SYNC_ALIGN_FEATURES];
|
||||
float align_target_feat[VJ_AUDIO_SYNC_ALIGN_FEATURES];
|
||||
int align_source_pos;
|
||||
@@ -227,7 +244,6 @@ typedef struct vj_audio_sync_shared_t
|
||||
int align_snap_cooldown_ms;
|
||||
volatile int align_video_fps_x1000;
|
||||
|
||||
/* Worker-thread live snap consensus state. */
|
||||
int align_live_candidate_delta;
|
||||
int align_live_candidate_conf_min;
|
||||
int align_live_candidate_conf_sum;
|
||||
@@ -236,28 +252,20 @@ typedef struct vj_audio_sync_shared_t
|
||||
long align_live_last_snap_ms;
|
||||
int align_live_last_snap_delta;
|
||||
|
||||
/* Rough, non-authoritative live basin exported to performer wide search. */
|
||||
int align_rough_hint_offset_ms;
|
||||
int align_rough_hint_conf;
|
||||
int align_rough_hint_count;
|
||||
long align_rough_hint_ms;
|
||||
|
||||
/* Current-clip target audio queue. Producer enqueues PCM cheaply;
|
||||
* audio_sync_thread drains it and runs target clock/Track Align analysis.
|
||||
*/
|
||||
|
||||
uint8_t *target_ring;
|
||||
int target_ring_frames;
|
||||
int target_ring_write_frame;
|
||||
long long target_write_frame_abs;
|
||||
|
||||
/* Oldest retained target frame in the ring. This is no longer the
|
||||
* worker consume cursor: Track Align needs retained target history for
|
||||
* stable correlation, while the worker still needs to process each
|
||||
* target block exactly once.
|
||||
*/
|
||||
|
||||
long long target_read_frame_abs;
|
||||
|
||||
/* Next target frame the sync worker must process into clock/features. */
|
||||
long long target_process_frame_abs;
|
||||
|
||||
int target_channels;
|
||||
@@ -280,16 +288,18 @@ typedef struct vj_audio_sync_shared_t
|
||||
volatile int wav_limit_ms;
|
||||
volatile int wav_silence_after_eof;
|
||||
|
||||
/* PLAIN+WAV Track Align cache. Once a strong WAV/video lock is found,
|
||||
* replay can snap immediately without re-running wide target analysis.
|
||||
* The cache is generation-bound, so changing the WAV path/source clears it.
|
||||
*/
|
||||
volatile int wav_plain_lock_valid;
|
||||
volatile int wav_plain_lock_generation;
|
||||
volatile int wav_plain_lock_delta_frames;
|
||||
volatile int wav_plain_lock_confidence_pct;
|
||||
|
||||
/* internal source detector state; only sync thread / push path writes it */
|
||||
|
||||
volatile int jack_connect_failures;
|
||||
volatile int jack_connect_giveup;
|
||||
volatile long jack_connect_first_fail_ms;
|
||||
volatile long jack_connect_next_retry_ms;
|
||||
volatile long jack_connect_last_log_ms;
|
||||
|
||||
double fast_energy;
|
||||
double slow_energy;
|
||||
double envelope;
|
||||
@@ -297,7 +307,6 @@ typedef struct vj_audio_sync_shared_t
|
||||
double beat_period_ms;
|
||||
long last_analysis_ms;
|
||||
|
||||
/* internal target-clock detector state for current-clip auto target */
|
||||
double target_fast_energy;
|
||||
double target_slow_energy;
|
||||
double target_envelope;
|
||||
@@ -371,10 +380,7 @@ void vj_audio_sync_track_align_reset_acquisition(vj_audio_sync_shared_t *s);
|
||||
int vj_audio_sync_track_align_source_ready(vj_audio_sync_shared_t *s, int min_source_features);
|
||||
int vj_audio_sync_track_align_last_snap(vj_audio_sync_shared_t *s, long *snap_ms, int *delta_frames);
|
||||
|
||||
/* Wide waveform snap support.
|
||||
* Probe candidate original-audio windows against the recent external master
|
||||
* feature window, then offer/consume a one-shot video-frame snap.
|
||||
*/
|
||||
|
||||
int vj_audio_sync_track_align_probe_target_audio(vj_audio_sync_shared_t *s,
|
||||
const uint8_t *src,
|
||||
int frames,
|
||||
|
||||
@@ -56,6 +56,9 @@
|
||||
#include <libveejay/vj-jack.h>
|
||||
#include <libveejay/vj-audio-beat.h>
|
||||
#include <libveejay/vj-audio-sync.h>
|
||||
#ifndef VJ_AUDIO_BEAT_ACTION_BREAK_BEAT
|
||||
#define VJ_AUDIO_BEAT_ACTION_BREAK_BEAT 4
|
||||
#endif
|
||||
#endif
|
||||
#include <libstream/vj-tag.h>
|
||||
#include <libstream/vj-vloopback.h>
|
||||
@@ -8670,6 +8673,8 @@ static const char *vj_audio_beat_event_action_name(int action)
|
||||
return "auto-fx";
|
||||
case VJ_AUDIO_BEAT_ACTION_FREEZE_AND_AUTO_FX:
|
||||
return "freeze+auto-fx";
|
||||
case VJ_AUDIO_BEAT_ACTION_BREAK_BEAT:
|
||||
return "break-beat";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
@@ -9229,7 +9234,7 @@ void vj_event_audio_beat_ui_config(void *ptr, const char format[], va_list ap)
|
||||
if(!vj_event_audio_beat_ready(v))
|
||||
return;
|
||||
|
||||
args[1] = vj_audio_beat_event_clampi(args[1], VJ_AUDIO_BEAT_ACTION_NONE, VJ_AUDIO_BEAT_ACTION_FREEZE_AND_AUTO_FX);
|
||||
args[1] = vj_audio_beat_event_clampi(args[1], VJ_AUDIO_BEAT_ACTION_NONE, VJ_AUDIO_BEAT_ACTION_BREAK_BEAT);
|
||||
args[8] = vj_audio_beat_event_clampi(args[8], VJ_AUDIO_BEAT_AUTO_OFF, VJ_AUDIO_BEAT_AUTO_CHAOS);
|
||||
args[9] = vj_audio_beat_event_clampi(args[9], 0, 100);
|
||||
|
||||
@@ -9405,7 +9410,7 @@ void vj_event_audio_beat_action(void *ptr, const char format[], va_list ap)
|
||||
|
||||
args[0] = vj_audio_beat_event_clampi(args[0],
|
||||
VJ_AUDIO_BEAT_ACTION_NONE,
|
||||
VJ_AUDIO_BEAT_ACTION_FREEZE_AND_AUTO_FX);
|
||||
VJ_AUDIO_BEAT_ACTION_BREAK_BEAT);
|
||||
|
||||
{
|
||||
int freeze = -1;
|
||||
|
||||
@@ -2362,7 +2362,7 @@ void vj_init_vevo_events(void)
|
||||
vj_event_audio_beat_action,
|
||||
1,
|
||||
VIMS_REQUIRE_ALL_PARAMS,
|
||||
"Action: 0=none, 1=freeze, 2=auto-fx, 3=freeze+auto-fx",
|
||||
"Action: 0=none, 1=freeze, 2=auto-fx, 3=freeze+auto-fx, 4=break-beat",
|
||||
2,
|
||||
NULL );
|
||||
|
||||
@@ -2428,7 +2428,7 @@ void vj_init_vevo_events(void)
|
||||
VIMS_REQUIRE_ALL_PARAMS,
|
||||
"Enabled state, 0 or 1",
|
||||
1,
|
||||
"Action: 0=none, 1=freeze, 2=auto-fx, 3=freeze+auto-fx",
|
||||
"Action: 0=none, 1=freeze, 2=auto-fx, 3=freeze+auto-fx, 4=break-beat",
|
||||
2,
|
||||
"Freeze duration in milliseconds",
|
||||
90,
|
||||
|
||||
@@ -44,7 +44,6 @@ enum {
|
||||
LAVPLAY_STATE_PLAYING = 2 /* speed != 0 */
|
||||
};
|
||||
|
||||
/* nmacro recorder, 5 lines code for play back of what you changed at navigation */
|
||||
enum {
|
||||
VJ_MACRO_PLAIN_RECORD = 0,
|
||||
VJ_MACRO_PLAIN_PLAY = 1,
|
||||
@@ -56,10 +55,6 @@ enum {
|
||||
#define AUDIO_MODE_SILENCE_FILL 0
|
||||
#define AUDIO_MODE_CONTENT 1
|
||||
|
||||
/* Coherent recording audio source selection.
|
||||
* AUTO follows the active audible external path when one is selected,
|
||||
* otherwise it records the original media audio.
|
||||
*/
|
||||
#define VJ_RECORD_AUDIO_SOURCE_AUTO 0
|
||||
#define VJ_RECORD_AUDIO_SOURCE_ORIGINAL 1
|
||||
#define VJ_RECORD_AUDIO_SOURCE_BEAT_JACK 2
|
||||
@@ -70,7 +65,6 @@ enum {
|
||||
#define DUMMY_DEFAULT_HEIGHT 288
|
||||
#define DUMMY_DEFAULT_FPS 25
|
||||
|
||||
/* Video Playback Setup, necessary items for reading and playing video */
|
||||
struct mjpeg_sync
|
||||
{
|
||||
unsigned long frame; /* Frame (0 - n) for double buffer */
|
||||
@@ -225,16 +219,35 @@ typedef struct vj_audio_beat_shared_t
|
||||
volatile long record_underruns;
|
||||
|
||||
#ifdef HAVE_JACK
|
||||
/*
|
||||
* External capture/clock provider.
|
||||
* Beat consumes this instead of owning JACK input directly.
|
||||
* NULL keeps legacy direct-JACK capture alive during transition.
|
||||
*/
|
||||
vj_audio_sync_shared_t *sync;
|
||||
#endif
|
||||
|
||||
} vj_audio_beat_shared_t;
|
||||
|
||||
|
||||
#define VJ_SCENE_ANALYSIS_MAX_SIDE 64
|
||||
#define VJ_SCENE_ANALYSIS_MAX_PIXELS (VJ_SCENE_ANALYSIS_MAX_SIDE * VJ_SCENE_ANALYSIS_MAX_SIDE)
|
||||
|
||||
typedef struct vj_scene_detect_t
|
||||
{
|
||||
volatile int valid;
|
||||
volatile long long frame;
|
||||
volatile int scene_id;
|
||||
volatile long long last_cut_frame;
|
||||
volatile int scene_age_frames;
|
||||
volatile int hard_cut;
|
||||
volatile int cut_score_q15;
|
||||
volatile int diff_q15;
|
||||
volatile int mean_q15;
|
||||
volatile int analysis_w;
|
||||
volatile int analysis_h;
|
||||
int prev_ready;
|
||||
double diff_ema;
|
||||
double diff_var;
|
||||
double mean_ema;
|
||||
uint8_t prev[VJ_SCENE_ANALYSIS_MAX_PIXELS];
|
||||
} vj_scene_detect_t;
|
||||
|
||||
typedef struct vj_audio_clock_osd_t {
|
||||
volatile long long prod_loops;
|
||||
volatile long long prod_anomalies;
|
||||
@@ -298,6 +311,7 @@ typedef struct {
|
||||
vj_audio_sync_shared_t audio_sync;
|
||||
#endif
|
||||
vj_audio_beat_shared_t audio_beat;
|
||||
vj_scene_detect_t scene_detect;
|
||||
|
||||
volatile int audio_mode;
|
||||
volatile int state;
|
||||
@@ -310,13 +324,6 @@ typedef struct {
|
||||
volatile double runtime_playback_rate;
|
||||
volatile long long anchor_frame;
|
||||
#ifdef HAVE_JACK
|
||||
/* Track Align re-anchor bookkeeping. When the user scratches, reverses,
|
||||
* pauses, or changes runtime FPS, the external JACK/master track keeps
|
||||
* moving forward. On return to normal +1 playback we can estimate the
|
||||
* expected media frame linearly from the audio clock, then let waveform
|
||||
* align fine-tune it. track_align_reacquire_seq lets performer-side wide
|
||||
* acquisition clear stale buckets without coupling libveejay to performer_t.
|
||||
*/
|
||||
volatile int track_align_reacquire_seq;
|
||||
volatile int track_align_linear_active;
|
||||
volatile long long track_align_linear_anchor_frame;
|
||||
@@ -326,13 +333,7 @@ typedef struct {
|
||||
volatile double track_align_linear_frame_accum;
|
||||
volatile int track_align_linear_mode;
|
||||
volatile int track_align_linear_id;
|
||||
/* Track Align correction edge handling.
|
||||
* Current Track Align corrections use the normal AUDIO_EDGE_JUMP
|
||||
* crossfade/declick path for arbitrary corrected seeks. AUDIO_EDGE_RESET
|
||||
* stays reserved for real reset boundaries such as sample start/min-frame
|
||||
* handling. These fields are kept for ABI/source compatibility with earlier
|
||||
* experimental builds; playback no longer mutes on track_align_audio_guard.
|
||||
*/
|
||||
|
||||
volatile int track_align_force_audio_edge_reset;
|
||||
volatile long long track_align_audio_guard_until_ms;
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user