xref: /aosp_15_r20/external/oboe/apps/OboeTester/app/src/main/cpp/analyzer/InfiniteRecording.h (revision 05767d913155b055644481607e6fa1e35e2fe72c)
1 /*
2  * Copyright (C) 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_INFINITE_RECORDING_H
18 #define OBOETESTER_INFINITE_RECORDING_H
19 
20 #include <memory>
21 #include <unistd.h>
22 
23 /**
24  * Record forever. Keep last data.
25  */
26 template <typename T>
27 class InfiniteRecording {
28 public:
InfiniteRecording(size_t maxSamples)29     InfiniteRecording(size_t maxSamples)
30             : mMaxSamples(maxSamples) {
31         mData = std::make_unique<T[]>(mMaxSamples);
32     }
33 
readFrom(T * buffer,size_t position,size_t count)34     int32_t readFrom(T *buffer, size_t position, size_t count) {
35         const size_t maxPosition = mWritten.load();
36         position = std::min(position, maxPosition);
37 
38         size_t numToRead = std::min(count, mMaxSamples);
39         numToRead = std::min(numToRead, maxPosition - position);
40         if (numToRead == 0) return 0;
41         // We may need to read in two parts if it wraps.
42         const size_t offset = position % mMaxSamples;
43         const size_t firstReadSize = std::min(numToRead, mMaxSamples - offset); // till end
44         std::copy(&mData[offset], &mData[offset + firstReadSize], buffer);
45         if (firstReadSize < numToRead) {
46             // Second read needed.
47             std::copy(&mData[0], &mData[numToRead - firstReadSize], &buffer[firstReadSize]);
48         }
49         return numToRead;
50     }
51 
write(T sample)52     void write(T sample) {
53         const size_t position = mWritten.load();
54         const size_t offset = position % mMaxSamples;
55         mData[offset] = sample;
56         mWritten++;
57     }
58 
getTotalWritten()59     int64_t getTotalWritten() {
60         return mWritten.load();
61     }
62 
63 private:
64     std::unique_ptr<T[]> mData;
65     std::atomic<size_t>  mWritten{0};
66     const size_t         mMaxSamples;
67 };
68 #endif //OBOETESTER_INFINITE_RECORDING_H
69