+void Mixer::get_one_frame_from_each_card(unsigned master_card_index, CaptureCard::NewFrame new_frames[MAX_CARDS], bool has_new_frame[MAX_CARDS], int num_samples[MAX_CARDS])
+{
+ // The first card is the master timer, so wait for it to have a new frame.
+ 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();
+ }
+ }
+ }
+}
+