xref: /aosp_15_r20/external/oboe/src/fifo/FifoBuffer.cpp (revision 05767d913155b055644481607e6fa1e35e2fe72c)
1*05767d91SRobert Wu /*
2*05767d91SRobert Wu  * Copyright 2015 The Android Open Source Project
3*05767d91SRobert Wu  *
4*05767d91SRobert Wu  * Licensed under the Apache License, Version 2.0 (the "License");
5*05767d91SRobert Wu  * you may not use this file except in compliance with the License.
6*05767d91SRobert Wu  * You may obtain a copy of the License at
7*05767d91SRobert Wu  *
8*05767d91SRobert Wu  *      http://www.apache.org/licenses/LICENSE-2.0
9*05767d91SRobert Wu  *
10*05767d91SRobert Wu  * Unless required by applicable law or agreed to in writing, software
11*05767d91SRobert Wu  * distributed under the License is distributed on an "AS IS" BASIS,
12*05767d91SRobert Wu  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*05767d91SRobert Wu  * See the License for the specific language governing permissions and
14*05767d91SRobert Wu  * limitations under the License.
15*05767d91SRobert Wu  */
16*05767d91SRobert Wu 
17*05767d91SRobert Wu #include <algorithm>
18*05767d91SRobert Wu #include <memory.h>
19*05767d91SRobert Wu #include <stdint.h>
20*05767d91SRobert Wu 
21*05767d91SRobert Wu #include "oboe/FifoControllerBase.h"
22*05767d91SRobert Wu #include "fifo/FifoController.h"
23*05767d91SRobert Wu #include "fifo/FifoControllerIndirect.h"
24*05767d91SRobert Wu #include "oboe/FifoBuffer.h"
25*05767d91SRobert Wu 
26*05767d91SRobert Wu namespace oboe {
27*05767d91SRobert Wu 
FifoBuffer(uint32_t bytesPerFrame,uint32_t capacityInFrames)28*05767d91SRobert Wu FifoBuffer::FifoBuffer(uint32_t bytesPerFrame, uint32_t capacityInFrames)
29*05767d91SRobert Wu         : mBytesPerFrame(bytesPerFrame)
30*05767d91SRobert Wu         , mStorage(nullptr)
31*05767d91SRobert Wu         , mFramesReadCount(0)
32*05767d91SRobert Wu         , mFramesUnderrunCount(0)
33*05767d91SRobert Wu {
34*05767d91SRobert Wu     mFifo = std::make_unique<FifoController>(capacityInFrames);
35*05767d91SRobert Wu     // allocate buffer
36*05767d91SRobert Wu     int32_t bytesPerBuffer = bytesPerFrame * capacityInFrames;
37*05767d91SRobert Wu     mStorage = new uint8_t[bytesPerBuffer];
38*05767d91SRobert Wu     mStorageOwned = true;
39*05767d91SRobert Wu }
40*05767d91SRobert Wu 
FifoBuffer(uint32_t bytesPerFrame,uint32_t capacityInFrames,std::atomic<uint64_t> * readCounterAddress,std::atomic<uint64_t> * writeCounterAddress,uint8_t * dataStorageAddress)41*05767d91SRobert Wu FifoBuffer::FifoBuffer( uint32_t  bytesPerFrame,
42*05767d91SRobert Wu                         uint32_t  capacityInFrames,
43*05767d91SRobert Wu                         std::atomic<uint64_t>  *readCounterAddress,
44*05767d91SRobert Wu                         std::atomic<uint64_t>  *writeCounterAddress,
45*05767d91SRobert Wu                         uint8_t  *dataStorageAddress
46*05767d91SRobert Wu                         )
47*05767d91SRobert Wu         : mBytesPerFrame(bytesPerFrame)
48*05767d91SRobert Wu         , mStorage(dataStorageAddress)
49*05767d91SRobert Wu         , mFramesReadCount(0)
50*05767d91SRobert Wu         , mFramesUnderrunCount(0)
51*05767d91SRobert Wu {
52*05767d91SRobert Wu     mFifo = std::make_unique<FifoControllerIndirect>(capacityInFrames,
53*05767d91SRobert Wu                                        readCounterAddress,
54*05767d91SRobert Wu                                        writeCounterAddress);
55*05767d91SRobert Wu     mStorage = dataStorageAddress;
56*05767d91SRobert Wu     mStorageOwned = false;
57*05767d91SRobert Wu }
58*05767d91SRobert Wu 
~FifoBuffer()59*05767d91SRobert Wu FifoBuffer::~FifoBuffer() {
60*05767d91SRobert Wu     if (mStorageOwned) {
61*05767d91SRobert Wu         delete[] mStorage;
62*05767d91SRobert Wu     }
63*05767d91SRobert Wu }
64*05767d91SRobert Wu 
convertFramesToBytes(int32_t frames)65*05767d91SRobert Wu int32_t FifoBuffer::convertFramesToBytes(int32_t frames) {
66*05767d91SRobert Wu     return frames * mBytesPerFrame;
67*05767d91SRobert Wu }
68*05767d91SRobert Wu 
read(void * buffer,int32_t numFrames)69*05767d91SRobert Wu int32_t FifoBuffer::read(void *buffer, int32_t numFrames) {
70*05767d91SRobert Wu     if (numFrames <= 0) {
71*05767d91SRobert Wu         return 0;
72*05767d91SRobert Wu     }
73*05767d91SRobert Wu     // safe because numFrames is guaranteed positive
74*05767d91SRobert Wu     uint32_t framesToRead = static_cast<uint32_t>(numFrames);
75*05767d91SRobert Wu     uint32_t framesAvailable = mFifo->getFullFramesAvailable();
76*05767d91SRobert Wu     framesToRead = std::min(framesToRead, framesAvailable);
77*05767d91SRobert Wu 
78*05767d91SRobert Wu     uint32_t readIndex = mFifo->getReadIndex(); // ranges 0 to capacity
79*05767d91SRobert Wu     uint8_t *destination = reinterpret_cast<uint8_t *>(buffer);
80*05767d91SRobert Wu     uint8_t *source = &mStorage[convertFramesToBytes(readIndex)];
81*05767d91SRobert Wu     if ((readIndex + framesToRead) > mFifo->getFrameCapacity()) {
82*05767d91SRobert Wu         // read in two parts, first part here is at the end of the mStorage buffer
83*05767d91SRobert Wu         int32_t frames1 = static_cast<int32_t>(mFifo->getFrameCapacity() - readIndex);
84*05767d91SRobert Wu         int32_t numBytes = convertFramesToBytes(frames1);
85*05767d91SRobert Wu         if (numBytes < 0) {
86*05767d91SRobert Wu             return static_cast<int32_t>(Result::ErrorOutOfRange);
87*05767d91SRobert Wu         }
88*05767d91SRobert Wu         memcpy(destination, source, static_cast<size_t>(numBytes));
89*05767d91SRobert Wu         destination += numBytes;
90*05767d91SRobert Wu         // read second part, which is at the beginning of mStorage
91*05767d91SRobert Wu         source = &mStorage[0];
92*05767d91SRobert Wu         int32_t frames2 = static_cast<uint32_t>(framesToRead - frames1);
93*05767d91SRobert Wu         numBytes = convertFramesToBytes(frames2);
94*05767d91SRobert Wu         if (numBytes < 0) {
95*05767d91SRobert Wu             return static_cast<int32_t>(Result::ErrorOutOfRange);
96*05767d91SRobert Wu         }
97*05767d91SRobert Wu         memcpy(destination, source, static_cast<size_t>(numBytes));
98*05767d91SRobert Wu     } else {
99*05767d91SRobert Wu         // just read in one shot
100*05767d91SRobert Wu         int32_t numBytes = convertFramesToBytes(framesToRead);
101*05767d91SRobert Wu         if (numBytes < 0) {
102*05767d91SRobert Wu             return static_cast<int32_t>(Result::ErrorOutOfRange);
103*05767d91SRobert Wu         }
104*05767d91SRobert Wu         memcpy(destination, source, static_cast<size_t>(numBytes));
105*05767d91SRobert Wu     }
106*05767d91SRobert Wu     mFifo->advanceReadIndex(framesToRead);
107*05767d91SRobert Wu 
108*05767d91SRobert Wu     return framesToRead;
109*05767d91SRobert Wu }
110*05767d91SRobert Wu 
write(const void * buffer,int32_t numFrames)111*05767d91SRobert Wu int32_t FifoBuffer::write(const void *buffer, int32_t numFrames) {
112*05767d91SRobert Wu     if (numFrames <= 0) {
113*05767d91SRobert Wu         return 0;
114*05767d91SRobert Wu     }
115*05767d91SRobert Wu     // Guaranteed positive.
116*05767d91SRobert Wu     uint32_t framesToWrite = static_cast<uint32_t>(numFrames);
117*05767d91SRobert Wu     uint32_t framesAvailable = mFifo->getEmptyFramesAvailable();
118*05767d91SRobert Wu     framesToWrite = std::min(framesToWrite, framesAvailable);
119*05767d91SRobert Wu 
120*05767d91SRobert Wu     uint32_t writeIndex = mFifo->getWriteIndex();
121*05767d91SRobert Wu     int byteIndex = convertFramesToBytes(writeIndex);
122*05767d91SRobert Wu     const uint8_t *source = reinterpret_cast<const uint8_t *>(buffer);
123*05767d91SRobert Wu     uint8_t *destination = &mStorage[byteIndex];
124*05767d91SRobert Wu     if ((writeIndex + framesToWrite) > mFifo->getFrameCapacity()) {
125*05767d91SRobert Wu         // write in two parts, first part here
126*05767d91SRobert Wu         int32_t frames1 = static_cast<uint32_t>(mFifo->getFrameCapacity() - writeIndex);
127*05767d91SRobert Wu         int32_t numBytes = convertFramesToBytes(frames1);
128*05767d91SRobert Wu         if (numBytes < 0) {
129*05767d91SRobert Wu             return static_cast<int32_t>(Result::ErrorOutOfRange);
130*05767d91SRobert Wu         }
131*05767d91SRobert Wu         memcpy(destination, source, static_cast<size_t>(numBytes));
132*05767d91SRobert Wu         // read second part
133*05767d91SRobert Wu         source += convertFramesToBytes(frames1);
134*05767d91SRobert Wu         destination = &mStorage[0];
135*05767d91SRobert Wu         int frames2 = static_cast<uint32_t>(framesToWrite - frames1);
136*05767d91SRobert Wu         numBytes = convertFramesToBytes(frames2);
137*05767d91SRobert Wu         if (numBytes < 0) {
138*05767d91SRobert Wu             return static_cast<int32_t>(Result::ErrorOutOfRange);
139*05767d91SRobert Wu         }
140*05767d91SRobert Wu         memcpy(destination, source, static_cast<size_t>(numBytes));
141*05767d91SRobert Wu     } else {
142*05767d91SRobert Wu         // just write in one shot
143*05767d91SRobert Wu         int32_t numBytes = convertFramesToBytes(framesToWrite);
144*05767d91SRobert Wu         if (numBytes < 0) {
145*05767d91SRobert Wu             return static_cast<int32_t>(Result::ErrorOutOfRange);
146*05767d91SRobert Wu         }
147*05767d91SRobert Wu         memcpy(destination, source, static_cast<size_t>(numBytes));
148*05767d91SRobert Wu     }
149*05767d91SRobert Wu     mFifo->advanceWriteIndex(framesToWrite);
150*05767d91SRobert Wu 
151*05767d91SRobert Wu     return framesToWrite;
152*05767d91SRobert Wu }
153*05767d91SRobert Wu 
readNow(void * buffer,int32_t numFrames)154*05767d91SRobert Wu int32_t FifoBuffer::readNow(void *buffer, int32_t numFrames) {
155*05767d91SRobert Wu     int32_t framesRead = read(buffer, numFrames);
156*05767d91SRobert Wu     if (framesRead < 0) {
157*05767d91SRobert Wu         return framesRead;
158*05767d91SRobert Wu     }
159*05767d91SRobert Wu     int32_t framesLeft = numFrames - framesRead;
160*05767d91SRobert Wu     mFramesReadCount += framesRead;
161*05767d91SRobert Wu     mFramesUnderrunCount += framesLeft;
162*05767d91SRobert Wu     // Zero out any samples we could not set.
163*05767d91SRobert Wu     if (framesLeft > 0) {
164*05767d91SRobert Wu         uint8_t *destination = reinterpret_cast<uint8_t *>(buffer);
165*05767d91SRobert Wu         destination += convertFramesToBytes(framesRead); // point to first byte not set
166*05767d91SRobert Wu         int32_t bytesToZero = convertFramesToBytes(framesLeft);
167*05767d91SRobert Wu         memset(destination, 0, static_cast<size_t>(bytesToZero));
168*05767d91SRobert Wu     }
169*05767d91SRobert Wu 
170*05767d91SRobert Wu     return framesRead;
171*05767d91SRobert Wu }
172*05767d91SRobert Wu 
173*05767d91SRobert Wu 
getBufferCapacityInFrames() const174*05767d91SRobert Wu uint32_t FifoBuffer::getBufferCapacityInFrames() const {
175*05767d91SRobert Wu     return mFifo->getFrameCapacity();
176*05767d91SRobert Wu }
177*05767d91SRobert Wu 
178*05767d91SRobert Wu } // namespace oboe
179