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 #ifndef OBOETESTER_FULL_DUPLEX_STREAM_H
18 #define OBOETESTER_FULL_DUPLEX_STREAM_H
19 
20 #include <unistd.h>
21 #include <sys/types.h>
22 
23 #include "oboe/Oboe.h"
24 
25 class FullDuplexStream : public oboe::AudioStreamCallback {
26 public:
FullDuplexStream()27     FullDuplexStream() {}
28     virtual ~FullDuplexStream() = default;
29 
setInputStream(oboe::AudioStream * stream)30     void setInputStream(oboe::AudioStream *stream) {
31         mInputStream = stream;
32     }
33 
getInputStream()34     oboe::AudioStream *getInputStream() {
35         return mInputStream;
36     }
37 
setOutputStream(oboe::AudioStream * stream)38     void setOutputStream(oboe::AudioStream *stream) {
39         mOutputStream = stream;
40     }
getOutputStream()41     oboe::AudioStream *getOutputStream() {
42         return mOutputStream;
43     }
44 
45     virtual oboe::Result start();
46 
47     virtual oboe::Result stop();
48 
49     /**
50      * Called when data is available on both streams.
51      * Caller should override this method.
52      */
53     virtual oboe::DataCallbackResult onBothStreamsReady(
54             const void *inputData,
55             int   numInputFrames,
56             void *outputData,
57             int   numOutputFrames
58             ) = 0;
59 
60     /**
61      * Called by Oboe when the stream is ready to process audio.
62      */
63     oboe::DataCallbackResult onAudioReady(
64             oboe::AudioStream *audioStream,
65             void *audioData,
66             int numFrames) override;
67 
68     int32_t getMNumInputBurstsCushion() const;
69 
70     /**
71      * Number of bursts to leave in the input buffer as a cushion.
72      * Typically 0 for latency measurements
73      * or 1 for glitch tests.
74      *
75      * @param mNumInputBurstsCushion
76      */
77     void setMNumInputBurstsCushion(int32_t mNumInputBurstsCushion);
78 
setMinimumFramesBeforeRead(int32_t numFrames)79     void setMinimumFramesBeforeRead(int32_t numFrames) {
80         mMinimumFramesBeforeRead = numFrames;
81     }
82 
getMinimumFramesBeforeRead()83     int32_t getMinimumFramesBeforeRead() const {
84         return mMinimumFramesBeforeRead;
85     }
86 
87 private:
88 
89     // TODO add getters and setters
90     static constexpr int32_t kNumCallbacksToDrain   = 20;
91     static constexpr int32_t kNumCallbacksToDiscard = 30;
92 
93     // let input fill back up, usually 0 or 1
94     int32_t mNumInputBurstsCushion =  0;
95     int32_t mMinimumFramesBeforeRead = 0;
96 
97     // We want to reach a state where the input buffer is empty and
98     // the output buffer is full.
99     // These are used in order.
100     // Drain several callback so that input is empty.
101     int32_t              mCountCallbacksToDrain = kNumCallbacksToDrain;
102     // Let the input fill back up slightly so we don't run dry.
103     int32_t              mCountInputBurstsCushion = mNumInputBurstsCushion;
104     // Discard some callbacks so the input and output reach equilibrium.
105     int32_t              mCountCallbacksToDiscard = kNumCallbacksToDiscard;
106 
107     oboe::AudioStream   *mInputStream = nullptr;
108     oboe::AudioStream   *mOutputStream = nullptr;
109 
110     int32_t              mBufferSize = 0;
111     std::unique_ptr<float[]> mInputBuffer;
112 };
113 
114 
115 #endif //OBOETESTER_FULL_DUPLEX_STREAM_H
116