1 /*
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>
24 #include <flowgraph/MonoToMultiConverter.h>
25 #include <flowgraph/RampLinear.h>
26 #include <flowgraph/SinkFloat.h>
27 #include <flowgraph/SinkI16.h>
28 #include <flowgraph/SinkI24.h>
29 #include <flowgraph/SourceFloat.h>
30 #include <flowgraph/SourceI16.h>
31 #include <flowgraph/SourceI24.h>
32
33 using namespace flowgraph;
34
configure(audio_format_t sourceFormat,int32_t sourceChannelCount,audio_format_t sinkFormat,int32_t sinkChannelCount)35 aaudio_result_t AAudioFlowGraph::configure(audio_format_t sourceFormat,
36 int32_t sourceChannelCount,
37 audio_format_t sinkFormat,
38 int32_t sinkChannelCount) {
39 AudioFloatOutputPort *lastOutput = nullptr;
40
41 ALOGV("%s() source format = 0x%08x, channels = %d, sink format = 0x%08x, channels = %d",
42 __func__, sourceFormat, sourceChannelCount, sinkFormat, sinkChannelCount);
43
44 switch (sourceFormat) {
45 case AUDIO_FORMAT_PCM_FLOAT:
46 mSource = std::make_unique<SourceFloat>(sourceChannelCount);
47 break;
48 case AUDIO_FORMAT_PCM_16_BIT:
49 mSource = std::make_unique<SourceI16>(sourceChannelCount);
50 break;
51 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
52 mSource = std::make_unique<SourceI24>(sourceChannelCount);
53 break;
54 default: // TODO add I32
55 ALOGE("%s() Unsupported source format = %d", __func__, sourceFormat);
56 return AAUDIO_ERROR_UNIMPLEMENTED;
57 }
58 lastOutput = &mSource->output;
59
60 // Apply volume as a ramp to avoid pops.
61 mVolumeRamp = std::make_unique<RampLinear>(sourceChannelCount);
62 lastOutput->connect(&mVolumeRamp->input);
63 lastOutput = &mVolumeRamp->output;
64
65 // For a pure float graph, there is chance that the data range may be very large.
66 // So we should clip to a reasonable value that allows a little headroom.
67 if (sourceFormat == AUDIO_FORMAT_PCM_FLOAT && sinkFormat == AUDIO_FORMAT_PCM_FLOAT) {
68 mClipper = std::make_unique<ClipToRange>(sourceChannelCount);
69 lastOutput->connect(&mClipper->input);
70 lastOutput = &mClipper->output;
71 }
72
73 // Expand the number of channels if required.
74 if (sourceChannelCount == 1 && sinkChannelCount > 1) {
75 mChannelConverter = std::make_unique<MonoToMultiConverter>(sinkChannelCount);
76 lastOutput->connect(&mChannelConverter->input);
77 lastOutput = &mChannelConverter->output;
78 } else if (sourceChannelCount != sinkChannelCount) {
79 ALOGE("%s() Channel reduction not supported.", __func__);
80 return AAUDIO_ERROR_UNIMPLEMENTED;
81 }
82
83 switch (sinkFormat) {
84 case AUDIO_FORMAT_PCM_FLOAT:
85 mSink = std::make_unique<SinkFloat>(sinkChannelCount);
86 break;
87 case AUDIO_FORMAT_PCM_16_BIT:
88 mSink = std::make_unique<SinkI16>(sinkChannelCount);
89 break;
90 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
91 mSink = std::make_unique<SinkI24>(sinkChannelCount);
92 break;
93 default: // TODO add I32
94 ALOGE("%s() Unsupported sink format = %d", __func__, sinkFormat);
95 return AAUDIO_ERROR_UNIMPLEMENTED;
96 }
97 lastOutput->connect(&mSink->input);
98
99 return AAUDIO_OK;
100 }
101
process(const void * source,void * destination,int32_t numFrames)102 void AAudioFlowGraph::process(const void *source, void *destination, int32_t numFrames) {
103 mSource->setData(source, numFrames);
104 mSink->read(destination, numFrames);
105 }
106
107 /**
108 * @param volume between 0.0 and 1.0
109 */
setTargetVolume(float volume)110 void AAudioFlowGraph::setTargetVolume(float volume) {
111 mVolumeRamp->setTarget(volume);
112 }
113
setRampLengthInFrames(int32_t numFrames)114 void AAudioFlowGraph::setRampLengthInFrames(int32_t numFrames) {
115 mVolumeRamp->setLengthInFrames(numFrames);
116 }
117