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