1 | // from https://stackoverflow.com/questions/27614987/is-it-possible-to-record-the-voice-from-bluetooth-headset-and-play-on-android-sp |
2 | |
3 | public static final int SAMPLE_RATE = 16000; |
4 | |
5 | private AudioRecord mRecorder; |
6 | private File mRecording; |
7 | private short[] mBuffer; |
8 | private boolean mIsRecording = false; |
9 | float iGain = 1.0f; |
10 | CheckBox gain; |
11 | Button showPref; |
12 | OnBluetoothRecording bluetoothRecording; |
13 | protected int bitsPerSamples = 16; |
14 | |
15 | p { |
16 | initRecorder(); |
17 | |
18 | Button bluetooth = (Button)findViewById(R.id.blue); |
19 | |
20 | showPref.setOnClickListener(new OnClickListener() { |
21 | |
22 | @Override |
23 | public void onClick(View v) { |
24 | startActivity(new Intent(getApplicationContext(),BluetoothPreferenceActivity.class)); |
25 | } |
26 | }); |
27 | |
28 | final Button button = (Button) findViewById(R.id.start); |
29 | button.setText(startRecordingLabel); |
30 | bluetooth.setOnClickListener(new OnClickListener() { |
31 | |
32 | @Override |
33 | public void onClick(View v) { |
34 | // TODO Auto-generated method stub |
35 | Intent i = new Intent(""); |
36 | } |
37 | }); |
38 | gain.setOnCheckedChangeListener(new OnCheckedChangeListener() { |
39 | |
40 | @Override |
41 | public void onCheckedChanged(CompoundButton buttonView, |
42 | boolean isChecked) { |
43 | |
44 | if (gain.isChecked()) { |
45 | iGain = 5.0f; |
46 | } else { |
47 | iGain = 2.0f; |
48 | } |
49 | } |
50 | }); |
51 | |
52 | button.setOnClickListener(new OnClickListener() { |
53 | @Override |
54 | public void onClick(final View v) { |
55 | BluetoothRecordingManager.checkAndRecord(getApplicationContext(), new OnBluetoothRecording() { |
56 | |
57 | @Override |
58 | public void onStartRecording(boolean state, boolean bluetoothFlag) { |
59 | |
60 | Log.d("CallBack","starting Recording"); |
61 | if (!mIsRecording) { |
62 | button.setText(stopRecordingLabel); |
63 | mIsRecording = true; |
64 | mRecorder.startRecording(); |
65 | mRecording = getFile("raw"); |
66 | startBufferedWrite(mRecording); |
67 | } else { |
68 | button.setText(startRecordingLabel); |
69 | mIsRecording = false; |
70 | mRecorder.stop(); |
71 | File waveFile = getFile("wav"); |
72 | try { |
73 | rawToWave(mRecording, waveFile); |
74 | } catch (IOException e) { |
75 | Toast.makeText(MainActivity.this, e.getMessage(), |
76 | Toast.LENGTH_SHORT).show(); |
77 | } |
78 | Toast.makeText(MainActivity.this, |
79 | "Recorded to " + waveFile.getName(), |
80 | Toast.LENGTH_SHORT).show(); |
81 | } |
82 | } |
83 | |
84 | @Override |
85 | public void onCancelRecording() { |
86 | } |
87 | }, true); |
88 | } |
89 | }); |
90 | } |
91 | |
92 | svoid cleanMeUp() { |
93 | mRecorder.release(); |
94 | } |
95 | |
96 | private void initRecorder() { |
97 | int bufferSize = AudioRecord.getMinBufferSize(SAMPLE_RATE, |
98 | AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT); |
99 | mBuffer = new short[bufferSize]; |
100 | mRecorder = new AudioRecord(MediaRecorder.AudioSource.MIC, SAMPLE_RATE, |
101 | AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, |
102 | bufferSize); |
103 | } |
104 | |
105 | private void startBufferedWrite(final File file) { |
106 | new Thread(new Runnable() { |
107 | @Override |
108 | public void run() { |
109 | DataOutputStream output = null; |
110 | try { |
111 | output = new DataOutputStream(new BufferedOutputStream( |
112 | new FileOutputStream(file))); |
113 | while (mIsRecording) { |
114 | double sum = 0; |
115 | |
116 | int readSize = mRecorder.read(mBuffer, 0, |
117 | mBuffer.length); |
118 | |
119 | final int bytesPerSample = bitsPerSamples / 8; |
120 | final int emptySpace = 64 - bitsPerSamples; |
121 | int byteIndex = 0; |
122 | int byteIndex2 = 0; |
123 | int temp = 0; |
124 | int mLeftTemp = 0; |
125 | int mRightTemp = 0; |
126 | int a = 0; |
127 | int x = 0; |
128 | |
129 | for (int frameIndex = 0; frameIndex < readSize; frameIndex++) { |
130 | |
131 | for (int c = 0; c < 1; c++) { |
132 | |
133 | if (iGain != 1) { |
134 | |
135 | long accumulator = 0; |
136 | for (int b = 0; b < bytesPerSample; b++) { |
137 | |
138 | accumulator += ((long) (mBuffer[byteIndex++] & 0xFF)) << (b * 8 + emptySpace); |
139 | } |
140 | |
141 | double sample = ((double) accumulator / (double) Long.MAX_VALUE); |
142 | |
143 | sample *= iGain; |
144 | |
145 | |
146 | int intValue = (int) ((double) sample * (double) Integer.MAX_VALUE); |
147 | |
148 | for (int i = 0; i < bytesPerSample; i++) { |
149 | mBuffer[i + byteIndex2] = (byte) (intValue >>> ((i + 2) * 8) & 0xff); |
150 | } |
151 | byteIndex2 += bytesPerSample; |
152 | |
153 | } |
154 | }// end for(channel) |
155 | |
156 | // mBuffer[frameIndex] *=iGain; |
157 | if (mBuffer[frameIndex] > 32765) { |
158 | mBuffer[frameIndex] = 32767; |
159 | } else if (mBuffer[frameIndex] < -32767) { |
160 | mBuffer[frameIndex] = -32767; |
161 | } |
162 | |
163 | output.writeShort(mBuffer[frameIndex]); |
164 | sum += mBuffer[frameIndex] * mBuffer[frameIndex]; |
165 | } |
166 | |
167 | if (readSize > 0) { |
168 | final double amplitude = sum / readSize; |
169 | mProgressBar.setProgress((int) Math.sqrt(amplitude)); |
170 | } |
171 | } |
172 | } catch (IOException e) { |
173 | Toast.makeText(MainActivity.this, e.getMessage(), |
174 | Toast.LENGTH_SHORT).show(); |
175 | } finally { |
176 | mProgressBar.setProgress(0); |
177 | if (output != null) { |
178 | try { |
179 | output.flush(); |
180 | } catch (IOException e) { |
181 | Toast.makeText(MainActivity.this, e.getMessage(), |
182 | Toast.LENGTH_SHORT).show(); |
183 | } finally { |
184 | try { |
185 | output.close(); |
186 | } catch (IOException e) { |
187 | Toast.makeText(MainActivity.this, e.getMessage(), |
188 | Toast.LENGTH_SHORT).show(); |
189 | } |
190 | } |
191 | } |
192 | } |
193 | } |
194 | }).start(); |
195 | } |
196 | |
197 | private void rawToWave(final File rawFile, final File waveFile) |
198 | throws IOException { |
199 | |
200 | byte[] rawData = new byte[(int) rawFile.length()]; |
201 | DataInputStream input = null; |
202 | try { |
203 | |
204 | input = new DataInputStream(new FileInputStream(rawFile)); |
205 | input.read(rawData); |
206 | } finally { |
207 | if (input != null) { |
208 | input.close(); |
209 | } |
210 | } |
211 | |
212 | DataOutputStream output = null; |
213 | try { |
214 | output = new DataOutputStream(new FileOutputStream(waveFile)); |
215 | // WAVE header |
216 | // see http://ccrma.stanford.edu/courses/422/projects/WaveFormat/ |
217 | writeString(output, "RIFF"); // chunk id |
218 | writeInt(output, 36 + rawData.length); // chunk size |
219 | writeString(output, "WAVE"); // format |
220 | writeString(output, "fmt "); // subchunk 1 id |
221 | writeInt(output, 16); // subchunk 1 size |
222 | writeShort(output, (short) 1); // audio format (1 = PCM) |
223 | writeShort(output, (short) 1); // number of channels |
224 | writeInt(output, SAMPLE_RATE); // sample rate |
225 | writeInt(output, SAMPLE_RATE * 2); // byte rate |
226 | writeShort(output, (short) 2); // block align |
227 | writeShort(output, (short) 16); // bits per sample |
228 | writeString(output, "data"); // subchunk 2 id |
229 | writeInt(output, rawData.length); // subchunk 2 size |
230 | // Audio data (conversion big endian -> little endian) |
231 | short[] shorts = new short[rawData.length / 2]; |
232 | ByteBuffer.wrap(rawData).order(ByteOrder.LITTLE_ENDIAN) |
233 | .asShortBuffer().get(shorts); |
234 | ByteBuffer bytes = ByteBuffer.allocate(shorts.length * 2); |
235 | |
236 | for (short s : shorts) { |
237 | |
238 | // Apply Gain |
239 | /* |
240 | * s *= iGain; if(s>32767) { s=32767; } else if(s<-32768) { |
241 | * s=-32768; } |
242 | */ |
243 | bytes.putShort(s); |
244 | } |
245 | output.write(bytes.array()); |
246 | } finally { |
247 | if (output != null) { |
248 | output.close(); |
249 | } |
250 | } |
251 | } |
252 | |
253 | private File getFile(final String suffix) { |
254 | Time time = new Time(); |
255 | time.setToNow(); |
256 | return new File(Environment.getExternalStorageDirectory(), |
257 | time.format("%Y%m%d%H%M%S") + "." + suffix); |
258 | } |
259 | |
260 | private void writeInt(final DataOutputStream output, final int value) |
261 | throws IOException { |
262 | output.write(value >> 0); |
263 | output.write(value >> 8); |
264 | output.write(value >> 16); |
265 | output.write(value >> 24); |
266 | } |
267 | |
268 | private void writeShort(final DataOutputStream output, final short value) |
269 | throws IOException { |
270 | output.write(value >> 0); |
271 | output.write(value >> 8); |
272 | } |
273 | |
274 | private void writeString(final DataOutputStream output, final String value) |
275 | throws IOException { |
276 | for (int i = 0; i < value.length(); i++) { |
277 | output.write(value.charAt(i)); |
278 | } |
279 | } |
download show line numbers debug dex old transpilations
Travelled to 7 computer(s): bhatertpkbcr, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tvejysmllsmz, vouqrxazstgt, xrpafgyirdlv
No comments. add comment
Snippet ID: | #1027049 |
Snippet name: | Android AudioRecord Test [dev.] |
Eternal ID of this version: | #1027049/2 |
Text MD5: | 6b34464e707c96816d32ea8b9c511738 |
Author: | stefan |
Category: | javax / stefan's os |
Type: | JavaX source code (desktop) |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2020-02-15 12:09:20 |
Source code size: | 10184 bytes / 279 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 378 / 567 |
Version history: | 1 change(s) |
Referenced in: | [show references] |