1 /*
2 * Copyright (c) 2024, Alliance for Open Media. All rights reserved
3 *
4 * This source code is subject to the terms of the BSD 3-Clause Clear License
5 * and the Alliance for Open Media Patent License 1.0. If the BSD 3-Clause Clear
6 * License was not distributed with this source code in the LICENSE file, you
7 * can obtain it at www.aomedia.org/license/software-license/bsd-3-c-c. If the
8 * Alliance for Open Media Patent License 1.0 was not distributed with this
9 * source code in the PATENTS file, you can obtain it at
10 * www.aomedia.org/license/patent.
11 */
12
13 #include <algorithm>
14 #include <cstddef>
15 #include <cstdlib>
16 #include <utility>
17 #include <vector>
18
19 #include "benchmark/benchmark.h"
20 #include "iamf/cli/ambisonic_encoder/ambisonic_encoder.h"
21
22 namespace iamf_tools {
23 namespace {
24
25 // Measure execution time of coefficient calculation using both implemented
26 // methods.
BM_SHCalculation(benchmark::State & state)27 static void BM_SHCalculation(benchmark::State& state) {
28 const size_t buffer_size = 1;
29 const int number_of_input_channels = 512;
30 const int ambisonic_order = 7;
31
32 // Create an array of azimuth/elevation pairs with random directions.
33 std::vector<std::pair<float, float>> directions;
34 for (int i = 0; i < number_of_input_channels; i++) {
35 float azimuth =
36 static_cast<float>(rand()) / static_cast<float>(RAND_MAX) * 360.0f;
37 float elevation =
38 static_cast<float>(rand()) / static_cast<float>(RAND_MAX) * 180.0f -
39 90.0f;
40 directions.push_back(std::make_pair(azimuth, elevation));
41 }
42
43 // Create an Ambisonic encoder object.
44 AmbisonicEncoder encoder(buffer_size, number_of_input_channels,
45 ambisonic_order);
46
47 for (auto _ : state) {
48 // Assign sources to the encoder at all available input channels.
49 for (int i = 0; i < number_of_input_channels; i++) {
50 encoder.SetSource(i, 1.0f, directions[i].first, directions[i].second,
51 1.0f);
52 }
53 }
54 }
55
56 BENCHMARK(BM_SHCalculation)->Args({0})->Args({1});
57
58 // Measure matrix multiplication time at different numbers of input channels.
59 // Test with matrix data set to zeros and filled with random data.
60 // TODO(b/374695317): Optimise matrix multiplication to avoid multiplication by
61 // columns of zeros (inactive inputs).
BM_MatrixMultiplication(benchmark::State & state)62 static void BM_MatrixMultiplication(benchmark::State& state) {
63 const size_t buffer_size = 256;
64 const int number_of_input_channels = state.range(0);
65 const int ambisonic_order = 7;
66 const bool fill_with_random_data = state.range(1) == 1;
67
68 // Create input buffer
69 std::vector<float> input_buffer(number_of_input_channels * buffer_size, 0.0f);
70 if (fill_with_random_data) {
71 std::generate(input_buffer.begin(), input_buffer.end(), []() {
72 return static_cast<float>(rand()) / static_cast<float>(RAND_MAX);
73 });
74 } else {
75 std::fill(input_buffer.begin(), input_buffer.end(), 0.0f);
76 }
77
78 // Create output buffer.
79 std::vector<float> output_buffer(
80 (ambisonic_order + 1) * (ambisonic_order + 1) * buffer_size, 0.0f);
81
82 // Create an Ambisonic encoder object.
83 AmbisonicEncoder encoder(buffer_size, number_of_input_channels,
84 ambisonic_order);
85
86 // Create an array of azimuth/elevation pairs with random directions.
87 std::vector<std::pair<float, float>> directions;
88 for (int i = 0; i < number_of_input_channels; i++) {
89 float azimuth =
90 static_cast<float>(rand()) / static_cast<float>(RAND_MAX) * 360.0f;
91 float elevation =
92 static_cast<float>(rand()) / static_cast<float>(RAND_MAX) * 180.0f -
93 90.0f;
94 directions.push_back(std::make_pair(azimuth, elevation));
95 }
96
97 // Assign sources to the encoder at all available input channels.
98 for (int i = 0; i < number_of_input_channels; i++) {
99 encoder.SetSource(i, 1.0f, directions[i].first, directions[i].second, 1.0f);
100 }
101
102 for (auto _ : state) {
103 // Perform matrix multiplication.
104 encoder.ProcessPlanarAudioData(input_buffer, output_buffer);
105 }
106 }
107
108 // Setup benchmark
109 BENCHMARK(BM_MatrixMultiplication)
110 ->Args({16, 0})
111 ->Args({16, 1})
112 ->Args({32, 0})
113 ->Args({32, 1})
114 ->Args({64, 0})
115 ->Args({64, 1})
116 ->Args({128, 0})
117 ->Args({128, 1});
118
119 } // namespace
120 } // namespace iamf_tools
121