[mixer_service] Move filters to lib/processing
This change also removes unused point filter.
Bug: 87651
Multiply: audio-libprocessing-unittests
Multiply: audio_core_unittests
Multiply: audio_mixer_unittests
Multiply: audio-core-api-pipeline-tests
Multiply: audio-core-fidelity-test
Multiply: audio_fidelity_tests
Change-Id: Ia2020f6a63e9ae08e7f5bf3c7e0b1df2d02dd155
Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/693305
Reviewed-by: Tom Bergan <tombergan@google.com>
Commit-Queue: Alper Gungormusler <alperg@google.com>
diff --git a/src/media/audio/audio_core/BUILD.gn b/src/media/audio/audio_core/BUILD.gn
index 45d7499..a0657b2 100644
--- a/src/media/audio/audio_core/BUILD.gn
+++ b/src/media/audio/audio_core/BUILD.gn
@@ -248,7 +248,7 @@
output_name = "audio_core"
deps = [
":audio_core_main",
- "//src/media/audio/audio_core/mixer:empty_coefficient_tables",
+ "//src/media/audio/lib/processing:empty_coefficient_tables",
]
}
@@ -256,7 +256,7 @@
output_name = "audio_core_with_prebuilt_coefficient_tables"
deps = [
":audio_core_main",
- "//src/media/audio/audio_core/mixer:prebuilt_coefficient_tables",
+ "//src/media/audio/lib/processing:prebuilt_coefficient_tables",
]
}
@@ -333,13 +333,13 @@
"//src/lib/storage/vfs/cpp",
"//src/lib/testing/loop_fixture",
"//src/media/audio/audio_core/mixer",
- "//src/media/audio/audio_core/mixer:prebuilt_coefficient_tables",
"//src/media/audio/effects/test_effects:test_effects_v2",
"//src/media/audio/lib/clock/testing",
"//src/media/audio/lib/effects_loader",
"//src/media/audio/lib/effects_loader/testing",
"//src/media/audio/lib/format",
"//src/media/audio/lib/processing",
+ "//src/media/audio/lib/processing:prebuilt_coefficient_tables",
"//third_party/googletest:gmock",
"//zircon/system/ulib/async-loop:async-loop-cpp",
"//zircon/system/ulib/async-loop:async-loop-default",
@@ -373,7 +373,7 @@
sources = [ "policy_loader_fuzzer.cc" ]
deps = [
":audio_core_lib",
- "//src/media/audio/audio_core/mixer:prebuilt_coefficient_tables",
+ "//src/media/audio/lib/processing:prebuilt_coefficient_tables",
]
}
diff --git a/src/media/audio/audio_core/mixer/BUILD.gn b/src/media/audio/audio_core/mixer/BUILD.gn
index 72cb626..c0f5b57 100644
--- a/src/media/audio/audio_core/mixer/BUILD.gn
+++ b/src/media/audio/audio_core/mixer/BUILD.gn
@@ -9,25 +9,9 @@
public_deps = [ "//src/media/audio/lib/format:constants" ]
}
-source_set("coefficient_table") {
- sources = [
- "coefficient_table.cc",
- "coefficient_table.h",
- ]
-
- public_deps = [
- ":constants",
- "//sdk/lib/stdcompat",
- "//sdk/lib/syslog/cpp",
- ]
-}
-
source_set("mixer") {
sources = [
"channel_strip.h",
- "coefficient_table_cache.h",
- "filter.cc",
- "filter.h",
"gain.cc",
"gain.h",
"intersect.cc",
@@ -47,7 +31,6 @@
]
public_deps = [
- ":coefficient_table",
":constants",
"//sdk/fidl/fuchsia.media",
"//zircon/system/ulib/fbl",
@@ -86,25 +69,6 @@
deps = [ "tools" ]
}
-# Any executable which uses :mixer (either directly or transitively) must also
-# include either prebuilt or empty coefficient tables, via one of the following
-# two build rules. The decision of which tables to include is usually left to
-# the top-most build rule (i.e., the executable), since that rule often has the
-# most insight into system constraints, such as code size.
-
-source_set("prebuilt_coefficient_tables") {
- sources = [ "$target_gen_dir/coefficient_table_data_prebuilt.cc" ]
- deps = [
- ":build_coefficient_table_data_prebuilt_cc",
- ":coefficient_table",
- ]
-}
-
-source_set("empty_coefficient_tables") {
- sources = [ "coefficient_table_data_empty.cc" ]
- deps = [ ":coefficient_table" ]
-}
-
group("tests") {
testonly = true
deps = [
@@ -121,9 +85,6 @@
sources = [
"bookkeeping_unittest.cc",
"channel_strip_unittest.cc",
- "coefficient_table_cache_unittest.cc",
- "coefficient_table_unittest.cc",
- "filter_unittest.cc",
"gain_unittest.cc",
"intersect_unittest.cc",
"no_op_unittest.cc",
@@ -137,10 +98,10 @@
deps = [
":mixer",
"//src/lib/fxl/test:gtest_main",
- "//src/media/audio/audio_core/mixer:prebuilt_coefficient_tables",
"//src/media/audio/lib/format",
"//src/media/audio/lib/format2",
"//src/media/audio/lib/processing",
+ "//src/media/audio/lib/processing:prebuilt_coefficient_tables",
"//src/media/audio/lib/test:constants",
"//third_party/googletest:gmock",
"//zircon/system/ulib/fbl",
@@ -162,7 +123,7 @@
"//sdk/lib/syslog/cpp",
"//src/lib/fxl/test:gtest_main",
"//src/lib/testing/loop_fixture",
- "//src/media/audio/audio_core/mixer:prebuilt_coefficient_tables",
+ "//src/media/audio/lib/processing:prebuilt_coefficient_tables",
"//third_party/googletest:gmock",
]
}
@@ -176,27 +137,3 @@
}
}
}
-
-# This executable is run automatically as part of the build deps for
-# :prebuilt_coefficient_tables. It can be run manually -- the binary
-# can be found adjacent to other host tools.
-executable("gen_audio_filter_coefficient_tables") {
- sources = [
- "coefficient_table.cc",
- "coefficient_table.h",
- "constants.h",
- "gen_coefficient_tables.cc",
- ]
- deps = [
- "//sdk/lib/stdcompat",
- "//src/media/audio/lib/format:constants",
- ]
- defines = [ "BUILDING_FUCHSIA_AUDIO_HOST_TOOL=1" ]
-}
-
-compiled_action("build_coefficient_table_data_prebuilt_cc") {
- tool = ":gen_audio_filter_coefficient_tables"
- outputs = [ "$target_gen_dir/coefficient_table_data_prebuilt.cc" ]
- args = [ rebase_path(target_gen_dir, root_build_dir) +
- "/coefficient_table_data_prebuilt.cc" ]
-}
diff --git a/src/media/audio/audio_core/mixer/coefficient_table_data_empty.cc b/src/media/audio/audio_core/mixer/coefficient_table_data_empty.cc
deleted file mode 100644
index f77eadd..0000000
--- a/src/media/audio/audio_core/mixer/coefficient_table_data_empty.cc
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright 2020 The Fuchsia Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "src/media/audio/audio_core/mixer/coefficient_table.h"
-
-namespace media::audio::mixer {
-
-// This file is linked by builds that have no prebuilt coefficient tables.
-const cpp20::span<const PrebuiltSincFilterCoefficientTable> kPrebuiltSincFilterCoefficientTables;
-
-} // namespace media::audio::mixer
diff --git a/src/media/audio/audio_core/mixer/sinc_sampler.cc b/src/media/audio/audio_core/mixer/sinc_sampler.cc
index 541e39b1..840871f 100644
--- a/src/media/audio/audio_core/mixer/sinc_sampler.cc
+++ b/src/media/audio/audio_core/mixer/sinc_sampler.cc
@@ -11,12 +11,14 @@
#include "src/media/audio/audio_core/mixer/channel_strip.h"
#include "src/media/audio/audio_core/mixer/constants.h"
-#include "src/media/audio/audio_core/mixer/filter.h"
#include "src/media/audio/audio_core/mixer/position_manager.h"
+#include "src/media/audio/lib/processing/filter.h"
#include "src/media/audio/lib/processing/sampler.h"
namespace media::audio::mixer {
+using ::media_audio::SincFilter;
+
template <int32_t DestChanCount, typename SourceSampleType, int32_t SourceChanCount>
class SincSamplerImpl : public SincSampler {
public:
diff --git a/src/media/audio/audio_core/mixer/sinc_sampler_unittest.cc b/src/media/audio/audio_core/mixer/sinc_sampler_unittest.cc
index 1077cc7..adbe995 100644
--- a/src/media/audio/audio_core/mixer/sinc_sampler_unittest.cc
+++ b/src/media/audio/audio_core/mixer/sinc_sampler_unittest.cc
@@ -10,8 +10,8 @@
#include <fbl/algorithm.h>
#include <gtest/gtest.h>
-#include "src/media/audio/audio_core/mixer/filter.h"
#include "src/media/audio/lib/format/constants.h"
+#include "src/media/audio/lib/processing/filter.h"
#include "src/media/audio/lib/processing/gain.h"
namespace media::audio::mixer {
@@ -433,8 +433,8 @@
auto mixer = SelectSincSampler(1, 1, 48000, 48000, fuchsia::media::AudioSampleFormat::FLOAT);
ASSERT_NE(mixer, nullptr);
- EXPECT_EQ(mixer->pos_filter_width().raw_value(), SincFilter::kFracSideLength - 1);
- EXPECT_EQ(mixer->neg_filter_width().raw_value(), SincFilter::kFracSideLength - 1);
+ EXPECT_EQ(mixer->pos_filter_width().raw_value(), media_audio::SincFilter::kFracSideLength - 1);
+ EXPECT_EQ(mixer->neg_filter_width().raw_value(), media_audio::SincFilter::kFracSideLength - 1);
}
// Test basic position advancing, for integer rate and same-sized source and dest buffers.
diff --git a/src/media/audio/audio_core/mixer/test/BUILD.gn b/src/media/audio/audio_core/mixer/test/BUILD.gn
index d9e8b4f..d31b1b8 100644
--- a/src/media/audio/audio_core/mixer/test/BUILD.gn
+++ b/src/media/audio/audio_core/mixer/test/BUILD.gn
@@ -42,10 +42,10 @@
"//src/lib/fxl/test:test_settings",
"//src/lib/testing/loop_fixture",
"//src/media/audio/audio_core/mixer",
- "//src/media/audio/audio_core/mixer:prebuilt_coefficient_tables",
"//src/media/audio/lib/analysis",
"//src/media/audio/lib/format",
"//src/media/audio/lib/processing",
+ "//src/media/audio/lib/processing:prebuilt_coefficient_tables",
"//third_party/googletest:gmock",
"//zircon/system/ulib/fbl",
]
diff --git a/src/media/audio/audio_core/mixer/tools/BUILD.gn b/src/media/audio/audio_core/mixer/tools/BUILD.gn
index 67fefdf..99a933c 100644
--- a/src/media/audio/audio_core/mixer/tools/BUILD.gn
+++ b/src/media/audio/audio_core/mixer/tools/BUILD.gn
@@ -22,11 +22,11 @@
deps = [
"//src/lib/fxl",
"//src/media/audio/audio_core/mixer",
- "//src/media/audio/audio_core/mixer:empty_coefficient_tables",
"//src/media/audio/audio_core/mixer/test:frequency_set",
"//src/media/audio/lib/analysis",
"//src/media/audio/lib/format",
"//src/media/audio/lib/processing",
+ "//src/media/audio/lib/processing:empty_coefficient_tables",
"//src/performance/lib/profiler",
"//zircon/system/ulib/perftest",
]
diff --git a/src/media/audio/audio_core/test/api/BUILD.gn b/src/media/audio/audio_core/test/api/BUILD.gn
index 0544649..36ea335 100644
--- a/src/media/audio/audio_core/test/api/BUILD.gn
+++ b/src/media/audio/audio_core/test/api/BUILD.gn
@@ -86,16 +86,16 @@
source = "audio_core_fidelity_test.cc"
executable_deps = [
":fidelity_results",
- "//src/media/audio/audio_core/mixer:coefficient_table",
"//src/media/audio/lib/analysis",
+ "//src/media/audio/lib/processing:coefficient_table",
]
}
audio_core_api_test_component("audio_core_thermal_test") {
source = "audio_core_thermal_test.cc"
executable_deps = [
- "//src/media/audio/audio_core/mixer:coefficient_table",
"//src/media/audio/lib/analysis",
+ "//src/media/audio/lib/processing:coefficient_table",
]
}
diff --git a/src/media/audio/audio_core/test/api/audio_core_fidelity_test.cc b/src/media/audio/audio_core/test/api/audio_core_fidelity_test.cc
index 01f1891..f9db2a8 100644
--- a/src/media/audio/audio_core/test/api/audio_core_fidelity_test.cc
+++ b/src/media/audio/audio_core/test/api/audio_core_fidelity_test.cc
@@ -9,11 +9,11 @@
#include "fuchsia/media/audio/cpp/fidl.h"
#include "src/media/audio/audio_core/driver_output.h"
-#include "src/media/audio/audio_core/mixer/coefficient_table.h"
#include "src/media/audio/audio_core/test/api/fidelity_results.h"
#include "src/media/audio/audio_core/testing/integration/hermetic_fidelity_test.h"
#include "src/media/audio/audio_core/threading_model.h"
#include "src/media/audio/lib/analysis/generators.h"
+#include "src/media/audio/lib/processing/coefficient_table.h"
using ASF = fuchsia::media::AudioSampleFormat;
@@ -39,7 +39,7 @@
AUDIO_STREAM_UNIQUE_ID_BUILTIN_SPEAKERS;
static constexpr size_t kFilterWidthFrames =
- mixer::SincFilterCoefficientTable::kMaxFracSideLength >> Fixed::Format::FractionalBits;
+ media_audio::SincFilterCoefficientTable::kMaxFracSideLength >> Fixed::Format::FractionalBits;
static HermeticPipelineTest::PipelineConstants pipeline_constants(int32_t source_rate,
int32_t num_mix_stages = 1) {
diff --git a/src/media/audio/audio_core/test/api/fuzzer/BUILD.gn b/src/media/audio/audio_core/test/api/fuzzer/BUILD.gn
index 5e584a4..72463a4 100644
--- a/src/media/audio/audio_core/test/api/fuzzer/BUILD.gn
+++ b/src/media/audio/audio_core/test/api/fuzzer/BUILD.gn
@@ -15,9 +15,9 @@
"//sdk/lib/media/audio/cpp",
"//src/media/audio/audio_core:audio-core-for-test_audio_core_nodevfs_component",
"//src/media/audio/audio_core:audio_core_lib",
- "//src/media/audio/audio_core/mixer:prebuilt_coefficient_tables",
"//src/media/audio/audio_core/testing",
"//src/media/audio/lib/audio_test_devmgr:audio-test-devmgr",
+ "//src/media/audio/lib/processing:prebuilt_coefficient_tables",
"//src/media/audio/lib/test:hermetic_audio_test",
]
services = [
diff --git a/src/media/audio/audio_core/test/config_validator/BUILD.gn b/src/media/audio/audio_core/test/config_validator/BUILD.gn
index 32be814..e6c137b 100644
--- a/src/media/audio/audio_core/test/config_validator/BUILD.gn
+++ b/src/media/audio/audio_core/test/config_validator/BUILD.gn
@@ -9,6 +9,6 @@
"//src/lib/files",
"//src/lib/fxl/test:gtest_main",
"//src/media/audio/audio_core:audio_core_lib",
- "//src/media/audio/audio_core/mixer:prebuilt_coefficient_tables",
+ "//src/media/audio/lib/processing:prebuilt_coefficient_tables",
]
}
diff --git a/src/media/audio/audio_core/testing/integration/BUILD.gn b/src/media/audio/audio_core/testing/integration/BUILD.gn
index a70522f..98e31c7 100644
--- a/src/media/audio/audio_core/testing/integration/BUILD.gn
+++ b/src/media/audio/audio_core/testing/integration/BUILD.gn
@@ -30,12 +30,12 @@
"//sdk/lib/sys/inspect/cpp",
"//sdk/lib/syslog/cpp",
"//src/media/audio/audio_core:audio_core_lib",
- "//src/media/audio/audio_core/mixer:prebuilt_coefficient_tables",
"//src/media/audio/effects/test_effects:test_effects_v2",
"//src/media/audio/lib/analysis",
"//src/media/audio/lib/clock",
"//src/media/audio/lib/format",
"//src/media/audio/lib/processing",
+ "//src/media/audio/lib/processing:prebuilt_coefficient_tables",
"//src/media/audio/lib/test:comparators",
"//src/media/audio/lib/test:constants",
"//src/media/audio/lib/test:test_fixture",
diff --git a/src/media/audio/audio_core/tools/output_pipeline_benchmark/pipeline_benchmark.gni b/src/media/audio/audio_core/tools/output_pipeline_benchmark/pipeline_benchmark.gni
index d1cc6d6..1a29c97 100644
--- a/src/media/audio/audio_core/tools/output_pipeline_benchmark/pipeline_benchmark.gni
+++ b/src/media/audio/audio_core/tools/output_pipeline_benchmark/pipeline_benchmark.gni
@@ -79,12 +79,12 @@
"//sdk/fidl/fuchsia.media",
"//src/lib/fxl",
"//src/media/audio/audio_core:audio_core_lib",
- "//src/media/audio/audio_core/mixer:prebuilt_coefficient_tables",
"//src/media/audio/audio_core/testing",
"//src/media/audio/lib/analysis",
"//src/media/audio/lib/clock/testing",
"//src/media/audio/lib/effects_loader",
"//src/media/audio/lib/format",
+ "//src/media/audio/lib/processing:prebuilt_coefficient_tables",
"//src/performance/lib/profiler",
"//zircon/system/ulib/perftest",
]
diff --git a/src/media/audio/lib/clock/testing/BUILD.gn b/src/media/audio/lib/clock/testing/BUILD.gn
index 7d4a5fb..a1db839 100644
--- a/src/media/audio/lib/clock/testing/BUILD.gn
+++ b/src/media/audio/lib/clock/testing/BUILD.gn
@@ -37,7 +37,7 @@
"//src/lib/fxl/test:gtest_main",
"//src/lib/testing/loop_fixture",
"//src/media/audio/audio_core:audio_core_lib",
- "//src/media/audio/audio_core/mixer:prebuilt_coefficient_tables",
+ "//src/media/audio/lib/processing:prebuilt_coefficient_tables",
]
}
diff --git a/src/media/audio/lib/processing/BUILD.gn b/src/media/audio/lib/processing/BUILD.gn
index f9505f5..9070960 100644
--- a/src/media/audio/lib/processing/BUILD.gn
+++ b/src/media/audio/lib/processing/BUILD.gn
@@ -9,6 +9,19 @@
deps = [ ":audio-libprocessing-unittests" ]
}
+source_set("coefficient_table") {
+ sources = [
+ "coefficient_table.cc",
+ "coefficient_table.h",
+ ]
+
+ public_deps = [
+ "//sdk/lib/stdcompat",
+ "//sdk/lib/syslog/cpp",
+ "//src/media/audio/lib/format2:fixed",
+ ]
+}
+
source_set("processing") {
sources = [
"gain_control.cc",
@@ -25,6 +38,9 @@
source_set("sampler") {
sources = [
+ "coefficient_table_cache.h",
+ "filter.cc",
+ "filter.h",
"gain.h",
"point_sampler.cc",
"point_sampler.h",
@@ -32,8 +48,10 @@
]
deps = [
+ ":coefficient_table",
"//sdk/lib/syslog/cpp",
"//src/media/audio/lib/format2",
+ "//zircon/system/ulib/trace",
]
# Building without optimizations causes significant slowdowns for these components; the additional
@@ -53,12 +71,54 @@
]
}
+# Any executable which uses `sampler` (either directly or transitively) must also include either
+# `prebuilt_coefficient_tables` or `empty_coefficient_tables` below. The decision of which tables to
+# include is usually left to the top-most build rule (i.e., the executable), since that rule often
+# has the most insight into system constraints, such as code size.
+source_set("prebuilt_coefficient_tables") {
+ sources = [ "$target_gen_dir/coefficient_table_data_prebuilt.cc" ]
+ deps = [
+ ":build_coefficient_table_data_prebuilt_cc",
+ ":coefficient_table",
+ ]
+}
+
+source_set("empty_coefficient_tables") {
+ sources = [ "coefficient_table_data_empty.cc" ]
+ deps = [ ":coefficient_table" ]
+}
+
+# This executable is run automatically as part of the build deps for `prebuilt_coefficient_tables`.
+# It can also be run manually - the binary can be found adjacent to other host tools.
+executable("gen_audio_filter_coefficient_tables") {
+ sources = [
+ "coefficient_table.cc",
+ "coefficient_table.h",
+ "gen_coefficient_tables.cc",
+ ]
+ deps = [
+ "//sdk/lib/stdcompat",
+ "//src/media/audio/lib/format2:fixed",
+ ]
+ defines = [ "BUILDING_FUCHSIA_AUDIO_HOST_TOOL=1" ]
+}
+
+compiled_action("build_coefficient_table_data_prebuilt_cc") {
+ tool = ":gen_audio_filter_coefficient_tables"
+ outputs = [ "$target_gen_dir/coefficient_table_data_prebuilt.cc" ]
+ args = [ rebase_path(target_gen_dir, root_build_dir) +
+ "/coefficient_table_data_prebuilt.cc" ]
+}
+
executable("unittest-bin") {
visibility = [ ":*" ]
testonly = true
output_name = "audio-libprocessing-unittests"
sources = [
+ "coefficient_table_cache_unittest.cc",
+ "coefficient_table_unittest.cc",
+ "filter_unittest.cc",
"gain_control_unittest.cc",
"gain_unittest.cc",
"point_sampler_unittest.cc",
@@ -66,9 +126,12 @@
]
deps = [
+ ":coefficient_table",
":processing",
+ "//sdk/lib/syslog/cpp",
"//src/lib/fxl/test:gtest_main",
"//src/media/audio/lib/format2",
+ "//src/media/audio/lib/processing:prebuilt_coefficient_tables",
"//third_party/googletest:gmock",
]
}
diff --git a/src/media/audio/audio_core/mixer/coefficient_table.cc b/src/media/audio/lib/processing/coefficient_table.cc
similarity index 70%
rename from src/media/audio/audio_core/mixer/coefficient_table.cc
rename to src/media/audio/lib/processing/coefficient_table.cc
index 0a9393d..7cd09a3 100644
--- a/src/media/audio/audio_core/mixer/coefficient_table.cc
+++ b/src/media/audio/lib/processing/coefficient_table.cc
@@ -1,33 +1,15 @@
-// Copyright 2020 The Fuchsia Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
+// Copyright 2022 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
-#include "src/media/audio/audio_core/mixer/coefficient_table.h"
+#include "src/media/audio/lib/processing/coefficient_table.h"
#include <algorithm>
+#include <limits>
+#include <memory>
-namespace media::audio::mixer {
+namespace media_audio {
-// Calculate our nearest-neighbor filter. With it we perform frame-rate conversion.
-std::unique_ptr<CoefficientTable> PointFilterCoefficientTable::Create(Inputs inputs) {
- CoefficientTableBuilder table(inputs.side_length, inputs.num_frac_bits);
-
- // kHalfFrameIdx should always be the last idx in the filter table, because our ctor sets
- // side_length to (1 << (num_frac_bits - 1)), which == (frac_size >> 1)
- const int64_t kHalfFrameIdx = 1 << (inputs.num_frac_bits - 1); // frac_half
- FX_CHECK(inputs.side_length == kHalfFrameIdx + 1);
-
- // Just a rectangular window, with the exact midpoint performing averaging (for zero phase).
- for (auto idx = 0; idx < kHalfFrameIdx; ++idx) {
- table[idx] = 1.0f;
- }
-
- // Here we average, so that we are zero-phase
- table[kHalfFrameIdx] = 0.5f;
-
- return table.Build();
-}
-
-// Calculate our linear-interpolation filter. With it we perform frame-rate conversion.
std::unique_ptr<CoefficientTable> LinearFilterCoefficientTable::Create(Inputs inputs) {
CoefficientTableBuilder table(inputs.side_length, inputs.num_frac_bits);
@@ -51,7 +33,6 @@
return table.Build();
}
-// Calculate our windowed-sinc FIR filter. With it we perform band-limited frame-rate conversion.
std::unique_ptr<CoefficientTable> SincFilterCoefficientTable::Create(Inputs inputs) {
CoefficientTableBuilder table(inputs.side_length, inputs.num_frac_bits);
@@ -102,4 +83,4 @@
return table.Build();
}
-} // namespace media::audio::mixer
+} // namespace media_audio
diff --git a/src/media/audio/audio_core/mixer/coefficient_table.h b/src/media/audio/lib/processing/coefficient_table.h
similarity index 66%
rename from src/media/audio/audio_core/mixer/coefficient_table.h
rename to src/media/audio/lib/processing/coefficient_table.h
index 1699a51..d9ab300 100644
--- a/src/media/audio/audio_core/mixer/coefficient_table.h
+++ b/src/media/audio/lib/processing/coefficient_table.h
@@ -1,22 +1,23 @@
-// Copyright 2020 The Fuchsia Authors. All rights reserved.
+// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef SRC_MEDIA_AUDIO_AUDIO_CORE_MIXER_COEFFICIENT_TABLE_H_
-#define SRC_MEDIA_AUDIO_AUDIO_CORE_MIXER_COEFFICIENT_TABLE_H_
+#ifndef SRC_MEDIA_AUDIO_LIB_PROCESSING_COEFFICIENT_TABLE_H_
+#define SRC_MEDIA_AUDIO_LIB_PROCESSING_COEFFICIENT_TABLE_H_
#include <lib/stdcompat/span.h>
+#include <algorithm>
#include <cmath>
-#include <map>
#include <memory>
-#include <mutex>
+#include <optional>
+#include <tuple>
+#include <utility>
#include <vector>
-#include "src/media/audio/audio_core/mixer/constants.h"
-#include "src/media/audio/lib/format/constants.h"
+#include "src/media/audio/lib/format2/fixed.h"
-// coefficient_table.h is included by gen_coefficient_tables.cc, which does not have access to
+// `coefficient_table.h` is included by `gen_coefficient_tables.cc`, which does not have access to
// Fuchsia headers because it is compiled as a host binary.
#ifndef BUILDING_FUCHSIA_AUDIO_HOST_TOOL
#include <lib/syslog/cpp/macros.h> // nogncheck
@@ -25,22 +26,22 @@
#define FX_CHECK(cond) assert(cond)
#endif
-namespace media::audio::mixer {
+namespace media_audio {
-// CoefficientTable is a shim around std::vector that maps indicies into a physical addressing
-// scheme that is most optimal WRT to how this table is typically accessed. Specifically accesses
-// are most commonly with an integral stride (that is 1 << frac_bits stride). Optimize for this use
-// case by placing these values physically contiguously in memory.
+// `CoefficientTable` is a shim around `std::vector` that maps indices into a physical addressing
+// scheme that is most optimal with respect to how this table is typically accessed. More
+// specifically, they are most commonly accessed with an integral stride (that is `1 << frac_bits`
+// stride). We optimize for this use case by placing these values physically contiguously in memory.
//
// Coefficient tables represent one side of a symmetric convolution filter. Coefficients cover the
-// entire discrete space of fractional position values, but for any calculation we reference only
-// a small subset of these values (see ReadSlice for an example).
+// entire discrete space of fractional position values, but for any calculation we reference only a
+// small subset of these values (see `ReadSlice` below for an example).
class CoefficientTable {
public:
- // |width| is the filter width of this table, in fixed point format with |frac_bits| of fractional
- // precision. The |width| will determine the number of entries in the table, which will be |width|
- // rounded up to the nearest integer in the same fixed-point format. |data| provides the raw table
- // data ordered by physical address. If |data| is empty, storage is allocated automatically.
+ // `width` is the filter width of this table, in fixed point format with `frac_bits` of fractional
+ // precision. The `width` will determine the number of entries in the table, which will be `width`
+ // rounded up to the nearest integer in the same fixed-point format. `data` provides the raw table
+ // data ordered by physical address. If `data` is empty, storage is allocated automatically.
CoefficientTable(int64_t width, int32_t frac_bits, cpp20::span<const float> data)
: stride_(ComputeStride(width, frac_bits)),
frac_filter_width_(width),
@@ -48,22 +49,24 @@
frac_mask_((1 << frac_bits_) - 1),
storage_(data.empty() ? std::make_optional<std::vector<float>>(stride_ * (1 << frac_bits))
: std::nullopt),
- table_(data.empty() ? cpp20::span<const float>(&(*storage_)[0], storage_->size()) : data) {
+ table_(data.empty() ? cpp20::span<const float>(storage_->begin(), storage_->end()) : data) {
FX_CHECK(frac_filter_width_ >= 0);
FX_CHECK(static_cast<int64_t>(table_.size()) == stride_ * (1 << frac_bits));
}
const float& operator[](int64_t offset) const { return table_[PhysicalIndex(offset)]; }
- // Reads |num_coefficients| coefficients starting at |offset|. The result is a pointer to
- // |num_coefficients| coefficients with the following semantics:
+ // Reads `num_coefficients` coefficients starting at `offset`. The result is a pointer to
+ // `num_coefficients` coefficients with the following semantics:
//
+ // ```
// auto c = new CoefficientTable(width, frac_bits);
// auto f = c->ReadSlice(offset, size);
// ASSERT_EQ(f[0], c[off + 0 << frac_bits]);
// ASSERT_EQ(f[1], c[off + 1 << frac_bits]);
// ...
// ASSERT_EQ(f[size], c[off + size << frac_bits]);
+ // ```
const float* ReadSlice(int64_t offset, int64_t num_coefficients) const {
if (num_coefficients <= 0 ||
offset + ((num_coefficients - 1) << frac_bits_) > frac_filter_width_) {
@@ -103,8 +106,8 @@
cpp20::span<const float> table_;
};
-// CoefficientTableBuilder constructs a single CoefficientTable.
-// Once constructed, the CoefficientTable is immutable.
+// `CoefficientTableBuilder` constructs a single `CoefficientTable`.
+// Once constructed, the `CoefficientTable` is immutable.
class CoefficientTableBuilder {
public:
CoefficientTableBuilder(int64_t width, int32_t frac_bits)
@@ -122,34 +125,10 @@
std::unique_ptr<CoefficientTable> table_;
};
-// Nearest-neighbor "zero-order interpolation" resampler, implemented using the convolution
-// filter. Length on both sides is half a frame + 1 subframe (expressed in our fixed-point
-// fractional scale), modulo the stretching effects of downsampling.
-//
-// Example: for frac_size 1000, filter_length would be 500, entailing coefficient values for
-// locations from that exact position, up to positions as much as 500 away. This means:
-// - Fractional source pos 1.499 requires frames between 0.999 and 1.999, thus source frame 1
-// - Fractional source pos 1.500 requires frames between 1.000 and 2.000, thus source frames 1 and 2
-// - Fractional source pos 1.501 requires frames between 1.001 and 2.001, thus source frame 2
-// For source pos .5, we average the pre- and post- values so as to achieve zero phase delay
-class PointFilterCoefficientTable {
- public:
- struct Inputs {
- int64_t side_length;
- int32_t num_frac_bits;
-
- bool operator<(const Inputs& rhs) const {
- return std::tie(side_length, num_frac_bits) < std::tie(rhs.side_length, rhs.num_frac_bits);
- }
- };
-
- static std::unique_ptr<CoefficientTable> Create(Inputs);
-};
-
// Linear interpolation, implemented using the convolution filter.
// Length on both sides is one frame, modulo the stretching effects of downsampling.
//
-// Example: for frac_size 1000, filter_length would be 999, entailing coefficient values for
+// Example: for `frac_size` 1000, `filter_length` would be 999, entailing coefficient values for
// locations from that exact position, up to positions as much as 999 away. This means:
// -Fractional source pos 1.999 requires frames between 1.000 and 2.998, thus source frames 1 and 2
// -Fractional source pos 2.001 requires frames between 1.002 and 3.000, thus source frames 2 and 3
@@ -166,6 +145,7 @@
}
};
+ // Creates linear-interpolation filter with frame-rate conversion.
static std::unique_ptr<CoefficientTable> Create(Inputs);
};
@@ -201,8 +181,8 @@
static_cast<int64_t>(std::ceil(static_cast<double>(filter_length * source_frame_rate) /
static_cast<double>(dest_frame_rate)));
- // For down-sampling ratios beyond kMaxDownsampleRatioForFullSideTaps the effective number of
- // side taps decreases proportionally -- rate-conversion quality gracefully degrades.
+ // For down-sampling ratios beyond `kMaxDownsampleRatioForFullSideTaps` the effective number
+ // of side taps decreases proportionally -- rate-conversion quality gracefully degrades.
filter_length = std::min(filter_length, kMaxFracSideLength);
}
@@ -217,10 +197,11 @@
};
}
+ // Creates windowed-sinc FIR filter with band-limited frame-rate conversion.
static std::unique_ptr<CoefficientTable> Create(Inputs);
};
-// These global structs This global struct describes a set of prebuilt coefficient tables.
+// This global struct describes a set of prebuilt coefficient tables.
struct PrebuiltSincFilterCoefficientTable {
int32_t source_rate;
int32_t dest_rate;
@@ -228,11 +209,10 @@
};
// The list of prebuilt coefficient tables.
-// This uses std::array so it can directly reference data in .rodata without reallocating
-// (std::vector would allocate and copy from .rodata).
+// This uses `std::array` so it can directly reference data in `.rodata` without reallocating.
extern const cpp20::span<const PrebuiltSincFilterCoefficientTable>
kPrebuiltSincFilterCoefficientTables;
-} // namespace media::audio::mixer
+} // namespace media_audio
-#endif // SRC_MEDIA_AUDIO_AUDIO_CORE_MIXER_COEFFICIENT_TABLE_H_
+#endif // SRC_MEDIA_AUDIO_LIB_PROCESSING_COEFFICIENT_TABLE_H_
diff --git a/src/media/audio/audio_core/mixer/coefficient_table_cache.h b/src/media/audio/lib/processing/coefficient_table_cache.h
similarity index 74%
rename from src/media/audio/audio_core/mixer/coefficient_table_cache.h
rename to src/media/audio/lib/processing/coefficient_table_cache.h
index d8a7c28..4f80023 100644
--- a/src/media/audio/audio_core/mixer/coefficient_table_cache.h
+++ b/src/media/audio/lib/processing/coefficient_table_cache.h
@@ -1,34 +1,34 @@
-// Copyright 2020 The Fuchsia Authors. All rights reserved.
+// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef SRC_MEDIA_AUDIO_AUDIO_CORE_MIXER_COEFFICIENT_TABLE_CACHE_H_
-#define SRC_MEDIA_AUDIO_AUDIO_CORE_MIXER_COEFFICIENT_TABLE_CACHE_H_
+#ifndef SRC_MEDIA_AUDIO_LIB_PROCESSING_COEFFICIENT_TABLE_CACHE_H_
+#define SRC_MEDIA_AUDIO_LIB_PROCESSING_COEFFICIENT_TABLE_CACHE_H_
#include <lib/fit/function.h>
#include <lib/syslog/cpp/macros.h>
-#include <zircon/compiler.h>
#include <map>
#include <memory>
#include <mutex>
+#include <utility>
#include "src/lib/fxl/synchronization/thread_annotations.h"
-#include "src/media/audio/audio_core/mixer/coefficient_table.h"
+#include "src/media/audio/lib/processing/coefficient_table.h"
-namespace media::audio::mixer {
+namespace media_audio {
-// A cache of CoefficientTables. These use a lot of memory so we try to reuse them as much as
-// possible. For example, different Filters might use the same underlying coefficient table with
-// slightly different Filter parameters. Additionally, different mixers might use the same Filter.
+// A cache of `CoefficientTables`. These use a lot of memory so we try to reuse them as much as
+// possible. For example, different filters might use the same underlying coefficient table with
+// slightly different filter parameters. Additionally, different samplers might use the same filter.
//
-// InputT defines the set of inputs that are used to construct the CoefficientTable.
+// `InputT` defines the set of inputs that are used to construct the CoefficientTable.
template <class InputT>
class CoefficientTableCache {
public:
- // Thread-safe reference-counted pointer to a cached CoefficientTable.
- // This is like a std::shared_ptr, except the destructor runs atomically with Get()
- // to simplify cache garbage collection.
+ // Thread-safe reference-counted pointer to a cached `CoefficientTable`.
+ // This is like a `std::shared_ptr`, except the destructor runs atomically with a `Get` call to
+ // simplify cache garbage collection.
class SharedPtr {
public:
SharedPtr() = default;
@@ -70,13 +70,13 @@
explicit CoefficientTableCache(fit::function<CoefficientTable*(const InputT&)> create_table)
: create_table_(std::move(create_table)) {}
- // Get returns a cached table for the given inputs, or if a cached tabled does not exist, a new
- // table is created and stored in the cache.
+ // Returns a cached table for the given inputs, or if a cached tabled does not exist, a new table
+ // is created and stored in the cache.
SharedPtr Get(InputT inputs) {
return AddEntry(inputs, [this, inputs]() { return create_table_(inputs); });
}
- // Add is like Get, but uses the given table rather than creating a new one.
+ // Similar to `Get`, but uses the given table rather than creating a new one.
SharedPtr Add(InputT inputs, CoefficientTable* table) {
return AddEntry(inputs, [table]() { return table; });
}
@@ -87,7 +87,7 @@
// This allows multiple threads to create tables concurrently.
mutex_.lock();
- // std::map guarantees that iterators are not invalidated until erased.
+ // `std::map` guarantees that iterators are not invalidated until erased.
// We hold onto this iterator until the reference is dropped.
auto lookup_result = cache_.insert(std::make_pair(inputs, std::make_unique<Entry>()));
auto it = lookup_result.first;
@@ -129,8 +129,8 @@
fit::function<CoefficientTable*(InputT)> create_table_;
};
-// LazySharedCoefficientTable is a wrapper around CoefficientTables that are constructed lazily.
-// This is a simple way to construct a CoefficientTable table in any thread (such as the FIDL loop
+// `LazySharedCoefficientTable` is a wrapper around `CoefficientTables` that are constructed lazily.
+// This is a simple way to construct a `CoefficientTable` table in any thread (such as the FIDL loop
// thread) but delay the potentially-expensive step of building the table until the table is
// actually needed, possibly on another thread.
template <class InputT>
@@ -157,6 +157,6 @@
typename CacheT::SharedPtr ptr_;
};
-} // namespace media::audio::mixer
+} // namespace media_audio
#endif // SRC_MEDIA_AUDIO_AUDIO_CORE_MIXER_COEFFICIENT_TABLE_CACHE_H_
diff --git a/src/media/audio/audio_core/mixer/coefficient_table_cache_unittest.cc b/src/media/audio/lib/processing/coefficient_table_cache_unittest.cc
similarity index 93%
rename from src/media/audio/audio_core/mixer/coefficient_table_cache_unittest.cc
rename to src/media/audio/lib/processing/coefficient_table_cache_unittest.cc
index 24b1d29..7189fe5 100644
--- a/src/media/audio/audio_core/mixer/coefficient_table_cache_unittest.cc
+++ b/src/media/audio/lib/processing/coefficient_table_cache_unittest.cc
@@ -1,14 +1,16 @@
-// Copyright 2020 The Fuchsia Authors. All rights reserved.
+// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "src/media/audio/audio_core/mixer/coefficient_table_cache.h"
+#include "src/media/audio/lib/processing/coefficient_table_cache.h"
+
+#include <utility>
#include <gtest/gtest.h>
-#include "src/media/audio/lib/format/constants.h"
+#include "src/media/audio/lib/format2/fixed.h"
-namespace media::audio::mixer {
+namespace media_audio {
namespace {
CoefficientTable* MakeCoefficientTable() {
@@ -111,4 +113,4 @@
}
} // namespace
-} // namespace media::audio::mixer
+} // namespace media_audio
diff --git a/src/media/audio/lib/processing/coefficient_table_data_empty.cc b/src/media/audio/lib/processing/coefficient_table_data_empty.cc
new file mode 100644
index 0000000..afd2ca3
--- /dev/null
+++ b/src/media/audio/lib/processing/coefficient_table_data_empty.cc
@@ -0,0 +1,14 @@
+// Copyright 2022 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <lib/stdcompat/span.h>
+
+#include "src/media/audio/lib/processing/coefficient_table.h"
+
+namespace media_audio {
+
+// This file is linked by builds that have no prebuilt coefficient tables.
+const cpp20::span<const PrebuiltSincFilterCoefficientTable> kPrebuiltSincFilterCoefficientTables;
+
+} // namespace media_audio
diff --git a/src/media/audio/audio_core/mixer/coefficient_table_unittest.cc b/src/media/audio/lib/processing/coefficient_table_unittest.cc
similarity index 88%
rename from src/media/audio/audio_core/mixer/coefficient_table_unittest.cc
rename to src/media/audio/lib/processing/coefficient_table_unittest.cc
index d9d748f..dcf6121 100644
--- a/src/media/audio/audio_core/mixer/coefficient_table_unittest.cc
+++ b/src/media/audio/lib/processing/coefficient_table_unittest.cc
@@ -2,13 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "src/media/audio/audio_core/mixer/coefficient_table.h"
+#include "src/media/audio/lib/processing/coefficient_table.h"
#include <gtest/gtest.h>
-#include "src/media/audio/lib/format/constants.h"
+#include "src/media/audio/lib/format2/fixed.h"
-namespace media::audio::mixer {
+namespace media_audio {
+namespace {
TEST(CoefficientTableTest, AllIndicesAccessible) {
Fixed width(10);
@@ -32,8 +33,8 @@
cpp20::span<const float>{});
for (int64_t fraction = 0; fraction < kOneFrame.raw_value(); ++fraction) {
- // Each fractional value will have a block in the vector. Now check that
- // every valid integral value is contiguous for this fractional value.
+ // Each fractional value will have a block in the vector. Now check that every valid integral
+ // value is contiguous for this fractional value.
auto block_index = fraction * width.Ceiling();
for (int64_t integer = 0; integer < width.Ceiling(); ++integer) {
auto fixed_value = (integer << Fixed::Format::FractionalBits) + fraction;
@@ -62,4 +63,5 @@
}
}
-} // namespace media::audio::mixer
+} // namespace
+} // namespace media_audio
diff --git a/src/media/audio/audio_core/mixer/filter.cc b/src/media/audio/lib/processing/filter.cc
similarity index 88%
rename from src/media/audio/audio_core/mixer/filter.cc
rename to src/media/audio/lib/processing/filter.cc
index c6dd1d0..bf3a53a 100644
--- a/src/media/audio/audio_core/mixer/filter.cc
+++ b/src/media/audio/lib/processing/filter.cc
@@ -1,22 +1,31 @@
-// Copyright 2019 The Fuchsia Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
+// Copyright 2022 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
-#include "src/media/audio/audio_core/mixer/filter.h"
+#include "src/media/audio/lib/processing/filter.h"
#include <lib/syslog/cpp/macros.h>
#include <lib/trace/event.h>
#include <lib/zx/clock.h>
#include <iomanip>
+#include <ios>
+#include <limits>
#include <memory>
-#include <mutex>
+#include <vector>
-#include "src/media/audio/audio_core/mixer/coefficient_table.h"
-#include "src/media/audio/audio_core/mixer/logging_flags.h"
+#include "src/media/audio/lib/processing/coefficient_table.h"
-namespace media::audio::mixer {
+namespace media_audio {
-// Display the filter table values.
+namespace {
+
+// Debug computation of output values (`ComputeSample`), from coefficients and input values.
+// Extremely verbose, only useful in a controlled unittest setting.
+constexpr bool kTraceFilterComputation = false;
+
+} // namespace
+
void Filter::DisplayTable(const CoefficientTable& filter_coefficients) {
FX_LOGS(INFO) << "Filter: source rate " << source_rate_ << ", dest rate " << dest_rate_
<< ", length 0x" << std::hex << side_length_;
@@ -45,12 +54,12 @@
FX_LOGS(INFO) << " **************************************************************";
}
-// For frac_offset in [0.0, 1.0) we require source frames on each side depending on filter length.
-// Source frames are at integral positions, but we treat frac_offset as filter center, so source
+// For `frac_offset` in [0.0, 1.0) we require source frames on each side depending on filter length.
+// Source frames are at integral positions, but we treat `frac_offset` as filter center, so source
// frames appear to be fractionally positioned.
//
// Filter coefficients cover the entire discrete space of fractional positions, but any calculation
-// references only a subset of these, using a one-frame stride (frac_size_). Coefficient tables
+// references only a subset of these, using a one-frame stride (`frac_size_`). Coefficient tables
// internally store values with an integer stride contiguously, which is what these loops want.
// Ex:
// coefficient_ptr[1] == filter_coefficients[frac_offset + frac_size_];
@@ -167,23 +176,14 @@
return cache;
}
-// static
-PointFilter::CacheT* const PointFilter::cache_ =
- new PointFilter::CacheT([](PointFilterCoefficientTable::Inputs inputs) {
- TRACE_DURATION("audio", "CreatePointFilterTable");
- return PointFilterCoefficientTable::Create(inputs).release();
- });
-
-// static
LinearFilter::CacheT* const LinearFilter::cache_ =
new LinearFilter::CacheT([](LinearFilterCoefficientTable::Inputs inputs) {
TRACE_DURATION("audio", "CreateLinearFilterTable");
return LinearFilterCoefficientTable::Create(inputs).release();
});
-// static
-// Must initialize persistent_cache_ first as it's used by the Create function.
+// Must initialize `persistent_cache_` first as it's used by the `Create` function.
std::vector<SincFilter::CacheT::SharedPtr>* SincFilter::persistent_cache_ = nullptr;
SincFilter::CacheT* const SincFilter::cache_ = CreateSincFilterCoefficientTableCache();
-} // namespace media::audio::mixer
+} // namespace media_audio
diff --git a/src/media/audio/audio_core/mixer/filter.h b/src/media/audio/lib/processing/filter.h
similarity index 68%
rename from src/media/audio/audio_core/mixer/filter.h
rename to src/media/audio/lib/processing/filter.h
index aefb8f0..6ee56b0 100644
--- a/src/media/audio/audio_core/mixer/filter.h
+++ b/src/media/audio/lib/processing/filter.h
@@ -1,28 +1,24 @@
-// Copyright 2019 The Fuchsia Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
+// Copyright 2022 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
-#ifndef SRC_MEDIA_AUDIO_AUDIO_CORE_MIXER_FILTER_H_
-#define SRC_MEDIA_AUDIO_AUDIO_CORE_MIXER_FILTER_H_
+#ifndef SRC_MEDIA_AUDIO_LIB_PROCESSING_FILTER_H_
+#define SRC_MEDIA_AUDIO_LIB_PROCESSING_FILTER_H_
#include <lib/syslog/cpp/macros.h>
-#include <cmath>
-#include <memory>
#include <vector>
-#include "src/media/audio/audio_core/mixer/coefficient_table.h"
-#include "src/media/audio/audio_core/mixer/coefficient_table_cache.h"
-#include "src/media/audio/audio_core/mixer/constants.h"
-#include "src/media/audio/lib/format/constants.h"
+#include "src/media/audio/lib/format2/fixed.h"
+#include "src/media/audio/lib/processing/coefficient_table.h"
+#include "src/media/audio/lib/processing/coefficient_table_cache.h"
-namespace media::audio::mixer {
+namespace media_audio {
// This class represents a symmetric, convolution-based filter, to be applied to an audio stream.
-//
-// Param side_length is the number of subframes included on each side, including center subframe 0.
-// Child classes differ only in their filter coefficients.
class Filter {
public:
+ // `side_length` is the number of subframes included on each side, including center subframe 0.
Filter(int32_t source_rate, int32_t dest_rate, int64_t side_length,
int32_t num_frac_bits = Fixed::Format::FractionalBits)
: source_rate_(source_rate),
@@ -37,8 +33,17 @@
FX_DCHECK(num_frac_bits_ > 0);
}
+ // Computes sample at `center` frame with `frac_offset`.
virtual float ComputeSample(int64_t frac_offset, float* center) = 0;
+ // Displays the filter table values. Used for debugging purposes only.
+ virtual void Display() = 0;
+
+ // Eagerly precomputes needed data. If not called, needed data will be lazily computed on the
+ // first `ComputeSample` call.
+ // TODO(fxbug.dev/45074): This is for tests only and can be removed once filter creation is eager.
+ virtual void EagerlyPrepare() = 0;
+
int32_t source_rate() const { return source_rate_; }
int32_t dest_rate() const { return dest_rate_; }
int64_t side_length() const { return side_length_; }
@@ -46,13 +51,6 @@
int64_t frac_size() const { return frac_size_; }
double rate_conversion_ratio() const { return rate_conversion_ratio_; }
- // used for debugging purposes only
- virtual void Display() = 0;
-
- // Eagerly precompute needed data. If not called, lazily compute on the first ComputeSample() call
- // TODO(fxbug.dev/45074): This is for tests only and can be removed once filter creation is eager.
- virtual void EagerlyPrepare() = 0;
-
protected:
float ComputeSampleFromTable(const CoefficientTable& filter_coefficients, int64_t frac_offset,
float* center);
@@ -69,43 +67,13 @@
double rate_conversion_ratio_;
};
-// See PointFilterCoefficientTable.
-class PointFilter : public Filter {
- public:
- PointFilter(int32_t source_rate, int32_t dest_rate,
- int32_t num_frac_bits = Fixed::Format::FractionalBits)
- : Filter(source_rate, dest_rate,
- /* side_length= */ (1 << (num_frac_bits - 1)) + 1, num_frac_bits),
- filter_coefficients_(cache_, Inputs{
- .side_length = this->side_length(),
- .num_frac_bits = this->num_frac_bits(),
- }) {}
-
- float ComputeSample(int64_t frac_offset, float* center) override {
- return ComputeSampleFromTable(*filter_coefficients_, frac_offset, center);
- }
-
- void Display() override { DisplayTable(*filter_coefficients_); }
-
- const float& operator[](int64_t index) { return (*filter_coefficients_)[index]; }
-
- void EagerlyPrepare() override { filter_coefficients_.get(); }
-
- private:
- using Inputs = PointFilterCoefficientTable::Inputs;
- using CacheT = CoefficientTableCache<Inputs>;
-
- static CacheT* const cache_;
- LazySharedCoefficientTable<Inputs> filter_coefficients_;
-};
-
-// See LinearFilterCoefficientTable.
+// See `LinearFilterCoefficientTable`.
class LinearFilter : public Filter {
public:
LinearFilter(int32_t source_rate, int32_t dest_rate,
int32_t num_frac_bits = Fixed::Format::FractionalBits)
: Filter(source_rate, dest_rate,
- /* side_length= */ 1 << num_frac_bits, num_frac_bits),
+ /*side_length=*/1 << num_frac_bits, num_frac_bits),
filter_coefficients_(cache_, Inputs{
.side_length = this->side_length(),
.num_frac_bits = this->num_frac_bits(),
@@ -129,7 +97,7 @@
LazySharedCoefficientTable<Inputs> filter_coefficients_;
};
-// See SincFilterCoefficientTable.
+// See `SincFilterCoefficientTable`.
class SincFilter : public Filter {
public:
static constexpr auto kSideTaps = SincFilterCoefficientTable::kSideTaps;
@@ -171,6 +139,6 @@
LazySharedCoefficientTable<Inputs> filter_coefficients_;
};
-} // namespace media::audio::mixer
+} // namespace media_audio
#endif // SRC_MEDIA_AUDIO_AUDIO_CORE_MIXER_FILTER_H_
diff --git a/src/media/audio/audio_core/mixer/filter_unittest.cc b/src/media/audio/lib/processing/filter_unittest.cc
similarity index 75%
rename from src/media/audio/audio_core/mixer/filter_unittest.cc
rename to src/media/audio/lib/processing/filter_unittest.cc
index 658b239..de59328 100644
--- a/src/media/audio/audio_core/mixer/filter_unittest.cc
+++ b/src/media/audio/lib/processing/filter_unittest.cc
@@ -1,59 +1,16 @@
-// Copyright 2019 The Fuchsia Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
+// Copyright 2022 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
-#include "src/media/audio/audio_core/mixer/filter.h"
+#include "src/media/audio/lib/processing/filter.h"
#include <lib/syslog/cpp/macros.h>
#include <gtest/gtest.h>
-namespace media::audio::mixer {
+namespace media_audio {
namespace {
-TEST(PointFilterTest, Construction) {
- {
- auto source_rate = 48000;
- auto dest_rate = 48000;
- int32_t expected_num_frac_bits = Fixed::Format::FractionalBits; // default
- PointFilter filter(source_rate, dest_rate);
- auto expected_side_length = (1 << (expected_num_frac_bits - 1)) + 1;
-
- EXPECT_EQ(filter.source_rate(), source_rate);
- EXPECT_EQ(filter.dest_rate(), dest_rate);
- EXPECT_EQ(filter.num_frac_bits(), expected_num_frac_bits);
- EXPECT_EQ(filter.side_length(), expected_side_length);
- EXPECT_DOUBLE_EQ(filter.rate_conversion_ratio(), 1.0);
- }
-
- {
- auto source_rate = 16000;
- auto dest_rate = 48000;
- int32_t expected_num_frac_bits = Fixed::Format::FractionalBits; // default
- PointFilter filter(source_rate, dest_rate);
- auto expected_side_length = (1 << (expected_num_frac_bits - 1)) + 1;
-
- EXPECT_EQ(filter.source_rate(), source_rate);
- EXPECT_EQ(filter.dest_rate(), dest_rate);
- EXPECT_EQ(filter.num_frac_bits(), expected_num_frac_bits);
- EXPECT_EQ(filter.side_length(), expected_side_length);
- EXPECT_DOUBLE_EQ(filter.rate_conversion_ratio(), 3.0);
- }
-
- {
- auto source_rate = 44100;
- auto dest_rate = 22050;
- int32_t num_frac_bits = 4;
- PointFilter filter(source_rate, dest_rate, num_frac_bits);
- auto expected_side_length = (1 << (num_frac_bits - 1)) + 1;
-
- EXPECT_EQ(filter.source_rate(), source_rate);
- EXPECT_EQ(filter.dest_rate(), dest_rate);
- EXPECT_EQ(filter.num_frac_bits(), num_frac_bits);
- EXPECT_EQ(filter.side_length(), expected_side_length);
- EXPECT_DOUBLE_EQ(filter.rate_conversion_ratio(), 0.5);
- }
-}
-
TEST(LinearFilterTest, Construction) {
{
auto source_rate = 48000;
@@ -160,24 +117,6 @@
}
}
-TEST(PointFilterTest, FilterCoefficients) {
- auto source_rate = 48000;
- auto dest_rate = 48000;
- int32_t num_frac_bits = 4;
- PointFilter filter(source_rate, dest_rate, num_frac_bits);
-
- const auto frac_half = 1 << (num_frac_bits - 1);
- const auto expected_side_length = frac_half + 1;
- EXPECT_EQ(filter.side_length(), expected_side_length);
-
- EXPECT_FLOAT_EQ(filter[0], 1.0f);
- for (auto idx = 1; idx < frac_half; ++idx) {
- EXPECT_FLOAT_EQ(filter[idx], 1.0f);
- }
-
- EXPECT_FLOAT_EQ(filter[frac_half], 0.5f);
-}
-
TEST(LinearFilterTest, FilterCoefficients) {
auto source_rate = 48000;
auto dest_rate = 48000;
@@ -252,22 +191,6 @@
EXPECT_DOUBLE_EQ(filter.rate_conversion_ratio(), 2.0);
}
-// TODO(mpuryear): validate other rate-conversion ratios
-TEST(PointFilterTest, ComputeSample) {
- auto source_rate = 48000;
- auto dest_rate = 48000;
- int32_t num_frac_bits = 4;
- auto frac_size = 1 << num_frac_bits;
- auto frac_half = frac_size >> 1;
- PointFilter filter(source_rate, dest_rate, num_frac_bits);
-
- float data[] = {0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f};
-
- EXPECT_FLOAT_EQ(filter.ComputeSample(0, &data[1]), data[1]);
- EXPECT_FLOAT_EQ(filter.ComputeSample(frac_half, &data[2]), (data[2] + data[3]) / 2);
- EXPECT_FLOAT_EQ(filter.ComputeSample(frac_size - 1, &data[3]), data[4]);
-}
-
TEST(LinearFilterTest, ComputeSample) {
auto source_rate = 48000;
auto dest_rate = 48000;
@@ -289,7 +212,7 @@
int32_t num_frac_bits) {
SincFilter filter(source_rate, dest_rate, side_length, num_frac_bits);
- // If values outside indices [1,33] are used in ComputeSample, data compares will fail.
+ // If values outside indices [1,33] are used in `ComputeSample`, data compares will fail.
float data[] = {
999999.0f, //
0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, //
@@ -308,8 +231,8 @@
SCOPED_TRACE("Compute(17.0) == [17]");
EXPECT_FLOAT_EQ(filter.ComputeSample(0, &data[17]), data[17]);
- // These values are only calculated to a specific quality tolerance (related to side_length and
- // num_frac_bits), so the only SAFE things to do here are rough comparisons.
+ // These values are only calculated to a specific quality tolerance (related to `side_length` and
+ // `num_frac_bits`), so the only SAFE things to do here are rough comparisons.
SCOPED_TRACE("[17] < Compute(17.25)");
EXPECT_LT(data[17], filter.ComputeSample(frac_half, &data[17]));
@@ -359,4 +282,4 @@
}
} // namespace
-} // namespace media::audio::mixer
+} // namespace media_audio
diff --git a/src/media/audio/audio_core/mixer/gen_coefficient_tables.cc b/src/media/audio/lib/processing/gen_coefficient_tables.cc
similarity index 82%
rename from src/media/audio/audio_core/mixer/gen_coefficient_tables.cc
rename to src/media/audio/lib/processing/gen_coefficient_tables.cc
index 1419c04..aff9a78 100644
--- a/src/media/audio/audio_core/mixer/gen_coefficient_tables.cc
+++ b/src/media/audio/lib/processing/gen_coefficient_tables.cc
@@ -8,14 +8,15 @@
#include <iostream>
#include <vector>
-#include "src/media/audio/audio_core/mixer/coefficient_table.h"
-
-using media::audio::Fixed;
-using media::audio::mixer::CoefficientTable;
-using media::audio::mixer::SincFilterCoefficientTable;
+#include "src/media/audio/lib/format2/fixed.h"
+#include "src/media/audio/lib/processing/coefficient_table.h"
namespace {
+using ::media_audio::CoefficientTable;
+using ::media_audio::Fixed;
+using ::media_audio::SincFilterCoefficientTable;
+
struct Key {
int32_t source_rate;
int32_t dest_rate;
@@ -41,16 +42,16 @@
out << "//\n";
out << "// Generated by gen_coefficient_tables.cc.\n";
out << "\n";
- out << "#include \"src/media/audio/audio_core/mixer/coefficient_table.h\"\n";
+ out << "#include \"src/media/audio/lib/processing/coefficient_table.h\"\n";
out << "\n";
- out << "namespace media::audio::mixer {\n";
+ out << "namespace media_audio {\n";
out << "\n";
out << "// Static asserts to validate that the generated code is not out-of-date\n";
- out << "static_assert(media::audio::kPtsFractionalBits == " << Fixed::Format::FractionalBits
+ out << "static_assert(media_audio::kPtsFractionalBits == " << Fixed::Format::FractionalBits
<< ");\n";
- out << "static_assert(media::audio::mixer::SincFilterCoefficientTable::kSideTaps == "
+ out << "static_assert(media_audio::SincFilterCoefficientTable::kSideTaps == "
<< SincFilterCoefficientTable::kSideTaps << ");\n";
- out << "static_assert(media::audio::mixer::SincFilterCoefficientTable::kFracSideLength == "
+ out << "static_assert(media_audio::SincFilterCoefficientTable::kFracSideLength == "
<< SincFilterCoefficientTable::kFracSideLength << ");\n";
out << "\n";
@@ -108,7 +109,7 @@
"kPrebuiltSincFilterCoefficientTables(kPrebuiltTables, static_cast<size_t>("
<< tables.size() << "));\n";
out << "\n";
- out << "} // namespace media::audio::mixer\n";
+ out << "} // namespace media_audio\n";
return 0;
}
diff --git a/src/media/audio/lib/test/BUILD.gn b/src/media/audio/lib/test/BUILD.gn
index 23b4324f..e4b2f04 100644
--- a/src/media/audio/lib/test/BUILD.gn
+++ b/src/media/audio/lib/test/BUILD.gn
@@ -92,11 +92,11 @@
"//sdk/lib/sys/inspect/cpp",
"//sdk/lib/syslog/cpp",
"//src/media/audio/audio_core:audio_core_lib",
- "//src/media/audio/audio_core/mixer:prebuilt_coefficient_tables",
"//src/media/audio/effects/test_effects:test_effects_v2",
"//src/media/audio/lib/analysis",
"//src/media/audio/lib/clock",
"//src/media/audio/lib/format",
+ "//src/media/audio/lib/processing:prebuilt_coefficient_tables",
"//src/media/audio/lib/wav",
"//src/power/fidl/testing:test.thermal",
"//third_party/googletest:gtest",