blob: 61b50f3fa8e6217e06ffb5bd390f06d62a4bd2bd [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>
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>
Phil Burk04e805b2018-03-27 09:13:53 -070029#include <flowgraph/SinkI32.h>
Phil Burk0127c1b2018-03-29 13:48:06 -070030#include <flowgraph/SourceFloat.h>
31#include <flowgraph/SourceI16.h>
32#include <flowgraph/SourceI24.h>
Phil Burk04e805b2018-03-27 09:13:53 -070033#include <flowgraph/SourceI32.h>
Phil Burk0127c1b2018-03-29 13:48:06 -070034
35using namespace flowgraph;
36
37aaudio_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
Phil Burk04e805b2018-03-27 09:13:53 -070043 // TODO change back to ALOGD
44 ALOGI("%s() source format = 0x%08x, channels = %d, sink format = 0x%08x, channels = %d",
Phil Burk0127c1b2018-03-29 13:48:06 -070045 __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;
Phil Burk04e805b2018-03-27 09:13:53 -070057 case AUDIO_FORMAT_PCM_32_BIT:
58 mSource = std::make_unique<SourceI32>(sourceChannelCount);
59 break;
60 default:
Phil Burk0127c1b2018-03-29 13:48:06 -070061 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;
Phil Burk04e805b2018-03-27 09:13:53 -070099 case AUDIO_FORMAT_PCM_32_BIT:
100 mSink = std::make_unique<SinkI32>(sinkChannelCount);
101 break;
102 default:
Phil Burk0127c1b2018-03-29 13:48:06 -0700103 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
111void 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 */
119void AAudioFlowGraph::setTargetVolume(float volume) {
120 mVolumeRamp->setTarget(volume);
121}
122
123void AAudioFlowGraph::setRampLengthInFrames(int32_t numFrames) {
124 mVolumeRamp->setLengthInFrames(numFrames);
125}