android play sound with AudioTrack - android

hello I have this code
AudioTrack audioTrack;
public void playAccordeon() {
int minBufferSize = AudioTrack.getMinBufferSize(44100,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT);
int bufferSize = 512;
if (audioTrack == null) {
audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, 44100,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT, minBufferSize,
AudioTrack.MODE_STREAM);
audioTrack.play();
}
int i = 0;
byte[] s = new byte[bufferSize];
try {
InputStream fin = getResources().openRawResource(R.raw.accordeon);
while ((i = fin.read(s)) != -1) {
audioTrack.write(s, 0, i);
}
fin.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
its works but there is one problem, when I play sound first time it plays fine, but second and third.. play have sound like "click" (I tried many sound files)
what to do? thanks

Related

Choppy audio playback with AudioTrack.write

I am using AudioTrack library to play pcm samples that are being streamed via wifi. The problem is the playback is very choppy while playing on Lenovo K900 (4.1.2), whereas it is seamless while playing on OnePlusOne (Marshmallow 6.0.1 cyanogen) handset.
To rule out streaming delay I first loaded the entire stream in an array then played the audio by looping over the pre-populated array. Still things do not improve at all.
Now K900 is running Android 4.1.2 whereas the android sdk I used is for API23, I mean when I open the definition of AudioTrack class it open the class file of API23. Is it causing any problem?
int bufferSize = AudioTrack.getMinBufferSize(SAMPLE_RATE, AudioFormat.CHANNEL_OUT_MONO,
AudioFormat.ENCODING_PCM_8BIT);
if (bufferSize == AudioTrack.ERROR || bufferSize == AudioTrack.ERROR_BAD_VALUE) {
bufferSize = SAMPLE_RATE * 2;
}
int readBytes;
int bufSize=2123880;//size of the file being streamed
byte[] buffer=new byte[bufSize];
//bufferSize*=2;
DataInputStream in = new DataInputStream(socket.getInputStream());
readBytes=0;
while(true) {
try {
if(in.available()>0){
readBytes+=in.read(buffer, readBytes, in.available());
// audioTrack.write(buffer,0,readBytes);
}else{
break;
}
} catch (SocketTimeoutException s) {
System.out.println("Socket timed out!");
//audioTrack.release();
break;
} catch (IOException e) {
e.printStackTrace();
//audioTrack.release();
break;
}
}
in.close();
readBytes=0;
AudioTrack audioTrack = new AudioTrack(
AudioManager.STREAM_MUSIC,
SAMPLE_RATE,
AudioFormat.CHANNEL_OUT_MONO,
AudioFormat.ENCODING_PCM_8BIT,
bufferSize,
AudioTrack.MODE_STREAM);
audioTrack.play();
while(readBytes<bufSize){
readBytes+=audioTrack.write(buffer,readBytes,bufferSize);
}
audioTrack.release();
I tested with samples having different sampling rate ranging from 19250hz to 44100hz. For all cases K900 strong text is playing choppy whereas Oneplus one plays smooth. I dont think that K900 is underpowered to pull up this easy job.
Kindly assist.
EDIT
Here is the code I intend to use:
try {
//dataInputStream = new DataInputStream(socket.getInputStream());
//response = dataInputStream.readUTF();
int bufferSize = AudioTrack.getMinBufferSize(SAMPLE_RATE, AudioFormat.CHANNEL_OUT_MONO,
AudioFormat.ENCODING_PCM_8BIT);
if (bufferSize == AudioTrack.ERROR || bufferSize == AudioTrack.ERROR_BAD_VALUE) {
bufferSize = SAMPLE_RATE * 2;
}
int readBytes;
byte[] buffer = new byte[bufferSize];
bufferSize = bufferSize * 2;
AudioTrack audioTrack = new AudioTrack(
AudioManager.STREAM_MUSIC,
SAMPLE_RATE,
AudioFormat.CHANNEL_OUT_STEREO,
AudioFormat.ENCODING_PCM_8BIT,
bufferSize,
AudioTrack.MODE_STREAM);
audioTrack.play();
DataInputStream in = new DataInputStream(socket.getInputStream());
while (true) {
try {
if (in.available() > 0) {
readBytes = in.read(buffer, 0, buffer.length);
audioTrack.write(buffer, 0, readBytes);
}
} catch (SocketTimeoutException s) {
System.out.println("Socket timed out!");
audioTrack.release();
in.close();
socket.close();
break;
} catch (IOException e) {
e.printStackTrace();
audioTrack.release();
in.close();
socket.close();
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
Thanks,
Debojit

AudioTrack is not playing audio file properly as it is making noise instead

I have recorded user's voice successfully using mediaplayer and the file is stored in sd card.
now i want to play that voice using audio track. But when I do it is making noise.
Y so.?
Here is the code to play sound..
private void PlayAudioFileViaAudioTrack(String filePath) throws IOException
{
// We keep temporarily filePath globally as we have only two sample sounds now..
if (filePath==null)
return;
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);
if (at==null){
Log.d("TCAudio", "audio track is not initialised ");
return;
}
int count = 512 * 1024; // 512 kb
//Reading the file..
byte[] byteData = null;
File file = null;
file = new File(filePath);
byteData = new byte[(int)count];
FileInputStream in = null;
try {
in = new FileInputStream( file );
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
int bytesread = 0, ret = 0;
int size = (int) file.length();
at.play();
while (bytesread < size) { ret = in.read( byteData,0, count); if (ret != -1) { // Write the byte array to the track
at.write(byteData,0, ret); bytesread += ret; } else break; } in.close(); at.stop(); at.release(); }
Noise could be due to a small buffer.
Try:
int intSize = android.media.AudioTrack.getMinBufferSize(44100,
AudioFormat.CHANNEL_CONFIGURATION_STEREO,
AudioFormat.ENCODING_PCM_16BIT);
init *= 2;
If you work with exactly the minimum buffer size, it might result in noisy sound. Having twice the minimum size is a good practice (in my experience).
I have just resolve this by adding buffer size and check this code this will resolve your problem.
void playRecord(int position) {
if (position==0){
m=8000;
String folder_main = "MyVoiceChanger";
File filee = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + folder_main + "/Recording.mp3");
int shortSizeInBytes = Short.SIZE / Byte.SIZE;
int bufferSizeInBytes = (int) (filee.length() / shortSizeInBytes);
short[] audioData = new short[bufferSizeInBytes];
try {
InputStream inputStream = new FileInputStream(filee);
BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
DataInputStream dataInputStream = new DataInputStream(bufferedInputStream);
int i = 0;
while (dataInputStream.available() > 0) {
try {
audioData[i] = dataInputStream.readShort();
i++;
}catch (EOFException e){
e.printStackTrace();
}
}
dataInputStream.close();
try {
bufferSizeInBytes = AudioTrack.getMinBufferSize(
m,
RECORDER_CHANNELS,
RECORDER_AUDIO_ENCODING
);
audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,44100, AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT, bufferSizeInBytes, AudioTrack.MODE_STREAM);
Log.i("Buffer", "playRecord: "+bufferSizeInBytes);
final int finalBufferSizeInBytes = bufferSizeInBytes;
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
audioTrack = new AudioTrack(3, m, 2, 2, finalBufferSizeInBytes, 1);
try {
audioTrack.play();
Log.i("Usman", "Audio "+audioTrack);
}catch (Exception e){
e.printStackTrace();
}
}
});
}catch (Exception e){
e.printStackTrace();
}
mediaPlayer.prepareAsync();
audioTrack.write(audioData, 0, bufferSizeInBytes);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}

Playing a wav file in Android using AudioTrack: noisy sound

To produce sound on Android, I am using AudioTrack.
I have been able to produce sine waves, sawtooth waves, square waves but it would be nice to have a more realistic sound.
I found that .wav files were the easiest to play on AudioTrack because they are basically just a sequence of bytes with a header.
So I have got my wav file in the res/raw folder and I tried playing it with this code :
public void writeWav(){
byte[] byteData = null;
InputStream is = getResources().openRawResource(R.raw.high);
byteData = new byte[mBufferSize];
try {
is.read(byteData);
is.close();
}
catch (FileNotFoundException e) {}
catch (IOException e) {}
mAudioTrack.write(byteData, 0, byteData.length);
}
But all I get is noise. I realize there are lots of questions about AudioTrack and wav files, but I couldn't find an answer to my noise problem.
Use this method to play sound using audioTrack. It works for me
public void playAudioTrack() {
int sampleFreq = 16000;
File file = new File("--filePath--");
int shortSizeInBytes = Short.SIZE / Byte.SIZE;
int minBufferSize = AudioTrack.getMinBufferSize(sampleFreq, AudioFormat.CHANNEL_OUT_MONO,
AudioFormat.ENCODING_PCM_16BIT);
int bufferSizeInBytes = (int)(file.length() / shortSizeInBytes);
final AudioTrack at = new AudioTrack(AudioManager.STREAM_MUSIC, sampleFreq,
AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, minBufferSize,
AudioTrack.MODE_STREAM);
int i = 0;
byte[] s = new byte[bufferSizeInBytes];
try {
final FileInputStream fin = new FileInputStream("--filePath--");
final DataInputStream dis = new DataInputStream(fin);
at.setNotificationMarkerPosition((int)(file.length() / 2));
at.play();
while ((i = dis.read(s, 0, bufferSizeInBytes)) > -1) {
at.write(s, 0, i);
}
} catch (FileNotFoundException e) {
} catch (IOException e) {
} catch (Exception e) {
}
}

Audio Record and play loopback buffer issue, Issue while writing the data into audiotrack

Here I am trying to do recording and playing a voice at a time, It is working fine for few seconds and force closing showing error at buffer writing to audiotrack(m_track.write(buffer, 0, BUF_SIZE);).
Please check the below code, and suggest whether I am initializing audio track object correctly.
int SAMPLE_RATE = 8000;
int BUF_SIZE = 1024;
byte[] buffer = new byte[BUF_SIZE];
function()
{
try
{
buffersize = AudioRecord
.getMinBufferSize(SAMPLE_RATE, AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT);
} catch (Throwable t) {
Log.e("Audio", "Buffer size failed");
}
if (buffersize <= BUF_SIZE) {
buffersize = BUF_SIZE;
}
try {
m_record = new AudioRecord(MediaRecorder.AudioSource.MIC,
SAMPLE_RATE, AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT, buffersize * 2);
m_track = new AudioTrack(AudioManager.STREAM_VOICE_CALL,
SAMPLE_RATE, AudioFormat.CHANNEL_OUT_MONO,
AudioFormat.ENCODING_PCM_16BIT, buffersize * 2,
AudioTrack.MODE_STREAM);
m_track.setPlaybackRate(SAMPLE_RATE);
} catch (Throwable t) {
Log.e("Audio", "Audio Failed");
}
m_record.startRecording();
m_track.play();
try {
m_thread = new Runnable() {
public void run() {
while (m_isRun) {
m_record.read(buffer, 0, BUF_SIZE);
m_track.write(buffer, 0, BUF_SIZE);
}
}
};
m_thread.run();
} catch (Exception e) {
Log.e("ERROR", "exception: " + e.getLocalizedMessage());
}
Log.i("D2Record", "loopback exit");
}
I'm not exactly familiar with the topic but I think you're having problems with buffer sizes. I'm leaving most of the code away and concentrate mainly on buffer handling.
int SAMPLE_RATE = 8000;
int BUF_SIZE = 1024;
int buffersize = AudioRecord
.getMinBufferSize(SAMPLE_RATE, AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT);
bufferSize = Math.Max(bufferSize, AudioTrack
.getMinBufferSize(SAMPLE_RATE, AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT);
bufferSize = Math.max(bufferSize, BUF_SIZE);
byte[] buffer = new byte[bufferSize];
m_record = new AudioRecord(MediaRecorder.AudioSource.MIC,
SAMPLE_RATE, AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT, bufferSize);
m_track = new AudioTrack(AudioManager.STREAM_VOICE_CALL,
SAMPLE_RATE, AudioFormat.CHANNEL_OUT_MONO,
AudioFormat.ENCODING_PCM_16BIT, bufferSize,
AudioTrack.MODE_STREAM);
m_track.setPlaybackRate(SAMPLE_RATE);
m_record.startRecording();
m_track.play();
while (m_isRun) {
// You should check 'read' for errors after read.
int read = m_record.read(buffer, 0, bufferSize);
// You should check 'wrote' for errors after write.
int wrote = m_track.write(buffer, 0, read);
}

Android AudioTrack playing .wav file, getting only white noise

When I play a file with the following code:
private void PlayAudioFileViaAudioTrack(int ResId) throws IOException {
int intSize = android.media.AudioTrack.getMinBufferSize(11025, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT);
AudioTrack at = new AudioTrack(AudioManager.STREAM_MUSIC, 11025, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, intSize,
AudioTrack.MODE_STREAM);
int count = 256 * 1024; // 256 kb
byte[] byteData = null;
byteData = new byte[(int) count];
InputStream in = null;
AssetFileDescriptor fd = null;
fd = mResources.openRawResourceFd(ResId);
in = mResources.openRawResource(ResId);
int bytesRead = 0, amount = 0;
int size = (int) fd.getLength();
at.play();
while (bytesRead < size) {
amount = in.read(byteData, 0, count);
if (amount != -1) {
at.write(byteData, 0, amount);
}
}
in.close();
at.stop();
at.release();
}
The only thing I hear is static, white noise. I've checked that my .wav file has the same properties (samplerate,bitrate). I don't have to much knowledge about raw audio data(PCM), so I was wondering if anyone could see what's wrong with my code.
from your code i can see that you just read data from the wav file and just import them to the AudioTrack. Wav files have a small header as you can see here https://ccrma.stanford.edu/courses/422/projects/WaveFormat/ So you have to skip the header and point your file descriptor at the right place where the actual audio data are.
Also when you playing an audio file and you are dealing with byte operations you should take care of the Endianess. Take a look here Using AudioTrack in Android to play a WAV file
Below my code (some checks and the WAV header skip are missing) that works in both Nexus One and Galaxy S with a wav file with frequency 8000Hz and 16 bit encoding.
public void playWav(){
int minBufferSize = AudioTrack.getMinBufferSize(8000, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT);
int bufferSize = 512;
AudioTrack at = new AudioTrack(AudioManager.STREAM_MUSIC, 8000, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, minBufferSize, AudioTrack.MODE_STREAM);
String filepath = Environment.getExternalStorageDirectory().getAbsolutePath();
int i = 0;
byte[] s = new byte[bufferSize];
try {
FileInputStream fin = new FileInputStream(filepath + "/REFERENCE.wav");
DataInputStream dis = new DataInputStream(fin);
at.play();
while((i = dis.read(s, 0, bufferSize)) > -1){
at.write(s, 0, i);
}
at.stop();
at.release();
dis.close();
fin.close();
} catch (FileNotFoundException e) {
// TODO
e.printStackTrace();
} catch (IOException e) {
// TODO
e.printStackTrace();
}
}
That looks WAY more complicated than what I did. I played sounds using this. I think .wav files would work just as well.
MediaPlayer mpPlayProgram = new MediaPlayer();
mpPlayProgram.setDataSource("/sdcard/file.mp3");
mpPlayProgram.prepare();
mpPlayProgram.start();
mpPlayProgram.release();
For static resources, it's even easier:
MediaPlayer mpStart = MediaPlayer.create(this, resID);
mpStart.start();
mpStart.release();
If you have saved file in wav format and want to play it using AudioTrack then follow this code:
File file=new File(Environment.getExternalStorageDirectory()+"/AudioRecorder/fahim.wav");
InputStream is;
DataInputStream dis = null ;
BufferedInputStream bis;
try
{
is = new FileInputStream(file);
bis = new BufferedInputStream(is, 8000);
dis = new DataInputStream(bis); // Create a DataInputStream to read the audio data from the saved file
}
catch (FileNotFoundException e1)
{
ShowToast("fILE NOT FOUND:"+e1.getMessage());
}
int i = 0; // Read the file into the "music" array
music=new byte[(int) file.length()];
try
{
while (dis.available() > 0)
{
music[i] = dis.readByte(); // This assignment does not reverse the order
i++;
}
}
catch (IOException e)
{
ShowToast("I/O Exception:"+e.getMessage());
}
try {dis.close();} catch (IOException e) {e.printStackTrace();}
int minBufferSize = AudioTrack.getMinBufferSize(11025, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT);
AudioTrack at = new AudioTrack(AudioManager.STREAM_MUSIC, 11025, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, minBufferSize, AudioTrack.MODE_STREAM);
at.play();
ShowToast("size:"+music.length);
//*/
at.write(music, 0, music.length);

Categories

Resources