Recording pcm file and playing it through Audiotrack crashing - java

i am recording a pcm file thorugh AudioRecorder and create a file in sdcard. when recording is done i play the same file with Audiotrack but it crash. in logcat it says "Invalid audio buffer size". also my file size on sdcard is 0.0kb ,which i didn't understand why. here is the code. `
public void startRecord() {
File file = new File(Environment.getExternalStorageDirectory(),
"test.pcm");
int sampleFreq = 11025;
try {
file.createNewFile();
OutputStream outputStream = new FileOutputStream(file);
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(
outputStream);
DataOutputStream dataOutputStream = new DataOutputStream(
bufferedOutputStream);
int minBufferSize = AudioRecord.getMinBufferSize(sampleFreq,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT);
short[] audioData = new short[minBufferSize];
AudioRecord audioRecord = new AudioRecord(
MediaRecorder.AudioSource.MIC, sampleFreq,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT, minBufferSize);
audioRecord.startRecording();
while (recording) {
int numberOfShort = audioRecord.read(audioData, 0,
minBufferSize);
for (int i = 0; i < numberOfShort; i++) {
dataOutputStream.writeShort(audioData[i]);
}
}
audioRecord.stop();
dataOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public void PLaying(int explosion) {
File file = new File(Environment.getExternalStorageDirectory(),
"test.pcm");
int shortSizeInBytes = Short.SIZE / Byte.SIZE;
int bufferSizeInBytes = (int) (file.length() / shortSizeInBytes);
short[] audioData = new short[bufferSizeInBytes];
try {
InputStream inputStream = new FileInputStream(file);
BufferedInputStream bufferedInputStream = new BufferedInputStream(
inputStream);
DataInputStream dataInputStream = new DataInputStream(
bufferedInputStream);
int i = 0;
while (dataInputStream.available() > 0) {
audioData[i] = dataInputStream.readShort();
i++;
}
dataInputStream.close();
int sampleFreq = explosion;
AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
sampleFreq, AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT, bufferSizeInBytes,
AudioTrack.MODE_STREAM);
audioTrack.play();
audioTrack.write(audioData, 0, bufferSizeInBytes);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
`

Do You have integrated the stop method? Please Show us a Little bit more code. The Problem is, if You haven´t implemented a correct stop mehtod, it will Loop forever..Have You done something like this:
yourStopButton.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View view){
recording=false;
}
});
And then, don´t Forget to do the same in onStart and set recording to true.

This code looks dodgy
while (recording) {
int numberOfShort = audioRecord.read(audioData, 0,
minBufferSize);
for (int i = 0; i < numberOfShort; i++) {
dataOutputStream.writeShort(audioData[i]);
}
}
What is the value of recording. Where does the value change. If it does not change it will be an endless loop (unless and exception is thrown).

Divide the minimum buffer size by 2 when constructing the AudioRecord instance

Related

Android - Audio Clipping when recording audio (crest/peak clipping and periodic 0 bit values in between)

I am trying to record an audio stream via a Bluetooth device. I am using Bluetooth SCO for getting Bluetooth audio and AudioRecord class to record audio.
I am recording RAW .PCM files with MONO Channel with a sampling rate of 16000
I am calculating BufferSize like this
private static final int BUFFER_SIZE_FACTOR = 2;
private static final int BUFFER_SIZE = AudioRecord.getMinBufferSize(SAMPLING_RATE_IN_HZ,CHANNEL_CONFIG, AUDIO_FORMAT) * BUFFER_SIZE_FACTOR;
This is how I am getting/writing audio currently,
private class RecordingRunnable implements Runnable {
#Override
public void run() {
setFileNameAndPath();
final ByteBuffer buffer = ByteBuffer.allocateDirect(BUFFER_SIZE);
try (final FileOutputStream outStream = new FileOutputStream(mFilePath)) {
while (recordingInProgress.get()) {
int result = recorder.read(buffer, BUFFER_SIZE);
if (result < 0) {
throw new RuntimeException("Reading of audio buffer failed: " +
getBufferReadFailureReason(result));
}
outStream.write(buffer.array(), 0, BUFFER_SIZE);
buffer.clear();
}
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException("Writing of recorded audio failed", e);
}
}
I did a little research and found that the clipping effect could be because of the wrong Byte order (LITTLE_ENDIAN or BIG_ENDIAN) or Because of poor multithreading. However in this current implementation, I am not able to understand how bytes are being ordered and saved & what can I do to fix the clipping/noise problem.
I am starting my recorder runnable like this
recordingThread = new Thread(new RecordingRunnable(), "Recording Thread");
recordingThread.start();
recordingThread.setPriority(Thread.MAX_PRIORITY);
I got same issue and I resolved this problem with below code.
private byte[] short2byte(short[] sData, int size) {
int shortArrsize = size;
byte[] bytes = new byte[shortArrsize * 2];
for (int i = 0; i < shortArrsize; i++) {
bytes[i * 2] = (byte) (sData[i] & 0x00FF);
bytes[(i * 2) + 1] = (byte) (sData[i] >> 8);
sData[i] = 0;
}
return bytes;
}
......
int bufferSize = AudioRecord.getMinBufferSize(48000, AudioFormat.CHANNEL_IN_STEREO, AudioFormat.ENCODING_PCM_16BIT);
short[] buffer = new short[bufferSize];
int source = MediaRecorder.AudioSource.VOICE_RECOGNITION;
mAudioRecorder = new AudioRecord(source, 48000,
AudioFormat.CHANNEL_IN_STEREO, AudioFormat.ENCODING_PCM_16BIT, bufferSize);
int state = mAudioRecorder.getState();
if (state != AudioRecord.STATE_INITIALIZED) {
Log.e(TAG, "Can not support");
return;
}
mAudioRecorder.startRecording();
while (mIsRecording) {
int bufferReadResult = mAudioRecorder.read(buffer, 0, bufferSize);
if (bufferReadResult < 0) {
continue;
}
try {
byte data[] = short2byte(buffer, bufferReadResult);
fos.write(data, 0, bufferReadResult * 2);
} catch (IOException e) {
e.printStackTrace();
}
}

AudioSystem Write, AudioInputStream from modified bytes obtained from InputStream, Java

I obtaining bytes from InputStream, but I need to modify and save them to Wav File.
Here my code:
Socket Sending Audio Obtained from Microphone.
AudioFormat adfmt = new AudioFormat(8000.0f, 8, 1, true , true);
int bufferSize = (int) adfmt.getSampleRate()* adfmt.getFrameSize();
byte[] buffer = new byte[bufferSize];
Socket clientSocketO = new Socket(...);
OutputStream output = clientSocketO.getOutputStream();
DataLine.Info dlInfo = new DataLine.Info(TargetDataLine.class, adfmt);
TargetDataLine tdLine = (TargetDataLine) AudioSystem.getLine(dlInfo);
tdLine.open(adfmt);
tdLine.start(); // start capturing
boolean bRunningO = true;
while (bRunningO) {
int count = tdLine.read(buffer, 0, buffer.length);
if (count > 0) {
byte[] outgoingBytes = Arrays.copyOf(buffer, count);
output.write(outgoingBytes);
}
}
tdLine.flush();
In the Other Side Socket receiving bytes :
AudioFormat adfmt = new AudioFormat(8000.0f, 8, 1, true , true);
int bufferSize = (int) adfmt.getSampleRate()* adfmt.getFrameSize();
byte[] buffer = new byte[bufferSize];
Socket clientSocketI = new Socket(...);
InputStream input = clientSocketI.getInputStream();
String fileName = System.getProperty("file.separator") + "SomeFile.wav"
File fileStreamedWav = new File((new File("")).getAbsolutePath() + fileName);
AudioInputStream ais;
ByteArrayInputStream bis;
DataLine.Info dlInfo = new DataLine.Info(SourceDataLine.class, adfmt);
//SourceDataLine sdLine = (SourceDataLine) AudioSystem.getLine(dlInfo);
//sdLine.open(adfmt);
//sdLine.start(); // start playback
AudioFileFormat.Type afType = AudioFileFormat.Type.WAVE;
boolean bRunningI = true;
while (bRunningI) {
try {
int read = input.read(buffer); //Socket Reading bytes
byte[] incomingBytes;
if (read > 0) {
incomingBytes = Arrays.copyOf(buffer, read);
if (incomingBytes!= null) {
//sdLine.write(incomingBytes, 0, incomingBytes.length);
//Same Size bytes, but isn't necessary submit the put Code
byte[] changedBytes = MethodChangerBytes(incomingBytes);
bis = new ByteArrayInputStream(changedBytes);
ais = new AudioInputStream(bis, adfmt,
changedBytes.length/adfmt.getFrameSize());
int W = AudioSystem.write(ais, afType, fileStreamedWav);
System.out.println("AudioSystem.write:" + W);
}
}
} catch (IOException e) {
bRunningI = false;
}
}
Here the code modifier of Bytes, for Now assume amplify by two...
byte[] MethodChangerBytes(byte[] incoming) {
byte[] outgoing = new byte[incoming.length];
for (int i = 0; i < incoming.length; i ++) {
// Really is not important what happens here
double Sample = (double)(short)(((incoming[i] - 128) & 0xFF) << 8);
Sample *= 2.0;
outgoing[i] = (byte)(((int()Sample >> 8) + 128) & 0xFF);
}
return outgoing;
}
When sdLine is uncommented then I can here all sound transmitted.
AudioInputStream(InputStream stream, AudioFormat format, long length)
AudioSystem.write(AudioInputStream stream, AudioFileFormat.Type fileType, File out)
The problem:
This code Only Save the Last Bytes obtained from MethodChangerBytes.
Question:
How Save all bytes processed Wav bytes until Socket connection is closed?
Thank you
Have a buffer:
ByteArrayOutputStream outputStream=new ByteArrayOutputStream();
write to this buffer then move the writing outside the loop; when all bytes are read save:
boolean bRunningI = true;
try {
while (bRunningI) {
int read = input.read(buffer); //Socket Reading bytes
byte[] incomingBytes;
if (read > 0) {
incomingBytes = Arrays.copyOf(buffer, read);
if (incomingBytes!= null) {
//sdLine.write(incomingBytes, 0, incomingBytes.length);
//Same Size bytes, but isn't necessary submit the put Code
byte[] changedBytes = MethodChangerBytes(incomingBytes);
outputStream.write(changedBytes, 0, changedBytes.length);
}
}
}
byte[] allBytes=outputStream.toByteArray();
bis = new ByteArrayInputStream(allBytes);
ais = new AudioInputStream(bis, adfmt,
changedBytes.length/adfmt.getFrameSize());
int W = AudioSystem.write(ais, afType, fileStreamedWav);
System.out.println("AudioSystem.write:" + W);
} catch (IOException e) {
bRunningI = false;
}

How to implement a high-pass filter for an audio signal?

I am trying to do a music identification application like shazam. This is an android app. First i have captured an audio signal through the MIC. Next I have implemented the hanning window function and FFT to the audio signal as shown as following code :
private class RecordAudio extends AsyncTask<Void, double[], Void> {
#Override
protected Void doInBackground(Void... params) {
started = true;
try {
DataOutputStream dos = new DataOutputStream(
new BufferedOutputStream(new FileOutputStream(
recordingFile)));
int bufferSize = AudioRecord.getMinBufferSize(frequency,
channelConfiguration, audioEncoding);
audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,
frequency, channelConfiguration, audioEncoding,
bufferSize);
short[] buffer = new short[blockSize];
double[] toTransform = new double[blockSize];
long t = System.currentTimeMillis();
long end = t + 15000;
audioRecord.startRecording();
while (started) {
//System.currentTimeMillis() < end
int bufferReadResult = audioRecord.read(buffer, 0,
blockSize);
for (int i = 0; i < blockSize && i < bufferReadResult; i++) {
toTransform[i] = (double) buffer[i] / 32768.0;
dos.writeShort(buffer[i]);
}
toTransform = hann(toTransform);
transformer.ft(toTransform);
publishProgress(toTransform);
}
audioRecord.stop();
dos.close();
} catch (Throwable t) {
Log.e("AudioRecord", "Recording Failed");
}
return null;
}
Now my question is how do I need to apply high pass filter to my audio signal. Is there any API for this ??
Please some one help me to do this function.
Code modification part
private class RecordAudio extends AsyncTask<Void, double[], Void> {
#Override
protected Void doInBackground(Void... params) {
started = true;
try {
DataOutputStream dos = new DataOutputStream(
new BufferedOutputStream(new FileOutputStream(
recordingFile)));
int bufferSize = AudioRecord.getMinBufferSize(sampleRate,
channelConfiguration, audioEncoding);
audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,
sampleRate, channelConfiguration, audioEncoding,
bufferSize);
short[] buffer = new short[blockSize];
double[] toTransform = new double[blockSize];
long t = System.currentTimeMillis();
long end = t + 15000;
audioRecord.startRecording();
while (started) {
//System.currentTimeMillis() < end
int bufferReadResult = audioRecord.read(buffer, 0,
blockSize);
for (int i = 0; i < blockSize && i < bufferReadResult; i++) {
toTransform[i] = (double) buffer[i] / 32768.0;
dos.writeShort(buffer[i]);
}
toTransform = hann(toTransform);
transformer.ft(toTransform);
publishProgress(toTransform);
//new part
//sample rate = 8000
highPassFilter(toTransform, sampleRate);
}
audioRecord.stop();
dos.close();
} catch (Throwable t) {
Log.e("AudioRecord", "Recording Failed");
}
return null;
}
Here is my high pass filter method:
public void highPassFilter(double []frequency, int samplerate){
double [] f = new double[frequency.length];
for (int n=1; n<frequency.length; n++){
f[n] = (double)frequency[n]/samplerate;
double x = (double)Math.exp(-2 * Math.PI * f[n]);
double []a = new double[] { (1+x)/2, -(1+x)/2 };
double []b = new double[] { x };
}
}
Thanks !!
I think the signal processing could be done in the native level(C,C++) libs only You may try
this (TarsosDSP)
If the above doesn't help then try this SO Answer.

Recording sound of music app [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I am developing android musical piano application. in which i am using soundpool to play audios but how can i record sound so that user can sing and record his own voice along with recording music beats
Here are wo functions one for recording and other for playing
private void startRecord(){
File file = new File(Environment.getExternalStorageDirectory(), "test.pcm");
try {
file.createNewFile();
recording=true;
OutputStream outputStream = new FileOutputStream(file);
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream);
DataOutputStream dataOutputStream = new DataOutputStream(bufferedOutputStream);
int minBufferSize = AudioRecord.getMinBufferSize(SmpleRate,
AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT);
short[] audioData = new short[minBufferSize];
AudioRecord audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,
SmpleRate,
AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT,
minBufferSize);
AudioManager audio=(AudioManager)this.getSystemService(Context.AUDIO_SERVICE);
audio.setMicrophoneMute(true);
//int sessionId=audioRecord.getAudioSessionId();
// NoiseSuppressor.create(sessionId);
audioRecord.startRecording();
while(recording){
int numberOfShort = audioRecord.read(audioData, 0, minBufferSize);
for(int i = 0; i < numberOfShort; i++){
dataOutputStream.writeShort(audioData[i]);
}
}
audioRecord.stop();
dataOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
void playRecord(){
File file = new File(Environment.getExternalStorageDirectory(), "test.pcm");
int shortSizeInBytes = Short.SIZE/Byte.SIZE;
int bufferSizeInBytes = (int)(file.length()/shortSizeInBytes);
short[] audioData = new short[bufferSizeInBytes];
try {
InputStream inputStream = new FileInputStream(file);
BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
DataInputStream dataInputStream = new DataInputStream(bufferedInputStream);
int i = 0;
while(dataInputStream.available() > 0){
audioData[i] = dataInputStream.readShort();
i++;
}
dataInputStream.close();
AudioTrack audioTrack = new AudioTrack(
AudioManager.STREAM_MUSIC,
SmpleRate,
AudioFormat.CHANNEL_OUT_MONO,
AudioFormat.ENCODING_PCM_16BIT,
bufferSizeInBytes,
AudioTrack.MODE_STREAM);
audioTrack.play();
audioTrack.write(audioData, 0, bufferSizeInBytes);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}

Decode mp3 to pcm, and play with audiotrack in Google Android

First of all, if not using function decode_path , I can play .wav file with my code , and it works fine I use Jlayer and audio track to play the song.
Second, if I use function decode_path it can decode mp3 to pcm file , and pass the byte[] to function PlayAudioTrack, and let it play.
The quesion is,I don't know where my code is wrong , I use 320Kbps, 44.1Khz stereo type, Layer3 mp3, but the AudioTrack plays noise but no music~!!!!
can anyone ?
???
My code
public void PlayAudioTrack(String filePath) throws IOException{
int intSize = android.media.AudioTrack.getMinBufferSize(44100, AudioFormat.CHANNEL_CONFIGURATION_STEREO,
AudioFormat.ENCODING_PCM_16BIT);
AudioTrack at = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_CONFIGURATION_STEREO,
AudioFormat.ENCODING_PCM_16BIT, intSize, AudioTrack.MODE_STREAM);
//Reading the file..
int count = 512 * 1024; // 512 kb
// byte[] byteData = null;
// byteData = new byte[(int)count];
//we can decode correct byte data here
byte[] byteData = null;
byteData = decode_path(filePath, 0, 20000);
File file = null;
file = new File(filePath);
FileInputStream in = null;
try {
in = new FileInputStream( file );
} catch (FileNotFoundException e) {
e.printStackTrace();
}
int bytesread = 0, ret = 0;
int size = (int) file.length();
at.play();
while (bytesread < size) {
Log.e("devon","write byte array with sizes");
ret = in.read( byteData,0, count);
if (ret != -1) {
Log.e("devon","Write the byte array to the track");
at.write(byteData,0, ret);
bytesread += ret;
}else break;
}
at.stop();
at.release();
}
public static byte[] decode_path(String path, int startMs, int maxMs)
throws IOException{
ByteArrayOutputStream outStream = new ByteArrayOutputStream(1024);
float totalMs = 0;
boolean seeking = true;
File file = new File(path);
InputStream inputStream = new BufferedInputStream(new FileInputStream(file), 8 * 1024);
try {
Bitstream bitstream = new Bitstream(inputStream);
Decoder decoder = new Decoder();
boolean done = false;
while (! done) {
Header frameHeader = bitstream.readFrame();
if (frameHeader == null) {
done = true;
} else {
totalMs += frameHeader.ms_per_frame();
if (totalMs >= startMs) {
seeking = false;
}
if (! seeking) {
SampleBuffer output = (SampleBuffer) decoder.decodeFrame(frameHeader, bitstream);
if (output.getSampleFrequency() != 44100
|| output.getChannelCount() != 2) {
throw new IllegalArgumentException("mono or non-44100 MP3 not supported");
}
short[] pcm = output.getBuffer();
for (short s : pcm) {
outStream.write(s & 0xff);
outStream.write((s >> 8 ) & 0xff);
}
}
if (totalMs >= (startMs + maxMs)) {
done = true;
}
}
bitstream.closeFrame();
}
return outStream.toByteArray();
} catch (BitstreamException e) {
throw new IOException("Bitstream error: " + e);
} catch (DecoderException e) {
Log.w(TAG, "Decoder error", e);
throw new IOException("Decoder error: " + e);
}
}
public void PlayAudioTrack(String filePath) throws IOException{
int intSize = android.media.AudioTrack.getMinBufferSize(44100, AudioFormat.CHANNEL_CONFIGURATION_STEREO,
AudioFormat.ENCODING_PCM_16BIT);
AudioTrack at = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_CONFIGURATION_STEREO,
AudioFormat.ENCODING_PCM_16BIT, intSize, AudioTrack.MODE_STREAM);
//Reading the file..
int count = 512 * 1024; // 512 kb
// byte[] byteData = null;
// byteData = new byte[(int)count];
//we can decode correct byte data here
byte[] byteData = null;
byteData = decode_path(filePath, 0, 20000);
int temp =0;
at.play();
while (temp<byteData.length)
{
at.write(byteData, temp, count);
temp+= count;
}
at.stop();
at.release();
}

Categories

Resources