问题
Basically, I use AudioRecord to record a sound file to sdcard directory. It records for 5 seconds and then playback using AudioTrack.
Well, for me, the recorded file doesn't exist. Maybe it didn't record successfully. Anything I did wrong in recording? what about the playback portion?
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
int minBufferSize = AudioTrack.getMinBufferSize(44100, AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT);
audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT, minBufferSize, AudioTrack.MODE_STREAM);
recordSound();
}
private void recordSound(){
File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/"+"recordsound");
// /mnt/sdcard/recordsound
// Delete any previous recording.
if (file.exists())
file.delete();
try {
file.createNewFile();
// Create a DataOuputStream to write the audio data into the saved file.
OutputStream os = new FileOutputStream(file);
BufferedOutputStream bos = new BufferedOutputStream(os);
dos = new DataOutputStream(bos);
// Create a new AudioRecord object to record the audio.
int bufferSize = audioRecord.getMinBufferSize(FREQUENCY, CHANNEL_CONFIGURATION, AUDIO_ENCODING);
audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, FREQUENCY, CHANNEL_CONFIGURATION, AUDIO_ENCODING, bufferSize);
short[] buffer = new short[bufferSize];
audioRecord.startRecording();
new Timer().schedule(stop(), 5000); //time in miliseconds
// while (audioRecord.RECORDSTATE_RECORDING==1)
{
int bufferReadResult = audioRecord.read(buffer, 0, bufferSize);
for (int i = 0; i < bufferReadResult; i++)
dos.writeShort(buffer[i]);
}
// dos.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private TimerTask stop()
{
TimerTask t = new TimerTask() {
@Override
public void run() {
// TODO Auto-generated method stub
audioTrack.stop();
audioTrack.release();
try {
dos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
playfilesound();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
return t;
}
private void playfilesound() throws IOException
{
int count = 512 * 1024; // 512 kb
//Reading the file..
byte[] byteData = null;
File file = null;
file = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/"+"recordsound"); //filePath
if (file.exists())
{
int a=0;
}
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();
audioTrack.play();
while (bytesread < size) { // Write the byte array to the track
ret = in.read( byteData,0, count); //ret =size in bytes
if (ret != -1) {
audioTrack.write(byteData,0, ret);
bytesread += ret; } //ret
else break; } //while
in.close(); audioTrack.stop(); audioTrack.release();
}
回答1:
If your requirement is while it is recording it should play(means looping back audio), In your while loop thread, you are storing the recorded data (audioData bufer), there itself you can copy it to player object with in the while loop (player.write(audioData, 0, numShortsRead);). You said like your UI thread is stuck, it might be because of you are giving more priority to Audio record thread.
Check the below the code which I used for above loop back requirement:
boolean m_isRun=true;
public void loopback() {
// Prepare the AudioRecord & AudioTrack
try {
buffersize = AudioRecord.getMinBufferSize(SAMPLE_RATE,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT);
if (buffersize <= BUF_SIZE) {
buffersize = BUF_SIZE;
}
Log.i(LOG_TAG,"Initializing Audio Record and Audio Playing objects");
m_record = new AudioRecord(MediaRecorder.AudioSource.MIC,
SAMPLE_RATE, AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT, buffersize * 1);
m_track = new AudioTrack(AudioManager.STREAM_ALARM,
SAMPLE_RATE, AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT, buffersize * 1,
AudioTrack.MODE_STREAM);
m_track.setPlaybackRate(SAMPLE_RATE);
} catch (Throwable t) {
Log.e("Error", "Initializing Audio Record and Play objects Failed "+t.getLocalizedMessage());
}
m_record.startRecording();
Log.i(LOG_TAG,"Audio Recording started");
m_track.play();
Log.i(LOG_TAG,"Audio Playing started");
while (m_isRun) {
m_record.read(buffer, 0, BUF_SIZE);
m_track.write(buffer, 0, buffer.length);
}
Log.i(LOG_TAG, "loopback exit");
}
private void do_loopback() {
m_thread = new Thread(new Runnable() {
public void run() {
loopback();
}
});
One more thing, If your requirement is record for few seconds and then play, while it is playing your record should start again, you can do that with a delay handler thread with a time out, In that thread you can stop recording copy the buffer, then start recording.
来源:https://stackoverflow.com/questions/15130374/android-audiorecord-to-file-then-use-audiotrack-for-playback