blob: b7e0ae674170c21f986f2c6336e2cabba9f6f88b [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
Robert Wu67375a12022-08-25 22:04:29 +000023#include <flowgraph/Limiter.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,
Robert Wud559ba52023-06-29 00:08:51 +000042 int32_t sourceSampleRate,
Phil Burk0127c1b2018-03-29 13:48:06 -070043 audio_format_t sinkFormat,
Robert Wud7400832021-12-04 01:11:19 +000044 int32_t sinkChannelCount,
Robert Wud559ba52023-06-29 00:08:51 +000045 int32_t sinkSampleRate,
Robert Wu8393bed2021-12-08 02:08:48 +000046 bool useMonoBlend,
Robert Wud559ba52023-06-29 00:08:51 +000047 bool useVolumeRamps,
Robert Wub7e30fa2021-12-09 01:00:16 +000048 float audioBalance,
Robert Wud559ba52023-06-29 00:08:51 +000049 aaudio::resampler::MultiChannelResampler::Quality resamplerQuality) {
Robert Wu057f0832021-12-03 20:41:07 +000050 FlowGraphPortFloatOutput *lastOutput = nullptr;
Phil Burk0127c1b2018-03-29 13:48:06 -070051
Robert Wud559ba52023-06-29 00:08:51 +000052 ALOGD("%s() source format = 0x%08x, channels = %d, sample rate = %d, "
53 "sink format = 0x%08x, channels = %d, sample rate = %d, "
54 "useMonoBlend = %d, audioBalance = %f, useVolumeRamps %d",
55 __func__, sourceFormat, sourceChannelCount, sourceSampleRate, sinkFormat,
56 sinkChannelCount, sinkSampleRate, useMonoBlend, audioBalance, useVolumeRamps);
Phil Burk0127c1b2018-03-29 13:48:06 -070057
58 switch (sourceFormat) {
59 case AUDIO_FORMAT_PCM_FLOAT:
60 mSource = std::make_unique<SourceFloat>(sourceChannelCount);
61 break;
62 case AUDIO_FORMAT_PCM_16_BIT:
63 mSource = std::make_unique<SourceI16>(sourceChannelCount);
64 break;
65 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
66 mSource = std::make_unique<SourceI24>(sourceChannelCount);
67 break;
Phil Burk04e805b2018-03-27 09:13:53 -070068 case AUDIO_FORMAT_PCM_32_BIT:
69 mSource = std::make_unique<SourceI32>(sourceChannelCount);
70 break;
71 default:
Phil Burk0127c1b2018-03-29 13:48:06 -070072 ALOGE("%s() Unsupported source format = %d", __func__, sourceFormat);
73 return AAUDIO_ERROR_UNIMPLEMENTED;
74 }
75 lastOutput = &mSource->output;
76
Robert Wu8393bed2021-12-08 02:08:48 +000077 if (useMonoBlend) {
78 mMonoBlend = std::make_unique<MonoBlend>(sourceChannelCount);
79 lastOutput->connect(&mMonoBlend->input);
80 lastOutput = &mMonoBlend->output;
81 }
Phil Burk0127c1b2018-03-29 13:48:06 -070082
83 // For a pure float graph, there is chance that the data range may be very large.
Robert Wu67375a12022-08-25 22:04:29 +000084 // So we should limit to a reasonable value that allows a little headroom.
Phil Burk0127c1b2018-03-29 13:48:06 -070085 if (sourceFormat == AUDIO_FORMAT_PCM_FLOAT && sinkFormat == AUDIO_FORMAT_PCM_FLOAT) {
Robert Wu67375a12022-08-25 22:04:29 +000086 mLimiter = std::make_unique<Limiter>(sourceChannelCount);
87 lastOutput->connect(&mLimiter->input);
88 lastOutput = &mLimiter->output;
Phil Burk0127c1b2018-03-29 13:48:06 -070089 }
90
Robert Wud559ba52023-06-29 00:08:51 +000091 if (sourceSampleRate != sinkSampleRate) {
Robert Wue8b58962023-07-21 19:48:56 +000092 mResampler.reset(aaudio::resampler::MultiChannelResampler::make(sourceChannelCount,
Robert Wud559ba52023-06-29 00:08:51 +000093 sourceSampleRate, sinkSampleRate, resamplerQuality));
Robert Wue8b58962023-07-21 19:48:56 +000094 mRateConverter = std::make_unique<SampleRateConverter>(sourceChannelCount,
Robert Wud559ba52023-06-29 00:08:51 +000095 *mResampler);
96 lastOutput->connect(&mRateConverter->input);
97 lastOutput = &mRateConverter->output;
98 }
99
Phil Burk0127c1b2018-03-29 13:48:06 -0700100 // Expand the number of channels if required.
101 if (sourceChannelCount == 1 && sinkChannelCount > 1) {
102 mChannelConverter = std::make_unique<MonoToMultiConverter>(sinkChannelCount);
103 lastOutput->connect(&mChannelConverter->input);
104 lastOutput = &mChannelConverter->output;
105 } else if (sourceChannelCount != sinkChannelCount) {
106 ALOGE("%s() Channel reduction not supported.", __func__);
107 return AAUDIO_ERROR_UNIMPLEMENTED;
108 }
109
Robert Wud559ba52023-06-29 00:08:51 +0000110 if (useVolumeRamps) {
Robert Wub7e30fa2021-12-09 01:00:16 +0000111 // Apply volume ramps to set the left/right audio balance and target volumes.
112 // The signals will be decoupled, volume ramps will be applied, before the signals are
113 // combined again.
114 mMultiToManyConverter = std::make_unique<MultiToManyConverter>(sinkChannelCount);
115 mManyToMultiConverter = std::make_unique<ManyToMultiConverter>(sinkChannelCount);
116 lastOutput->connect(&mMultiToManyConverter->input);
117 for (int i = 0; i < sinkChannelCount; i++) {
118 mVolumeRamps.emplace_back(std::make_unique<RampLinear>(1));
119 mPanningVolumes.emplace_back(1.0f);
120 lastOutput = mMultiToManyConverter->outputs[i].get();
121 lastOutput->connect(&(mVolumeRamps[i].get()->input));
122 lastOutput = &(mVolumeRamps[i].get()->output);
123 lastOutput->connect(mManyToMultiConverter->inputs[i].get());
124 }
125 lastOutput = &mManyToMultiConverter->output;
126 setAudioBalance(audioBalance);
Robert Wu8393bed2021-12-08 02:08:48 +0000127 }
Robert Wu8393bed2021-12-08 02:08:48 +0000128
Phil Burk0127c1b2018-03-29 13:48:06 -0700129 switch (sinkFormat) {
130 case AUDIO_FORMAT_PCM_FLOAT:
131 mSink = std::make_unique<SinkFloat>(sinkChannelCount);
132 break;
133 case AUDIO_FORMAT_PCM_16_BIT:
134 mSink = std::make_unique<SinkI16>(sinkChannelCount);
135 break;
136 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
137 mSink = std::make_unique<SinkI24>(sinkChannelCount);
138 break;
Phil Burk04e805b2018-03-27 09:13:53 -0700139 case AUDIO_FORMAT_PCM_32_BIT:
140 mSink = std::make_unique<SinkI32>(sinkChannelCount);
141 break;
142 default:
Phil Burk0127c1b2018-03-29 13:48:06 -0700143 ALOGE("%s() Unsupported sink format = %d", __func__, sinkFormat);
144 return AAUDIO_ERROR_UNIMPLEMENTED;
145 }
146 lastOutput->connect(&mSink->input);
147
148 return AAUDIO_OK;
149}
150
Robert Wud559ba52023-06-29 00:08:51 +0000151int32_t AAudioFlowGraph::pull(void *destination, int32_t targetFramesToRead) {
152 return mSink->read(destination, targetFramesToRead);
153}
154
155int32_t AAudioFlowGraph::process(const void *source, int32_t numFramesToWrite, void *destination,
156 int32_t targetFramesToRead) {
157 mSource->setData(source, numFramesToWrite);
158 return mSink->read(destination, targetFramesToRead);
Phil Burk0127c1b2018-03-29 13:48:06 -0700159}
160
161/**
162 * @param volume between 0.0 and 1.0
163 */
164void AAudioFlowGraph::setTargetVolume(float volume) {
Robert Wu8393bed2021-12-08 02:08:48 +0000165 for (int i = 0; i < mVolumeRamps.size(); i++) {
166 mVolumeRamps[i]->setTarget(volume * mPanningVolumes[i]);
167 }
168 mTargetVolume = volume;
Phil Burk0127c1b2018-03-29 13:48:06 -0700169}
170
Robert Wu8393bed2021-12-08 02:08:48 +0000171/**
172 * @param audioBalance between -1.0 and 1.0
173 */
174void AAudioFlowGraph::setAudioBalance(float audioBalance) {
175 if (mPanningVolumes.size() >= 2) {
176 float leftMultiplier = 0;
177 float rightMultiplier = 0;
178 mBalance.computeStereoBalance(audioBalance, &leftMultiplier, &rightMultiplier);
179 mPanningVolumes[0] = leftMultiplier;
180 mPanningVolumes[1] = rightMultiplier;
181 mVolumeRamps[0]->setTarget(mTargetVolume * leftMultiplier);
182 mVolumeRamps[1]->setTarget(mTargetVolume * rightMultiplier);
183 }
184}
185
186/**
187 * @param numFrames to slowly adjust for volume changes
188 */
Phil Burk0127c1b2018-03-29 13:48:06 -0700189void AAudioFlowGraph::setRampLengthInFrames(int32_t numFrames) {
Robert Wu8393bed2021-12-08 02:08:48 +0000190 for (auto& ramp : mVolumeRamps) {
191 ramp->setLengthInFrames(numFrames);
192 }
Phil Burk0127c1b2018-03-29 13:48:06 -0700193}