• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2019 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 #include <memory>
18 
19 #include "FilterAudioStream.h"
20 
21 using namespace oboe;
22 using namespace flowgraph;
23 
24 // Output callback uses FixedBlockReader::read()
25 //                <= SourceFloatCaller::onProcess()
26 //                <=== DataConversionFlowGraph::read()
27 //                <== FilterAudioStream::onAudioReady()
28 //
29 // Output blocking uses no block adapter because AAudio can accept
30 // writes of any size. It uses DataConversionFlowGraph::read() <== FilterAudioStream::write() <= app
31 //
32 // Input callback uses FixedBlockWriter::write()
33 //                <= DataConversionFlowGraph::write()
34 //                <= FilterAudioStream::onAudioReady()
35 //
36 // Input blocking uses FixedBlockReader::read() // TODO may not need block adapter
37 //                <= SourceFloatCaller::onProcess()
38 //                <=== SinkFloat::read()
39 //                <= DataConversionFlowGraph::read()
40 //                <== FilterAudioStream::read()
41 //                <= app
42 
configureFlowGraph()43 Result FilterAudioStream::configureFlowGraph() {
44     mFlowGraph = std::make_unique<DataConversionFlowGraph>();
45     bool isOutput = getDirection() == Direction::Output;
46 
47     AudioStream *sourceStream =  isOutput ? this : mChildStream.get();
48     AudioStream *sinkStream =  isOutput ? mChildStream.get() : this;
49 
50     mRateScaler = ((double) sourceStream->getSampleRate()) / sinkStream->getSampleRate();
51 
52     return mFlowGraph->configure(sourceStream, sinkStream);
53 }
54 
55 // Put the data to be written at the source end of the flowgraph.
56 // Then read (pull) the data from the flowgraph and write it to the
57 // child stream.
write(const void * buffer,int32_t numFrames,int64_t timeoutNanoseconds)58 ResultWithValue<int32_t> FilterAudioStream::write(const void *buffer,
59                                int32_t numFrames,
60                                int64_t timeoutNanoseconds) {
61     int32_t framesWritten = 0;
62     mFlowGraph->setSource(buffer, numFrames);
63     while (true) {
64         int32_t numRead = mFlowGraph->read(mBlockingBuffer.get(),
65                 getFramesPerBurst(),
66                 timeoutNanoseconds);
67         if (numRead < 0) {
68             return ResultWithValue<int32_t>::createBasedOnSign(numRead);
69         }
70         if (numRead == 0) {
71             break; // finished processing the source buffer
72         }
73         auto writeResult = mChildStream->write(mBlockingBuffer.get(),
74                                                numRead,
75                                                timeoutNanoseconds);
76         if (!writeResult) {
77             return writeResult;
78         }
79         framesWritten += writeResult.value();
80     }
81     return ResultWithValue<int32_t>::createBasedOnSign(framesWritten);
82 }
83 
84 // Read (pull) the data we want from the sink end of the flowgraph.
85 // The necessary data will be read from the child stream using a flowgraph callback.
read(void * buffer,int32_t numFrames,int64_t timeoutNanoseconds)86 ResultWithValue<int32_t> FilterAudioStream::read(void *buffer,
87                                                   int32_t numFrames,
88                                                   int64_t timeoutNanoseconds) {
89     int32_t framesRead = mFlowGraph->read(buffer, numFrames, timeoutNanoseconds);
90     return ResultWithValue<int32_t>::createBasedOnSign(framesRead);
91 }
92 
93