blob: 0792fc5222464110e5f7e15dfd2862f7e485b6d6 [file] [log] [blame]
Phil Burkbb78a732018-03-28 15:37:19 -07001/*
2 * Copyright 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/*
18 * Test FlowGraph
19 */
20
21#include <iostream>
22
23#include <gtest/gtest.h>
24
25#include "flowgraph/ClipToRange.h"
Robert Wud7400832021-12-04 01:11:19 +000026#include "flowgraph/MonoBlend.h"
Phil Burkbb78a732018-03-28 15:37:19 -070027#include "flowgraph/MonoToMultiConverter.h"
28#include "flowgraph/SourceFloat.h"
29#include "flowgraph/RampLinear.h"
30#include "flowgraph/SinkFloat.h"
31#include "flowgraph/SinkI16.h"
32#include "flowgraph/SinkI24.h"
33#include "flowgraph/SourceI16.h"
34#include "flowgraph/SourceI24.h"
35
36using namespace flowgraph;
37
38constexpr int kBytesPerI24Packed = 3;
39
40TEST(test_flowgraph, module_sinki16) {
41 static const float input[] = {1.0f, 0.5f, -0.25f, -1.0f, 0.0f, 53.9f, -87.2f};
42 static const int16_t expected[] = {32767, 16384, -8192, -32768, 0, 32767, -32768};
43 int16_t output[20];
44 SourceFloat sourceFloat{1};
45 SinkI16 sinkI16{1};
46
47 int numInputFrames = sizeof(input) / sizeof(input[0]);
48 sourceFloat.setData(input, numInputFrames);
49 sourceFloat.output.connect(&sinkI16.input);
50
51 int numOutputFrames = sizeof(output) / sizeof(int16_t);
52 int32_t numRead = sinkI16.read(output, numOutputFrames);
53 ASSERT_EQ(numInputFrames, numRead);
54 for (int i = 0; i < numRead; i++) {
55 EXPECT_EQ(expected[i], output[i]);
56 }
57}
58
59TEST(test_flowgraph, module_mono_to_stereo) {
60 static const float input[] = {1.0f, 2.0f, 3.0f};
61 float output[100] = {};
62 SourceFloat sourceFloat{1};
63 MonoToMultiConverter monoToStereo{2};
64 SinkFloat sinkFloat{2};
65
66 sourceFloat.setData(input, 3);
67
68 sourceFloat.output.connect(&monoToStereo.input);
69 monoToStereo.output.connect(&sinkFloat.input);
70
71 int32_t numRead = sinkFloat.read(output, 8);
72 ASSERT_EQ(3, numRead);
73 EXPECT_EQ(input[0], output[0]);
74 EXPECT_EQ(input[0], output[1]);
75 EXPECT_EQ(input[1], output[2]);
76 EXPECT_EQ(input[1], output[3]);
77}
78
79TEST(test_flowgraph, module_ramp_linear) {
Robert Wuc3278fe2021-06-23 16:51:40 +000080 constexpr int singleNumOutput = 1;
Phil Burkbb78a732018-03-28 15:37:19 -070081 constexpr int rampSize = 5;
82 constexpr int numOutput = 100;
83 constexpr float value = 1.0f;
Robert Wuc3278fe2021-06-23 16:51:40 +000084 constexpr float initialTarget = 10.0f;
85 constexpr float finalTarget = 100.0f;
86 constexpr float tolerance = 0.0001f; // arbitrary
Phil Burkbb78a732018-03-28 15:37:19 -070087 float output[numOutput] = {};
88 RampLinear rampLinear{1};
89 SinkFloat sinkFloat{1};
90
91 rampLinear.input.setValue(value);
92 rampLinear.setLengthInFrames(rampSize);
Phil Burkbb78a732018-03-28 15:37:19 -070093 rampLinear.output.connect(&sinkFloat.input);
94
Robert Wuc3278fe2021-06-23 16:51:40 +000095 // Check that the values go to the initial target instantly.
96 rampLinear.setTarget(initialTarget);
97 int32_t singleNumRead = sinkFloat.read(output, singleNumOutput);
98 ASSERT_EQ(singleNumRead, singleNumOutput);
99 EXPECT_NEAR(value * initialTarget, output[0], tolerance);
100
101 // Now set target and check that the linear ramp works as expected.
102 rampLinear.setTarget(finalTarget);
Phil Burkbb78a732018-03-28 15:37:19 -0700103 int32_t numRead = sinkFloat.read(output, numOutput);
Robert Wuc3278fe2021-06-23 16:51:40 +0000104 const float incrementSize = (finalTarget - initialTarget) / rampSize;
Phil Burkbb78a732018-03-28 15:37:19 -0700105 ASSERT_EQ(numOutput, numRead);
Robert Wuc3278fe2021-06-23 16:51:40 +0000106
Phil Burkbb78a732018-03-28 15:37:19 -0700107 int i = 0;
108 for (; i < rampSize; i++) {
Robert Wuc3278fe2021-06-23 16:51:40 +0000109 float expected = value * (initialTarget + i * incrementSize);
Phil Burkbb78a732018-03-28 15:37:19 -0700110 EXPECT_NEAR(expected, output[i], tolerance);
111 }
112 for (; i < numOutput; i++) {
Robert Wuc3278fe2021-06-23 16:51:40 +0000113 float expected = value * finalTarget;
Phil Burkbb78a732018-03-28 15:37:19 -0700114 EXPECT_NEAR(expected, output[i], tolerance);
115 }
116}
117
118// It is easiest to represent packed 24-bit data as a byte array.
119// This test will read from input, convert to float, then write
120// back to output as bytes.
121TEST(test_flowgraph, module_packed_24) {
122 static const uint8_t input[] = {0x01, 0x23, 0x45,
123 0x67, 0x89, 0xAB,
124 0xCD, 0xEF, 0x5A};
125 uint8_t output[99] = {};
126 SourceI24 sourceI24{1};
127 SinkI24 sinkI24{1};
128
129 int numInputFrames = sizeof(input) / kBytesPerI24Packed;
130 sourceI24.setData(input, numInputFrames);
131 sourceI24.output.connect(&sinkI24.input);
132
133 int32_t numRead = sinkI24.read(output, sizeof(output) / kBytesPerI24Packed);
134 ASSERT_EQ(numInputFrames, numRead);
135 for (size_t i = 0; i < sizeof(input); i++) {
136 EXPECT_EQ(input[i], output[i]);
137 }
138}
139
140TEST(test_flowgraph, module_clip_to_range) {
141 constexpr float myMin = -2.0f;
142 constexpr float myMax = 1.5f;
143
144 static const float input[] = {-9.7, 0.5f, -0.25, 1.0f, 12.3};
145 static const float expected[] = {myMin, 0.5f, -0.25, 1.0f, myMax};
146 float output[100];
147 SourceFloat sourceFloat{1};
148 ClipToRange clipper{1};
149 SinkFloat sinkFloat{1};
150
151 int numInputFrames = sizeof(input) / sizeof(input[0]);
152 sourceFloat.setData(input, numInputFrames);
153
154 clipper.setMinimum(myMin);
155 clipper.setMaximum(myMax);
156
157 sourceFloat.output.connect(&clipper.input);
158 clipper.output.connect(&sinkFloat.input);
159
160 int numOutputFrames = sizeof(output) / sizeof(output[0]);
161 int32_t numRead = sinkFloat.read(output, numOutputFrames);
162 ASSERT_EQ(numInputFrames, numRead);
163 constexpr float tolerance = 0.000001f; // arbitrary
164 for (int i = 0; i < numRead; i++) {
165 EXPECT_NEAR(expected[i], output[i], tolerance);
166 }
167}
Robert Wud7400832021-12-04 01:11:19 +0000168
169TEST(test_flowgraph, module_mono_blend) {
170 // Two channel to two channel with 3 inputs and outputs.
171 constexpr int numChannels = 2;
172 constexpr int numFrames = 3;
173
174 static const float input[] = {-0.7, 0.5, -0.25, 1.25, 1000, 2000};
175 static const float expected[] = {-0.1, -0.1, 0.5, 0.5, 1500, 1500};
176 float output[100];
177 SourceFloat sourceFloat{numChannels};
178 MonoBlend monoBlend{numChannels};
179 SinkFloat sinkFloat{numChannels};
180
181 sourceFloat.setData(input, numFrames);
182
183 sourceFloat.output.connect(&monoBlend.input);
184 monoBlend.output.connect(&sinkFloat.input);
185
186 int32_t numRead = sinkFloat.read(output, numFrames);
187 ASSERT_EQ(numRead, numFrames);
188 constexpr float tolerance = 0.000001f; // arbitrary
189 for (int i = 0; i < numRead; i++) {
190 EXPECT_NEAR(expected[i], output[i], tolerance);
191 }
192}
193