Skip to content

Commit ec1a4d7

Browse files
committed
libobs: Add ASIO monitoring track
On windows, this adds an additional audio track (Track 7) which is used to output a mix of monitored sources. Currently the mixing is left to WASAPI on windows for WASAPI monitoring devices. But ASIO SDK doesn't allow multiple clients (although individual drivers might allow it) and therefore can not mix them. So we have to do the mixing on obs side. Signed-off-by: pkv <[email protected]>
1 parent 511330c commit ec1a4d7

File tree

8 files changed

+56
-29
lines changed

8 files changed

+56
-29
lines changed

libobs/media-io/audio-io.c

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ struct audio_output {
7676
audio_input_callback_t input_cb;
7777
void *input_param;
7878
pthread_mutex_t input_mutex;
79-
struct audio_mix mixes[MAX_AUDIO_MIXES];
79+
struct audio_mix mixes[MAX_AUDIO_MIXES_NEW];
8080
};
8181

8282
/* ------------------------------------------------------------------------- */
@@ -133,7 +133,7 @@ static inline void clamp_audio_output(struct audio_output *audio, size_t bytes)
133133
{
134134
size_t float_size = bytes / sizeof(float);
135135

136-
for (size_t mix_idx = 0; mix_idx < MAX_AUDIO_MIXES; mix_idx++) {
136+
for (size_t mix_idx = 0; mix_idx < MAX_AUDIO_MIXES_NEW; mix_idx++) {
137137
struct audio_mix *mix = &audio->mixes[mix_idx];
138138

139139
/* do not process mixing if a specific mix is inactive */
@@ -160,7 +160,7 @@ static inline void clamp_audio_output(struct audio_output *audio, size_t bytes)
160160
static void input_and_output(struct audio_output *audio, uint64_t audio_time, uint64_t prev_time)
161161
{
162162
size_t bytes = AUDIO_OUTPUT_FRAMES * audio->block_size;
163-
struct audio_output_data data[MAX_AUDIO_MIXES];
163+
struct audio_output_data data[MAX_AUDIO_MIXES_NEW];
164164
uint32_t active_mixes = 0;
165165
uint64_t new_ts = 0;
166166
bool success;
@@ -173,14 +173,14 @@ static void input_and_output(struct audio_output *audio, uint64_t audio_time, ui
173173

174174
/* get mixers */
175175
pthread_mutex_lock(&audio->input_mutex);
176-
for (size_t i = 0; i < MAX_AUDIO_MIXES; i++) {
176+
for (size_t i = 0; i < MAX_AUDIO_MIXES_NEW; i++) {
177177
if (audio->mixes[i].inputs.num)
178178
active_mixes |= (1 << i);
179179
}
180180
pthread_mutex_unlock(&audio->input_mutex);
181181

182182
/* clear mix buffers */
183-
for (size_t mix_idx = 0; mix_idx < MAX_AUDIO_MIXES; mix_idx++) {
183+
for (size_t mix_idx = 0; mix_idx < MAX_AUDIO_MIXES_NEW; mix_idx++) {
184184
struct audio_mix *mix = &audio->mixes[mix_idx];
185185

186186
memset(mix->buffer, 0, sizeof(mix->buffer));
@@ -198,7 +198,7 @@ static void input_and_output(struct audio_output *audio, uint64_t audio_time, ui
198198
clamp_audio_output(audio, bytes);
199199

200200
/* output */
201-
for (size_t i = 0; i < MAX_AUDIO_MIXES; i++)
201+
for (size_t i = 0; i < MAX_AUDIO_MIXES_NEW; i++)
202202
do_audio_output(audio, i, new_ts, AUDIO_OUTPUT_FRAMES);
203203
}
204204

@@ -291,7 +291,7 @@ bool audio_output_connect(audio_t *audio, size_t mi, const struct audio_convert_
291291
{
292292
bool success = false;
293293

294-
if (!audio || mi >= MAX_AUDIO_MIXES)
294+
if (!audio || mi >= MAX_AUDIO_MIXES_NEW)
295295
return false;
296296

297297
pthread_mutex_lock(&audio->input_mutex);
@@ -330,7 +330,7 @@ bool audio_output_connect(audio_t *audio, size_t mi, const struct audio_convert_
330330

331331
void audio_output_disconnect(audio_t *audio, size_t mix_idx, audio_output_callback_t callback, void *param)
332332
{
333-
if (!audio || mix_idx >= MAX_AUDIO_MIXES)
333+
if (!audio || mix_idx >= MAX_AUDIO_MIXES_NEW)
334334
return;
335335

336336
pthread_mutex_lock(&audio->input_mutex);
@@ -403,7 +403,7 @@ void audio_output_close(audio_t *audio)
403403
pthread_mutex_destroy(&audio->input_mutex);
404404
}
405405

406-
for (size_t mix_idx = 0; mix_idx < MAX_AUDIO_MIXES; mix_idx++) {
406+
for (size_t mix_idx = 0; mix_idx < MAX_AUDIO_MIXES_NEW; mix_idx++) {
407407
struct audio_mix *mix = &audio->mixes[mix_idx];
408408

409409
for (size_t i = 0; i < mix->inputs.num; i++)
@@ -424,7 +424,7 @@ bool audio_output_active(const audio_t *audio)
424424
if (!audio)
425425
return false;
426426

427-
for (size_t mix_idx = 0; mix_idx < MAX_AUDIO_MIXES; mix_idx++) {
427+
for (size_t mix_idx = 0; mix_idx < MAX_AUDIO_MIXES_NEW; mix_idx++) {
428428
const struct audio_mix *mix = &audio->mixes[mix_idx];
429429

430430
if (mix->inputs.num != 0)

libobs/media-io/audio-io.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,14 @@
2424
#ifdef __cplusplus
2525
extern "C" {
2626
#endif
27-
27+
#ifdef _WIN32
28+
// extra track for ASIO monitoring on windows only
29+
#define MAX_AUDIO_MIXES_NEW 7
30+
#else
31+
#define MAX_AUDIO_MIXES_NEW 6
32+
#endif
2833
#define MAX_AUDIO_MIXES 6
34+
2935
#define MAX_AUDIO_CHANNELS 8
3036
#define MAX_DEVICE_INPUT_CHANNELS 64
3137
#define AUDIO_OUTPUT_FRAMES 1024

libobs/obs-audio.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ static inline void mix_audio(struct audio_output_data *mixes, obs_source_t *sour
128128
total_floats -= start_point;
129129
}
130130

131-
for (size_t mix_idx = 0; mix_idx < MAX_AUDIO_MIXES; mix_idx++) {
131+
for (size_t mix_idx = 0; mix_idx < MAX_AUDIO_MIXES_NEW; mix_idx++) {
132132
for (size_t ch = 0; ch < channels; ch++) {
133133
register float *mix = mixes[mix_idx].data[ch];
134134
register float *aud = source->audio_output_buf[mix_idx][ch];

libobs/obs-internal.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -869,7 +869,7 @@ struct obs_source {
869869
struct deque audio_input_buf[MAX_AUDIO_CHANNELS];
870870
size_t last_audio_input_buf_size;
871871
DARRAY(struct audio_action) audio_actions;
872-
float *audio_output_buf[MAX_AUDIO_MIXES][MAX_AUDIO_CHANNELS];
872+
float *audio_output_buf[MAX_AUDIO_MIXES_NEW][MAX_AUDIO_CHANNELS];
873873
float *audio_mix_buf[MAX_AUDIO_CHANNELS];
874874
struct resample_info sample_info;
875875
audio_resampler_t *resampler;
@@ -1258,7 +1258,7 @@ struct obs_output {
12581258

12591259
struct pause_data pause;
12601260

1261-
struct deque audio_buffer[MAX_AUDIO_MIXES][MAX_AV_PLANES];
1261+
struct deque audio_buffer[MAX_AUDIO_MIXES_NEW][MAX_AV_PLANES];
12621262
uint64_t audio_start_ts;
12631263
uint64_t video_start_ts;
12641264
size_t audio_size;

libobs/obs-output.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ static inline void free_packets(struct obs_output *output)
269269

270270
static inline void clear_raw_audio_buffers(obs_output_t *output)
271271
{
272-
for (size_t i = 0; i < MAX_AUDIO_MIXES; i++) {
272+
for (size_t i = 0; i < MAX_AUDIO_MIXES_NEW; i++) {
273273
for (size_t j = 0; j < MAX_AV_PLANES; j++) {
274274
deque_free(&output->audio_buffer[i][j]);
275275
}
@@ -918,7 +918,7 @@ audio_t *obs_output_audio(const obs_output_t *output)
918918

919919
static inline size_t get_first_mixer(const obs_output_t *output)
920920
{
921-
for (size_t i = 0; i < MAX_AUDIO_MIXES; i++) {
921+
for (size_t i = 0; i < MAX_AUDIO_MIXES_NEW; i++) {
922922
if ((((size_t)1 << i) & output->mixer_mask) != 0) {
923923
return i;
924924
}
@@ -2448,7 +2448,7 @@ static inline void start_video_encoders(struct obs_output *output, encoded_callb
24482448
static inline void start_raw_audio(obs_output_t *output)
24492449
{
24502450
if (output->info.raw_audio2) {
2451-
for (int idx = 0; idx < MAX_AUDIO_MIXES; idx++) {
2451+
for (int idx = 0; idx < MAX_AUDIO_MIXES_NEW; idx++) {
24522452
if ((output->mixer_mask & ((size_t)1 << idx)) != 0) {
24532453
audio_output_connect(output->audio, idx, get_audio_conversion(output),
24542454
default_raw_audio_callback, output);
@@ -2824,7 +2824,7 @@ static inline void stop_video_encoders(obs_output_t *output, encoded_callback_t
28242824
static inline void stop_raw_audio(obs_output_t *output)
28252825
{
28262826
if (output->info.raw_audio2) {
2827-
for (int idx = 0; idx < MAX_AUDIO_MIXES; idx++) {
2827+
for (int idx = 0; idx < MAX_AUDIO_MIXES_NEW; idx++) {
28282828
if ((output->mixer_mask & ((size_t)1 << idx)) != 0) {
28292829
audio_output_disconnect(output->audio, idx, default_raw_audio_callback, output);
28302830
}

libobs/obs-source-transition.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -869,7 +869,7 @@ static void process_audio(obs_source_t *transition, obs_source_t *child, struct
869869
if (pos > AUDIO_OUTPUT_FRAMES)
870870
return;
871871

872-
for (size_t mix_idx = 0; mix_idx < MAX_AUDIO_MIXES; mix_idx++) {
872+
for (size_t mix_idx = 0; mix_idx < MAX_AUDIO_MIXES_NEW; mix_idx++) {
873873
struct audio_output_data *output = &audio->output[mix_idx];
874874
struct audio_output_data *input = &child_audio.output[mix_idx];
875875

libobs/obs-source.c

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -172,10 +172,10 @@ enum obs_module_load_state obs_source_load_state(const char *id)
172172

173173
static void allocate_audio_output_buffer(struct obs_source *source)
174174
{
175-
size_t size = sizeof(float) * AUDIO_OUTPUT_FRAMES * MAX_AUDIO_CHANNELS * MAX_AUDIO_MIXES;
175+
size_t size = sizeof(float) * AUDIO_OUTPUT_FRAMES * MAX_AUDIO_CHANNELS * MAX_AUDIO_MIXES_NEW;
176176
float *ptr = bzalloc(size);
177177

178-
for (size_t mix = 0; mix < MAX_AUDIO_MIXES; mix++) {
178+
for (size_t mix = 0; mix < MAX_AUDIO_MIXES_NEW; mix++) {
179179
size_t mix_pos = mix * AUDIO_OUTPUT_FRAMES * MAX_AUDIO_CHANNELS;
180180

181181
for (size_t i = 0; i < MAX_AUDIO_CHANNELS; i++) {
@@ -5224,7 +5224,7 @@ static void apply_audio_actions(obs_source_t *source, size_t channels, size_t sa
52245224

52255225
pthread_mutex_unlock(&source->audio_actions_mutex);
52265226

5227-
for (size_t mix = 0; mix < MAX_AUDIO_MIXES; mix++) {
5227+
for (size_t mix = 0; mix < MAX_AUDIO_MIXES_NEW; mix++) {
52285228
if ((source->audio_mixers & (1 << mix)) != 0)
52295229
multiply_vol_data(source, mix, channels, vol_data);
52305230
}
@@ -5259,11 +5259,11 @@ static void apply_audio_volume(obs_source_t *source, uint32_t mixers, size_t cha
52595259

52605260
if (vol == 0.0f || mixers == 0) {
52615261
memset(source->audio_output_buf[0][0], 0,
5262-
AUDIO_OUTPUT_FRAMES * sizeof(float) * MAX_AUDIO_CHANNELS * MAX_AUDIO_MIXES);
5262+
AUDIO_OUTPUT_FRAMES * sizeof(float) * MAX_AUDIO_CHANNELS * MAX_AUDIO_MIXES_NEW);
52635263
return;
52645264
}
52655265

5266-
for (size_t mix = 0; mix < MAX_AUDIO_MIXES; mix++) {
5266+
for (size_t mix = 0; mix < MAX_AUDIO_MIXES_NEW; mix++) {
52675267
uint32_t mix_and_val = (1 << mix);
52685268
if ((source->audio_mixers & mix_and_val) != 0 && (mixers & mix_and_val) != 0)
52695269
multiply_output_audio(source, mix, channels, vol);
@@ -5276,7 +5276,7 @@ static void custom_audio_render(obs_source_t *source, uint32_t mixers, size_t ch
52765276
bool success;
52775277
uint64_t ts;
52785278

5279-
for (size_t mix = 0; mix < MAX_AUDIO_MIXES; mix++) {
5279+
for (size_t mix = 0; mix < MAX_AUDIO_MIXES_NEW; mix++) {
52805280
for (size_t ch = 0; ch < channels; ch++) {
52815281
audio_data.output[mix].data[ch] = source->audio_output_buf[mix][ch];
52825282
}
@@ -5293,7 +5293,7 @@ static void custom_audio_render(obs_source_t *source, uint32_t mixers, size_t ch
52935293
if (!success || !source->audio_ts || !mixers)
52945294
return;
52955295

5296-
for (size_t mix = 0; mix < MAX_AUDIO_MIXES; mix++) {
5296+
for (size_t mix = 0; mix < MAX_AUDIO_MIXES_NEW; mix++) {
52975297
uint32_t mix_bit = 1 << mix;
52985298

52995299
if ((mixers & mix_bit) == 0)
@@ -5355,7 +5355,7 @@ static inline void process_audio_source_tick(obs_source_t *source, uint32_t mixe
53555355

53565356
pthread_mutex_unlock(&source->audio_buf_mutex);
53575357

5358-
for (size_t mix = 1; mix < MAX_AUDIO_MIXES; mix++) {
5358+
for (size_t mix = 1; mix < MAX_AUDIO_MIXES_NEW; mix++) {
53595359
uint32_t mix_and_val = (1 << mix);
53605360

53615361
if (audio_submix) {
@@ -5435,7 +5435,7 @@ void obs_source_get_audio_mix(const obs_source_t *source, struct obs_source_audi
54355435
if (!obs_ptr_valid(audio, "audio"))
54365436
return;
54375437

5438-
for (size_t mix = 0; mix < MAX_AUDIO_MIXES; mix++) {
5438+
for (size_t mix = 0; mix < MAX_AUDIO_MIXES_NEW; mix++) {
54395439
for (size_t ch = 0; ch < MAX_AUDIO_CHANNELS; ch++) {
54405440
audio->output[mix].data[ch] = source->audio_output_buf[mix][ch];
54415441
}
@@ -5519,10 +5519,31 @@ void obs_source_set_monitoring_type(obs_source_t *source, enum obs_monitoring_ty
55195519
}
55205520

55215521
source->monitoring_type = type;
5522+
5523+
#ifdef _WIN32
5524+
// On windows, assign to the extra asio monitoring track (track 7) all sources which have not type
5525+
// OBS_MONITORING_TYPE_NONE.
5526+
if (type != OBS_MONITORING_TYPE_NONE) {
5527+
source->audio_mixers |= 1 << (MAX_AUDIO_MIXES_NEW - 1);
5528+
} else {
5529+
source->audio_mixers &= ~(1 << (MAX_AUDIO_MIXES_NEW - 1));
5530+
}
5531+
#endif
55225532
}
55235533

55245534
enum obs_monitoring_type obs_source_get_monitoring_type(const obs_source_t *source)
55255535
{
5536+
#ifdef _WIN32
5537+
// If type is not OBS_MONITORING_TYPE_MONITOR_AND_OUTPUT, unselect the extra asio monitoring track (track 7) on
5538+
// windows.
5539+
uint32_t mixers = obs_source_get_audio_mixers(source);
5540+
if (source->monitoring_type != OBS_MONITORING_TYPE_MONITOR_AND_OUTPUT && mixers) {
5541+
if (mixers & 1 << (MAX_AUDIO_MIXES_NEW - 1)) {
5542+
mixers &= ~(1 << (MAX_AUDIO_MIXES_NEW - 1));
5543+
obs_source_set_audio_mixers((obs_source_t *)source, mixers);
5544+
}
5545+
}
5546+
#endif
55265547
return obs_source_valid(source, "obs_source_get_monitoring_type") ? source->monitoring_type
55275548
: OBS_MONITORING_TYPE_NONE;
55285549
}

libobs/obs-source.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ enum obs_media_state {
213213
typedef void (*obs_source_enum_proc_t)(obs_source_t *parent, obs_source_t *child, void *param);
214214

215215
struct obs_source_audio_mix {
216-
struct audio_output_data output[MAX_AUDIO_MIXES];
216+
struct audio_output_data output[MAX_AUDIO_MIXES_NEW];
217217
};
218218

219219
/**

0 commit comments

Comments
 (0)