From 1fc8b5d92fce7ac0b7e87ed3087e393774fd4b3c Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" Date: Thu, 25 Aug 2016 00:43:08 +0200 Subject: [PATCH] Add a benchmark for a simple audio chain; easier than profiling all of Nageru. --- .gitignore | 1 + Makefile | 12 ++++-- benchmark_audio_mixer.cpp | 86 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 96 insertions(+), 3 deletions(-) create mode 100644 benchmark_audio_mixer.cpp diff --git a/.gitignore b/.gitignore index e53266c..ea80de2 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ ui_display.h ui_input_mapping.h ui_mainwindow.h nageru +benchmark_audio_mixer diff --git a/Makefile b/Makefile index 1299697..b939b95 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,8 @@ OBJS=glwidget.o main.o mainwindow.o vumeter.o lrameter.o vu_common.o correlation OBJS += glwidget.moc.o mainwindow.moc.o vumeter.moc.o lrameter.moc.o correlation_meter.moc.o aboutdialog.moc.o ellipsis_label.moc.o input_mapping_dialog.moc.o nonlinear_fader.moc.o # Mixer objects -OBJS += mixer.o audio_mixer.o pbo_frame_allocator.o context.o ref_counted_frame.o theme.o resampling_queue.o httpd.o ebu_r128_proc.o flags.o image_input.o stereocompressor.o filter.o alsa_input.o alsa_output.o correlation_measurer.o disk_space_estimator.o +AUDIO_MIXER_OBJS = audio_mixer.o alsa_input.o ebu_r128_proc.o stereocompressor.o resampling_queue.o flags.o correlation_measurer.o filter.o disk_space_estimator.o +OBJS += mixer.o pbo_frame_allocator.o context.o ref_counted_frame.o theme.o httpd.o flags.o image_input.o alsa_output.o disk_space_estimator.o $(AUDIO_MIXER_OBJS) # Streaming and encoding objects OBJS += quicksync_encoder.o x264_encoder.o x264_speed_control.o video_encoder.o metacube2.o mux.o audio_encoder.o ffmpeg_raii.o @@ -30,6 +31,9 @@ ifeq ($(EMBEDDED_BMUSB),yes) OBJS += bmusb/bmusb.o bmusb/fake_capture.o endif +# Benchmark program. +BM_OBJS = benchmark_audio_mixer.o $(AUDIO_MIXER_OBJS) flags.o + %.o: %.cpp $(CXX) -MMD -MP $(CPPFLAGS) $(CXXFLAGS) -o $@ -c $< %.o: %.cc @@ -41,10 +45,12 @@ endif %.moc.cpp: %.h moc $< -o $@ -all: nageru +all: nageru benchmark_audio_mixer nageru: $(OBJS) $(CXX) -o $@ $^ $(LDFLAGS) $(LDLIBS) +benchmark_audio_mixer: $(BM_OBJS) + $(CXX) -o $@ $^ $(LDFLAGS) $(LDLIBS) mainwindow.o: mainwindow.cpp ui_mainwindow.h ui_display.h ui_audio_miniview.h ui_audio_expanded_view.h @@ -56,7 +62,7 @@ DEPS=$(OBJS:.o=.d) -include $(DEPS) clean: - $(RM) $(OBJS) $(DEPS) nageru ui_aboutdialog.h ui_mainwindow.h ui_display.h ui_about.h ui_audio_miniview.h ui_audio_expanded_view.h aboutdialog.moc.cpp correlation_meter.moc.cpp lrameter.moc.cpp vumeter.moc.cpp glwidget.moc.cpp mainwindow.moc.cpp window.moc.cpp chain-*.frag *.dot + $(RM) $(OBJS) $(BM_OBJS) $(DEPS) nageru benchmark_audio_mixer ui_aboutdialog.h ui_mainwindow.h ui_display.h ui_about.h ui_audio_miniview.h ui_audio_expanded_view.h aboutdialog.moc.cpp correlation_meter.moc.cpp lrameter.moc.cpp vumeter.moc.cpp glwidget.moc.cpp mainwindow.moc.cpp window.moc.cpp chain-*.frag *.dot PREFIX=/usr/local install: diff --git a/benchmark_audio_mixer.cpp b/benchmark_audio_mixer.cpp new file mode 100644 index 0000000..e61c4f4 --- /dev/null +++ b/benchmark_audio_mixer.cpp @@ -0,0 +1,86 @@ +// Rather simplistic benchmark of AudioMixer. Sets up a simple mapping +// with the default settings, feeds some white noise to the inputs and +// runs a while. Useful for e.g. profiling. + +#include +#include +#include +#include +#include "audio_mixer.h" +#include "timebase.h" + +#define NUM_BENCHMARK_CARDS 4 +#define NUM_WARMUP_FRAMES 100 +#define NUM_BENCHMARK_FRAMES 1000 +#define NUM_CHANNELS 8 +#define NUM_SAMPLES 1024 + +using namespace std; +using namespace std::chrono; + +uint8_t samples[(NUM_SAMPLES * NUM_CHANNELS + 1024) * sizeof(uint16_t)]; + +void callback(float level_lufs, float peak_db, + std::vector bus_levels, + float global_level_lufs, float range_low_lufs, float range_high_lufs, + float final_makeup_gain_db, + float correlation) +{ + // Empty. +} + +int main(void) +{ + for (unsigned i = 0; i < NUM_SAMPLES * NUM_CHANNELS + 1024; ++i) { + samples[i] = rand() & 0xff; + } + AudioMixer mixer(NUM_BENCHMARK_CARDS); + mixer.set_audio_level_callback(callback); + + InputMapping mapping; + + InputMapping::Bus bus1; + bus1.device = DeviceSpec{InputSourceType::CAPTURE_CARD, 0}; + bus1.source_channel[0] = 0; + bus1.source_channel[1] = 1; + mapping.buses.push_back(bus1); + + InputMapping::Bus bus2; + bus2.device = DeviceSpec{InputSourceType::CAPTURE_CARD, 3}; + bus2.source_channel[0] = 6; + bus2.source_channel[1] = 4; + mapping.buses.push_back(bus2); + + mixer.set_input_mapping(mapping); + + size_t out_samples = 0; + + steady_clock::time_point start, end; + for (unsigned i = 0; i < NUM_WARMUP_FRAMES + NUM_BENCHMARK_FRAMES; ++i) { + if (i == NUM_WARMUP_FRAMES) { + start = steady_clock::now(); + } + // Feed the inputs. + for (unsigned card_index = 0; card_index < NUM_BENCHMARK_CARDS; ++card_index) { + bmusb::AudioFormat audio_format; + audio_format.bits_per_sample = 16; + audio_format.num_channels = NUM_CHANNELS; + + unsigned num_samples = NUM_SAMPLES + (rand() % 9) - 5; + bool ok = mixer.add_audio(DeviceSpec{InputSourceType::CAPTURE_CARD, card_index}, samples, num_samples, audio_format, NUM_SAMPLES * TIMEBASE / OUTPUT_FREQUENCY); + assert(ok); + } + + double pts = double(i) * NUM_SAMPLES / OUTPUT_FREQUENCY; + vector output = mixer.get_output(pts, NUM_SAMPLES, ResamplingQueue::ADJUST_RATE); + if (i >= NUM_WARMUP_FRAMES) { + out_samples += output.size(); + } + } + end = steady_clock::now(); + + double elapsed = duration(end - start).count(); + double simulated = double(out_samples) / (OUTPUT_FREQUENCY * 2); + printf("%ld samples produced in %.1f ms (%.1f%% CPU, %.1fx realtime).\n", + out_samples, elapsed * 1e3, 100.0 * elapsed / simulated, simulated / elapsed); +} -- 2.39.2