blob: d3e291226194d1dd8ed1d6e79c917b50ca5b1fed [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 Wud7400832021-12-04 01:11:19 +000024#include <flowgraph/MonoBlend.h>
Phil Burk0127c1b2018-03-29 13:48:06 -070025#include <flowgraph/MonoToMultiConverter.h>
26#include <flowgraph/RampLinear.h>
27#include <flowgraph/SinkFloat.h>
28#include <flowgraph/SinkI16.h>
29#include <flowgraph/SinkI24.h>
Phil Burk04e805b2018-03-27 09:13:53 -070030#include <flowgraph/SinkI32.h>
Phil Burk0127c1b2018-03-29 13:48:06 -070031#include <flowgraph/SourceFloat.h>
32#include <flowgraph/SourceI16.h>
33#include <flowgraph/SourceI24.h>
Phil Burk04e805b2018-03-27 09:13:53 -070034#include <flowgraph/SourceI32.h>
Phil Burk0127c1b2018-03-29 13:48:06 -070035
36using namespace flowgraph;
37
38aaudio_result_t AAudioFlowGraph::configure(audio_format_t sourceFormat,
39 int32_t sourceChannelCount,
40 audio_format_t sinkFormat,
Robert Wud7400832021-12-04 01:11:19 +000041 int32_t sinkChannelCount,
42 bool useMonoBlend) {
Robert Wu057f0832021-12-03 20:41:07 +000043 FlowGraphPortFloatOutput *lastOutput = nullptr;
Phil Burk0127c1b2018-03-29 13:48:06 -070044
Phil Burk04e805b2018-03-27 09:13:53 -070045 // TODO change back to ALOGD
46 ALOGI("%s() source format = 0x%08x, channels = %d, sink format = 0x%08x, channels = %d",
Phil Burk0127c1b2018-03-29 13:48:06 -070047 __func__, sourceFormat, sourceChannelCount, sinkFormat, sinkChannelCount);
48
49 switch (sourceFormat) {
50 case AUDIO_FORMAT_PCM_FLOAT:
51 mSource = std::make_unique<SourceFloat>(sourceChannelCount);
52 break;
53 case AUDIO_FORMAT_PCM_16_BIT:
54 mSource = std::make_unique<SourceI16>(sourceChannelCount);
55 break;
56 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
57 mSource = std::make_unique<SourceI24>(sourceChannelCount);
58 break;
Phil Burk04e805b2018-03-27 09:13:53 -070059 case AUDIO_FORMAT_PCM_32_BIT:
60 mSource = std::make_unique<SourceI32>(sourceChannelCount);
61 break;
62 default:
Phil Burk0127c1b2018-03-29 13:48:06 -070063 ALOGE("%s() Unsupported source format = %d", __func__, sourceFormat);
64 return AAUDIO_ERROR_UNIMPLEMENTED;
65 }
66 lastOutput = &mSource->output;
67
68 // Apply volume as a ramp to avoid pops.
69 mVolumeRamp = std::make_unique<RampLinear>(sourceChannelCount);
70 lastOutput->connect(&mVolumeRamp->input);
71 lastOutput = &mVolumeRamp->output;
72
73 // For a pure float graph, there is chance that the data range may be very large.
74 // So we should clip to a reasonable value that allows a little headroom.
75 if (sourceFormat == AUDIO_FORMAT_PCM_FLOAT && sinkFormat == AUDIO_FORMAT_PCM_FLOAT) {
76 mClipper = std::make_unique<ClipToRange>(sourceChannelCount);
77 lastOutput->connect(&mClipper->input);
78 lastOutput = &mClipper->output;
79 }
80
Robert Wud7400832021-12-04 01:11:19 +000081 if (useMonoBlend) {
82 mMonoBlend = std::make_unique<MonoBlend>(sourceChannelCount);
83 lastOutput->connect(&mMonoBlend->input);
84 lastOutput = &mMonoBlend->output;
85 }
86
Phil Burk0127c1b2018-03-29 13:48:06 -070087 // Expand the number of channels if required.
88 if (sourceChannelCount == 1 && sinkChannelCount > 1) {
89 mChannelConverter = std::make_unique<MonoToMultiConverter>(sinkChannelCount);
90 lastOutput->connect(&mChannelConverter->input);
91 lastOutput = &mChannelConverter->output;
92 } else if (sourceChannelCount != sinkChannelCount) {
93 ALOGE("%s() Channel reduction not supported.", __func__);
94 return AAUDIO_ERROR_UNIMPLEMENTED;
95 }
96
97 switch (sinkFormat) {
98 case AUDIO_FORMAT_PCM_FLOAT:
99 mSink = std::make_unique<SinkFloat>(sinkChannelCount);
100 break;
101 case AUDIO_FORMAT_PCM_16_BIT:
102 mSink = std::make_unique<SinkI16>(sinkChannelCount);
103 break;
104 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
105 mSink = std::make_unique<SinkI24>(sinkChannelCount);
106 break;
Phil Burk04e805b2018-03-27 09:13:53 -0700107 case AUDIO_FORMAT_PCM_32_BIT:
108 mSink = std::make_unique<SinkI32>(sinkChannelCount);
109 break;
110 default:
Phil Burk0127c1b2018-03-29 13:48:06 -0700111 ALOGE("%s() Unsupported sink format = %d", __func__, sinkFormat);
112 return AAUDIO_ERROR_UNIMPLEMENTED;
113 }
114 lastOutput->connect(&mSink->input);
115
116 return AAUDIO_OK;
117}
118
119void AAudioFlowGraph::process(const void *source, void *destination, int32_t numFrames) {
120 mSource->setData(source, numFrames);
121 mSink->read(destination, numFrames);
122}
123
124/**
125 * @param volume between 0.0 and 1.0
126 */
127void AAudioFlowGraph::setTargetVolume(float volume) {
128 mVolumeRamp->setTarget(volume);
129}
130
131void AAudioFlowGraph::setRampLengthInFrames(int32_t numFrames) {
132 mVolumeRamp->setLengthInFrames(numFrames);
133}