- {
- unique_lock<mutex> lock(bmusb_mutex);
-
- cards[master_card_index].new_frames_changed.wait(lock, [this, master_card_index]{ return !cards[master_card_index].new_frames.empty(); });
-
- for (unsigned card_index = 0; card_index < num_cards; ++card_index) {
- CaptureCard *card = &cards[card_index];
- if (card->new_frames.empty()) {
- assert(card_index != master_card_index);
- card->queue_length_policy.update_policy(-1);
- continue;
- }
- new_frames[card_index] = move(card->new_frames.front());
- has_new_frame[card_index] = true;
- card->new_frames.pop();
- card->new_frames_changed.notify_all();
-
- int num_samples_times_timebase = OUTPUT_FREQUENCY * new_frames[card_index].length + card->fractional_samples;
- num_samples[card_index] = num_samples_times_timebase / TIMEBASE;
- card->fractional_samples = num_samples_times_timebase % TIMEBASE;
- assert(num_samples[card_index] >= 0);
-
- if (card_index != master_card_index) {
- // If we have excess frames compared to the policy for this card,
- // drop frames from the head.
- card->queue_length_policy.update_policy(card->new_frames.size());
- while (card->new_frames.size() > card->queue_length_policy.get_safe_queue_length()) {
- card->new_frames.pop();
- }
- }
- }
- }
-
- // Resample the audio as needed, including from previously dropped frames.
- assert(num_cards > 0);
- for (unsigned frame_num = 0; frame_num < new_frames[master_card_index].dropped_frames + 1; ++frame_num) {
- {
- // Signal to the audio thread to process this frame.
- unique_lock<mutex> lock(audio_mutex);
- audio_task_queue.push(AudioTask{pts_int, num_samples[master_card_index]});
- audio_task_queue_changed.notify_one();
- }
- if (frame_num != new_frames[master_card_index].dropped_frames) {
- // For dropped frames, increase the pts. Note that if the format changed
- // in the meantime, we have no way of detecting that; we just have to
- // assume the frame length is always the same.
- ++stats_dropped_frames;
- pts_int += new_frames[master_card_index].length;
- }
- }
-
- if (audio_level_callback != nullptr) {
- unique_lock<mutex> lock(compressor_mutex);
- double loudness_s = r128.loudness_S();
- double loudness_i = r128.integrated();
- double loudness_range_low = r128.range_min();
- double loudness_range_high = r128.range_max();
-
- audio_level_callback(loudness_s, 20.0 * log10(peak),
- loudness_i, loudness_range_low, loudness_range_high,
- gain_staging_db, 20.0 * log10(final_makeup_gain),
- correlation.get_correlation());
- }