Monday, 26 August 2013

Wav file recorded using AudioRecord sounds speeded up and skips frames when replaying

Wav file recorded using AudioRecord sounds speeded up and skips frames
when replaying

I am using AudioRecord to read mic data and RandomAccessFile to write a
wav file. This is the code:
public class MainActivity extends Activity {
AudioManager am = null;
AudioRecord record =null;
// AudioTrack track =null;
final int SAMPLE_FREQUENCY = 44100;
final int SIZE_OF_RECORD_ARRAY = 1024; // 1024 ORIGINAL
final int WAV_SAMPLE_MULTIPLICATION_FACTOR = 1;
int i= 0;
boolean isPlaying = false;
private volatile boolean keepThreadRunning;
// private RandomAccessFile stateFile, stateFileTemp, savToDisk;
private RandomAccessFile savToDisk;
private FileDescriptor fd = new FileDescriptor();
private File delFile, renFile;
String stateFileLoc =
Environment.getExternalStorageDirectory().getPath();
// To keep hederWriter() happy
private short nChannels = 1;
private int sRate = SAMPLE_FREQUENCY;
private short mBitsPersample = 16; // represents 16 bits of one PCM
sample
private int payload;
class MyThread extends Thread{
private volatile boolean needsToPassThrough;
// /*
MyThread(){
super();
}
MyThread(boolean newPTV){
this.needsToPassThrough = newPTV;
}
// */
// /*
@Override
public void run(){
short[] lin = new short[SIZE_OF_RECORD_ARRAY];
// byte[] lin = new byte[SIZE_OF_RECORD_ARRAY];
int num = 0;
// /*
if(needsToPassThrough){
record.startRecording();
// track.play();
}
// */
while (keepThreadRunning) {
// while (!isInterrupted()) {
// num = record.read(lin, 0, SIZE_OF_RECORD_ARRAY);
num = record.read(lin, 0, lin.length);
try {
// savToDisk.write(lin); // use only this line if lin
is a byte array
// use the for loop block below if lin is an array of
short
for(i=0;i <lin.length; i++)
savToDisk.writeShort(Short.reverseBytes(lin[i]));
// payload += lin.length; // use this line if lin is
an array of byte
payload = payload + (lin.length)*2;
fd.sync();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
/*
catch (SyncFailedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
*/
}
// /*
record.stop();
// track.stop();
record.release();
// track.release();
// */
}
// */
// /*
public void stopThread(){
keepThreadRunning = false;
}
// */
}
MyThread newThread;
private void init() {
int min = AudioRecord.getMinBufferSize(SAMPLE_FREQUENCY,
AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT);
// Toast.makeText(getApplicationContext(), Integer.toString(min),
Toast.LENGTH_SHORT).show(); // Shows 4096
record = new
AudioRecord(MediaRecorder.AudioSource.VOICE_COMMUNICATION,
SAMPLE_FREQUENCY, AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT, min);
// int maxJitter = AudioTrack.getMinBufferSize(SAMPLE_FREQUENCY,
AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT);
// track = new AudioTrack(AudioManager.MODE_IN_COMMUNICATION,
SAMPLE_FREQUENCY, AudioFormat.CHANNEL_OUT_MONO,
AudioFormat.ENCODING_PCM_16BIT, maxJitter,
AudioTrack.MODE_STREAM);
am = (AudioManager) this.getSystemService(Context.AUDIO_SERVICE);
am.setMode(AudioManager.MODE_IN_COMMUNICATION);
try {
savToDisk = new
RandomAccessFile(stateFileLoc+"/audSampData.wav", "rw");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
fd = savToDisk.getFD();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void writeHeader(){
try {
savToDisk.setLength(0); // Set file length to 0, to prevent
unexpected behavior in case the file already existed
savToDisk.writeBytes("RIFF");
savToDisk.writeInt(0); // Final file size not known yet, write 0
savToDisk.writeBytes("WAVE");
savToDisk.writeBytes("fmt ");
savToDisk.writeInt(Integer.reverseBytes(16)); // Sub-chunk
size, 16 for PCM
savToDisk.writeShort(Short.reverseBytes((short) 1)); //
AudioFormat, 1 for PCM
savToDisk.writeShort(Short.reverseBytes(nChannels));// Number
of channels, 1 for mono, 2 for stereo
savToDisk.writeInt(Integer.reverseBytes(sRate)); // Sample rate
savToDisk.writeInt(Integer.reverseBytes(sRate*nChannels*mBitsPersample/8));
// Byte rate, SampleRate*NumberOfChannels*mBitsPersample/8
savToDisk.writeShort(Short.reverseBytes((short)(nChannels*mBitsPersample/8)));
// Block align, NumberOfChannels*mBitsPersample/8
savToDisk.writeShort(Short.reverseBytes(mBitsPersample)); //
Bits per sample
savToDisk.writeBytes("data");
savToDisk.writeInt(0); // Data chunk size not known yet, write 0
fd.sync();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
protected void onResume(){
super.onResume();
// newThread.stopThread();
Log.d("MYLOG", "onResume() called");
init();
writeHeader();
keepThreadRunning = true;
// */
// newThread = new MyThread(true);
newThread = new MyThread(isPlaying);
newThread.start();
}
@Override
protected void onPause(){
super.onPause();
Log.d("MYLOG", "onPause() called");
newThread.stopThread();
// android.os.Process.killProcess(android.os.Process.myPid());
try {
savToDisk.seek(4);
savToDisk.writeInt(Integer.reverseBytes(36+payload));
savToDisk.seek(40);
savToDisk.writeInt(Integer.reverseBytes(payload));
savToDisk.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setVolumeControlStream(AudioManager.MODE_IN_COMMUNICATION);
payload = 0;
Log.d("MYLOG","onCreate() called");
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is
present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
protected void onDestroy() {
super.onDestroy();
newThread.stopThread();
// android.os.Process.killProcess(android.os.Process.myPid());
// killProcess(android.os.Process.myPid());
// newThread.interrupt();
// delFile.delete();
Log.d("MYLOG", "onDestroy() called");
/*
try {
savToDisk.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
*/
}
public void passStop(View view){
Button playBtn = (Button) findViewById(R.id.button1);
// /*
if(!isPlaying){
record.startRecording();
// track.play();
isPlaying = true;
playBtn.setText("Pause");
}
else{
record.stop();
// track.pause();
isPlaying=false;
playBtn.setText("Pass through");
}
// */
}
}
When I play the wav file in an audio player, it sounds speeded up, and
also seems to skip frames. What could be the reasons for this? I believe
the skipping frames problem is probably due to the fact that I have used
writeShort() function to write out each element of the short array that
stores the audio sample data separately, but if that is the case please
suggest a workaround to it that involves writing data as shorts (and not
using the write(byte[]) function, because I need to use parts of this code
in my main project which involves obtaining audio samples in a short
array).

No comments:

Post a Comment