88#include "wasapi-output.h"
99
1010#define ACTUALLY_DEFINE_GUID (name , l , w1 , w2 , b1 , b2 , b3 , b4 , b5 , b6 , b7 , b8 ) \
11- EXTERN_C const GUID DECLSPEC_SELECTANY name = {l, w1, w2, {b1, b2, b3, b4, b5, b6, b7, b8}}
11+ EXTERN_C const GUID DECLSPEC_SELECTANY name = {l, w1, w2, {b1, b2, b3, b4, b5, b6, b7, b8}}
1212
1313#define do_log (level , format , ...) \
14- blog(level, "[audio monitoring: '%s'] " format, obs_source_get_name(monitor->source), ##__VA_ARGS__)
14+ blog(level, "[audio monitoring: '%s'] " format, obs_source_get_name(monitor->source), ##__VA_ARGS__)
1515
1616#define warn (format , ...) do_log(LOG_WARNING, format, ##__VA_ARGS__)
1717#define info (format , ...) do_log(LOG_INFO, format, ##__VA_ARGS__)
@@ -50,7 +50,7 @@ struct audio_monitor {
5050/* #define DEBUG_AUDIO */
5151
5252static bool process_audio_delay (struct audio_monitor * monitor , float * * data , uint32_t * frames , uint64_t ts ,
53- uint32_t pad )
53+ uint32_t pad , bool sync_to_video )
5454{
5555 obs_source_t * s = monitor -> source ;
5656 uint64_t last_frame_ts = s -> last_frame_ts ;
@@ -71,34 +71,50 @@ static bool process_audio_delay(struct audio_monitor *monitor, float **data, uin
7171 deque_push_back (& monitor -> delay_buffer , frames , sizeof (* frames ));
7272 deque_push_back (& monitor -> delay_buffer , * data , * frames * blocksize );
7373
74- if (!monitor -> prev_video_ts ) {
75- monitor -> prev_video_ts = last_frame_ts ;
76-
77- } else if (monitor -> prev_video_ts == last_frame_ts ) {
78- monitor -> time_since_prev += util_mul_div64 (* frames , 1000000000ULL , monitor -> sample_rate );
79- } else {
80- monitor -> time_since_prev = 0 ;
74+ if (sync_to_video ) {
75+ if (!monitor -> prev_video_ts ) {
76+ monitor -> prev_video_ts = last_frame_ts ;
77+ } else if (monitor -> prev_video_ts == last_frame_ts ) {
78+ monitor -> time_since_prev += util_mul_div64 (* frames , 1000000000ULL , monitor -> sample_rate );
79+ } else {
80+ monitor -> time_since_prev = 0 ;
81+ }
8182 }
8283
8384 while (monitor -> delay_buffer .size != 0 ) {
8485 size_t size ;
85- bool bad_diff ;
8686
8787 deque_peek_front (& monitor -> delay_buffer , & cur_ts , sizeof (ts ));
8888 front_ts = cur_ts - util_mul_div64 (pad , 1000000000ULL , monitor -> sample_rate );
89- diff = (int64_t )front_ts - (int64_t )last_frame_ts ;
90- bad_diff = !last_frame_ts || llabs (diff ) > 5000000000 || monitor -> time_since_prev > 100000000ULL ;
9189
92- /* delay audio if rushing */
93- if (!bad_diff && diff > 75000000 ) {
90+ if (sync_to_video ) {
91+ diff = (int64_t )front_ts - (int64_t )last_frame_ts ;
92+ bool bad_diff = !last_frame_ts || llabs (diff ) > 5000000000 ||
93+ monitor -> time_since_prev > 100000000ULL ;
94+
95+ /* delay audio if rushing */
96+ if (!bad_diff && diff > 10000000 ) {
97+ #ifdef DEBUG_AUDIO
98+ blog (LOG_INFO ,
99+ "audio rushing, cutting audio, "
100+ "diff: %lld, delay buffer size: %lu, "
101+ "v: %llu: a: %llu" ,
102+ diff , (unsigned long )monitor -> delay_buffer .size , last_frame_ts , front_ts );
103+ #endif
104+ return false;
105+ }
106+ } else {
107+ diff = (int64_t )front_ts - (int64_t )cur_time ;
108+ if (diff > 10000000 ) {
94109#ifdef DEBUG_AUDIO
95- blog (LOG_INFO ,
96- "audio rushing, cutting audio , "
97- "diff: %lld, delay buffer size: %lu, "
98- "v : %llu: a : %llu" ,
99- diff , (int )monitor -> delay_buffer .size , last_frame_ts , front_ts );
110+ blog (LOG_INFO ,
111+ "audio ahead of synctime, waiting , "
112+ "diff: %lld, delay buffer size: %lu, "
113+ "cur_time : %llu, front_ts : %llu" ,
114+ diff , (unsigned long )monitor -> delay_buffer .size , cur_time , front_ts );
100115#endif
101- return false;
116+ return false;
117+ }
102118 }
103119
104120 deque_pop_front (& monitor -> delay_buffer , NULL , sizeof (ts ));
@@ -109,15 +125,30 @@ static bool process_audio_delay(struct audio_monitor *monitor, float **data, uin
109125 deque_pop_front (& monitor -> delay_buffer , monitor -> buf .array , size );
110126
111127 /* cut audio if dragging */
112- if (!bad_diff && diff < -75000000 && monitor -> delay_buffer .size > 0 ) {
128+ if (sync_to_video ) {
129+ bool bad_diff = !last_frame_ts || llabs (diff ) > 5000000000 ||
130+ monitor -> time_since_prev > 100000000ULL ;
131+ if (!bad_diff && diff < -10000000 && monitor -> delay_buffer .size > 0 ) {
113132#ifdef DEBUG_AUDIO
114- blog (LOG_INFO ,
115- "audio dragging, cutting audio, "
116- "diff: %lld, delay buffer size: %lu, "
117- "v: %llu: a: %llu" ,
118- diff , (int )monitor -> delay_buffer .size , last_frame_ts , front_ts );
133+ blog (LOG_INFO ,
134+ "audio dragging, cutting audio, "
135+ "diff: %lld, delay buffer size: %lu, "
136+ "v: %llu: a: %llu" ,
137+ diff , (unsigned long )monitor -> delay_buffer .size , last_frame_ts , front_ts );
119138#endif
120- continue ;
139+ continue ;
140+ }
141+ } else {
142+ if (diff < -10000000 && monitor -> delay_buffer .size > 0 ) {
143+ #ifdef DEBUG_AUDIO
144+ blog (LOG_INFO ,
145+ "audio behind synctime, dropping, "
146+ "diff: %lld, delay buffer size: %lu, "
147+ "cur_time: %llu, front_ts: %llu" ,
148+ diff , (unsigned long )monitor -> delay_buffer .size , cur_time , front_ts );
149+ #endif
150+ continue ;
151+ }
121152 }
122153
123154 * data = monitor -> buf .array ;
@@ -154,7 +185,7 @@ static bool audio_monitor_init_wasapi(struct audio_monitor *monitor)
154185 HRESULT hr ;
155186
156187 /* ------------------------------------------ *
157- * Init device */
188+ * Init device */
158189
159190 hr = CoCreateInstance (& CLSID_MMDeviceEnumerator , NULL , CLSCTX_ALL , & IID_IMMDeviceEnumerator , (void * * )& immde );
160191 if (FAILED (hr )) {
@@ -179,7 +210,7 @@ static bool audio_monitor_init_wasapi(struct audio_monitor *monitor)
179210 }
180211
181212 /* ------------------------------------------ *
182- * Init client */
213+ * Init client */
183214
184215 hr = device -> lpVtbl -> Activate (device , & IID_IAudioClient , CLSCTX_ALL , NULL , (void * * )& monitor -> client );
185216 device -> lpVtbl -> Release (device );
@@ -194,14 +225,15 @@ static bool audio_monitor_init_wasapi(struct audio_monitor *monitor)
194225 goto fail ;
195226 }
196227
197- hr = monitor -> client -> lpVtbl -> Initialize (monitor -> client , AUDCLNT_SHAREMODE_SHARED , 0 , 10000000 , 0 , wfex , NULL );
228+ /* Initialize the audio client. Use a buffer duration of 200000 * 100 ns = 20 ms */
229+ hr = monitor -> client -> lpVtbl -> Initialize (monitor -> client , AUDCLNT_SHAREMODE_SHARED , 0 , 200000 , 0 , wfex , NULL );
198230 if (FAILED (hr )) {
199231 warn ("%s: Failed to initialize: %08lX" , __FUNCTION__ , hr );
200232 goto fail ;
201233 }
202234
203235 /* ------------------------------------------ *
204- * Init resampler */
236+ * Init resampler */
205237
206238 const struct audio_output_info * info = audio_output_get_info (obs -> audio .audio );
207239 WAVEFORMATEXTENSIBLE * ext = (WAVEFORMATEXTENSIBLE * )wfex ;
@@ -224,7 +256,7 @@ static bool audio_monitor_init_wasapi(struct audio_monitor *monitor)
224256 }
225257
226258 /* ------------------------------------------ *
227- * Init client */
259+ * Init client */
228260
229261 hr = monitor -> client -> lpVtbl -> GetBufferSize (monitor -> client , & frames );
230262 if (FAILED (hr )) {
@@ -310,13 +342,11 @@ static void on_audio_playback(void *param, obs_source_t *source, const struct au
310342 }
311343
312344 bool decouple_audio = source -> async_unbuffered && source -> async_decoupled ;
345+ uint64_t ts = audio_data -> timestamp - ts_offset ;
313346
314- if (monitor -> source_has_video && !decouple_audio ) {
315- uint64_t ts = audio_data -> timestamp - ts_offset ;
316-
317- if (!process_audio_delay (monitor , (float * * )(& resample_data [0 ]), & resample_frames , ts , pad )) {
318- goto unlock ;
319- }
347+ bool sync_to_video = monitor -> source_has_video && !decouple_audio ;
348+ if (!process_audio_delay (monitor , (float * * )(& resample_data [0 ]), & resample_frames , ts , pad , sync_to_video )) {
349+ goto unlock ;
320350 }
321351
322352 IAudioRenderClient * const render = monitor -> render ;
0 commit comments