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 package com.google.sample.oboe.manualtest;
18 
19 import android.content.Context;
20 import android.util.AttributeSet;
21 import android.view.LayoutInflater;
22 
23 
24 import android.view.View;
25 import android.widget.RadioButton;
26 import android.widget.SeekBar;
27 import android.widget.TextView;
28 import android.widget.LinearLayout;
29 
30 public class BufferSizeView extends LinearLayout {
31     private OboeAudioStream mStream;
32 
33     private static final int FADER_THRESHOLD_MAX = 1000; // must match layout
34     private static final int USE_FADER = -1;
35     private static final int DEFAULT_NUM_BURSTS = 2;
36     private TextView mTextLabel;
37     private SeekBar mFader;
38     private ExponentialTaper mTaper;
39     private RadioButton mBufferSizeRadio1;
40     private RadioButton mBufferSizeRadio2;
41     private RadioButton mBufferSizeRadio3;
42     private int mCachedCapacity;
43     private int mFramesPerBurst;
44     private int mNumBursts;
45 
46     private SeekBar.OnSeekBarChangeListener mFaderListener = new SeekBar.OnSeekBarChangeListener() {
47         @Override
48         public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
49             mNumBursts = USE_FADER;
50             updateRadioButtons();
51             setBufferSizeByPosition(progress);
52         }
53 
54         @Override
55         public void onStartTrackingTouch(SeekBar seekBar) {
56         }
57 
58         @Override
59         public void onStopTrackingTouch(SeekBar seekBar) {
60         }
61     };
62 
BufferSizeView(Context context)63     public BufferSizeView(Context context) {
64         super(context);
65         initializeViews(context);
66     }
67 
BufferSizeView(Context context, AttributeSet attrs)68     public BufferSizeView(Context context, AttributeSet attrs) {
69         super(context, attrs);
70         initializeViews(context);
71     }
72 
BufferSizeView(Context context, AttributeSet attrs, int defStyle)73     public BufferSizeView(Context context,
74                           AttributeSet attrs,
75                           int defStyle) {
76         super(context, attrs, defStyle);
77         initializeViews(context);
78     }
79 
setFaderNormalizedProgress(double fraction)80     void setFaderNormalizedProgress(double fraction) {
81         mFader.setProgress((int) (fraction * FADER_THRESHOLD_MAX));
82     }
83 
84     /**
85      * Inflates the views in the layout.
86      *
87      * @param context the current context for the view.
88      */
initializeViews(Context context)89     private void initializeViews(Context context) {
90         LayoutInflater inflater = (LayoutInflater) context
91                 .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
92         inflater.inflate(R.layout.buffer_size_view, this);
93 
94         mTextLabel = (TextView) findViewById(R.id.textThreshold);
95         mFader = (SeekBar) findViewById(R.id.faderBufferSize);
96         mFader.setOnSeekBarChangeListener(mFaderListener);
97         mTaper = new ExponentialTaper(0.0, 1.0, 10.0);
98         mFader.setProgress(0);
99 
100         mBufferSizeRadio1 = (RadioButton) findViewById(R.id.bufferSize1);
101         mBufferSizeRadio1.setOnClickListener(new View.OnClickListener() {
102             @Override
103             public void onClick(View view) {
104                 onSizeRadioButtonClicked(view, 1);
105             }
106         });
107         mBufferSizeRadio2 = (RadioButton) findViewById(R.id.bufferSize2);
108         mBufferSizeRadio2.setOnClickListener(new View.OnClickListener() {
109             @Override
110             public void onClick(View view) {
111                 onSizeRadioButtonClicked(view, 2);
112             }
113         });
114         mBufferSizeRadio3 = (RadioButton) findViewById(R.id.bufferSize3);
115         mBufferSizeRadio3.setOnClickListener(new View.OnClickListener() {
116             @Override
117             public void onClick(View view) {
118                 onSizeRadioButtonClicked(view, 3);
119             }
120         });
121         mNumBursts = DEFAULT_NUM_BURSTS;
122         updateRadioButtons();
123         updateBufferSize();
124     }
125 
updateRadioButtons()126     public void updateRadioButtons() {
127         if (mBufferSizeRadio3 != null) {
128             mBufferSizeRadio1.setChecked(mNumBursts == 1);
129             mBufferSizeRadio2.setChecked(mNumBursts == 2);
130             mBufferSizeRadio3.setChecked(mNumBursts == 3);
131         }
132     }
133 
onSizeRadioButtonClicked(View view, int numBursts)134     private void onSizeRadioButtonClicked(View view, int numBursts) {
135         boolean checked = ((RadioButton) view).isChecked();
136         if (!checked) return;
137         mNumBursts = numBursts;
138         setBufferSizeByNumBursts(numBursts);
139     }
140 
141     // sets mStream, mCachedCapacity and mFramesPerBurst
onStreamOpened(OboeAudioStream stream)142     public void onStreamOpened(OboeAudioStream stream) {
143         mStream = stream;
144         if (mStream != null) {
145             int capacity = mStream.getBufferCapacityInFrames();
146             if (capacity > 0) mCachedCapacity = capacity;
147             int framesPerBurst = mStream.getFramesPerBurst();
148             if (framesPerBurst > 0) mFramesPerBurst = framesPerBurst;
149         }
150         updateBufferSize();
151     }
152 
setBufferSizeByNumBursts(int numBursts)153     private void setBufferSizeByNumBursts(int numBursts) {
154         int sizeFrames = -1;
155         if (mStream != null) {
156             int framesPerBurst = mStream.getFramesPerBurst();
157             if (framesPerBurst > 0) {
158                 sizeFrames = numBursts * framesPerBurst;
159             }
160         }
161         StringBuffer message = new StringBuffer();
162         message.append("bufferSize = #" + numBursts);
163 
164         setBufferSize(message, sizeFrames);
165     }
166 
setBufferSizeByPosition(int progress)167     private void setBufferSizeByPosition(int progress) {
168         int sizeFrames = -1;
169         double normalizedThreshold = 0.0;
170 
171         StringBuffer message = new StringBuffer();
172 
173         normalizedThreshold = mTaper.linearToExponential(
174                 ((double) progress) / FADER_THRESHOLD_MAX);
175         if (normalizedThreshold < 0.0) normalizedThreshold = 0.0;
176         else if (normalizedThreshold > 1.0) normalizedThreshold = 1.0;
177         int percent = (int) (normalizedThreshold * 100);
178         message.append("bufferSize = " + percent + "%");
179 
180         if (mCachedCapacity > 0) {
181             sizeFrames = (int) (normalizedThreshold * mCachedCapacity);
182         }
183         setBufferSize(message, sizeFrames);
184     }
185 
setBufferSize(StringBuffer message, int sizeFrames)186     private void setBufferSize(StringBuffer message, int sizeFrames) {
187         if (mStream != null) {
188             message.append(", " + sizeFrames);
189             if (mStream != null && sizeFrames >= 0) {
190                 mStream.setBufferSizeInFrames(sizeFrames);
191             }
192             int bufferSize = mStream.getBufferSizeInFrames();
193             if (bufferSize >= 0) {
194                 message.append(" / " + bufferSize);
195             }
196             message.append(" / " + mCachedCapacity);
197         }
198         mTextLabel.setText(message.toString());
199     }
200 
updateBufferSize()201     private void updateBufferSize() {
202         if (mNumBursts == USE_FADER) {
203             int progress = mFader.getProgress();
204             setBufferSizeByPosition(progress);
205         } else {
206             setBufferSizeByNumBursts(mNumBursts);
207         }
208     }
209 
210     @Override
setEnabled(boolean enabled)211     public void setEnabled(boolean enabled) {
212         super.setEnabled(enabled);
213         mFader.setEnabled(enabled);
214     }
215 }
216