1 /*
2  * Copyright (C) 2021 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 package com.android.cts.verifier.audio.audiolib;
17 
18 /**
19  * Implements a circular buffer of float data
20  */
21 public class CircularBufferFloat {
22     private float[] mData;
23     private int mCursor;
24     private int mNumValidSamples;
25 
CircularBufferFloat(int numSamples)26     public CircularBufferFloat(int numSamples) {
27         mData = new float[numSamples];
28     }
29 
30     /**
31      * Adds an array of float values to this buffer.
32      * @param buffer    The float values to store.
33      * @return The number of values stored.
34      */
write(float[] buffer)35     public int write(float[] buffer) {
36         return write(buffer, 0, buffer.length);
37     }
38 
39     /**
40      * Adds a (subset of a) an array of float values to this buffer
41      * @param buffer    The values to store.
42      * @param offset    The offset of the first value to store.
43      * @param numSamples    The number of values to store.
44      * @return The number of values stored.
45      */
write(float[] buffer, int offset, int numSamples)46     public int write(float[] buffer, int offset, int numSamples) {
47         if (numSamples > mData.length) {
48             throw new IllegalArgumentException("Tried to write more than maxSamples.");
49         }
50         if ((mCursor + numSamples) > mData.length) {
51             // Wraps so write in two parts.
52             int numWrite1 = mData.length - mCursor;
53             System.arraycopy(buffer, offset, mData, mCursor, numWrite1);
54             offset += numWrite1;
55             int numWrite2 = numSamples - numWrite1;
56             System.arraycopy(buffer, offset, mData, 0, numWrite2);
57             mCursor = numWrite2;
58         } else {
59             System.arraycopy(buffer, offset, mData, mCursor, numSamples);
60             mCursor += numSamples;
61             if (mCursor == mData.length) {
62                 mCursor = 0;
63             }
64         }
65         mNumValidSamples += numSamples;
66         if (mNumValidSamples > mData.length) {
67             mNumValidSamples = mData.length;
68         }
69         return numSamples;
70     }
71 
72     /**
73      * Reads the most recently written samples into the provided buffer.
74      * @param buffer    The buffer to receive the most recent values.
75      * @return The number of values retrieved.
76      */
readMostRecent(float[] buffer)77     public int readMostRecent(float[] buffer) {
78         return readMostRecent(buffer, 0, buffer.length);
79     }
80 
81     /**
82      * Read the most recently written values.
83      * @param buffer    The buffer to receive the values
84      * @param offset    The offset within the buffer to receive the values
85      * @param numSamples    The number of values to retrieve.
86      * @return number of values read
87      */
readMostRecent(float[] buffer, int offset, int numSamples)88     public int readMostRecent(float[] buffer, int offset, int numSamples) {
89 
90         if (numSamples > mNumValidSamples) {
91             numSamples = mNumValidSamples;
92         }
93         int cursor = mCursor; // read once in case it gets updated by another thread
94         // Read in two parts.
95         if ((cursor - numSamples) < 0) {
96             int numRead1 = numSamples - cursor;
97             System.arraycopy(mData, mData.length - numRead1, buffer, offset, numRead1);
98             offset += numRead1;
99             int numRead2 = cursor;
100             System.arraycopy(mData, 0, buffer, offset, numRead2);
101         } else {
102             System.arraycopy(mData, cursor - numSamples, buffer, offset, numSamples);
103         }
104 
105         return numSamples;
106     }
107 
108     /**
109      * (Logically) clears all the values from this circular buffer.
110      */
erase()111     public void erase() {
112         mNumValidSamples = 0;
113         mCursor = 0;
114     }
115 
116     /**
117      * @return  The maximum number of values that can be stored.
118      * i.e. the capacity of this circular buffer.
119      */
getSize()120     public int getSize() {
121         return mData.length;
122     }
123 }
124