X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=mixer.cpp;h=aabc67e543fdfade00bc018f86d2cdd837b5d266;hb=8f83d8ec96c5dd1a1b9d17489d3a93bde3eacac2;hp=e8bbc028222b6a0f3724f7bf584d9d3410824ffb;hpb=4bbcd111d04f36a42cf3d40f18fcee5a91c6322a;p=nageru diff --git a/mixer.cpp b/mixer.cpp index e8bbc02..aabc67e 100644 --- a/mixer.cpp +++ b/mixer.cpp @@ -105,8 +105,7 @@ Mixer::Mixer(const QSurfaceFormat &format, unsigned num_cards) num_cards(num_cards), mixer_surface(create_surface(format)), h264_encoder_surface(create_surface(format)), - audio_mixer(num_cards), - correlation(OUTPUT_FREQUENCY) + audio_mixer(num_cards) { CHECK(init_movit(MOVIT_SHADER_DIR, MOVIT_DEBUG_OFF)); check_error(); @@ -232,13 +231,6 @@ Mixer::Mixer(const QSurfaceFormat &format, unsigned num_cards) cbcr_position_attribute_index = glGetAttribLocation(cbcr_program_num, "position"); cbcr_texcoord_attribute_index = glGetAttribLocation(cbcr_program_num, "texcoord"); - r128.init(2, OUTPUT_FREQUENCY); - r128.integr_start(); - - // hlen=16 is pretty low quality, but we use quite a bit of CPU otherwise, - // and there's a limit to how important the peak meter is. - peak_resampler.setup(OUTPUT_FREQUENCY, OUTPUT_FREQUENCY * 4, /*num_channels=*/2, /*hlen=*/16, /*frel=*/1.0); - if (global_flags.enable_alsa_output) { alsa.reset(new ALSAOutput(OUTPUT_FREQUENCY, /*num_channels=*/2)); } @@ -285,8 +277,11 @@ void Mixer::configure_card(unsigned card_index, CaptureInterface *capture, bool card->fractional_samples = 0; card->last_timecode = -1; card->capture->configure_card(); - audio_mixer.reset_card(card_index); - audio_mixer.set_name(card_index, card->capture->get_description()); + + DeviceSpec device{InputSourceType::CAPTURE_CARD, card_index}; + audio_mixer.reset_resampler(device); + audio_mixer.set_display_name(device, card->capture->get_description()); + audio_mixer.trigger_state_changed_callback(); } @@ -302,36 +297,13 @@ int unwrap_timecode(uint16_t current_wrapped, int last) } } -float find_peak(const float *samples, size_t num_samples) -{ - float m = fabs(samples[0]); - for (size_t i = 1; i < num_samples; ++i) { - m = max(m, fabs(samples[i])); - } - return m; -} - -void deinterleave_samples(const vector &in, vector *out_l, vector *out_r) -{ - size_t num_samples = in.size() / 2; - out_l->resize(num_samples); - out_r->resize(num_samples); - - const float *inptr = in.data(); - float *lptr = &(*out_l)[0]; - float *rptr = &(*out_r)[0]; - for (size_t i = 0; i < num_samples; ++i) { - *lptr++ = *inptr++; - *rptr++ = *inptr++; - } -} - } // namespace void Mixer::bm_frame(unsigned card_index, uint16_t timecode, FrameAllocator::Frame video_frame, size_t video_offset, VideoFormat video_format, FrameAllocator::Frame audio_frame, size_t audio_offset, AudioFormat audio_format) { + DeviceSpec device{InputSourceType::CAPTURE_CARD, card_index}; CaptureCard *card = &cards[card_index]; if (is_mode_scanning[card_index]) { @@ -381,17 +353,20 @@ void Mixer::bm_frame(unsigned card_index, uint16_t timecode, if (dropped_frames > MAX_FPS * 2) { fprintf(stderr, "Card %d lost more than two seconds (or time code jumping around; from 0x%04x to 0x%04x), resetting resampler\n", card_index, card->last_timecode, timecode); - audio_mixer.reset_card(card_index); + audio_mixer.reset_resampler(device); dropped_frames = 0; } else if (dropped_frames > 0) { // Insert silence as needed. fprintf(stderr, "Card %d dropped %d frame(s) (before timecode 0x%04x), inserting silence.\n", card_index, dropped_frames, timecode); - audio_mixer.add_silence(card_index, silence_samples, dropped_frames, frame_length); + bool success; + do { + success = audio_mixer.add_silence(device, silence_samples, dropped_frames, frame_length); + } while (!success); } - audio_mixer.add_audio(card_index, audio_frame.data + audio_offset, num_samples, audio_format, frame_length); + audio_mixer.add_audio(device, audio_frame.data + audio_offset, num_samples, audio_format, frame_length); // Done with the audio, so release it. if (audio_frame.owner) { @@ -566,9 +541,9 @@ void Mixer::thread_func() int stats_dropped_frames = 0; while (!should_quit) { - CaptureCard::NewFrame new_frames[MAX_CARDS]; - bool has_new_frame[MAX_CARDS] = { false }; - int num_samples[MAX_CARDS] = { 0 }; + CaptureCard::NewFrame new_frames[MAX_VIDEO_CARDS]; + bool has_new_frame[MAX_VIDEO_CARDS] = { false }; + int num_samples[MAX_VIDEO_CARDS] = { 0 }; unsigned master_card_index = theme->map_signal(master_clock_channel); assert(master_card_index < num_cards); @@ -576,7 +551,6 @@ void Mixer::thread_func() get_one_frame_from_each_card(master_card_index, new_frames, has_new_frame, num_samples); schedule_audio_resampling_tasks(new_frames[master_card_index].dropped_frames, num_samples[master_card_index], new_frames[master_card_index].length); stats_dropped_frames += new_frames[master_card_index].dropped_frames; - send_audio_level_callback(); handle_hotplugged_cards(); @@ -678,7 +652,7 @@ void Mixer::thread_func() resource_pool->clean_context(); } -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]) +void Mixer::get_one_frame_from_each_card(unsigned master_card_index, CaptureCard::NewFrame new_frames[MAX_VIDEO_CARDS], bool has_new_frame[MAX_VIDEO_CARDS], int num_samples[MAX_VIDEO_CARDS]) { start: // The first card is the master timer, so wait for it to have a new frame. @@ -866,25 +840,6 @@ void Mixer::render_one_frame(int64_t duration) } } -void Mixer::send_audio_level_callback() -{ - if (audio_level_callback == nullptr) { - return; - } - - unique_lock lock(audio_measure_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, to_db(peak), - loudness_i, loudness_range_low, loudness_range_high, - audio_mixer.get_gain_staging_db(), - audio_mixer.get_final_makeup_gain_db(), - correlation.get_correlation()); -} - void Mixer::audio_thread_func() { while (!should_quit) { @@ -902,51 +857,17 @@ void Mixer::audio_thread_func() ResamplingQueue::RateAdjustmentPolicy rate_adjustment_policy = task.adjust_rate ? ResamplingQueue::ADJUST_RATE : ResamplingQueue::DO_NOT_ADJUST_RATE; - process_audio_one_frame(task.pts_int, task.num_samples, rate_adjustment_policy); - } -} - -void Mixer::process_audio_one_frame(int64_t frame_pts_int, int num_samples, ResamplingQueue::RateAdjustmentPolicy rate_adjustment_policy) -{ - vector samples_out = audio_mixer.get_output(double(frame_pts_int) / TIMEBASE, num_samples, rate_adjustment_policy); - - // Upsample 4x to find interpolated peak. - peak_resampler.inp_data = samples_out.data(); - peak_resampler.inp_count = samples_out.size() / 2; - - vector interpolated_samples_out; - interpolated_samples_out.resize(samples_out.size()); - { - unique_lock lock(audio_measure_mutex); - - while (peak_resampler.inp_count > 0) { // About four iterations. - peak_resampler.out_data = &interpolated_samples_out[0]; - peak_resampler.out_count = interpolated_samples_out.size() / 2; - peak_resampler.process(); - size_t out_stereo_samples = interpolated_samples_out.size() / 2 - peak_resampler.out_count; - peak = max(peak, find_peak(interpolated_samples_out.data(), out_stereo_samples * 2)); - peak_resampler.out_data = nullptr; + vector samples_out = audio_mixer.get_output( + double(task.pts_int) / TIMEBASE, + task.num_samples, + rate_adjustment_policy); + + // Send the samples to the sound card, then add them to the output. + if (alsa) { + alsa->write(samples_out); } + video_encoder->add_audio(task.pts_int, move(samples_out)); } - - // Find R128 levels and L/R correlation. - vector left, right; - deinterleave_samples(samples_out, &left, &right); - float *ptrs[] = { left.data(), right.data() }; - { - unique_lock lock(audio_measure_mutex); - r128.process(left.size(), ptrs); - audio_mixer.set_current_loudness(r128.loudness_M()); - correlation.process_samples(samples_out); - } - - // Send the samples to the sound card. - if (alsa) { - alsa->write(samples_out); - } - - // And finally add them to the output. - video_encoder->add_audio(frame_pts_int, move(samples_out)); } void Mixer::subsample_chroma(GLuint src_tex, GLuint dst_tex) @@ -1042,16 +963,6 @@ void Mixer::channel_clicked(int preview_num) theme->channel_clicked(preview_num); } -void Mixer::reset_meters() -{ - unique_lock lock(audio_measure_mutex); - peak_resampler.reset(); - peak = 0.0f; - r128.reset(); - r128.integr_start(); - correlation.reset(); -} - void Mixer::start_mode_scanning(unsigned card_index) { assert(card_index < num_cards);