├── README.md
└── main
├── AndroidManifest.xml
├── java
└── com
│ └── sample
│ ├── MainActivity.java
│ └── audio
│ ├── calculators
│ ├── AudioCalculator.java
│ ├── FrequencyCalculator.java
│ └── RealDoubleFFT.java
│ └── core
│ ├── Callback.java
│ └── Recorder.java
└── res
├── layout
└── activity_main.xml
├── mipmap-hdpi
└── ic_launcher.png
├── mipmap-mdpi
└── ic_launcher.png
├── mipmap-xhdpi
└── ic_launcher.png
├── mipmap-xxhdpi
└── ic_launcher.png
├── mipmap-xxxhdpi
└── ic_launcher.png
└── values
├── colors.xml
├── dimens.xml
├── strings.xml
└── styles.xml
/README.md:
--------------------------------------------------------------------------------
1 | # Android-Audio-Sample
2 |
3 | Este é um app Android de exemplo, simples e direto, cuja intenção é extrair informações básicas do áudio gravado, freqüência, amplitude e decibel. Baseado em um antigo exemplo da Google, o Spectrum Analyzer.
4 |
5 | 
6 |
--------------------------------------------------------------------------------
/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/main/java/com/sample/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.sample;
2 |
3 | import android.app.Activity;
4 | import android.content.pm.ActivityInfo;
5 | import android.os.Bundle;
6 | import android.os.Handler;
7 | import android.os.Looper;
8 | import android.widget.TextView;
9 |
10 | import com.sample.audio.calculators.AudioCalculator;
11 | import com.sample.audio.core.Callback;
12 | import com.sample.audio.core.Recorder;
13 |
14 | public class MainActivity extends Activity {
15 |
16 | private Recorder recorder;
17 | private AudioCalculator audioCalculator;
18 | private Handler handler;
19 |
20 | private TextView textAmplitude;
21 | private TextView textDecibel;
22 | private TextView textFrequency;
23 |
24 | @Override
25 | protected void onCreate(Bundle savedInstanceState) {
26 | super.onCreate(savedInstanceState);
27 | setContentView(R.layout.activity_main);
28 | setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
29 |
30 | recorder = new Recorder(callback);
31 | audioCalculator = new AudioCalculator();
32 | handler = new Handler(Looper.getMainLooper());
33 |
34 | textAmplitude = (TextView) findViewById(R.id.textAmplitude);
35 | textDecibel = (TextView) findViewById(R.id.textDecibel);
36 | textFrequency = (TextView) findViewById(R.id.textFrequency);
37 | }
38 |
39 | private Callback callback = new Callback() {
40 |
41 | @Override
42 | public void onBufferAvailable(byte[] buffer) {
43 | audioCalculator.setBytes(buffer);
44 | int amplitude = audioCalculator.getAmplitude();
45 | double decibel = audioCalculator.getDecibel();
46 | double frequency = audioCalculator.getFrequency();
47 |
48 | final String amp = String.valueOf(amplitude + " Amp");
49 | final String db = String.valueOf(decibel + " db");
50 | final String hz = String.valueOf(frequency + " Hz");
51 |
52 | handler.post(new Runnable() {
53 | @Override
54 | public void run() {
55 | textAmplitude.setText(amp);
56 | textDecibel.setText(db);
57 | textFrequency.setText(hz);
58 | }
59 | });
60 | }
61 | };
62 |
63 | @Override
64 | protected void onResume() {
65 | super.onResume();
66 | recorder.start();
67 | }
68 |
69 | @Override
70 | protected void onPause() {
71 | super.onPause();
72 | recorder.stop();
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/main/java/com/sample/audio/calculators/AudioCalculator.java:
--------------------------------------------------------------------------------
1 | package com.sample.audio.calculators;
2 |
3 | import android.util.Log;
4 |
5 | public class AudioCalculator {
6 |
7 | private byte[] bytes;
8 | private int[] amplitudes;
9 | private double[] decibels;
10 | private double frequency;
11 | private int amplitude;
12 | private double decibel;
13 |
14 | public AudioCalculator() {
15 | }
16 |
17 | public AudioCalculator(byte[] bytes) {
18 | this.bytes = bytes;
19 | amplitudes = null;
20 | decibels = null;
21 | frequency = 0.0D;
22 | amplitude = 0;
23 | decibel = 0.0D;
24 | }
25 |
26 | public void setBytes(byte[] bytes) {
27 | this.bytes = bytes;
28 | amplitudes = null;
29 | decibels = null;
30 | frequency = 0.0D;
31 | amplitude = 0;
32 | decibel = 0.0D;
33 | }
34 |
35 | public int[] getAmplitudes() {
36 | if (amplitudes == null) amplitudes = getAmplitudesFromBytes(bytes);
37 | return amplitudes;
38 | }
39 |
40 | public double[] getDecibels() {
41 | if (amplitudes == null) amplitudes = getAmplitudesFromBytes(bytes);
42 | if (decibels == null) {
43 | decibels = new double[amplitudes.length];
44 | for (int i = 0; i < amplitudes.length; i++) {
45 | decibels[i] = resizeNumber(getRealDecibel(amplitudes[i]));
46 | }
47 | }
48 | return decibels;
49 | }
50 |
51 | public int[] getAmplitudeLevels() {
52 | if (amplitudes == null) getAmplitudes();
53 | int major = 0;
54 | int minor = 0;
55 | for (int i : amplitudes) {
56 | if (i > major) major = i;
57 | if (i < minor) minor = i;
58 | }
59 | amplitude = Math.max(major, minor * (-1));
60 | return new int[] {major, minor};
61 | }
62 |
63 | public int getAmplitude() {
64 | if (amplitude == 0) getAmplitudeLevels();
65 | return amplitude;
66 | }
67 |
68 | public double getDecibel() {
69 | if (decibel == 0.0D) decibel = resizeNumber(getRealDecibel(amplitude));
70 | return decibel;
71 | }
72 |
73 | public double getFrequency() {
74 | if (frequency == 0.0D) frequency = retrieveFrequency();
75 | return frequency;
76 | }
77 |
78 | private double retrieveFrequency() {
79 | int length = bytes.length / 2;
80 | int sampleSize = 8192;
81 | while (sampleSize > length) sampleSize = sampleSize >> 1;
82 |
83 | FrequencyCalculator frequencyCalculator = new FrequencyCalculator(sampleSize);
84 | frequencyCalculator.feedData(bytes, length);
85 |
86 | return resizeNumber(frequencyCalculator.getFreq());
87 | }
88 |
89 | private double getRealDecibel(int amplitude) {
90 | if (amplitude < 0) amplitude *= -1;
91 | double amp = (((double) amplitude) / 32767.0d) * 100.0d;
92 | if (amp == 0.0d) {
93 | amp = 1.0d;
94 | }
95 | double decibel = Math.sqrt(100.0d / amp);
96 | decibel *= decibel;
97 | if (decibel > 100.0d) {
98 | decibel = 100.0d;
99 | }
100 | return ((-1.0d * decibel) + 1.0d) / Math.PI;
101 | }
102 |
103 | public double resizeNumber(double value) {
104 | int temp = (int) (value * 10.0d);
105 | return temp / 10.0d;
106 | }
107 |
108 | private int[] getAmplitudesFromBytes(byte[] bytes) {
109 | int[] amps = new int[bytes.length / 2];
110 | for (int i = 0; i < bytes.length; i += 2) {
111 | short buff = bytes[i + 1];
112 | short buff2 = bytes[i];
113 |
114 | buff = (short) ((buff & 0xFF) << 8);
115 | buff2 = (short) (buff2 & 0xFF);
116 |
117 | short res = (short) (buff | buff2);
118 | amps[i == 0 ? 0 : i / 2] = (int) res;
119 | }
120 | return amps;
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/main/java/com/sample/audio/calculators/FrequencyCalculator.java:
--------------------------------------------------------------------------------
1 | package com.sample.audio.calculators;
2 |
3 | import java.util.Arrays;
4 |
5 | public class FrequencyCalculator {
6 |
7 | private RealDoubleFFT spectrumAmpFFT;
8 | private double[] spectrumAmpOutCum;
9 | private double[] spectrumAmpOutTmp;
10 | private double[] spectrumAmpOut;
11 | private double[] spectrumAmpOutDB;
12 | private double[] spectrumAmpIn;
13 | private double[] spectrumAmpInTmp;
14 | private double[] wnd;
15 | private double[][] spectrumAmpOutArray;
16 |
17 | private int fftLen;
18 | private int spectrumAmpPt;
19 | private int spectrumAmpOutArrayPt = 0;
20 | private int nAnalysed = 0;
21 |
22 | private void init(int fftlen) {
23 | fftLen = fftlen;
24 | spectrumAmpOutCum = new double[fftlen];
25 | spectrumAmpOutTmp = new double[fftlen];
26 | spectrumAmpOut = new double[fftlen];
27 | spectrumAmpOutDB = new double[fftlen];
28 | spectrumAmpIn = new double[fftlen];
29 | spectrumAmpInTmp = new double[fftlen];
30 | spectrumAmpFFT = new RealDoubleFFT(fftlen);
31 | spectrumAmpOutArray = new double[(int) Math.ceil((double) 1 / fftlen)][];
32 |
33 | for (int i = 0; i < spectrumAmpOutArray.length; i++) {
34 | spectrumAmpOutArray[i] = new double[fftlen];
35 | }
36 | wnd = new double[fftlen];
37 | for (int i = 0; i < wnd.length; i++) {
38 | wnd[i] = Math.asin(Math.sin(Math.PI * i / wnd.length)) / Math.PI * 2;
39 | }
40 | }
41 |
42 | public FrequencyCalculator(int fftlen) {
43 | init(fftlen);
44 | }
45 |
46 | private short getShortFromBytes(int index) {
47 | index *= 2;
48 | short buff = bytes[index + 1];
49 | short buff2 = bytes[index];
50 |
51 | buff = (short) ((buff & 0xFF) << 8);
52 | buff2 = (short) (buff2 & 0xFF);
53 |
54 | return (short) (buff | buff2);
55 | }
56 |
57 | private byte[] bytes;
58 |
59 | public void feedData(byte[] ds, int dsLen) {
60 | bytes = ds;
61 | int dsPt = 0;
62 | while (dsPt < dsLen) {
63 | while (spectrumAmpPt < fftLen && dsPt < dsLen) {
64 | double s = getShortFromBytes(dsPt++) / 32768.0;
65 | spectrumAmpIn[spectrumAmpPt++] = s;
66 | }
67 | if (spectrumAmpPt == fftLen) {
68 | for (int i = 0; i < fftLen; i++) {
69 | spectrumAmpInTmp[i] = spectrumAmpIn[i] * wnd[i];
70 | }
71 | spectrumAmpFFT.ft(spectrumAmpInTmp);
72 | fftToAmp(spectrumAmpOutTmp, spectrumAmpInTmp);
73 | System.arraycopy(spectrumAmpOutTmp, 0, spectrumAmpOutArray[spectrumAmpOutArrayPt], 0, spectrumAmpOutTmp.length);
74 | spectrumAmpOutArrayPt = (spectrumAmpOutArrayPt + 1) % spectrumAmpOutArray.length;
75 | for (int i = 0; i < fftLen; i++) {
76 | spectrumAmpOutCum[i] += spectrumAmpOutTmp[i];
77 | }
78 | nAnalysed++;
79 | int n2 = spectrumAmpIn.length / 2;
80 | System.arraycopy(spectrumAmpIn, n2, spectrumAmpIn, 0, n2);
81 | spectrumAmpPt = n2;
82 | }
83 | }
84 | }
85 |
86 | private void fftToAmp(double[] dataOut, double[] data) {
87 | double scaler = 2.0 * 2.0 / (data.length * data.length);
88 | dataOut[0] = data[0] * data[0] * scaler / 4.0;
89 | int j = 1;
90 | for (int i = 1; i < data.length - 1; i += 2, j++) {
91 | dataOut[j] = (data[i] * data[i] + data[i + 1] * data[i + 1]) * scaler;
92 | }
93 | dataOut[j] = data[data.length - 1] * data[data.length - 1] * scaler / 4.0;
94 | }
95 |
96 | public double getFreq() {
97 | if (nAnalysed != 0) {
98 | int outLen = spectrumAmpOut.length;
99 | double[] sAOC = spectrumAmpOutCum;
100 | for (int j = 0; j < outLen; j++) {
101 | sAOC[j] /= nAnalysed;
102 | }
103 | System.arraycopy(sAOC, 0, spectrumAmpOut, 0, outLen);
104 | Arrays.fill(sAOC, 0.0);
105 | nAnalysed = 0;
106 | for (int i = 0; i < outLen; i++) {
107 | spectrumAmpOutDB[i] = 10.0 * Math.log10(spectrumAmpOut[i]);
108 | }
109 | }
110 |
111 | double maxAmpDB = 20 * Math.log10(0.125 / 32768);
112 | double maxAmpFreq = 0;
113 | for (int i = 1; i < spectrumAmpOutDB.length; i++) {
114 | if (spectrumAmpOutDB[i] > maxAmpDB) {
115 | maxAmpDB = spectrumAmpOutDB[i];
116 | maxAmpFreq = i;
117 | }
118 | }
119 | int sampleRate = 44100;
120 | maxAmpFreq = maxAmpFreq * sampleRate / fftLen;
121 | if (sampleRate / fftLen < maxAmpFreq && maxAmpFreq < sampleRate / 2 - sampleRate / fftLen) {
122 | int id = (int) (Math.round(maxAmpFreq / sampleRate * fftLen));
123 | double x1 = spectrumAmpOutDB[id - 1];
124 | double x2 = spectrumAmpOutDB[id];
125 | double x3 = spectrumAmpOutDB[id + 1];
126 | double a = (x3 + x1) / 2 - x2;
127 | double b = (x3 - x1) / 2;
128 | if (a < 0) {
129 | double xPeak = -b / (2 * a);
130 | if (Math.abs(xPeak) < 1) {
131 | maxAmpFreq += xPeak * sampleRate / fftLen;
132 | }
133 | }
134 | }
135 | return maxAmpFreq;
136 | }
137 | }
138 |
--------------------------------------------------------------------------------
/main/java/com/sample/audio/calculators/RealDoubleFFT.java:
--------------------------------------------------------------------------------
1 | package com.sample.audio.calculators;
2 |
3 | public class RealDoubleFFT {
4 |
5 | public double norm_factor;
6 | private double wavetable[];
7 | private double[] ch; // reusable work array
8 | private int ndim;
9 |
10 | public RealDoubleFFT(int n) {
11 | ndim = n;
12 | norm_factor = n;
13 | if (wavetable == null || wavetable.length != (2 * ndim + 15)) {
14 | wavetable = new double[2 * ndim + 15];
15 | }
16 | rffti(ndim, wavetable);
17 | ch = new double[n];
18 | }
19 |
20 | public void ft(double x[]) {
21 | if (x.length != ndim)
22 | throw new IllegalArgumentException("The length of data can not match that of the wavetable");
23 | rfftf(ndim, x, wavetable, ch);
24 | }
25 |
26 |
27 | ///////////////////////////////////// Mixed ////////////////////////////////////
28 |
29 |
30 | static final int[] ntryh = new int[]{4, 2, 3, 5};
31 |
32 | void radf2(int ido, int l1, final double cc[], double ch[],
33 | final double wtable[], int offset) {
34 | int i, k, ic;
35 | double ti2, tr2;
36 | int iw1;
37 | iw1 = offset;
38 |
39 | for (k = 0; k < l1; k++) {
40 | ch[2 * k * ido] = cc[k * ido] + cc[(k + l1) * ido];
41 | ch[(2 * k + 1) * ido + ido - 1] = cc[k * ido] - cc[(k + l1) * ido];
42 | }
43 | if (ido < 2) return;
44 | if (ido != 2) {
45 | for (k = 0; k < l1; k++) {
46 | for (i = 2; i < ido; i += 2) {
47 | ic = ido - i;
48 | tr2 = wtable[i - 2 + iw1] * cc[i - 1 + (k + l1) * ido] + wtable[i - 1 + iw1] * cc[i + (k + l1) * ido];
49 | ti2 = wtable[i - 2 + iw1] * cc[i + (k + l1) * ido] - wtable[i - 1 + iw1] * cc[i - 1 + (k + l1) * ido];
50 | ch[i + 2 * k * ido] = cc[i + k * ido] + ti2;
51 | ch[ic + (2 * k + 1) * ido] = ti2 - cc[i + k * ido];
52 | ch[i - 1 + 2 * k * ido] = cc[i - 1 + k * ido] + tr2;
53 | ch[ic - 1 + (2 * k + 1) * ido] = cc[i - 1 + k * ido] - tr2;
54 | }
55 | }
56 | if (ido % 2 == 1) return;
57 | }
58 | for (k = 0; k < l1; k++) {
59 | ch[(2 * k + 1) * ido] = -cc[ido - 1 + (k + l1) * ido];
60 | ch[ido - 1 + 2 * k * ido] = cc[ido - 1 + k * ido];
61 | }
62 | }
63 |
64 | void radf3(int ido, int l1, final double cc[], double ch[],
65 | final double wtable[], int offset) {
66 | final double taur = -0.5D;
67 | final double taui = 0.866025403784439D;
68 | int i, k, ic;
69 | double ci2, di2, di3, cr2, dr2, dr3, ti2, ti3, tr2, tr3;
70 | int iw1, iw2;
71 | iw1 = offset;
72 | iw2 = iw1 + ido;
73 |
74 | for (k = 0; k < l1; k++) {
75 | cr2 = cc[(k + l1) * ido] + cc[(k + 2 * l1) * ido];
76 | ch[3 * k * ido] = cc[k * ido] + cr2;
77 | ch[(3 * k + 2) * ido] = taui * (cc[(k + l1 * 2) * ido] - cc[(k + l1) * ido]);
78 | ch[ido - 1 + (3 * k + 1) * ido] = cc[k * ido] + taur * cr2;
79 | }
80 | if (ido == 1) return;
81 | for (k = 0; k < l1; k++) {
82 | for (i = 2; i < ido; i += 2) {
83 | ic = ido - i;
84 | dr2 = wtable[i - 2 + iw1] * cc[i - 1 + (k + l1) * ido] + wtable[i - 1 + iw1] * cc[i + (k + l1) * ido];
85 | di2 = wtable[i - 2 + iw1] * cc[i + (k + l1) * ido] - wtable[i - 1 + iw1] * cc[i - 1 + (k + l1) * ido];
86 | dr3 = wtable[i - 2 + iw2] * cc[i - 1 + (k + l1 * 2) * ido] + wtable[i - 1 + iw2] * cc[i + (k + l1 * 2) * ido];
87 | di3 = wtable[i - 2 + iw2] * cc[i + (k + l1 * 2) * ido] - wtable[i - 1 + iw2] * cc[i - 1 + (k + l1 * 2) * ido];
88 | cr2 = dr2 + dr3;
89 | ci2 = di2 + di3;
90 | ch[i - 1 + 3 * k * ido] = cc[i - 1 + k * ido] + cr2;
91 | ch[i + 3 * k * ido] = cc[i + k * ido] + ci2;
92 | tr2 = cc[i - 1 + k * ido] + taur * cr2;
93 | ti2 = cc[i + k * ido] + taur * ci2;
94 | tr3 = taui * (di2 - di3);
95 | ti3 = taui * (dr3 - dr2);
96 | ch[i - 1 + (3 * k + 2) * ido] = tr2 + tr3;
97 | ch[ic - 1 + (3 * k + 1) * ido] = tr2 - tr3;
98 | ch[i + (3 * k + 2) * ido] = ti2 + ti3;
99 | ch[ic + (3 * k + 1) * ido] = ti3 - ti2;
100 | }
101 | }
102 | }
103 |
104 | void radf4(int ido, int l1, final double cc[], double ch[], final double wtable[], int offset) {
105 | final double hsqt2 = 0.7071067811865475D;
106 | int i, k, ic;
107 | double ci2, ci3, ci4, cr2, cr3, cr4, ti1, ti2, ti3, ti4, tr1, tr2, tr3, tr4;
108 | int iw1, iw2, iw3;
109 | iw1 = offset;
110 | iw2 = offset + ido;
111 | iw3 = iw2 + ido;
112 | for (k = 0; k < l1; k++) {
113 | tr1 = cc[(k + l1) * ido] + cc[(k + 3 * l1) * ido];
114 | tr2 = cc[k * ido] + cc[(k + 2 * l1) * ido];
115 | ch[4 * k * ido] = tr1 + tr2;
116 | ch[ido - 1 + (4 * k + 3) * ido] = tr2 - tr1;
117 | ch[ido - 1 + (4 * k + 1) * ido] = cc[k * ido] - cc[(k + 2 * l1) * ido];
118 | ch[(4 * k + 2) * ido] = cc[(k + 3 * l1) * ido] - cc[(k + l1) * ido];
119 | }
120 | if (ido < 2) return;
121 | if (ido != 2) {
122 | for (k = 0; k < l1; k++) {
123 | for (i = 2; i < ido; i += 2) {
124 | ic = ido - i;
125 | cr2 = wtable[i - 2 + iw1] * cc[i - 1 + (k + l1) * ido] + wtable[i - 1 + iw1] * cc[i + (k + l1) * ido];
126 | ci2 = wtable[i - 2 + iw1] * cc[i + (k + l1) * ido] - wtable[i - 1 + iw1] * cc[i - 1 + (k + l1) * ido];
127 | cr3 = wtable[i - 2 + iw2] * cc[i - 1 + (k + 2 * l1) * ido] + wtable[i - 1 + iw2] * cc[i + (k + 2 * l1) * ido];
128 | ci3 = wtable[i - 2 + iw2] * cc[i + (k + 2 * l1) * ido] - wtable[i - 1 + iw2] * cc[i - 1 + (k + 2 * l1) * ido];
129 | cr4 = wtable[i - 2 + iw3] * cc[i - 1 + (k + 3 * l1) * ido] + wtable[i - 1 + iw3] * cc[i + (k + 3 * l1) * ido];
130 | ci4 = wtable[i - 2 + iw3] * cc[i + (k + 3 * l1) * ido] - wtable[i - 1 + iw3] * cc[i - 1 + (k + 3 * l1) * ido];
131 | tr1 = cr2 + cr4;
132 | tr4 = cr4 - cr2;
133 | ti1 = ci2 + ci4;
134 | ti4 = ci2 - ci4;
135 | ti2 = cc[i + k * ido] + ci3;
136 | ti3 = cc[i + k * ido] - ci3;
137 | tr2 = cc[i - 1 + k * ido] + cr3;
138 | tr3 = cc[i - 1 + k * ido] - cr3;
139 | ch[i - 1 + 4 * k * ido] = tr1 + tr2;
140 | ch[ic - 1 + (4 * k + 3) * ido] = tr2 - tr1;
141 | ch[i + 4 * k * ido] = ti1 + ti2;
142 | ch[ic + (4 * k + 3) * ido] = ti1 - ti2;
143 | ch[i - 1 + (4 * k + 2) * ido] = ti4 + tr3;
144 | ch[ic - 1 + (4 * k + 1) * ido] = tr3 - ti4;
145 | ch[i + (4 * k + 2) * ido] = tr4 + ti3;
146 | ch[ic + (4 * k + 1) * ido] = tr4 - ti3;
147 | }
148 | }
149 | if (ido % 2 == 1) return;
150 | }
151 | for (k = 0; k < l1; k++) {
152 | ti1 = -hsqt2 * (cc[ido - 1 + (k + l1) * ido] + cc[ido - 1 + (k + 3 * l1) * ido]);
153 | tr1 = hsqt2 * (cc[ido - 1 + (k + l1) * ido] - cc[ido - 1 + (k + 3 * l1) * ido]);
154 | ch[ido - 1 + 4 * k * ido] = tr1 + cc[ido - 1 + k * ido];
155 | ch[ido - 1 + (4 * k + 2) * ido] = cc[ido - 1 + k * ido] - tr1;
156 | ch[(4 * k + 1) * ido] = ti1 - cc[ido - 1 + (k + 2 * l1) * ido];
157 | ch[(4 * k + 3) * ido] = ti1 + cc[ido - 1 + (k + 2 * l1) * ido];
158 | }
159 | }
160 |
161 | void radf5(int ido, int l1, final double cc[], double ch[], final double wtable[], int offset) {
162 | final double tr11 = 0.309016994374947D;
163 | final double ti11 = 0.951056516295154D;
164 | final double tr12 = -0.809016994374947D;
165 | final double ti12 = 0.587785252292473D;
166 | int i, k, ic;
167 | double ci2, di2, ci4, ci5, di3, di4, di5, ci3, cr2, cr3, dr2, dr3, dr4, dr5, cr5, cr4, ti2, ti3, ti5, ti4, tr2, tr3, tr4, tr5;
168 | int iw1, iw2, iw3, iw4;
169 | iw1 = offset;
170 | iw2 = iw1 + ido;
171 | iw3 = iw2 + ido;
172 | iw4 = iw3 + ido;
173 |
174 | for (k = 0; k < l1; k++) {
175 | cr2 = cc[(k + 4 * l1) * ido] + cc[(k + l1) * ido];
176 | ci5 = cc[(k + 4 * l1) * ido] - cc[(k + l1) * ido];
177 | cr3 = cc[(k + 3 * l1) * ido] + cc[(k + 2 * l1) * ido];
178 | ci4 = cc[(k + 3 * l1) * ido] - cc[(k + 2 * l1) * ido];
179 | ch[5 * k * ido] = cc[k * ido] + cr2 + cr3;
180 | ch[ido - 1 + (5 * k + 1) * ido] = cc[k * ido] + tr11 * cr2 + tr12 * cr3;
181 | ch[(5 * k + 2) * ido] = ti11 * ci5 + ti12 * ci4;
182 | ch[ido - 1 + (5 * k + 3) * ido] = cc[k * ido] + tr12 * cr2 + tr11 * cr3;
183 | ch[(5 * k + 4) * ido] = ti12 * ci5 - ti11 * ci4;
184 | }
185 | if (ido == 1) return;
186 | for (k = 0; k < l1; ++k) {
187 | for (i = 2; i < ido; i += 2) {
188 | ic = ido - i;
189 | dr2 = wtable[i - 2 + iw1] * cc[i - 1 + (k + l1) * ido] + wtable[i - 1 + iw1] * cc[i + (k + l1) * ido];
190 | di2 = wtable[i - 2 + iw1] * cc[i + (k + l1) * ido] - wtable[i - 1 + iw1] * cc[i - 1 + (k + l1) * ido];
191 | dr3 = wtable[i - 2 + iw2] * cc[i - 1 + (k + 2 * l1) * ido] + wtable[i - 1 + iw2] * cc[i + (k + 2 * l1) * ido];
192 | di3 = wtable[i - 2 + iw2] * cc[i + (k + 2 * l1) * ido] - wtable[i - 1 + iw2] * cc[i - 1 + (k + 2 * l1) * ido];
193 | dr4 = wtable[i - 2 + iw3] * cc[i - 1 + (k + 3 * l1) * ido] + wtable[i - 1 + iw3] * cc[i + (k + 3 * l1) * ido];
194 | di4 = wtable[i - 2 + iw3] * cc[i + (k + 3 * l1) * ido] - wtable[i - 1 + iw3] * cc[i - 1 + (k + 3 * l1) * ido];
195 | dr5 = wtable[i - 2 + iw4] * cc[i - 1 + (k + 4 * l1) * ido] + wtable[i - 1 + iw4] * cc[i + (k + 4 * l1) * ido];
196 | di5 = wtable[i - 2 + iw4] * cc[i + (k + 4 * l1) * ido] - wtable[i - 1 + iw4] * cc[i - 1 + (k + 4 * l1) * ido];
197 | cr2 = dr2 + dr5;
198 | ci5 = dr5 - dr2;
199 | cr5 = di2 - di5;
200 | ci2 = di2 + di5;
201 | cr3 = dr3 + dr4;
202 | ci4 = dr4 - dr3;
203 | cr4 = di3 - di4;
204 | ci3 = di3 + di4;
205 | ch[i - 1 + 5 * k * ido] = cc[i - 1 + k * ido] + cr2 + cr3;
206 | ch[i + 5 * k * ido] = cc[i + k * ido] + ci2 + ci3;
207 | tr2 = cc[i - 1 + k * ido] + tr11 * cr2 + tr12 * cr3;
208 | ti2 = cc[i + k * ido] + tr11 * ci2 + tr12 * ci3;
209 | tr3 = cc[i - 1 + k * ido] + tr12 * cr2 + tr11 * cr3;
210 | ti3 = cc[i + k * ido] + tr12 * ci2 + tr11 * ci3;
211 | tr5 = ti11 * cr5 + ti12 * cr4;
212 | ti5 = ti11 * ci5 + ti12 * ci4;
213 | tr4 = ti12 * cr5 - ti11 * cr4;
214 | ti4 = ti12 * ci5 - ti11 * ci4;
215 | ch[i - 1 + (5 * k + 2) * ido] = tr2 + tr5;
216 | ch[ic - 1 + (5 * k + 1) * ido] = tr2 - tr5;
217 | ch[i + (5 * k + 2) * ido] = ti2 + ti5;
218 | ch[ic + (5 * k + 1) * ido] = ti5 - ti2;
219 | ch[i - 1 + (5 * k + 4) * ido] = tr3 + tr4;
220 | ch[ic - 1 + (5 * k + 3) * ido] = tr3 - tr4;
221 | ch[i + (5 * k + 4) * ido] = ti3 + ti4;
222 | ch[ic + (5 * k + 3) * ido] = ti4 - ti3;
223 | }
224 | }
225 | }
226 |
227 | void radfg(int ido, int ip, int l1, int idl1, double cc[], double c1[], double c2[], double ch[], double ch2[], final double wtable[], int offset) {
228 | final double twopi = 2.0D * Math.PI; //6.28318530717959;
229 | int idij, ipph, i, j, k, l, j2, ic, jc, lc, ik, is, nbd;
230 | double dc2, ai1, ai2, ar1, ar2, ds2, dcp, arg, dsp, ar1h, ar2h;
231 | int iw1 = offset;
232 |
233 | arg = twopi / ip;
234 | dcp = Math.cos(arg);
235 | dsp = Math.sin(arg);
236 | ipph = (ip + 1) / 2;
237 | nbd = (ido - 1) / 2;
238 | if (ido != 1) {
239 | for (ik = 0; ik < idl1; ik++) ch2[ik] = c2[ik];
240 | for (j = 1; j < ip; j++)
241 | for (k = 0; k < l1; k++)
242 | ch[(k + j * l1) * ido] = c1[(k + j * l1) * ido];
243 | if (nbd <= l1) {
244 | is = -ido;
245 | for (j = 1; j < ip; j++) {
246 | is += ido;
247 | idij = is - 1;
248 | for (i = 2; i < ido; i += 2) {
249 | idij += 2;
250 | for (k = 0; k < l1; k++) {
251 | ch[i - 1 + (k + j * l1) * ido] =
252 | wtable[idij - 1 + iw1] * c1[i - 1 + (k + j * l1) * ido]
253 | + wtable[idij + iw1] * c1[i + (k + j * l1) * ido];
254 | ch[i + (k + j * l1) * ido] =
255 | wtable[idij - 1 + iw1] * c1[i + (k + j * l1) * ido]
256 | - wtable[idij + iw1] * c1[i - 1 + (k + j * l1) * ido];
257 | }
258 | }
259 | }
260 | } else {
261 | is = -ido;
262 | for (j = 1; j < ip; j++) {
263 | is += ido;
264 | for (k = 0; k < l1; k++) {
265 | idij = is - 1;
266 | for (i = 2; i < ido; i += 2) {
267 | idij += 2;
268 | ch[i - 1 + (k + j * l1) * ido] =
269 | wtable[idij - 1 + iw1] * c1[i - 1 + (k + j * l1) * ido]
270 | + wtable[idij + iw1] * c1[i + (k + j * l1) * ido];
271 | ch[i + (k + j * l1) * ido] =
272 | wtable[idij - 1 + iw1] * c1[i + (k + j * l1) * ido]
273 | - wtable[idij + iw1] * c1[i - 1 + (k + j * l1) * ido];
274 | }
275 | }
276 | }
277 | }
278 | if (nbd >= l1) {
279 | for (j = 1; j < ipph; j++) {
280 | jc = ip - j;
281 | for (k = 0; k < l1; k++) {
282 | for (i = 2; i < ido; i += 2) {
283 | c1[i - 1 + (k + j * l1) * ido] = ch[i - 1 + (k + j * l1) * ido] + ch[i - 1 + (k + jc * l1) * ido];
284 | c1[i - 1 + (k + jc * l1) * ido] = ch[i + (k + j * l1) * ido] - ch[i + (k + jc * l1) * ido];
285 | c1[i + (k + j * l1) * ido] = ch[i + (k + j * l1) * ido] + ch[i + (k + jc * l1) * ido];
286 | c1[i + (k + jc * l1) * ido] = ch[i - 1 + (k + jc * l1) * ido] - ch[i - 1 + (k + j * l1) * ido];
287 | }
288 | }
289 | }
290 | } else {
291 | for (j = 1; j < ipph; j++) {
292 | jc = ip - j;
293 | for (i = 2; i < ido; i += 2) {
294 | for (k = 0; k < l1; k++) {
295 | c1[i - 1 + (k + j * l1) * ido] =
296 | ch[i - 1 + (k + j * l1) * ido] + ch[i - 1 + (k + jc * l1) * ido];
297 | c1[i - 1 + (k + jc * l1) * ido] = ch[i + (k + j * l1) * ido] - ch[i + (k + jc * l1) * ido];
298 | c1[i + (k + j * l1) * ido] = ch[i + (k + j * l1) * ido] + ch[i + (k + jc * l1) * ido];
299 | c1[i + (k + jc * l1) * ido] = ch[i - 1 + (k + jc * l1) * ido] - ch[i - 1 + (k + j * l1) * ido];
300 | }
301 | }
302 | }
303 | }
304 | } else {
305 | for (ik = 0; ik < idl1; ik++) c2[ik] = ch2[ik];
306 | }
307 | for (j = 1; j < ipph; j++) {
308 | jc = ip - j;
309 | for (k = 0; k < l1; k++) {
310 | c1[(k + j * l1) * ido] = ch[(k + j * l1) * ido] + ch[(k + jc * l1) * ido];
311 | c1[(k + jc * l1) * ido] = ch[(k + jc * l1) * ido] - ch[(k + j * l1) * ido];
312 | }
313 | }
314 |
315 | ar1 = 1;
316 | ai1 = 0;
317 | for (l = 1; l < ipph; l++) {
318 | lc = ip - l;
319 | ar1h = dcp * ar1 - dsp * ai1;
320 | ai1 = dcp * ai1 + dsp * ar1;
321 | ar1 = ar1h;
322 | for (ik = 0; ik < idl1; ik++) {
323 | ch2[ik + l * idl1] = c2[ik] + ar1 * c2[ik + idl1];
324 | ch2[ik + lc * idl1] = ai1 * c2[ik + (ip - 1) * idl1];
325 | }
326 | dc2 = ar1;
327 | ds2 = ai1;
328 | ar2 = ar1;
329 | ai2 = ai1;
330 | for (j = 2; j < ipph; j++) {
331 | jc = ip - j;
332 | ar2h = dc2 * ar2 - ds2 * ai2;
333 | ai2 = dc2 * ai2 + ds2 * ar2;
334 | ar2 = ar2h;
335 | for (ik = 0; ik < idl1; ik++) {
336 | ch2[ik + l * idl1] += ar2 * c2[ik + j * idl1];
337 | ch2[ik + lc * idl1] += ai2 * c2[ik + jc * idl1];
338 | }
339 | }
340 | }
341 | for (j = 1; j < ipph; j++)
342 | for (ik = 0; ik < idl1; ik++)
343 | ch2[ik] += c2[ik + j * idl1];
344 |
345 | if (ido >= l1) {
346 | for (k = 0; k < l1; k++) {
347 | for (i = 0; i < ido; i++) {
348 | cc[i + k * ip * ido] = ch[i + k * ido];
349 | }
350 | }
351 | } else {
352 | for (i = 0; i < ido; i++) {
353 | for (k = 0; k < l1; k++) {
354 | cc[i + k * ip * ido] = ch[i + k * ido];
355 | }
356 | }
357 | }
358 | for (j = 1; j < ipph; j++) {
359 | jc = ip - j;
360 | j2 = 2 * j;
361 | for (k = 0; k < l1; k++) {
362 | cc[ido - 1 + (j2 - 1 + k * ip) * ido] = ch[(k + j * l1) * ido];
363 | cc[(j2 + k * ip) * ido] = ch[(k + jc * l1) * ido];
364 | }
365 | }
366 | if (ido == 1) return;
367 | if (nbd >= l1) {
368 | for (j = 1; j < ipph; j++) {
369 | jc = ip - j;
370 | j2 = 2 * j;
371 | for (k = 0; k < l1; k++) {
372 | for (i = 2; i < ido; i += 2) {
373 | ic = ido - i;
374 | cc[i - 1 + (j2 + k * ip) * ido] = ch[i - 1 + (k + j * l1) * ido] + ch[i - 1 + (k + jc * l1) * ido];
375 | cc[ic - 1 + (j2 - 1 + k * ip) * ido] = ch[i - 1 + (k + j * l1) * ido] - ch[i - 1 + (k + jc * l1) * ido];
376 | cc[i + (j2 + k * ip) * ido] = ch[i + (k + j * l1) * ido] + ch[i + (k + jc * l1) * ido];
377 | cc[ic + (j2 - 1 + k * ip) * ido] = ch[i + (k + jc * l1) * ido] - ch[i + (k + j * l1) * ido];
378 | }
379 | }
380 | }
381 | } else {
382 | for (j = 1; j < ipph; j++) {
383 | jc = ip - j;
384 | j2 = 2 * j;
385 | for (i = 2; i < ido; i += 2) {
386 | ic = ido - i;
387 | for (k = 0; k < l1; k++) {
388 | cc[i - 1 + (j2 + k * ip) * ido] = ch[i - 1 + (k + j * l1) * ido] + ch[i - 1 + (k + jc * l1) * ido];
389 | cc[ic - 1 + (j2 - 1 + k * ip) * ido] = ch[i - 1 + (k + j * l1) * ido] - ch[i - 1 + (k + jc * l1) * ido];
390 | cc[i + (j2 + k * ip) * ido] = ch[i + (k + j * l1) * ido] + ch[i + (k + jc * l1) * ido];
391 | cc[ic + (j2 - 1 + k * ip) * ido] = ch[i + (k + jc * l1) * ido] - ch[i + (k + j * l1) * ido];
392 | }
393 | }
394 | }
395 | }
396 | }
397 |
398 | void rfftf1(int n, double c[], final double wtable[], int offset, double[] ch) {
399 | int i;
400 | int k1, l1, l2, na, kh, nf, ip, iw, ido, idl1;
401 |
402 | System.arraycopy(wtable, offset, ch, 0, n);
403 |
404 | nf = (int) wtable[1 + 2 * n + offset];
405 | na = 1;
406 | l2 = n;
407 | iw = n - 1 + n + offset;
408 | for (k1 = 1; k1 <= nf; ++k1) {
409 | kh = nf - k1;
410 | ip = (int) wtable[kh + 2 + 2 * n + offset];
411 | l1 = l2 / ip;
412 | ido = n / l2;
413 | idl1 = ido * l1;
414 | iw -= (ip - 1) * ido;
415 | na = 1 - na;
416 | if (ip == 4) {
417 | if (na == 0) {
418 | radf4(ido, l1, c, ch, wtable, iw);
419 | } else {
420 | radf4(ido, l1, ch, c, wtable, iw);
421 | }
422 | } else if (ip == 2) {
423 | if (na == 0) {
424 | radf2(ido, l1, c, ch, wtable, iw);
425 | } else {
426 | radf2(ido, l1, ch, c, wtable, iw);
427 | }
428 | } else if (ip == 3) {
429 | if (na == 0) {
430 | radf3(ido, l1, c, ch, wtable, iw);
431 | } else {
432 | radf3(ido, l1, ch, c, wtable, iw);
433 | }
434 | } else if (ip == 5) {
435 | if (na == 0) {
436 | radf5(ido, l1, c, ch, wtable, iw);
437 | } else {
438 | radf5(ido, l1, ch, c, wtable, iw);
439 | }
440 | } else {
441 | if (ido == 1) na = 1 - na;
442 | if (na == 0) {
443 | radfg(ido, ip, l1, idl1, c, c, c, ch, ch, wtable, iw);
444 | na = 1;
445 | } else {
446 | radfg(ido, ip, l1, idl1, ch, ch, ch, c, c, wtable, iw);
447 | na = 0;
448 | }
449 | }
450 | l2 = l1;
451 | }
452 | if (na == 1) return;
453 | for (i = 0; i < n; i++) c[i] = ch[i];
454 | }
455 |
456 | void rfftf(int n, double r[], double wtable[], double[] ch) {
457 | if (n == 1) return;
458 | rfftf1(n, r, wtable, 0, ch);
459 | }
460 |
461 | void rffti1(int n, double wtable[], int offset) {
462 |
463 | final double twopi = 2.0D * Math.PI;
464 | double argh;
465 | int ntry = 0, i, j;
466 | double argld;
467 | int k1, l1, l2, ib;
468 | double fi;
469 | int ld, ii, nf, ip, nl, is, nq, nr;
470 | double arg;
471 | int ido, ipm;
472 | int nfm1;
473 |
474 | nl = n;
475 | nf = 0;
476 | j = 0;
477 |
478 | factorize_loop:
479 | while (true) {
480 | ++j;
481 | if (j <= 4)
482 | ntry = ntryh[j - 1];
483 | else
484 | ntry += 2;
485 | do {
486 | nq = nl / ntry;
487 | nr = nl - ntry * nq;
488 | if (nr != 0) continue factorize_loop;
489 | ++nf;
490 | wtable[nf + 1 + 2 * n + offset] = ntry;
491 |
492 | nl = nq;
493 | if (ntry == 2 && nf != 1) {
494 | for (i = 2; i <= nf; i++) {
495 | ib = nf - i + 2;
496 | wtable[ib + 1 + 2 * n + offset] = wtable[ib + 2 * n + offset];
497 | }
498 | wtable[2 + 2 * n + offset] = 2;
499 | }
500 | } while (nl != 1);
501 | break factorize_loop;
502 | }
503 | wtable[0 + 2 * n + offset] = n;
504 | wtable[1 + 2 * n + offset] = nf;
505 | argh = twopi / (n);
506 | is = 0;
507 | nfm1 = nf - 1;
508 | l1 = 1;
509 | if (nfm1 == 0) return;
510 | for (k1 = 1; k1 <= nfm1; k1++) {
511 | ip = (int) wtable[k1 + 1 + 2 * n + offset];
512 | ld = 0;
513 | l2 = l1 * ip;
514 | ido = n / l2;
515 | ipm = ip - 1;
516 | for (j = 1; j <= ipm; ++j) {
517 | ld += l1;
518 | i = is;
519 | argld = ld * argh;
520 |
521 | fi = 0;
522 | for (ii = 3; ii <= ido; ii += 2) {
523 | i += 2;
524 | fi += 1;
525 | arg = fi * argld;
526 | wtable[i - 2 + n + offset] = Math.cos(arg);
527 | wtable[i - 1 + n + offset] = Math.sin(arg);
528 | }
529 | is += ido;
530 | }
531 | l1 = l2;
532 | }
533 | }
534 |
535 | void rffti(int n, double wtable[]) {
536 | if (n == 1) return;
537 | rffti1(n, wtable, 0);
538 | }
539 |
540 | }
--------------------------------------------------------------------------------
/main/java/com/sample/audio/core/Callback.java:
--------------------------------------------------------------------------------
1 | package com.sample.audio.core;
2 |
3 | public interface Callback {
4 | void onBufferAvailable(byte[] buffer);
5 | }
--------------------------------------------------------------------------------
/main/java/com/sample/audio/core/Recorder.java:
--------------------------------------------------------------------------------
1 | package com.sample.audio.core;
2 |
3 | import android.media.AudioFormat;
4 | import android.media.AudioRecord;
5 | import android.media.MediaRecorder;
6 | import android.os.Process;
7 | import android.util.Log;
8 |
9 | public class Recorder {
10 |
11 | private int audioSource = MediaRecorder.AudioSource.DEFAULT;
12 | private int channelConfig = AudioFormat.CHANNEL_IN_MONO;
13 | private int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;
14 | private int sampleRate = 44100;
15 | private Thread thread;
16 | private Callback callback;
17 |
18 | public Recorder() {
19 | }
20 |
21 | public Recorder(Callback callback) {
22 | this.callback = callback;
23 | }
24 |
25 | public void setCallback(Callback callback) {
26 | this.callback = callback;
27 | }
28 |
29 | public void start() {
30 | if (thread != null) return;
31 | thread = new Thread(new Runnable() {
32 | @Override
33 | public void run() {
34 | Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_AUDIO);
35 |
36 | int minBufferSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioEncoding);
37 | AudioRecord recorder = new AudioRecord(audioSource, sampleRate, channelConfig, audioEncoding, minBufferSize);
38 |
39 | if (recorder.getState() == AudioRecord.STATE_UNINITIALIZED) {
40 | Thread.currentThread().interrupt();
41 | return;
42 | } else {
43 | Log.i(Recorder.class.getSimpleName(), "Started.");
44 | //callback.onStart();
45 | }
46 | byte[] buffer = new byte[minBufferSize];
47 | recorder.startRecording();
48 |
49 | while (thread != null && !thread.isInterrupted() && recorder.read(buffer, 0, minBufferSize) > 0) {
50 | callback.onBufferAvailable(buffer);
51 | }
52 | recorder.stop();
53 | recorder.release();
54 | }
55 | }, Recorder.class.getName());
56 | thread.start();
57 | }
58 |
59 | public void stop() {
60 | if (thread != null) {
61 | thread.interrupt();
62 | thread = null;
63 | }
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
17 |
18 |
28 |
29 |
39 |
40 |
--------------------------------------------------------------------------------
/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lucns/Android-Audio-Sample/adb84427f62481dc69a933a4e1a0473039edf818/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lucns/Android-Audio-Sample/adb84427f62481dc69a933a4e1a0473039edf818/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lucns/Android-Audio-Sample/adb84427f62481dc69a933a4e1a0473039edf818/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lucns/Android-Audio-Sample/adb84427f62481dc69a933a4e1a0473039edf818/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lucns/Android-Audio-Sample/adb84427f62481dc69a933a4e1a0473039edf818/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #efefef
4 | #d6d6d6
5 | #b3b3b3
6 | #a6a6a6
7 | #939393
8 | #888888
9 | #7b7b7b
10 | #747474
11 | #6c6c6c
12 | #686868
13 | #5e5e5e
14 | #4d4c4c
15 | #454545
16 | #3d3d3d
17 | #2e2e2e
18 | #282828
19 | #242424
20 | #202020
21 | #161616
22 | #121212
23 | #080808
24 |
25 | #5ebfff
26 | #3db1ff
27 | #0099ff
28 | #1281c1
29 | #145786
30 |
31 |
--------------------------------------------------------------------------------
/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 | 8dp
3 | 12dp
4 | 16dp
5 | 24dp
6 | 36dp
7 | 42dp
8 |
9 | 8dp
10 |
11 |
--------------------------------------------------------------------------------
/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Audio Sample
3 |
4 |
--------------------------------------------------------------------------------
/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
10 |
--------------------------------------------------------------------------------