blob: 2ed3e3c2e0b5ab2efdfea780dbfdde60bfb8d3fd [file] [log] [blame]
Phil Burk0127c1b2018-03-29 13:48:06 -07001/*
2 * Copyright (C) 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#define LOG_TAG "AAudioFlowGraph"
18//#define LOG_NDEBUG 0
19#include <utils/Log.h>
20
21#include "AAudioFlowGraph.h"
22
23#include <flowgraph/ClipToRange.h>
Robert Wu8393bed2021-12-08 02:08:48 +000024#include <flowgraph/ManyToMultiConverter.h>
Robert Wud7400832021-12-04 01:11:19 +000025#include <flowgraph/MonoBlend.h>
Phil Burk0127c1b2018-03-29 13:48:06 -070026#include <flowgraph/MonoToMultiConverter.h>
Robert Wu8393bed2021-12-08 02:08:48 +000027#include <flowgraph/MultiToManyConverter.h>
Phil Burk0127c1b2018-03-29 13:48:06 -070028#include <flowgraph/RampLinear.h>
29#include <flowgraph/SinkFloat.h>
30#include <flowgraph/SinkI16.h>
31#include <flowgraph/SinkI24.h>
Phil Burk04e805b2018-03-27 09:13:53 -070032#include <flowgraph/SinkI32.h>
Phil Burk0127c1b2018-03-29 13:48:06 -070033#include <flowgraph/SourceFloat.h>
34#include <flowgraph/SourceI16.h>
35#include <flowgraph/SourceI24.h>
Phil Burk04e805b2018-03-27 09:13:53 -070036#include <flowgraph/SourceI32.h>
Phil Burk0127c1b2018-03-29 13:48:06 -070037
Robert Wuedc850a2022-04-05 16:47:03 +000038using namespace FLOWGRAPH_OUTER_NAMESPACE::flowgraph;
Phil Burk0127c1b2018-03-29 13:48:06 -070039
40aaudio_result_t AAudioFlowGraph::configure(audio_format_t sourceFormat,
41 int32_t sourceChannelCount,
42 audio_format_t sinkFormat,
Robert Wud7400832021-12-04 01:11:19 +000043 int32_t sinkChannelCount,
Robert Wu8393bed2021-12-08 02:08:48 +000044 bool useMonoBlend,
Robert Wub7e30fa2021-12-09 01:00:16 +000045 float audioBalance,
46 bool isExclusive) {
Robert Wu057f0832021-12-03 20:41:07 +000047 FlowGraphPortFloatOutput *lastOutput = nullptr;
Phil Burk0127c1b2018-03-29 13:48:06 -070048
Phil Burk04e805b2018-03-27 09:13:53 -070049 // TODO change back to ALOGD
Robert Wu8393bed2021-12-08 02:08:48 +000050 ALOGI("%s() source format = 0x%08x, channels = %d, sink format = 0x%08x, channels = %d, "
Robert Wub7e30fa2021-12-09 01:00:16 +000051 "useMonoBlend = %d, audioBalance = %f, isExclusive %d",
Robert Wu8393bed2021-12-08 02:08:48 +000052 __func__, sourceFormat, sourceChannelCount, sinkFormat, sinkChannelCount,
Robert Wub7e30fa2021-12-09 01:00:16 +000053 useMonoBlend, audioBalance, isExclusive);
Phil Burk0127c1b2018-03-29 13:48:06 -070054
55 switch (sourceFormat) {
56 case AUDIO_FORMAT_PCM_FLOAT:
57 mSource = std::make_unique<SourceFloat>(sourceChannelCount);
58 break;
59 case AUDIO_FORMAT_PCM_16_BIT:
60 mSource = std::make_unique<SourceI16>(sourceChannelCount);
61 break;
62 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
63 mSource = std::make_unique<SourceI24>(sourceChannelCount);
64 break;
Phil Burk04e805b2018-03-27 09:13:53 -070065 case AUDIO_FORMAT_PCM_32_BIT:
66 mSource = std::make_unique<SourceI32>(sourceChannelCount);
67 break;
68 default:
Phil Burk0127c1b2018-03-29 13:48:06 -070069 ALOGE("%s() Unsupported source format = %d", __func__, sourceFormat);
70 return AAUDIO_ERROR_UNIMPLEMENTED;
71 }
72 lastOutput = &mSource->output;
73
Robert Wu8393bed2021-12-08 02:08:48 +000074 if (useMonoBlend) {
75 mMonoBlend = std::make_unique<MonoBlend>(sourceChannelCount);
76 lastOutput->connect(&mMonoBlend->input);
77 lastOutput = &mMonoBlend->output;
78 }
Phil Burk0127c1b2018-03-29 13:48:06 -070079
80 // For a pure float graph, there is chance that the data range may be very large.
81 // So we should clip to a reasonable value that allows a little headroom.
82 if (sourceFormat == AUDIO_FORMAT_PCM_FLOAT && sinkFormat == AUDIO_FORMAT_PCM_FLOAT) {
83 mClipper = std::make_unique<ClipToRange>(sourceChannelCount);
84 lastOutput->connect(&mClipper->input);
85 lastOutput = &mClipper->output;
86 }
87
88 // Expand the number of channels if required.
89 if (sourceChannelCount == 1 && sinkChannelCount > 1) {
90 mChannelConverter = std::make_unique<MonoToMultiConverter>(sinkChannelCount);
91 lastOutput->connect(&mChannelConverter->input);
92 lastOutput = &mChannelConverter->output;
93 } else if (sourceChannelCount != sinkChannelCount) {
94 ALOGE("%s() Channel reduction not supported.", __func__);
95 return AAUDIO_ERROR_UNIMPLEMENTED;
96 }
97
Robert Wub7e30fa2021-12-09 01:00:16 +000098 // Apply volume ramps for only exclusive streams.
99 if (isExclusive) {
100 // Apply volume ramps to set the left/right audio balance and target volumes.
101 // The signals will be decoupled, volume ramps will be applied, before the signals are
102 // combined again.
103 mMultiToManyConverter = std::make_unique<MultiToManyConverter>(sinkChannelCount);
104 mManyToMultiConverter = std::make_unique<ManyToMultiConverter>(sinkChannelCount);
105 lastOutput->connect(&mMultiToManyConverter->input);
106 for (int i = 0; i < sinkChannelCount; i++) {
107 mVolumeRamps.emplace_back(std::make_unique<RampLinear>(1));
108 mPanningVolumes.emplace_back(1.0f);
109 lastOutput = mMultiToManyConverter->outputs[i].get();
110 lastOutput->connect(&(mVolumeRamps[i].get()->input));
111 lastOutput = &(mVolumeRamps[i].get()->output);
112 lastOutput->connect(mManyToMultiConverter->inputs[i].get());
113 }
114 lastOutput = &mManyToMultiConverter->output;
115 setAudioBalance(audioBalance);
Robert Wu8393bed2021-12-08 02:08:48 +0000116 }
Robert Wu8393bed2021-12-08 02:08:48 +0000117
Phil Burk0127c1b2018-03-29 13:48:06 -0700118 switch (sinkFormat) {
119 case AUDIO_FORMAT_PCM_FLOAT:
120 mSink = std::make_unique<SinkFloat>(sinkChannelCount);
121 break;
122 case AUDIO_FORMAT_PCM_16_BIT:
123 mSink = std::make_unique<SinkI16>(sinkChannelCount);
124 break;
125 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
126 mSink = std::make_unique<SinkI24>(sinkChannelCount);
127 break;
Phil Burk04e805b2018-03-27 09:13:53 -0700128 case AUDIO_FORMAT_PCM_32_BIT:
129 mSink = std::make_unique<SinkI32>(sinkChannelCount);
130 break;
131 default:
Phil Burk0127c1b2018-03-29 13:48:06 -0700132 ALOGE("%s() Unsupported sink format = %d", __func__, sinkFormat);
133 return AAUDIO_ERROR_UNIMPLEMENTED;
134 }
135 lastOutput->connect(&mSink->input);
136
137 return AAUDIO_OK;
138}
139
140void AAudioFlowGraph::process(const void *source, void *destination, int32_t numFrames) {
141 mSource->setData(source, numFrames);
142 mSink->read(destination, numFrames);
143}
144
145/**
146 * @param volume between 0.0 and 1.0
147 */
148void AAudioFlowGraph::setTargetVolume(float volume) {
Robert Wu8393bed2021-12-08 02:08:48 +0000149 for (int i = 0; i < mVolumeRamps.size(); i++) {
150 mVolumeRamps[i]->setTarget(volume * mPanningVolumes[i]);
151 }
152 mTargetVolume = volume;
Phil Burk0127c1b2018-03-29 13:48:06 -0700153}
154
Robert Wu8393bed2021-12-08 02:08:48 +0000155/**
156 * @param audioBalance between -1.0 and 1.0
157 */
158void AAudioFlowGraph::setAudioBalance(float audioBalance) {
159 if (mPanningVolumes.size() >= 2) {
160 float leftMultiplier = 0;
161 float rightMultiplier = 0;
162 mBalance.computeStereoBalance(audioBalance, &leftMultiplier, &rightMultiplier);
163 mPanningVolumes[0] = leftMultiplier;
164 mPanningVolumes[1] = rightMultiplier;
165 mVolumeRamps[0]->setTarget(mTargetVolume * leftMultiplier);
166 mVolumeRamps[1]->setTarget(mTargetVolume * rightMultiplier);
167 }
168}
169
170/**
171 * @param numFrames to slowly adjust for volume changes
172 */
Phil Burk0127c1b2018-03-29 13:48:06 -0700173void AAudioFlowGraph::setRampLengthInFrames(int32_t numFrames) {
Robert Wu8393bed2021-12-08 02:08:48 +0000174 for (auto& ramp : mVolumeRamps) {
175 ramp->setLengthInFrames(numFrames);
176 }
Phil Burk0127c1b2018-03-29 13:48:06 -0700177}