static bool resample_audio_output(struct audio_input *input, struct audio_data *data) { bool success = true; if (input->resampler) { uint8_t *output[MAX_AV_PLANES]; uint32_t frames; uint64_t offset; memset(output, 0, sizeof(output)); success = audio_resampler_resample(input->resampler, output, &frames, &offset, (const uint8_t *const *)data->data, data->frames); for (size_t i = 0; i < MAX_AV_PLANES; i++) data->data[i] = output[i]; data->frames = frames; data->timestamp -= offset; } return success; }
/* resamples/remixes new audio to the designated main audio output format */ static void process_audio(obs_source_t source, const struct source_audio *audio) { if (source->sample_info.samples_per_sec != audio->samples_per_sec || source->sample_info.format != audio->format || source->sample_info.speakers != audio->speakers) reset_resampler(source, audio); if (source->audio_failed) return; if (source->resampler) { void *output; uint32_t frames; uint64_t offset; audio_resampler_resample(source->resampler, &output, &frames, audio->data, audio->frames, &offset); copy_audio_data(source, output, frames, audio->timestamp - offset); } else { copy_audio_data(source, audio->data, audio->frames, audio->timestamp); } }
/* resamples/remixes new audio to the designated main audio output format */ static void process_audio(obs_source_t source, const struct source_audio *audio) { if (source->sample_info.samples_per_sec != audio->samples_per_sec || source->sample_info.format != audio->format || source->sample_info.speakers != audio->speakers) reset_resampler(source, audio); if (source->audio_failed) return; if (source->resampler) { uint8_t *output[MAX_AV_PLANES]; uint32_t frames; uint64_t offset; memset(output, 0, sizeof(output)); audio_resampler_resample(source->resampler, output, &frames, &offset, audio->data, audio->frames); copy_audio_data(source, (const uint8_t *const *)output, frames, audio->timestamp - offset); } else { copy_audio_data(source, audio->data, audio->frames, audio->timestamp); } }
static void on_audio_playback(void *param, obs_source_t *source, const struct audio_data *audio_data, bool muted) { struct audio_monitor *monitor = param; IAudioRenderClient *render = monitor->render; uint8_t *resample_data[MAX_AV_PLANES]; float vol = source->user_volume; uint32_t resample_frames; uint64_t ts_offset; bool success; BYTE *output; if (pthread_mutex_trylock(&monitor->playback_mutex) != 0) { return; } if (os_atomic_load_long(&source->activate_refs) == 0) { goto unlock; } success = audio_resampler_resample(monitor->resampler, resample_data, &resample_frames, &ts_offset, (const uint8_t *const *)audio_data->data, (uint32_t)audio_data->frames); if (!success) { goto unlock; } UINT32 pad = 0; monitor->client->lpVtbl->GetCurrentPadding(monitor->client, &pad); bool decouple_audio = source->async_unbuffered && source->async_decoupled; if (monitor->source_has_video && !decouple_audio) { uint64_t ts = audio_data->timestamp - ts_offset; if (!process_audio_delay(monitor, (float**)(&resample_data[0]), &resample_frames, ts, pad)) { goto unlock; } } HRESULT hr = render->lpVtbl->GetBuffer(render, resample_frames, &output); if (FAILED(hr)) { goto unlock; } if (!muted) { /* apply volume */ if (!close_float(vol, 1.0f, EPSILON)) { register float *cur = (float*)resample_data[0]; register float *end = cur + resample_frames * monitor->channels; while (cur < end) *(cur++) *= vol; } memcpy(output, resample_data[0], resample_frames * monitor->channels * sizeof(float)); } render->lpVtbl->ReleaseBuffer(render, resample_frames, muted ? AUDCLNT_BUFFERFLAGS_SILENT : 0); unlock: pthread_mutex_unlock(&monitor->playback_mutex); }