Back to project page AndroidRecording.
The source code is released under:
Apache License
If you think the Android project AndroidRecording listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.
/* * Copyright (C) 2013 Steelkiwi Development, Julia Zudikova * //w w w. j a va 2 s. c o m * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.skd.androidrecording.audio; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import simplesound.pcm.PcmAudioHelper; import simplesound.pcm.WavAudioFormat; import android.media.AudioFormat; import android.media.AudioRecord; import android.media.MediaRecorder.AudioSource; import com.skd.androidrecording.fft.Complex; import com.skd.androidrecording.fft.FFT; /* * Takes a portion of PCM encoded audio signal (from microphone while recording), * transforms it using FFT, passes it to a visualizer and saves to a file. * In the end converts stored audio from a temporary RAW file to WAV. */ public class AudioRecordingThread extends Thread { private static final String FILE_NAME = "audiorecordtest.raw"; private static final int SAMPLING_RATE = 44100; private static final int FFT_POINTS = 1024; private static final int MAGIC_SCALE = 10; private String fileName_wav; private String fileName_raw; private int bufferSize; private byte[] audioBuffer; private boolean isRecording = true; private AudioRecordingHandler handler = null; public AudioRecordingThread(String fileWavName, AudioRecordingHandler handler) { this.fileName_wav = fileWavName; this.fileName_raw = getRawName(fileWavName); this.handler = handler; bufferSize = AudioRecord.getMinBufferSize(SAMPLING_RATE, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT); audioBuffer = new byte[bufferSize]; } @Override public void run() { FileOutputStream out = prepareWriting(); if (out == null) { return; } AudioRecord record = new AudioRecord(AudioSource.VOICE_RECOGNITION, /*AudioSource.MIC*/ SAMPLING_RATE, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSize); record.startRecording(); int read = 0; while (isRecording) { read = record.read(audioBuffer, 0, bufferSize); if ((read == AudioRecord.ERROR_INVALID_OPERATION) || (read == AudioRecord.ERROR_BAD_VALUE) || (read <= 0)) { continue; } proceed(); write(out); } record.stop(); record.release(); finishWriting(out); convertRawToWav(); } private void proceed() { double temp; Complex[] y; Complex[] complexSignal = new Complex[FFT_POINTS]; for (int i=0; i<FFT_POINTS; i++) { temp = (double)((audioBuffer[2*i] & 0xFF) | (audioBuffer[2*i+1] << 8)) / 32768.0F; complexSignal[i] = new Complex(temp * MAGIC_SCALE, 0d); } y = FFT.fft(complexSignal); /* * See http://developer.android.com/reference/android/media/audiofx/Visualizer.html#getFft(byte[]) for format explanation */ final byte[] y_byte = new byte[y.length*2]; y_byte[0] = (byte) y[0].re(); y_byte[1] = (byte) y[y.length - 1].re(); for (int i = 1; i < y.length - 1; i++) { y_byte[i*2] = (byte) y[i].re(); y_byte[i*2+1] = (byte) y[i].im(); } if (handler != null) { handler.onFftDataCapture(y_byte); } } private FileOutputStream prepareWriting() { File file = new File(fileName_raw); if (file.exists()) { file.delete(); } FileOutputStream out = null; try { out = new FileOutputStream(fileName_raw, true); } catch (FileNotFoundException e) { e.printStackTrace(); if (handler != null) { handler.onRecordingError(); } } return out; } private void write(FileOutputStream out) { try { out.write(audioBuffer); } catch (IOException e) { e.printStackTrace(); if (handler != null) { handler.onRecordingError(); } } } private void finishWriting(FileOutputStream out) { try { out.close(); } catch (IOException e) { e.printStackTrace(); if (handler != null) { handler.onRecordingError(); } } } private String getRawName(String fileWavName) { return String.format("%s/%s", getFileDir(fileWavName), FILE_NAME); } private String getFileDir(String fileWavName) { File file = new File(fileWavName); String dir = file.getParent(); return (dir == null) ? "" : dir; } private void convertRawToWav() { File file_raw = new File(fileName_raw); if (!file_raw.exists()) { return; } File file_wav = new File(fileName_wav); if (file_wav.exists()) { file_wav.delete(); } try { PcmAudioHelper.convertRawToWav(WavAudioFormat.mono16Bit(SAMPLING_RATE), file_raw, file_wav); file_raw.delete(); if (handler != null) { handler.onRecordSuccess(); } } catch (IOException e) { e.printStackTrace(); if (handler != null) { handler.onRecordSaveError(); } } } public synchronized void stopRecording() { isRecording = false; } }