]> git.sesse.net Git - nageru/commitdiff
Add a benchmark for a simple audio chain; easier than profiling all of Nageru.
authorSteinar H. Gunderson <sgunderson@bigfoot.com>
Wed, 24 Aug 2016 22:43:08 +0000 (00:43 +0200)
committerSteinar H. Gunderson <sgunderson@bigfoot.com>
Wed, 19 Oct 2016 22:55:44 +0000 (00:55 +0200)
.gitignore
Makefile
benchmark_audio_mixer.cpp [new file with mode: 0644]

index e53266c43078975d90555c7e9d552bc1a18d1f11..ea80de20624fd75bebdb4b3ddef7e1d6e35735cd 100644 (file)
@@ -8,3 +8,4 @@ ui_display.h
 ui_input_mapping.h
 ui_mainwindow.h
 nageru
+benchmark_audio_mixer
index 1299697e83782de4bdd2cb0175c5f33d8356f977..b939b95fb03de3b88a52dac0262f7ebbeaa856f0 100644 (file)
--- 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 (file)
index 0000000..e61c4f4
--- /dev/null
@@ -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 <stdio.h>
+#include <stdint.h>
+#include <vector>
+#include <chrono>
+#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<AudioMixer::BusLevel> 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<float> 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<double>(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);
+}