I am trying to record a wav file and read and save data of a wav file in android.Everything is working fine except differences in the values I am reading in Matlab with my saved data in android
here is my code
private static final int RECORDER_BPP = 16;
private static final String AUDIO_RECORDER_FILE_EXT_WAV = ".wav";
private static final String AUDIO_RECORDER_FOLDER = "AudioRecorder";
private static final String AUDIO_RECORDER_TEMP_FILE = "record_temp.raw";
private static final int RECORDER_SAMPLERATE = 44100;
private static final int RECORDER_CHANNELS = AudioFormat.CHANNEL_IN_MONO;
private static final int RECORDER_AUDIO_ENCODING = AudioFormat.ENCODING_PCM_16BIT;
private AudioRecord recorder = null;
private int bufferSize = 0;
private Thread recordingThread = null;
private boolean isRecording = false;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
setButtonHandlers();
enableButtons(false);
bufferSize = AudioRecord.getMinBufferSize(RECORDER_SAMPLERATE, RECORDER_CHANNELS, RECORDER_AUDIO_ENCODING);
}
private void setButtonHandlers() {
((Button) findViewById(R.id.btnStart)).setOnClickListener(btnClick);
((Button) findViewById(R.id.btnStop)).setOnClickListener(btnClick);
}
private void enableButton(int id, boolean isEnable) {
((Button) findViewById(id)).setEnabled(isEnable);
}
private void enableButtons(boolean isRecording) {
enableButton(R.id.btnStart, !isRecording);
enableButton(R.id.btnStop, isRecording);
}
private String getFilename() {
String filepath = Environment.getExternalStorageDirectory().getPath();
File file = new File(filepath, AUDIO_RECORDER_FOLDER);
if ( !file.exists()) {
file.mkdirs();
}
return (file.getAbsolutePath() + "/" + 11 + AUDIO_RECORDER_FILE_EXT_WAV);
}
private String getTempFilename() {
String filepath = Environment.getExternalStorageDirectory().getPath();
File file = new File(filepath, AUDIO_RECORDER_FOLDER);
if ( !file.exists()) {
file.mkdirs();
}
File tempFile = new File(filepath, AUDIO_RECORDER_TEMP_FILE);
if (tempFile.exists())
tempFile.delete();
return (file.getAbsolutePath() + "/" + AUDIO_RECORDER_TEMP_FILE);
}
private String getfftFilename() {
String filepath = Environment.getExternalStorageDirectory().getPath();
File file = new File(filepath, AUDIO_RECORDER_FOLDER);
if ( !file.exists()) {
file.mkdirs();
}
return (file.getAbsolutePath() + "/" + "fft" + ".txt");
}
private void startRecording() {
recorder = new AudioRecord(MediaRecorder.AudioSource.MIC,
RECORDER_SAMPLERATE, RECORDER_CHANNELS, RECORDER_AUDIO_ENCODING, bufferSize);
recorder.startRecording();
isRecording = true;
recordingThread = new Thread(new Runnable() {
#Override
public void run() {
writeAudioDataToFile();
}
}, "AudioRecorder Thread");
recordingThread.start();
}
private void writeAudioDataToFile() {
byte data[] = new byte[bufferSize];
String filename = getTempFilename();
FileOutputStream os = null;
try {
os = new FileOutputStream(filename);
}
catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
int read = 0;
if (null != os) {
while (isRecording) {
read = recorder.read(data, 0, bufferSize);
if (AudioRecord.ERROR_INVALID_OPERATION != read) {
try {
os.write(data);
}
catch (IOException e) {
e.printStackTrace();
}
}
}
}
try {
os.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
private void stopRecording() {
if (null != recorder) {
isRecording = false;
recorder.stop();
recorder.release();
recorder = null;
recordingThread = null;
}
copyWaveFile(getTempFilename(), getFilename());
////coding(getTempFilename(), getrainroom(), getstegan());
////decoding(getstegan(), getdecodeFilename(), getrainroom());
fftbegir(getTempFilename(), getfftFilename());
deleteTempFile();
}
private void deleteTempFile() {
File file = new File(getTempFilename());
file.delete();
}
private void copyWaveFile(String inFilename, String outFilename) {
FileInputStream in = null;
FileOutputStream out = null;
long totalAudioLen = 0;
long totalDataLen = totalAudioLen + 36;
long longSampleRate = RECORDER_SAMPLERATE;
int channels = 1;
long byteRate = RECORDER_BPP * RECORDER_SAMPLERATE * channels / 8;
byte[] data = new byte[bufferSize];
try {
in = new FileInputStream(inFilename);
out = new FileOutputStream(outFilename);
totalAudioLen = in.getChannel().size();
totalDataLen = totalAudioLen + 36;
AppLog.logString("File size: " + totalDataLen);
WriteWaveFileHeader(out, totalAudioLen, totalDataLen,
longSampleRate, channels, byteRate);
while (in.read(data) != -1) {
out.write(data);
}
in.close();
out.close();
}
catch (FileNotFoundException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
}
private void fftbegir(String input, String output) {
FileInputStream in5 = null;
FileOutputStream out5 = null;
FileOutputStream stream = null;
byte[] data7 = new byte[10000];
double[] data8;
long totalAudioLen = 0;
long totalDataLen = totalAudioLen + 36;
long longSampleRate = RECORDER_SAMPLERATE;
int channels = 1;
int i = 0;
int r, k, l;
double b;
int m = 2;
long byteRate = RECORDER_BPP * RECORDER_SAMPLERATE * channels / 8;
String filepath = Environment.getExternalStorageDirectory().getPath();
File tempFile = new File(filepath, AUDIO_RECORDER_TEMP_FILE);
try {
in5 = new FileInputStream(input);
out5 = new FileOutputStream(output);
String strI = "nxkxaprojext;)";
out5.write(strI.getBytes());
AppLog.logString("File size: " + totalDataLen);
totalAudioLen = in5.getChannel().size();
strI = Long.toString(totalAudioLen);
out5.write(strI.getBytes());
out5.write(" ".getBytes());
data8 = SoundDataUtils.load16BitPCMRawDataFileAsDoubleArray();
l = data8.length;
strI = Integer.toString(l);
out5.write(strI.getBytes());
out5.write(" ".getBytes());
while (l > m) {
m = m * 2;
}
strI = Integer.toString(m);
out5.write(strI.getBytes());
out5.write(" ".getBytes());
strI = Double.toString(data8[50]);
out5.write(strI.getBytes());
Complex[] x = new Complex[m];
while (i < l) {
strI = Double.toString(data8[i]);
out5.write(strI.getBytes());
out5.write(" ".getBytes());
//x[i] = new Complex(data8[i], 0);
i++;
}
in5.close();
///i--;
///for (i = l; i < m; i++) {
/// x[i] = new Complex(0, 0);
/// }
/// FFT f = new FFT();
//// Complex[] y = f.fft(x);
/*try {
for (i = 0; i < m; i++) {
b = y[i].re();
strI = Double.toString(b);
out5.write(strI.getBytes());
out5.write(" ".getBytes());
b = y[i].im();
strI = Double.toString(b);
out5.write(strI.getBytes());
out5.write("j".getBytes());
out5.write(" ".getBytes());
}
}*/// finally {
/// out5.close();
////}
}
catch (FileNotFoundException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
}
private void WriteWaveFileHeader(
FileOutputStream out, long totalAudioLen,
long totalDataLen, long longSampleRate, int channels,
long byteRate) throws IOException {
byte[] header = new byte[44];
header[0] = 'R'; // RIFF/WAVE header
header[1] = 'I';
header[2] = 'F';
header[3] = 'F';
header[4] = (byte) (totalDataLen & 0xff);
header[5] = (byte) ((totalDataLen >> 8) & 0xff);
header[6] = (byte) ((totalDataLen >> 16) & 0xff);
header[7] = (byte) ((totalDataLen >> 24) & 0xff);
header[8] = 'W';
header[9] = 'A';
header[10] = 'V';
header[11] = 'E';
header[12] = 'f'; // 'fmt ' chunk
header[13] = 'm';
header[14] = 't';
header[15] = ' ';
header[16] = 16; // 4 bytes: size of 'fmt ' chunk
header[17] = 0;
header[18] = 0;
header[19] = 0;
header[20] = 1; // format = 1
header[21] = 0;
header[22] = (byte) channels;
header[23] = 0;
header[24] = (byte) (longSampleRate & 0xff);
header[25] = (byte) ((longSampleRate >> 8) & 0xff);
header[26] = (byte) ((longSampleRate >> 16) & 0xff);
header[27] = (byte) ((longSampleRate >> 24) & 0xff);
header[28] = (byte) (byteRate & 0xff);
header[29] = (byte) ((byteRate >> 8) & 0xff);
header[30] = (byte) ((byteRate >> 16) & 0xff);
header[31] = (byte) ((byteRate >> 24) & 0xff);
header[32] = (byte) (1 * 16 / 8); // block align
header[33] = 0;
header[34] = RECORDER_BPP; // bits per sample
header[35] = 0;
header[36] = 'd';
header[37] = 'a';
header[38] = 't';
header[39] = 'a';
header[40] = (byte) (totalAudioLen & 0xff);
header[41] = (byte) ((totalAudioLen >> 8) & 0xff);
header[42] = (byte) ((totalAudioLen >> 16) & 0xff);
header[43] = (byte) ((totalAudioLen >> 24) & 0xff);
out.write(header, 0, 44);
}
private View.OnClickListener btnClick = new View.OnClickListener() {
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btnStart: {
AppLog.logString("Start Recording");
enableButtons(true);
startRecording();
break;
}
case R.id.btnStop: {
AppLog.logString("Start Recording");
enableButtons(false);
stopRecording();
break;
}
}
}
};
and SoundDataUtils class code is(in this class i I tried to convert 16bit to double)
public static double[] load16BitPCMRawDataFileAsDoubleArray() throws IOException {
String filepath = Environment.getExternalStorageDirectory().getPath();
File file = new File(filepath, "AudioRecorder");
if ( !file.exists()) {
file.mkdirs();
}
File tempFile = new File(filepath + "/AudioRecorder", "record_temp.raw");
InputStream in = null;
long size = tempFile.length();
try {
in = new FileInputStream(tempFile);
return readStreamAsDoubleArray(in, size);
}
catch (Exception e) {}
return null;
}
public static double[] readStreamAsDoubleArray(InputStream in, long size)
throws IOException {
int bufferSize = (int) (size / 2);
double[] result = new double[bufferSize];
DataInputStream is = new DataInputStream(in);
for (int i = 0; i < bufferSize; i++) {
result[i] = is.readShort() / 32768.0;
}
return result;
}
the first 20 values in android:
0.8359375 0.2265625 0.1171875 0.8359375 -1.0 -0.8359375 0.9375 0.71875 -0.5078125 -0.34375 -0.8359375 -0.71875 -0.8828125 0.4453125 -0.218780517578125 0.960906982421875 -0.710968017578125 -0.156280517578125 -0.7890625 0.7734375
the first 20 values in matlab:0.00326538085937500
0.000885009765625000
0.000457763671875000
0.00326538085937500
0.00390625000000000
0.00454711914062500
0.00366210937500000
0.00280761718750000
0.00582885742187500
0.00646972656250000
0.00454711914062500
0.00500488281250000
0.00436401367187500
0.00173950195312500
-0.000885009765625000
-0.00408935546875000
-0.00280761718750000
-0.000640869140625000
0.00473022460937500
0.00302124023437500
i am spending a lot of hours to finding problem.
Can someone help me? THANKS!
Related
How do I implement an IIR bandpass filter in my current android code? I have an android app which could record audio (frequency actually) and save it in a .wav file.
I have managed to find a IIR Filter Library online but I am not sure how to implement it into my code.
https://github.com/ddf/Minim/blob/master/src/ddf/minim/effects/BandPass.java
https://github.com/DASAR/Minim-Android/blob/master/src/ddf/minim/effects/IIRFilter.java
I am supposed to add the 18k-20k bandpass filter to the code before outputting the received sound signal into a .wav file.
My current code
package com.example.audio;
import ddf.minim.effects.*;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import com.varma.samples.audiorecorder.R;
import android.app.Activity;
import android.content.Context;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioRecord;
import android.media.AudioTrack;
import android.media.MediaRecorder;
import android.media.MediaScannerConnection;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.text.SpannableStringBuilder;
import android.text.style.RelativeSizeSpan;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
public class RecorderActivity extends Activity {
private static final int RECORDER_BPP = 16;
private static final String AUDIO_RECORDER_FILE_EXT_WAV = ".wav";
private static final String AUDIO_RECORDER_FOLDER = "AudioRecorder";
private static final String AUDIO_RECORDER_TEMP_FILE = "record_temp.raw";
private static final int RECORDER_SAMPLERATE = 44100;// 44100; //18000
private static final int RECORDER_CHANNELS = AudioFormat.CHANNEL_IN_STEREO; //AudioFormat.CHANNEL_IN_STEREO;
private static final int RECORDER_AUDIO_ENCODING = AudioFormat.ENCODING_PCM_16BIT;
private static final int PLAY_CHANNELS = AudioFormat.CHANNEL_OUT_STEREO; //AudioFormat.CHANNEL_OUT_STEREO;
private static final int FREQUENCY_LEFT = 2000; //Original:18000 (16 Dec)
private static final int FREQUENCY_RIGHT = 2000; //Original:18000 (16 Dec)
private static final int AMPLITUDE_LEFT = 1;
private static final int AMPLITUDE_RIGHT = 1;
private static final int DURATION_SECOND = 10;
private static final int SAMPLE_RATE = 44100;
private static final float SWEEP_RANGE = 1000.0f;
String store;
private AudioRecord recorder = null;
private int bufferSize = 0;
private Thread recordingThread = null;
private boolean isRecording = false;
double time;
float[] buffer1;
float[] buffer2;
byte[] byteBuffer1;
byte[] byteBuffer2;
byte[] byteBufferFinal;
int bufferIndex;
short x;
short y;
AudioTrack audioTrack;
Button btnPlay, btnStart, btnStop;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
setButtonHandlers();
enableButtons(false);
btnPlay = (Button) findViewById(R.id.btnPlay);
btnStop = (Button) findViewById(R.id.btnStop);
btnStart = (Button) findViewById(R.id.btnStart);
bufferSize = AudioRecord.getMinBufferSize(RECORDER_SAMPLERATE, RECORDER_CHANNELS, RECORDER_AUDIO_ENCODING);
buffer1 = new float[(int) (DURATION_SECOND * SAMPLE_RATE)];
buffer2 = new float[(int) (DURATION_SECOND * SAMPLE_RATE)];
float f1 = 0.0f, f2 = 0.0f;
for (int sample = 0, step = 0; sample < buffer1.length; sample++) {
time = sample / (SAMPLE_RATE * 1.0);
//f1 = (float)(FREQUENCY_LEFT + ((sample / (buffer1.length * 1.0)) * SWEEP_RANGE)); // frequency sweep
//f2 = (float)(FREQUENCY_RIGHT + ((sample / (buffer1.length * 1.0)) * SWEEP_RANGE)); // frequency sweep
f1 = FREQUENCY_LEFT; // static frequency
f2 = FREQUENCY_RIGHT; // static frequency
buffer1[sample] = (float) (AMPLITUDE_LEFT * Math.sin(2 * Math.PI * f1 * time));
buffer2[sample] = (float) (AMPLITUDE_RIGHT * Math.sin(2 * Math.PI * f2 * time));
}
byteBuffer1 = new byte[buffer1.length * 2]; // two bytes per audio
// frame, 16 bits
for (int i = 0, bufferIndex = 0; i < byteBuffer1.length; i++) {
x = (short) (buffer1[bufferIndex++] * 32767.0); // [2^16 - 1]/2 =
// 32767.0
byteBuffer1[i] = (byte) x; // low byte
byteBuffer1[++i] = (byte) (x >>> 8); // high byte
}
byteBuffer2 = new byte[buffer2.length * 2];
for (int j = 0, bufferIndex = 0; j < byteBuffer2.length; j++) {
y = (short) (buffer2[bufferIndex++] * 32767.0);
byteBuffer2[j] = (byte) y; // low byte
byteBuffer2[++j] = (byte) (y >>> 8); // high byte
}
byteBufferFinal = new byte[byteBuffer1.length * 2];
// LL RR LL RR LL RR
for (int k = 0, index = 0; index < byteBufferFinal.length - 4; k = k + 2) {
byteBufferFinal[index] = byteBuffer1[k]; // LEFT
// {0,1/4,5/8,9/12,13;...}
byteBufferFinal[index + 1] = byteBuffer1[k + 1];
index = index + 2;
byteBufferFinal[index] = byteBuffer2[k]; // RIGHT
// {2,3/6,7/10,11;...}
byteBufferFinal[index + 1] = byteBuffer2[k + 1];
index = index + 2;
}
try {
FileOutputStream ss = new FileOutputStream(Environment.getExternalStorageDirectory().getPath() + "/" + AUDIO_RECORDER_FOLDER + "/source.txt");
ss.write(byteBufferFinal);
ss.flush();
ss.close();
}
catch (IOException ioe){
Log.e("IO Error","Write source error.");
}
}
private void setButtonHandlers() {
((Button) findViewById(R.id.btnStart)).setOnClickListener(startClick);
((Button) findViewById(R.id.btnStop)).setOnClickListener(stopClick);
((Button) findViewById(R.id.btnPlay)).setOnClickListener(playClick);
}
private void enableButton(int id, boolean isEnable) {
((Button) findViewById(id)).setEnabled(isEnable);
}
private void enableButtons(boolean isRecording) {
enableButton(R.id.btnStart, !isRecording);
enableButton(R.id.btnStop, isRecording);
enableButton(R.id.btnPlay, isRecording);
}
private String getFilename() {
String filepath = Environment.getExternalStorageDirectory().getPath();
File file = new File(filepath, AUDIO_RECORDER_FOLDER);
if (!file.exists()) {
file.mkdirs();
}
MediaScannerConnection.scanFile(this, new String[]{filepath}, null, null);
store = file.getAbsolutePath() + "/" + "Audio"
+ AUDIO_RECORDER_FILE_EXT_WAV;
return store;
}
private String getTempFilename() {
String filepath = Environment.getExternalStorageDirectory().getPath();
File file = new File(filepath, AUDIO_RECORDER_FOLDER);
if (!file.exists()) {
file.mkdirs();
}
File tempFile = new File(filepath, AUDIO_RECORDER_TEMP_FILE);
if (tempFile.exists())
tempFile.delete();
return (file.getAbsolutePath() + "/" + AUDIO_RECORDER_TEMP_FILE);
}
private void startRecording() {
//BandPass bandpass = new BandPass(19000,2000,44100);
/* BandPass bandpass = new BandPass(50,2,SAMPLE_RATE);
int [] freqR = {FREQUENCY_RIGHT};
int [] freqL = {FREQUENCY_LEFT};
float[] testL = shortToFloat(freqR);
float [] testR = shortToFloat(freqL);
bandpass.process(testL,testR);
bandpass.printCoeff();
*/
recorder = new AudioRecord(MediaRecorder.AudioSource.CAMCORDER,
RECORDER_SAMPLERATE, RECORDER_CHANNELS,
RECORDER_AUDIO_ENCODING, bufferSize);
AudioManager am = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
am.setStreamVolume(AudioManager.STREAM_MUSIC, am.getStreamMaxVolume(AudioManager.STREAM_MUSIC), 0);
/*
* AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
* (int) RECORDER_SAMPLERATE,AudioFormat.CHANNEL_OUT_STEREO,
* AudioFormat.ENCODING_PCM_16BIT, bufferSize, AudioTrack.MODE_STREAM);
*/
audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
(int) SAMPLE_RATE, PLAY_CHANNELS,
AudioFormat.ENCODING_PCM_16BIT, byteBufferFinal.length,
AudioTrack.MODE_STATIC);
audioTrack.write(byteBufferFinal, 0, byteBufferFinal.length);
audioTrack.play();
BandPass bandpass = new BandPass(50,2,SAMPLE_RATE);
int [] freqR = {FREQUENCY_RIGHT};
int [] freqL = {FREQUENCY_LEFT};
float[] testL = shortToFloat(freqR);
float [] testR = shortToFloat(freqL);
bandpass.process(testL,testR);
bandpass.printCoeff();
audioTrack.setPlaybackRate(RECORDER_SAMPLERATE);
recorder.startRecording();
isRecording = true;
recordingThread = new Thread(new Runnable() {
#Override
public void run() {
try {
writeAudioDataToFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}, "AudioRecorder Thread");
recordingThread.start();
}
double[][] deinterleaveData(double[] samples, int numChannels) {
// assert(samples.length() % numChannels == 0);
int numFrames = samples.length / numChannels;
double[][] result = new double[numChannels][];
for (int ch = 0; ch < numChannels; ch++) {
result[ch] = new double[numFrames];
for (int i = 0; i < numFrames; i++) {
result[ch][i] = samples[numChannels * i + ch];
}
}
return result;
}
private void writeAudioDataToFile() throws IOException {
int read = 0;
byte data[] = new byte[bufferSize];
String filename = getTempFilename();
FileOutputStream os = null;
FileOutputStream rs = null;
try {
os = new FileOutputStream(filename);
rs = new FileOutputStream(getFilename().split(".wav")[0] + ".txt");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (null != os) {
while (isRecording) {
read = recorder.read(data, 0, bufferSize);
if (AudioRecord.ERROR_INVALID_OPERATION != read) {
try {
os.write(data);
rs.write(data);
} catch (IOException e) {
e.printStackTrace();
}
}
}
try {
os.close();
rs.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void stopRecording() {
if (null != recorder) {
isRecording = false;
audioTrack.flush();
audioTrack.stop();
audioTrack.release();
recorder.stop();
recorder.release();
recorder = null;
recordingThread = null;
}
copyWaveFile(getTempFilename(), getFilename());
deleteTempFile();
MediaScannerConnection.scanFile(this, new String[]{getFilename()}, null, null);
AudioManager am = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
am.setStreamVolume(AudioManager.STREAM_MUSIC, 0, 0);
}
private void deleteTempFile() {
File file = new File(getTempFilename());
file.delete();
}
private void copyWaveFile(String inFilename, String outFilename) {
FileInputStream in = null;
FileOutputStream out = null;
long totalAudioLen = 0;
long totalDataLen = totalAudioLen + 36;
long longSampleRate = RECORDER_SAMPLERATE;
int channels = 2;
long byteRate = RECORDER_BPP * RECORDER_SAMPLERATE * channels / 8;
byte[] data = new byte[bufferSize];
try {
in = new FileInputStream(inFilename);
out = new FileOutputStream(outFilename);
totalAudioLen = in.getChannel().size();
totalDataLen = totalAudioLen + 36;
WriteWaveFileHeader(out, totalAudioLen, totalDataLen,
longSampleRate, channels, byteRate);
while (in.read(data) != -1) {
out.write(data);
}
in.close();
out.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private void playWaveFile() {
String filepath = store;
Log.d("PLAYWAVEFILE", "I AM INSIDE");
// define the buffer size for audio track
int minBufferSize = AudioTrack.getMinBufferSize(8000,
AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT);
int bufferSize = 512;
audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
(int) RECORDER_SAMPLERATE, AudioFormat.CHANNEL_OUT_STEREO,
AudioFormat.ENCODING_PCM_16BIT, minBufferSize,
AudioTrack.MODE_STREAM);
int count = 0;
byte[] data = new byte[bufferSize];
try {
FileInputStream fileInputStream = new FileInputStream(filepath);
DataInputStream dataInputStream = new DataInputStream(
fileInputStream);
audioTrack.play();
Toast.makeText(RecorderActivity.this, "this is my Toast message!!! =)",
Toast.LENGTH_LONG).show();
while ((count = dataInputStream.read(data, 0, bufferSize)) > -1) {
Log.d("PLAYWAVEFILE", "WHILE INSIDE");
audioTrack.write(data, 0, count);
//BandPass bandpass = new BandPass(19000,2000,44100); //Actual
//BandPass bandpass = new BandPass(5000,2000,44100); //Test
//int [] freqR = {FREQUENCY_RIGHT};
//int [] freqL = {FREQUENCY_LEFT};
//float[] testR = shortToFloat(freqR);
//float [] testL = shortToFloat(freqL);
//bandpass.process(testR,testL);
// BandPass bandpass = new BandPass(19000,2000,44100);
//float bw = bandpass.getBandWidth();
//float hello = bandpass.getBandWidth();
//float freq = bandpass.frequency();
//float[] test = {FREQUENCY_RIGHT,FREQUENCY_LEFT};
//shortToFloat(test);
//test [0] = FREQUENCY_RIGHT;
//test [1] = FREQUENCY_LEFT;
//bandpass.process(FREQUENCY_LEFT,FREQUENCY_RIGHT);
//Log.d("MyApp","I am here");
//Log.d("ADebugTag", "Valueeees: " + Float.toString(hello));
//Log.d("Bandwidth: " , "Bandwidth: " + Float.toString(bw));
//Log.d("Frequency: " , "Frequency is " + Float.toString(freq));
//bandpass.setBandWidth(20);
//bandpass.printCoeff();
}
audioTrack.stop();
audioTrack.release();
dataInputStream.close();
fileInputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private void WriteWaveFileHeader(FileOutputStream out, long totalAudioLen,
long totalDataLen, long longSampleRate, int channels, long byteRate)
throws IOException {
byte[] header = new byte[44];
header[0] = 'R'; // RIFF/WAVE header
header[1] = 'I';
header[2] = 'F';
header[3] = 'F';
header[4] = (byte) (totalDataLen & 0xff);
header[5] = (byte) ((totalDataLen >> 8) & 0xff);
header[6] = (byte) ((totalDataLen >> 16) & 0xff);
header[7] = (byte) ((totalDataLen >> 24) & 0xff);
header[8] = 'W';
header[9] = 'A';
header[10] = 'V';
header[11] = 'E';
header[12] = 'f'; // 'fmt ' chunk
header[13] = 'm';
header[14] = 't';
header[15] = ' ';
header[16] = 16; // 4 bytes: size of 'fmt ' chunk
header[17] = 0;
header[18] = 0;
header[19] = 0;
header[20] = 1; // format = 1
header[21] = 0;
header[22] = (byte) channels;
header[23] = 0;
header[24] = (byte) (longSampleRate & 0xff);
header[25] = (byte) ((longSampleRate >> 8) & 0xff);
header[26] = (byte) ((longSampleRate >> 16) & 0xff);
header[27] = (byte) ((longSampleRate >> 24) & 0xff);
header[28] = (byte) (byteRate & 0xff);
header[29] = (byte) ((byteRate >> 8) & 0xff);
header[30] = (byte) ((byteRate >> 16) & 0xff);
header[31] = (byte) ((byteRate >> 24) & 0xff);
header[32] = (byte) (2 * 16 / 8); // block align
header[33] = 0;
header[34] = RECORDER_BPP; // bits per sample
header[35] = 0;
header[36] = 'd';
header[37] = 'a';
header[38] = 't';
header[39] = 'a';
header[40] = (byte) (totalAudioLen & 0xff);
header[41] = (byte) ((totalAudioLen >> 8) & 0xff);
header[42] = (byte) ((totalAudioLen >> 16) & 0xff);
header[43] = (byte) ((totalAudioLen >> 24) & 0xff);
out.write(header, 0, 44);
}
private View.OnClickListener startClick = new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
Thread recordThread = new Thread(new Runnable() {
#Override
public void run() {
isRecording = true;
startRecording();
}
});
recordThread.start();
btnStart.setEnabled(false);
btnStop.setEnabled(true);
btnPlay.setEnabled(false);
}
};
private View.OnClickListener stopClick = new View.OnClickListener() {
#Override
public void onClick(View v) {
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
stopRecording();
enableButtons(false);
btnPlay.setEnabled(true);
// stop();
}
}, 100);
}
};
private View.OnClickListener playClick = new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
playWaveFile();
btnPlay.setEnabled(true);
String filepath = store;
final String promptPlayRecord = "PlayWaveFile()\n" + filepath;
SpannableStringBuilder biggerText = new SpannableStringBuilder(promptPlayRecord);
biggerText.setSpan(new RelativeSizeSpan(2.05f), 0, promptPlayRecord.length(), 0);
Toast.makeText(RecorderActivity.this, biggerText, Toast.LENGTH_LONG).show();
}
};
}
The method below is to convert my 16-bit integer to float since the library uses float
/**
* Convert int[] audio to 32 bit float format.
* From [-32768,32768] to [-1,1]
* #param audio
*/
private float[] shortToFloat(int[] audio) {
Log.d("SHORTTOFLOAT","INSIDE SHORTTOFLOAT");
float[] converted = new float[audio.length];
for (int i = 0; i < converted.length; i++) {
// [-32768,32768] -> [-1,1]
converted[i] = audio[i] / 32768f; /* default range for Android PCM audio buffers) */
}
return converted;
}
Trying to implement bandpass filter under "SaveRecording" Method
//BandPass bandpass = new BandPass(19000,2000,44100);
Since I am trying to implement a range of 18k to 20k, I input the above values to the bandpass filter.
BandPass bandpass = new BandPass(50,2,44100); (This is just to test if the frequency has any changes since 18k-20k is not within human range)
int [] freqR = {FREQUENCY_RIGHT};
int [] freqL = {FREQUENCY_LEFT};
float[] testL = shortToFloat(freqR);
float [] testR = shortToFloat(freqL);
bandpass.process(testL,testR);
bandpass.printCoeff();
Since I am recording in STEREO, I am using the
public final synchronized void process(float[] sigLeft, float[] sigRight) {} found in the IIRFilter.java class.
However, I am not hearing any differences even though I implemented the above method. What am I doing wrong? Could anyone advise/help me?
Thank You so much! Terribly new in this signal processing. Any tips/hints on how to progress is much appreciated!!!
Updated
Since I have to output the .wav file with the filtered sound signal, I thought the way to do it is to put the BandPass filter under the "StartRecording" method, however, it is not working. Why is it that I am doing wrong?
private void startRecording() {
int count = 0;
recorder = new AudioRecord(MediaRecorder.AudioSource.CAMCORDER,
RECORDER_SAMPLERATE, RECORDER_CHANNELS,
RECORDER_AUDIO_ENCODING, bufferSize);
AudioManager am = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
am.setStreamVolume(AudioManager.STREAM_MUSIC, am.getStreamMaxVolume(AudioManager.STREAM_MUSIC), 0);
audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
(int) SAMPLE_RATE, PLAY_CHANNELS,
AudioFormat.ENCODING_PCM_16BIT, byteBufferFinal.length,
AudioTrack.MODE_STATIC);
BandPass bandpass = new BandPass(19000,2000,44100);
float[][] signals = deinterleaveData(byteToFloat(byteBufferFinal), 2);
bandpass.process(signals[0], signals[1]);
audioTrack.write(interleaveData(signals), 0, count, WRITE_NON_BLOCKING);
audioTrack.play();
//audioTrack.write(byteBufferFinal, 0, byteBufferFinal.length); //Original
audioTrack.setPlaybackRate(RECORDER_SAMPLERATE);
recorder.startRecording();
isRecording = true;
recordingThread = new Thread(new Runnable() {
#Override
public void run() {
try {
writeAudioDataToFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}, "AudioRecorder Thread");
recordingThread.start();
}
Updated (14 March 2016)
This is the image of the output .wav file shown by Audacity:
May I ask if it is considered filtered?
What are the characteristics that I should look out for to ensure that it is filtered correctly.
The above image produce by press the black triangle
The above image graph produced by the Analyse->Plot Specturm
What about this graph? Does it implement the bandpass filter successfully? Thank
There is an issue with how you interface with the Bandpass.java source, probably resulting from what appears to be a bit of a misconception: IIR filters do not process frequencies, but they rather process time-domain data samples (which may exhibit oscillatory behavior).
As such you have to provide those time domain samples as inputs to Bandpass.process(). Since you are reading raw bytes from file, you will need to convert those bytes to float. You could do this with:
/**
* Convert byte[] raw audio to 16 bit int format.
* #param rawdata
*/
private int[] byteToShort(byte[] rawdata) {
int[] converted = new int[rawdata.length / 2];
for (int i = 0; i < converted.length; i++) {
// Wave file data are stored in little-endian order
int lo = rawdata[2*i];
int hi = rawdata[2*i+1];
converted[i] = ((hi&0xFF)<<8) | (lo&0xFF);
}
return converted;
}
private float[] byteToFloat(byte[] audio) {
return shortToFloat(byteToShort(audio));
}
Also for stereo wave files, you will get samples from the wave files which are interleaved. So you will also need to deinterleave the samples. This can be achieved in a similar fashion as you've done with deinterleaveData, except you will need a variant converting to float[][] instead of to double[][] since Bandpass.process expects float arrays.
You will of course also need to recombine the two channels back together after the filtering but before feeding the resulting filtered signals back to the audioTrack:
float[] interleaveData(float[][] data) {
int numChannels = data.length;
int numFrames = data[0].length;
float[] result = new float[numFrames*numChannels];
for (int i = 0; i < numFrames; i++) {
for (int ch = 0; ch < numChannels; ch++) {
result[numChannels * i + ch] = data[ch][i];
}
}
return result;
}
You should now have the required building blocks to filter your audio:
BandPass bandpass = new BandPass(19000,2000,44100);
while ((count = dataInputStream.read(data, 0, bufferSize)) > -1) {
// decode and deinterleave stereo 16-bit per sample data
float[][] signals = deinterleaveData(byteToFloat(data), 2);
// filter data samples, updating the buffers with the filtered samples.
bandpass.process(signals[0], signals[1]);
// recombine signals for playback
audioTrack.write(interleaveData(signals), 0, count, WRITE_NON_BLOCKING);
}
P.S.: as a final note, you are currently reading all the wave file as data samples, header included. This will result in a short noisy burst at the beginning. To avoid this, you should skip the header.
There could be a few problems...
The audio file you are trying to filter may not have much content that is noticeable to the ear in the bandpass range you are trying to filter. Try filtering a much larger range to verify the filter works. Try filtering most the song.
If you cannot get the above to work, then the filter is not being implemented properly. You likely are not implementing the filter correctly. For a really simple filter your could try Y[n] = X[n] - .5*X[n-1] which is a High Pass FIR filter with zero at 0 Hz.
Good Luck!
I have question about Android decode mp3, mix few audio and encode to m4a (aac). For that I use Jlayer for android to decode mp3, audiotrack to play song, and MediaCodec with mediaformat to encode pcm. The problem is my output after encode is too fast for example: I should have 5 sec audio mix but instead I got ~ 1,5 sec. I thinking that I lose somewhere audio frames, but I dont sure about that. Thanks for answer.
(output file is ~ 25% faster that should be)
Decode mp3 code:
public void decodeMP3toPCM(Resources res, int resource) throws BitstreamException, DecoderException, IOException {
InputStream inputStream = new BufferedInputStream(res.openRawResource(resource), 1152);
Bitstream bitstream = new Bitstream(inputStream);
Decoder decoder = new Decoder();
boolean done = false;
while (!done) {
Header frameHeader = bitstream.readFrame();
if (frameHeader == null) {
done = true;
} else {
SampleBuffer output = (SampleBuffer) decoder.decodeFrame(frameHeader, bitstream);
mTimeCount += frameHeader.ms_per_frame();
short[] pcm = output.getBuffer();
mDataBuffer.addFrame(mViewId, pcm);
mReadedFrames++;
mAudioTrack.write(pcm, 0, pcm.length);
}
bitstream.closeFrame();
}
inputStream.close();
}
encode:
public class AudioEncoder {
private MediaCodec mediaCodec;
private BufferedOutputStream outputStream;
private String mediaType = "audio/mp4a-latm";
public AudioEncoder(String filePath) throws IOException {
File f = new File(filePath);
touch(f);
try {
outputStream = new BufferedOutputStream(new FileOutputStream(f));
} catch (Exception e) {
e.printStackTrace();
}
try {
//mediaCodec = MediaCodec.createEncoderByType(mediaType);
mediaCodec = MediaCodec.createByCodecName("OMX.google.aac.encoder");
} catch (IOException e) {
e.printStackTrace();
}
mediaCodec = MediaCodec.createEncoderByType(mediaType);
final int kSampleRates[] = { 8000, 11025, 22050, 44100, 48000 };
final int kBitRates[] = { 64000, 128000 };
MediaFormat mediaFormat = MediaFormat.createAudioFormat(mediaType,kSampleRates[3],2);
mediaFormat.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectLC);
mediaFormat.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, 4608);
mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, kBitRates[1]);
mediaCodec.configure(mediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
mediaCodec.start();
}
public void close() {
try {
mediaCodec.stop();
mediaCodec.release();
outputStream.flush();
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public synchronized void offerEncoder(byte[] input) {
Log.e("synchro ", input.length + " is coming");
try {
ByteBuffer[] inputBuffers = mediaCodec.getInputBuffers();
ByteBuffer[] outputBuffers = mediaCodec.getOutputBuffers();
int inputBufferIndex = mediaCodec.dequeueInputBuffer(-1);
if (inputBufferIndex >= 0) {
ByteBuffer inputBuffer = inputBuffers[inputBufferIndex];
inputBuffer.clear();
inputBuffer.put(input);
mediaCodec.queueInputBuffer(inputBufferIndex, 0, input.length, 0, 0);
}
MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
int outputBufferIndex = mediaCodec.dequeueOutputBuffer(bufferInfo, 0);
while (outputBufferIndex >= 0) {
int outBitsSize = bufferInfo.size;
int outPacketSize = outBitsSize + 7; // 7 is ADTS size
ByteBuffer outputBuffer = outputBuffers[outputBufferIndex];
outputBuffer.position(bufferInfo.offset);
outputBuffer.limit(bufferInfo.offset + outBitsSize);
byte[] outData = new byte[outPacketSize];
addADTStoPacket(outData, outPacketSize);
outputBuffer.get(outData, 7, outBitsSize);
outputBuffer.position(bufferInfo.offset);
outputStream.write(outData, 0, outData.length);
mediaCodec.releaseOutputBuffer(outputBufferIndex, false);
outputBufferIndex = mediaCodec.dequeueOutputBuffer(bufferInfo, 0);
}
} catch (Throwable t) {
t.printStackTrace();
}
}
private void addADTStoPacket(byte[] packet, int packetLen) {
int profile = 2; //AAC LC
//39=MediaCodecInfo.CodecProfileLevel.AACObjectELD;
int freqIdx = 4; //44.1KHz
int chanCfg = 2; //CPE
// fill in ADTS data
packet[0] = (byte) 0xFF;
packet[1] = (byte) 0xF9;
packet[2] = (byte) (((profile - 1) << 6) + (freqIdx << 2) + (chanCfg >> 2));
packet[3] = (byte) (((chanCfg & 3) << 6) + (packetLen >> 11));
packet[4] = (byte) ((packetLen & 0x7FF) >> 3);
packet[5] = (byte) (((packetLen & 7) << 5) + 0x1F);
packet[6] = (byte) 0xFC;
}
public void touch(File f) {
try {
if (!f.exists())
f.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
}
I have been trying to merge two WAVE files on Android for quite some time now but really can't seem to get it working properly.
Everything looks fine, the files are read, and written to the output file which is also readable at a later stage and has the file size I would expect to see.
The problems occur right after the app has finished merging. This message will show in the log: Error occured in updateListener, recording is aborted which is a message from extAudioRecorder and appears when the OnRecordPositionUpdateListener reaches the catch clause (the Exception has the following detailMessage: write failed: EBADF (Bad file number)). This does not seem to break anything so I'm not too worried about this.
The real problem arises when I try to create a MediaPlayer and call the setDataSource(String path) on the MediaPlayer instance. Whenever I do this with a merged file the following error message will show in the log: Unable to to create media player (the IOException that is thrown contains the following detailMessage: setDataSourceFD failed.: status=0x80000000). Note that the first time the file will play perfectly fine (this first file was not made by the combineWaveFiles() method). That Error message appears to indicate that the audio file's format is incorrect and/or can't be read by the MediaPlayer.
My question is if anyone sees any real problems with the code below (I know it's sub-optimal in many ways but I prefer to get it to work first then worry about performance).
public static String MergeRecordings(String cumulativeFile, String recordFile, int sampleRate, int bpp, int bufferSize, int channels) {
if (cumulativeFile == null) {
return recordFile;
} else if (recordFile == null) {
return cumulativeFile;
}
String outputFile = FileUtils.getFilePath(null, MDSettings.shared().getMainActivity());
FileUtils.combineWaveFiles(cumulativeFile, recordFile, outputFile, sampleRate, bpp, bufferSize, channels);
//FileUtils.removeFile(cumulativeFile);
//FileUtils.removeFile(recordFile);
return outputFile;
}
//creates a new file containing file1 + file2 stuck together as such.
private static void combineWaveFiles(String file1, String file2, String outputFile, int sampleRate, int bpp, int bufferSize, int channels) {
FileInputStream in1 = null, in2 = null;
FileOutputStream out = null;
long longSampleRate = sampleRate;
long byteRate = sampleRate * channels * bpp / 8;
byte[] data;
try {
try {
in1 = new FileInputStream(file1);
} catch (Exception e) { }
try {
in2 = new FileInputStream(file2);
} catch (FileNotFoundException e) { }
out = new FileOutputStream(outputFile);
long file1Size = 0;
long file2Size = 0;
if (in1 != null) { file1Size = in1.getChannel().size() - 44; }
if (in2 != null) { file2Size = in2.getChannel().size() - 44; }
long totalAudioLen = file1Size + file2Size;
long totalDataLen = totalAudioLen + 36;
FileUtils.writeWaveFileHeader(out, totalAudioLen, totalDataLen, longSampleRate, channels, byteRate, bpp);
if (in1 != null) {
in1.skip(44);
data = new byte[bufferSize];
if (file1Size < bufferSize) {
data = new byte[(int)file1Size];
}
while (in1.read(data) != -1) {
out.write(data);
file1Size -= bufferSize;
if (file1Size <= 0) {
break;
} else if (file1Size < bufferSize) {
data = new byte[(int)file1Size];
}
}
}
if (in2 != null) {
in2.skip(44);
data = new byte[bufferSize];
if (file2Size < bufferSize) {
data = new byte[(int)file2Size];
}
while (in2.read(data) != -1) {
out.write(data);
file2Size -= bufferSize;
if (file2Size <= 0) {
break;
} else if (file2Size < bufferSize) {
data = new byte[(int)file2Size];
}
}
}
out.close();
if (in1 != null) { in1.close(); }
if (in2 != null) { in2.close(); }
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private static void writeWaveFileHeader(FileOutputStream out, long totalAudioLen, long totalDataLen, long longSampleRate, int channels, long byteRate, int bpp)
throws IOException {
byte[] header = new byte[44];
header[0] = 'R';
header[1] = 'I';
header[2] = 'F';
header[3] = 'F';
header[4] = (byte)(totalDataLen & 0xff);
header[5] = (byte)((totalDataLen >> 8) & 0xff);
header[6] = (byte)((totalDataLen >> 16) & 0xff);
header[7] = (byte)((totalDataLen >> 24) & 0xff);
header[8] = 'W';
header[9] = 'A';
header[10] = 'V';
header[11] = 'E';
header[12] = 'f';
header[13] = 'm';
header[14] = 't';
header[15] = ' ';
header[16] = 16;
header[17] = 0;
header[18] = 0;
header[19] = 0;
header[20] = 1;
header[21] = 0;
header[22] = (byte) channels;
header[23] = 0;
header[24] = (byte)(longSampleRate & 0xff);
header[25] = (byte)((longSampleRate >> 8) & 0xff);
header[26] = (byte)((longSampleRate >> 16) & 0xff);
header[27] = (byte)((longSampleRate >> 24) & 0xff);
header[28] = (byte)(byteRate & 0xff);
header[29] = (byte)((byteRate >> 8) & 0xff);
header[30] = (byte)((byteRate >> 16) & 0xff);
header[31] = (byte)((byteRate >> 24) & 0xff);
header[32] = (byte)(channels * bpp); //(2 * 16 / 8);
header[33] = 0;
header[34] = (byte)bpp;
header[35] = 0;
header[36] = 'd';
header[37] = 'a';
header[38] = 't';
header[39] = 'a';
header[40] = (byte)(totalAudioLen & 0xff);
header[41] = (byte)((totalAudioLen >> 8) & 0xff);
header[42] = (byte)((totalAudioLen >> 16) & 0xff);
header[43] = (byte)((totalAudioLen >> 24) & 0xff);
out.write(header, 0, 44);
}
Large parts of this code are taken from this answer.
i do this exactly in my android app. Instead of two, i merge multiple files based on users selection. I use AsyncTask to merge the samples in the background. Take a look at it here. Just filter the section that you need. If you are curious about my app, its called Sound Recorder + Pro, Beside merge i do mix, add echo and amplify samples:
#Override
protected Void doInBackground(Void... params) {
isProcessingOn=true;
try {
DataOutputStream amplifyOutputStream = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(Environment.getExternalStorageDirectory() + "/Soundrecpluspro/" + year +"-"+ month +"-"+ date +"-"+ hour+"-" + min +"-"+ sec+"ME.wav")));
DataInputStream[] mergeFilesStream = new DataInputStream[selection.size()];
long[] sizes=new long[selection.size()];
for(int i=0; i<selection.size(); i++) {
File file = new File(Environment.getExternalStorageDirectory() + "/Soundrecpluspro/" +selection.get(i));
sizes[i] = (file.length()-44)/2;
}
for(int i =0; i<selection.size(); i++) {
mergeFilesStream[i] =new DataInputStream(new BufferedInputStream(new FileInputStream(Environment.getExternalStorageDirectory() + "/Soundrecpluspro/" +selection.get(i))));
if(i == selection.size()-1) {
mergeFilesStream[i].skip(24);
byte[] sampleRt = new byte[4];
mergeFilesStream[i].read(sampleRt);
ByteBuffer bbInt = ByteBuffer.wrap(sampleRt).order(ByteOrder.LITTLE_ENDIAN);
RECORDER_SAMPLERATE = bbInt.getInt();
mergeFilesStream[i].skip(16);
}
else {
mergeFilesStream[i].skip(44);
}
}
for(int b=0; b<selection.size(); b++) {
for(int i=0; i<(int)sizes[b]; i++) {
byte[] dataBytes = new byte[2];
try {
dataBytes[0] = mergeFilesStream[b].readByte();
dataBytes[1] = mergeFilesStream[b].readByte();
}
catch (EOFException e) {
amplifyOutputStream.close();
}
short dataInShort = ByteBuffer.wrap(dataBytes).order(ByteOrder.LITTLE_ENDIAN).getShort();
float dataInFloat= (float) dataInShort/37268.0f;
short outputSample = (short)(dataInFloat * 37268.0f);
byte[] dataFin = new byte[2];
dataFin[0] = (byte) (outputSample & 0xff);
dataFin[1] = (byte)((outputSample >> 8) & 0xff);
amplifyOutputStream.write(dataFin, 0 , 2);
}
}
amplifyOutputStream.close();
for(int i=0; i<selection.size(); i++) {
mergeFilesStream[i].close();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
long size =0;
try {
FileInputStream fileSize = new FileInputStream(Environment.getExternalStorageDirectory() + "/Soundrecpluspro/"+year +"-"+ month +"-"+ date +"-"+ hour+"-" + min +"-"+ sec+"ME.wav");
size = fileSize.getChannel().size();
fileSize.close();
} catch (FileNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
final int RECORDER_BPP = 16;
long datasize=size+36;
long byteRate = (RECORDER_BPP * RECORDER_SAMPLERATE)/8;
long longSampleRate = RECORDER_SAMPLERATE;
byte[] header = new byte[44];
header[0] = 'R'; // RIFF/WAVE header
header[1] = 'I';
header[2] = 'F';
header[3] = 'F';
header[4] = (byte) (datasize & 0xff);
header[5] = (byte) ((datasize >> 8) & 0xff);
header[6] = (byte) ((datasize >> 16) & 0xff);
header[7] = (byte) ((datasize >> 24) & 0xff);
header[8] = 'W';
header[9] = 'A';
header[10] = 'V';
header[11] = 'E';
header[12] = 'f'; // 'fmt ' chunk
header[13] = 'm';
header[14] = 't';
header[15] = ' ';
header[16] = 16; // 4 bytes: size of 'fmt ' chunk
header[17] = 0;
header[18] = 0;
header[19] = 0;
header[20] = 1; // format = 1
header[21] = 0;
header[22] = (byte) 1;
header[23] = 0;
header[24] = (byte) (longSampleRate & 0xff);
header[25] = (byte) ((longSampleRate >> 8) & 0xff);
header[26] = (byte) ((longSampleRate >> 16) & 0xff);
header[27] = (byte) ((longSampleRate >> 24) & 0xff);
header[28] = (byte) (byteRate & 0xff);
header[29] = (byte) ((byteRate >> 8) & 0xff);
header[30] = (byte) ((byteRate >> 16) & 0xff);
header[31] = (byte) ((byteRate >> 24) & 0xff);
header[32] = (byte) ((RECORDER_BPP) / 8); // block align
header[33] = 0;
header[34] = RECORDER_BPP; // bits per sample
header[35] = 0;
header[36] = 'd';
header[37] = 'a';
header[38] = 't';
header[39] = 'a';
header[40] = (byte) (size & 0xff);
header[41] = (byte) ((size >> 8) & 0xff);
header[42] = (byte) ((size >> 16) & 0xff);
header[43] = (byte) ((size >> 24) & 0xff);
// out.write(header, 0, 44);
try {
RandomAccessFile rFile = new RandomAccessFile(Environment.getExternalStorageDirectory() + "/Soundrecpluspro/" +year +"-"+ month +"-"+ date +"-"+ hour+"-" + min +"-"+ sec+ "ME.wav", "rw");
rFile.seek(0);
rFile.write(header);
rFile.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
Try with this code for concatenating the wav files:
public class ConcateSongActivity extends Activity {
Button mbutt;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mbutt = (Button)findViewById(R.id.button_clickme);
mbutt.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
try {
FileInputStream fis1 = new FileInputStream("/sdcard/MJdangerous.wav");
FileInputStream fis2 = new FileInputStream("/sdcard/MJBad.wav");
SequenceInputStream sis = new SequenceInputStream(fis1,fis2);
FileOutputStream fos = new FileOutputStream(new File("/sdcard/MJdangerousMJBad.wav"));
int temp;
try {
while ((temp = sis.read())!= -1){
fos.write(temp);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
} }
Note: don't forget to give this permission WRITE_EXTERNAL_STORAGE
other tricks:
This is the methods used to mix 3 sounds together:
private void mixFiles(){
try {
InputStream is1 = getResources().openRawResource(R.raw.test1);
List<Short> music1 = createMusicArray(is1);
InputStream is2 = getResources().openRawResource(R.raw.test2);
List<Short> music2 = createMusicArray(is2);
completeStreams(music1,music2);
short[] music1Array = buildShortArray(music1);
short[] music2Array = buildShortArray(music2);
short[] output = new short[music1Array.length];
for(int i=0; i < output.length; i++){
float samplef1 = music1Array[i] / 32768.0f;
float samplef2 = music2Array[i] / 32768.0f;
float mixed = samplef1 + samplef2;
// reduce the volume a bit:
mixed *= 0.8;
// hard clipping
if (mixed > 1.0f) mixed = 1.0f;
if (mixed < -1.0f) mixed = -1.0f;
short outputSample = (short)(mixed * 32768.0f);
output[i] = outputSample;
}
saveToFile(output);
} catch (NotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Once we have a PCM mixed sound, it can be transformed in a .wav file so that every player can read it.
/**
* Dealing with big endian streams
* #param byte0
* #param byte1
* #return a shrt with the two bytes swapped
*/
private static short swapBytes(byte byte0, byte byte1){
return (short)((byte1 & 0xff) << 8 | (byte0 & 0xff));
}
/**
* From file to byte[] array
* #param sample
* #param swap should swap bytes?
* #return
* #throws IOException
*/
public static byte[] sampleToByteArray(File sample, boolean swap) throws IOException{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(sample));
int BUFFERSIZE = 4096;
byte[] buffer = new byte[BUFFERSIZE];
while(bis.read(buffer) != - 1){
baos.write(buffer);
}
byte[] outputByteArray = baos.toByteArray();
bis.close();
baos.close();
if(swap){
for(int i=0; i < outputByteArray.length - 1; i=i+2){
byte byte0 = outputByteArray[i];
outputByteArray[i] = outputByteArray[i+1];
outputByteArray[i+1] = byte0;
}
}
return outputByteArray;
}
/**
* Read a file and returns its contents as array of shorts
* #param sample the sample file
* #param swap true if we should swap the bytes of short (reading a little-endian file), false otherwise (reading a big-endian file)
* #return
* #throws IOException
*/
public static short[] sampleToShortArray(File sample, boolean swap) throws IOException{
short[] outputArray = new short[(int)sample.length()/2];
byte[] outputByteArray = sampleToByteArray(sample,false);
for(int i=0, j=0; i < outputByteArray.length; i+= 2, j++){
if(swap){
outputArray[j] = swapBytes(outputByteArray[i], outputByteArray[i + 1]);
}
else{
outputArray[j] = swapBytes(outputByteArray[i + 1], outputByteArray[i]);
}
}
return outputArray;
}
public void completeStreams(List<Short> mListShort_1, List<Short> mListShort_2) {
//TODO: check length
int size_a = mListShort_1.size();
int size_b = mListShort_2.size();
if (size_a > size_b){
// adding series of '0'
for (int i = size_b+1; i <= size_a; i++) {
mListShort_2.set(i, (short) 0);
}
} else if (size_a < size_b) {
for (int i = size_a+1; i <= size_b; i++) {
mListShort_1.set(i, (short) 0);
}
} else {
//do nothing
}
}
Credits: nalitzis
I have been trying to get a print of an Image but I have not been successful so far.The printer is a locally manufactured 2" thermal printer having a printing resolution of 8dots/mm, 384dots/line, 203 dpi. The printer is based of a board having the "NXP 2388 ARM v7 Microproc." having a Memory FLASH size of 512 KB, RAM: 128 KB & a Receive Buffer Size of 16KB.
I followed this question till now.
Problem: The image I tried printing is of 576x95 res.
The image got printed(with some error LED lighting up and debug buzzer noise :D) but the orientation of the image was vertical instead of getting horizontally printed; that too at the very left side of the page and the top part of the image was cut-off
Assuming here that I din't passed some of the flags(while making the "packet") compatible with the printer that I have.
I have not worked on bluetooth printing before so any help is appreciable :)
My Existing Main Activity:
public class MainActivity extends Activity
{
// will show the statuses
TextView myLabel;
// will enable user to enter any text to be printed
EditText myTextbox;
EditText devName;
public TableLayout tl2;
String devid;
String[] pName;
String[] LODQTY;
String[] rte;
String[] stk;
String[] oQty;
String[] oVal;
String[] fQty;
BitSet dots;
int mWidth;
int mHeight;
String mStatus;
String TAG = "TAG";
public String msg;
// android built in classes for bluetooth operations
BluetoothAdapter mBluetoothAdapter;
BluetoothSocket mmSocket;
BluetoothDevice mmDevice;
OutputStream mmOutputStream;
InputStream mmInputStream;
Thread workerThread;
byte[] readBuffer;
int readBufferPosition;
int counter;
volatile boolean stopWorker;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
devName = (EditText) findViewById(R.id.etdevice);
devName.setText("BTprinter0377");
String[] product_info = new String[6];
product_info[0] = "CPL400^10^1^0^4^0.4^0";
product_info[1] = "CPL400^10^1^0^4^0.4^0";
product_info[2] = "CPL400^10^1^0^4^0.4^0";
product_info[3] = "CPL400^10^1^0^4^0.4^0";
product_info[4] = "CPL400^10^1^0^4^0.4^0";
product_info[5] = "CPL400^10^1^0^4^0.4^0";
tl2 = (TableLayout) findViewById(R.id.dynSummary);
LayoutInflater inflater = getLayoutInflater();
for (int current = 0; current <= (product_info.length - 1); current++) {
final TableRow row = (TableRow)inflater.inflate(R.layout.table_summary_row, tl2 , false);
TextView tv1 = (TextView)row.findViewById(R.id.tvSkuName);
TextView tv2 = (TextView)row.findViewById(R.id.tvOrderQty);
TextView tv3 = (TextView)row.findViewById(R.id.tvFreeQty);
TextView tv4 = (TextView)row.findViewById(R.id.tvSampleQty);
TextView tv5 = (TextView)row.findViewById(R.id.tvTotalOrderKg);
TextView tv6 = (TextView)row.findViewById(R.id.tvTotalFreeKg);
TextView tv7 = (TextView)row.findViewById(R.id.tvTotalSampleKg);
StringTokenizer tokens = new StringTokenizer(String.valueOf(product_info[current]), "^");
//System.out.println("tokens.nextToken().trim()"+tokens.nextToken().trim());
tv1.setText(tokens.nextToken().trim());
tv2.setText(tokens.nextToken().trim());
tv3.setText(tokens.nextToken().trim());
tv4.setText(tokens.nextToken().trim());
tv5.setText(tokens.nextToken().trim());
tv6.setText(tokens.nextToken().trim());
tv7.setText(tokens.nextToken().trim());
tl2.addView(row);
}
try {
// we have three buttons for specific functions
Button openButton = (Button) findViewById(R.id.open);
Button sendButton = (Button) findViewById(R.id.send);
Button closeButton = (Button) findViewById(R.id.close);
myLabel = (TextView) findViewById(R.id.label);
// open bluetooth connection
openButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
devid = devName.getText().toString().trim();
try {
findBT();
openBT();
} catch (IOException ex) {
}
}
});
// send data typed by the user to be printed
sendButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
try {
sendData();
} catch (IOException ex) {
}
}
});
// close bluetooth connection
closeButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
try {
closeBT();
} catch (IOException ex) {
}
}
});
} catch (NullPointerException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
/*
* This will find a bluetooth printer device
*/
void findBT() {
try {
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter == null) {
myLabel.setText("No bluetooth adapter available");
}
if (!mBluetoothAdapter.isEnabled()) {
Intent enableBluetooth = new Intent(
BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBluetooth, 0);
}
Set<BluetoothDevice> pairedDevices = mBluetoothAdapter
.getBondedDevices();
if (pairedDevices.size() > 0) {
for (BluetoothDevice device : pairedDevices) {
System.out.println("device.getName(): "+device.getName().toString());
if (device.getName().equals("BTprinter0377")) {
mmDevice = device;
break;
}
}
}
myLabel.setText("Bluetooth Device Found");
} catch (NullPointerException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
/*
* Tries to open a connection to the bluetooth printer device
*/
void openBT() throws IOException {
try {
// Standard SerialPortService ID
UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb");
mmSocket = mmDevice.createRfcommSocketToServiceRecord(uuid);
mmSocket.connect();
mmOutputStream = mmSocket.getOutputStream();
mmInputStream = mmSocket.getInputStream();
beginListenForData();
myLabel.setText("Bluetooth Opened");
} catch (NullPointerException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
/*
* After opening a connection to bluetooth printer device,
* we have to listen and check if a data were sent to be printed.
*/
void beginListenForData() {
try {
final Handler handler = new Handler();
// This is the ASCII code for a newline character
final byte delimiter = 10;
stopWorker = false;
readBufferPosition = 0;
readBuffer = new byte[1024];
workerThread = new Thread(new Runnable() {
public void run() {
while (!Thread.currentThread().isInterrupted()
&& !stopWorker) {
try {
int bytesAvailable = mmInputStream.available();
if (bytesAvailable > 0) {
byte[] packetBytes = new byte[bytesAvailable];
mmInputStream.read(packetBytes);
for (int i = 0; i < bytesAvailable; i++) {
byte b = packetBytes[i];
if (b == delimiter) {
byte[] encodedBytes = new byte[readBufferPosition];
System.arraycopy(readBuffer, 0,
encodedBytes, 0,
encodedBytes.length);
final String data = new String(
encodedBytes, "US-ASCII");
readBufferPosition = 0;
handler.post(new Runnable() {
public void run() {
myLabel.setText(data);
}
});
} else {
readBuffer[readBufferPosition++] = b;
}
}
}
} catch (IOException ex) {
stopWorker = true;
}
}
}
});
workerThread.start();
} catch (NullPointerException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
/*
* This will send data to be printed by the bluetooth printer
*/
void sendData() throws IOException {
System.out.println("tl2.getChildCount(): "+tl2.getChildCount());
try {
print_image("/sdcard/tryimg.png");
String msg22;
msg22 = "\n";
msg22 += "PN Or Fr Sa TOKg TFKg TSKg";
msg22 += "\n";
//mmOutputStream.write(msg22.getBytes());
// tell the user data were sent
myLabel.setText("Data Sent");
} catch (NullPointerException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
/*
* Close the connection to bluetooth printer.
*/
void closeBT() throws IOException {
try {
stopWorker = true;
mmOutputStream.close();
mmInputStream.close();
mmSocket.close();
myLabel.setText("Bluetooth Closed");
} catch (NullPointerException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
public String convertBitmap(Bitmap inputBitmap) {
mWidth = inputBitmap.getWidth();
mHeight = inputBitmap.getHeight();
convertArgbToGrayscale(inputBitmap, mWidth, mHeight);
mStatus = "ok";
return mStatus;
}
private void convertArgbToGrayscale(Bitmap bmpOriginal, int width,
int height) {
int pixel;
int k = 0;
int B = 0, G = 0, R = 0;
dots = new BitSet();
try {
for (int x = 0; x < height; x++) {
for (int y = 0; y < width; y++) {
// get one pixel color
pixel = bmpOriginal.getPixel(y, x);
// retrieve color of all channels
R = Color.red(pixel);
G = Color.green(pixel);
B = Color.blue(pixel);
// take conversion up to one single value by calculating
// pixel intensity.
R = G = B = (int) (0.299 * R + 0.587 * G + 0.114 * B);
// set bit into bitset, by calculating the pixel's luma
if (R < 55) {
dots.set(k);//this is the bitset that i'm printing
}
k++;
}
}
} catch (Exception e) {
// TODO: handle exception
Log.e(TAG, e.toString());
}
}
private void print_image(String file) throws IOException {
File fl = new File(file);
if (fl.exists()) {
Bitmap bmp = BitmapFactory.decodeFile(file);
convertBitmap(bmp);
mmOutputStream.write(PrinterCommands.SET_LINE_SPACING_24);
int offset = 0;
while (offset < bmp.getHeight()) {
mmOutputStream.write(PrinterCommands.SELECT_BIT_IMAGE_MODE);
for (int x = 0; x < bmp.getWidth(); ++x) {
for (int k = 0; k < 3; ++k) {
byte slice = 0;
for (int b = 0; b < 8; ++b) {
int y = (((offset / 8) + k) * 8) + b;
int i = (y * bmp.getWidth()) + x;
boolean v = false;
if (i < dots.length()) {
v = dots.get(i);
}
slice |= (byte) ((v ? 1 : 0) << (7 - b));
}
mmOutputStream.write(slice);
}
}
offset += 24;
mmOutputStream.write(PrinterCommands.FEED_LINE);
mmOutputStream.write(PrinterCommands.FEED_LINE);
mmOutputStream.write(PrinterCommands.FEED_LINE);
mmOutputStream.write(PrinterCommands.FEED_LINE);
mmOutputStream.write(PrinterCommands.FEED_LINE);
mmOutputStream.write(PrinterCommands.FEED_LINE);
}
mmOutputStream.write(PrinterCommands.SET_LINE_SPACING_30);
} else {
Toast.makeText(this, "file doesn't exists", Toast.LENGTH_SHORT).show();
}
}
}
The PrinterCommands Class:
public class PrinterCommands {
public static final byte[] INIT = {27, 64};
public static byte[] FEED_LINE = {10};
public static byte[] SELECT_FONT_A = {27, 33, 0};
public static byte[] SET_BAR_CODE_HEIGHT = {29, 104, 100};
public static byte[] PRINT_BAR_CODE_1 = {29, 107, 2};
public static byte[] SEND_NULL_BYTE = {0x00};
public static byte[] SELECT_PRINT_SHEET = {0x1B, 0x63, 0x30, 0x02};
public static byte[] FEED_PAPER_AND_CUT = {0x1D, 0x56, 66, 0x00};
public static byte[] SELECT_CYRILLIC_CHARACTER_CODE_TABLE = {0x1B, 0x74, 0x11};
public static byte[] SELECT_BIT_IMAGE_MODE = {0x1B, 0x2A, 33, (byte) 255, 3};
//public static byte[] SELECT_BIT_IMAGE_MODE = {0x1B, 0x2A, 0x64, 0x63, 48, (byte) 255};
public static byte[] SET_LINE_SPACING_24 = {0x1B, 0x33, 24};
public static byte[] SET_LINE_SPACING_30 = {0x1B, 0x33, 30};
public static byte[] TRANSMIT_DLE_PRINTER_STATUS = {0x10, 0x04, 0x01};
public static byte[] TRANSMIT_DLE_OFFLINE_PRINTER_STATUS = {0x10, 0x04, 0x02};
public static byte[] TRANSMIT_DLE_ERROR_STATUS = {0x10, 0x04, 0x03};
public static byte[] TRANSMIT_DLE_ROLL_PAPER_SENSOR_STATUS = {0x10, 0x04, 0x04};
}
As mentioned in the dev manual of the printer(pdf):
Bit Map Image Print
1. Select the image either from PC or from mobile's SD card.
2. Convert the image into monochrome bmp.
3. Resize the image to fit into the printer paper area if it is exceeding
4. Now read the processed image through fileinputstream and save it into byte array.
5. Make the packet of image and then send it to printer over outputstream.
The required packet structure:
The packet fields chart:
Alignment table & other info:
private byte[] printbyte = {(byte)0x1B,(byte)0x2A,(byte)0x6F,(byte)0x63}
File file = new File(Environment.getExternalStorageDirectory + File.seprator()+"file_name");
FileInputStream fin = new FileInputStream(file);
byte imageContent[] = new byte[(int)file.length()];
fin.read(imageContent);
byte [] width = hexToBuffer(Integer.toHexString(your_width));
byte [] height = hexToBuffer(Integer.toHexString(your_height));
byte[] imageToPrint = new byte[printbyte.lenght()+imageContent.lenght()+width.lenght()+height.lenght()];
System.arraycopy(imagetoprint,0,printbyte,0,printbyte.lenght());
System.arraycopy(imagetoprint,printbyte.lenght(),width ,0,width.lenght());
System.arraycopy(imagetoprint,width.lenght(),height,0,height.lenght());
System.arraycopy(imagetoprint,height.lenght(),imageContent,0,imageContent.lenght());
mmOutputStream.write(imagetoprint);
Hex to Buffer method -
public static byte[] hexToBuffer(String hexString)
throws NumberFormatException {
int length = hexString.length();
byte[] buffer = new byte[(length + 1) / 2];
boolean evenByte = true;
byte nextByte = 0;
int bufferOffset = 0;
if ((length % 2) == 1) {
evenByte = false;
}
for (int i = 0; i < length; i++) {
char c = hexString.charAt(i);
int nibble; // A "nibble" is 4 bits: a decimal 0..15
if ((c >= '0') && (c <= '9')) {
nibble = c - '0';
} else if ((c >= 'A') && (c <= 'F')) {
nibble = c - 'A' + 0x0A;
} else if ((c >= 'a') && (c <= 'f')) {
nibble = c - 'a' + 0x0A;
} else {
throw new NumberFormatException("Invalid hex digit '" + c +
"'.");
}
if (evenByte) {
nextByte = (byte) (nibble << 4);
} else {
nextByte += (byte) nibble;
buffer[bufferOffset++] = nextByte;
}
evenByte = !evenByte;
}
return buffer;
}
I have a thermal printer with bluetooth and Usb connection, if your printer support ESC/POS command search for its commands on internet,
for print raster image you should send this:
[Name] Print raster bit image
[Format] ASCII GS v 0 m xL xH yL yH d1...dk
Hex 1D 76 30 m xL xH yL yH d1...dk
Decimal 29 118 48 m xL xH yL yH d1...dk
[Range] 0£ m£ 3, 48£ m £ 51
0£ xL£ 255
0£ xH£ 255
0£ yL£ 255
0£ d£ 255
k=(xL+ xH*256)*(yL+yH*256)
Follow your printer guidelines, it is may be different from others.
I am just implementing sphinx4 speech recognition in java. What I need is how to record sound or convert any sound .wave file into 16khz 16bit mono little-endian file.
had to search a lot for this..but no specific guidance I have got. hope anyone from the stack overflow family can help me out or give me proper guidance in that.
1).
I need to just record audio in android with the 16khz 16bit mono little-endian file format in a wave file
or
2).
I need to convert the prerecorded file with any sampling rate with the 16khz 16bit mono little-endian format in java.
I need to implement one of the above features..so can anyone help me out fr this...thanks in advance
with the first option, I had created wav file with the above-stated configuration with the following code in android.
package com.varma.samples.audiorecorder;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.widget.Button;
public class RecorderActivity extends Activity {
private static final int RECORDER_BPP =16;
private static final String AUDIO_RECORDER_FILE_EXT_WAV = ".wav";
private static final String AUDIO_RECORDER_FOLDER = "AudioRecorder";
private static final String AUDIO_RECORDER_TEMP_FILE = "record_temp.raw";
private static final int RECORDER_SAMPLERATE = 16000;
private static final int RECORDER_CHANNELS = AudioFormat.CHANNEL_CONFIGURATION_MONO;
private static final int RECORDER_AUDIO_ENCODING = AudioFormat.ENCODING_PCM_16BIT;
private AudioRecord recorder = null;
private int bufferSize = 0;
private Thread recordingThread = null;
private boolean isRecording = false;
#SuppressLint("NewApi")
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
setButtonHandlers();
enableButtons(false);
bufferSize = AudioRecord.getMinBufferSize(RECORDER_SAMPLERATE,RECORDER_CHANNELS,RECORDER_AUDIO_ENCODING);
}
private void setButtonHandlers() {
((Button)findViewById(R.id.btnStart)).setOnClickListener(btnClick);
((Button)findViewById(R.id.btnStop)).setOnClickListener(btnClick);
}
private void enableButton(int id,boolean isEnable){
((Button)findViewById(id)).setEnabled(isEnable);
}
private void enableButtons(boolean isRecording) {
enableButton(R.id.btnStart,!isRecording);
enableButton(R.id.btnStop,isRecording);
}
private String getFilename(){
String filepath = Environment.getExternalStorageDirectory().getPath();
File file = new File(filepath,AUDIO_RECORDER_FOLDER);
if(!file.exists()){
file.mkdirs();
}
return (file.getAbsolutePath() + "/" + System.currentTimeMillis() + AUDIO_RECORDER_FILE_EXT_WAV);
}
private String getTempFilename(){
String filepath = Environment.getExternalStorageDirectory().getPath();
File file = new File(filepath,AUDIO_RECORDER_FOLDER);
if(!file.exists()){
file.mkdirs();
}
File tempFile = new File(filepath,AUDIO_RECORDER_TEMP_FILE);
if(tempFile.exists())
tempFile.delete();
return (file.getAbsolutePath() + "/" + AUDIO_RECORDER_TEMP_FILE);
}
#SuppressLint({ "NewApi", "NewApi" })
private void startRecording(){
recorder = new AudioRecord(MediaRecorder.AudioSource.MIC,
RECORDER_SAMPLERATE, RECORDER_CHANNELS,RECORDER_AUDIO_ENCODING, bufferSize);
recorder.startRecording();
isRecording = true;
recordingThread = new Thread(new Runnable() {
#Override
public void run() {
writeAudioDataToFile();
}
},"AudioRecorder Thread");
recordingThread.start();
}
#SuppressLint({ "NewApi", "NewApi", "NewApi" })
private void writeAudioDataToFile(){
byte data[] = new byte[bufferSize];
String filename = getTempFilename();
FileOutputStream os = null;
try {
os = new FileOutputStream(filename);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
int read = 0;
if(null != os){
while(isRecording){
read = recorder.read(data, 0, bufferSize);
if(AudioRecord.ERROR_INVALID_OPERATION != read){
try {
os.write(data);
} catch (IOException e) {
e.printStackTrace();
}
}
}
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
#SuppressLint({ "NewApi", "NewApi" })
private void stopRecording(){
if(null != recorder){
isRecording = false;
recorder.stop();
recorder.release();
recorder = null;
recordingThread = null;
}
copyWaveFile(getTempFilename(),getFilename());
deleteTempFile();
}
private void deleteTempFile() {
File file = new File(getTempFilename());
file.delete();
}
private void copyWaveFile(String inFilename,String outFilename){
FileInputStream in = null;
FileOutputStream out = null;
long totalAudioLen = 0;
long totalDataLen = totalAudioLen + 36;
long longSampleRate = 16000;
int channels = 1;
//long byteRate = RECORDER_BPP * RECORDER_SAMPLERATE * channels/8;
long byteRate = 256;
byte[] data = new byte[bufferSize];
try {
in = new FileInputStream(inFilename);
out = new FileOutputStream(outFilename);
totalAudioLen = in.getChannel().size();
totalDataLen = totalAudioLen + 36;
AppLog.logString("File size: " + totalDataLen);
WriteWaveFileHeader(out, totalAudioLen, totalDataLen,
longSampleRate, channels, byteRate);
while(in.read(data) != -1){
out.write(data);
}
in.close();
out.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private void WriteWaveFileHeader(
FileOutputStream out, long totalAudioLen,
long totalDataLen, long longSampleRate, int channels,
long byteRate) throws IOException {
byte[] header = new byte[44];
header[0] = 'R'; // RIFF/WAVE header
header[1] = 'I';
header[2] = 'F';
header[3] = 'F';
header[4] = (byte) (totalDataLen & 0xff);
header[5] = (byte) ((totalDataLen >> 8) & 0xff);
header[6] = (byte) ((totalDataLen >> 16) & 0xff);
header[7] = (byte) ((totalDataLen >> 24) & 0xff);
header[8] = 'W';
header[9] = 'A';
header[10] = 'V';
header[11] = 'E';
header[12] = 'f'; // 'fmt ' chunk
header[13] = 'm';
header[14] = 't';
header[15] = ' ';
header[16] = 16; // 4 bytes: size of 'fmt ' chunk
header[17] = 0;
header[18] = 0;
header[19] = 0;
header[20] = 1; // format = 1
header[21] = 0;
header[22] = (byte) channels;
header[23] = 0;
header[24] = (byte) (longSampleRate & 0xff);
header[25] = (byte) ((longSampleRate >> 8) & 0xff);
header[26] = (byte) ((longSampleRate >> 16) & 0xff);
header[27] = (byte) ((longSampleRate >> 24) & 0xff);
header[28] = (byte) (byteRate & 0xff);
header[29] = (byte) ((byteRate >> 8) & 0xff);
header[30] = (byte) ((byteRate >> 16) & 0xff);
header[31] = (byte) ((byteRate >> 24) & 0xff);
header[32] = (byte) (2 * 16 / 8); // block align
header[33] = 0;
header[34] = RECORDER_BPP; // bits per sample
header[35] = 0;
header[36] = 'd';
header[37] = 'a';
header[38] = 't';
header[39] = 'a';
header[40] = (byte) (totalAudioLen & 0xff);
header[41] = (byte) ((totalAudioLen >> 8) & 0xff);
header[42] = (byte) ((totalAudioLen >> 16) & 0xff);
header[43] = (byte) ((totalAudioLen >> 24) & 0xff);
out.write(header, 0, 44);
}
private View.OnClickListener btnClick = new View.OnClickListener() {
#Override
public void onClick(View v) {
switch(v.getId()){
case R.id.btnStart:{
AppLog.logString("Start Recording");
enableButtons(true);
startRecording();
break;
}
case R.id.btnStop:{
AppLog.logString("Start Recording");
enableButtons(false);
stopRecording();
break;
}
}
}
};
}