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