我正在编写一个Android应用程序,用于录制和循环播放音频。 像回声(录音,播放,循环运行)。
我已成功编写了使用临时文件录制和播放的应用程序,(写入文件,从同一文件中读取)。
使用中间缓冲区执行相同操作失败。
这是我的代码:
public class BufferMain extends ActionBarActivity {
private String TAG = "AUDIO_RECORD_PLAYBACK_SAURABH_BUFFER";
private boolean isRunning = false;
private AudioRecord recorder = null;
private AudioTrack track = null;
/* Buffer used to record and Playback Audio */
byte buffer[] = new byte[640];
int bufferSize;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_buffer_main);
enableButton(R.id.StartButton,true);
enableButton(R.id.StopButton,false);
/* Assign Button Click Handlers */
((Button)findViewById(R.id.StartButton)).setOnClickListener(btnClick);
((Button)findViewById(R.id.StopButton)).setOnClickListener(btnClick);
Log.d(TAG, "\n ==Starting Application.. ==");
}
/* Method for Recording and Playing in a loop */
public void run_loop (boolean isRunning)
{
int readbytes, writebytes, state;
Log.d(TAG, "===== Entering Loop ===== ");
if (isRunning == true) {
do {
bufferSize = 640; /* since configuration would return 640 size in buffer */
recorder = findAudioRecord(recorder);
if (recorder == null) {
Log.e(TAG, "====== findAudioRecord : Returned Error! =======");
return;
}
if (recorder.STATE_INITIALIZED == recorder.getState())
{
recorder.startRecording();
readbytes = 0; /* Reset read for next Iteration */
readbytes = recorder.read(buffer, 0, bufferSize);
/* Error Checking Code for AudioRecord */
if(-1 == checkAudioRecordforError(readbytes))
{
Log.d(TAG, "========= Read Error =========");
return;
}
Log.d(TAG, "\n\n===== Read : Sizeof Buffer:"+buffer.length+"=== readbytes: ["+readbytes+"]=====");
recorder.stop();
recorder.release();
}else {
state = recorder.getState();
Log.d(TAG, "========= Else Part : state : "+state+"=========");
}
Log.d(TAG, "========= Reading Completed =========");
/** ======== API for Playing =========== **/
track = findAudioTrack(track);
if (track == null) {
Log.e(TAG, "========= findAudioTrack : Returned Error! ========== ");
return;
}
if (track.STATE_INITIALIZED == track.getState())
{
writebytes = 0; /* Reset write bytes for next Iteration */
track.play();
writebytes = track.write(buffer, 0, bufferSize);
Log.d(TAG, "\n\n===== Write : Sizeof Buffer:"+ bufferSize +"==== writebytes: ["+writebytes+"]======== ");
/* Error Checking Code for AudioRecord */
if (-1 == checkAudioTrackforError(writebytes))
{
Log.d(TAG, "========= Write Error =========");
return;
}
track.stop();
track.release();
}
else {
state = track.getState();
Log.d(TAG, "========= Else Part : state : "+state+"=========");
}
} while(true);
}
return;
}
/* Method for Initializing AudioTrack for Playing Purpose */
public AudioTrack findAudioTrack (AudioTrack track)
{
Log.d(TAG, "========== Initialising Playing API ============");
bufferSize = AudioTrack.getMinBufferSize(8000,
AudioFormat.CHANNEL_OUT_MONO,
AudioFormat.ENCODING_PCM_16BIT); /* Return 640 */
Log.d(TAG, "========= AudioTrack ==> bufferSize : "+bufferSize+"=========");
if (bufferSize != AudioTrack.ERROR_BAD_VALUE)
{
track = new AudioTrack(AudioManager.STREAM_MUSIC, 8000,
AudioFormat.CHANNEL_OUT_MONO,
AudioFormat.ENCODING_PCM_16BIT, bufferSize,
AudioTrack.MODE_STREAM);
if (track.getState() == AudioTrack.STATE_UNINITIALIZED) {
Log.e(TAG, "=========== AudioTrack UnInitilaised ===========");
return null;
}
}
return track;
}
/* Method for Initializing AudioRecord for Recording Purpose */
public AudioRecord findAudioRecord (AudioRecord recorder)
{
Log.d(TAG, "======== Initializing Record API ==========");
bufferSize = AudioRecord.getMinBufferSize(8000,
AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT);
if (bufferSize != AudioRecord.ERROR_BAD_VALUE)
{
recorder = new AudioRecord(AudioSource.DEFAULT, 8000,
AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT, bufferSize);
if (recorder.getState() == AudioRecord.STATE_UNINITIALIZED) {
Log.e(TAG, "========= AudioRecord UnInitilaised ============= ");
return null;
}
}
return recorder;
}
/* Method for Error Checking - AudioRecord */
public int checkAudioRecordforError(int readbytes)
{
if (readbytes == recorder.ERROR_INVALID_OPERATION || readbytes == recorder.ERROR_BAD_VALUE)
{
if(readbytes == AudioRecord.ERROR_INVALID_OPERATION)
Log.d(TAG, "========= read Error : ERROR_INVALID_OPERATION ===========");
else if (readbytes == AudioRecord.ERROR_BAD_VALUE)
Log.d(TAG, "========= read Error : ERROR_BAD_VALUE ===========");
else if (readbytes == AudioRecord.ERROR)
Log.d(TAG, "========= read Error : ERROR Unknown ===========");
return -1;
}
return readbytes;
}
/* Method for Error Checking - AudioTrack */
public int checkAudioTrackforError(int writebytes)
{
if (writebytes == track.ERROR_INVALID_OPERATION || writebytes == track.ERROR_BAD_VALUE)
{
if(writebytes == track.ERROR_INVALID_OPERATION)
Log.d(TAG, "========= read Error : ERROR_INVALID_OPERATION ===========");
else if (writebytes == track.ERROR_BAD_VALUE)
Log.d(TAG, "========= read Error : ERROR_BAD_VALUE ===========");
else if (writebytes == track.ERROR)
Log.d(TAG, "========= read Error : ERROR Unknown ===========");
return -1;
}
return writebytes;
}
/* Method for Mapping Button Click */
private View.OnClickListener btnClick = new View.OnClickListener() {
@Override
public void onClick(View v) {
switch(v.getId()){
case R.id.StartButton:
{
Log.d(TAG, "======= Start Recording =======");
isRunning = true;
Log.d(TAG, "========== isRunning = true =============");
run_loop (isRunning);
enableButton(R.id.StartButton,false);
enableButton(R.id.StopButton,true);
break;
}
case R.id.StopButton:
{
Log.d(TAG, "======== Stop Recording =========");
isRunning = false;
Log.d(TAG, "========== isRunning = false =============");
run_loop (isRunning);
enableButton(R.id.StopButton,false);
enableButton(R.id.StartButton,true);
break;
}
}
}
};
/* Function to Enable/Disable Buttons */
private void enableButton(int id,boolean isEnable){
((Button)findViewById(id)).setEnabled(isEnable);
}
}
任何地方都没有读写失败。
Logcat输出:
D/AUDIO_RECORD_PLAYBACK_SAURABH_BUFFER( 3885): ==Starting Application.. ==
D/AUDIO_RECORD_PLAYBACK_SAURABH_BUFFER( 3885): ========Start Recording========
D/AUDIO_RECORD_PLAYBACK_SAURABH_BUFFER( 3885): ========== isRunning = true =============
D/AUDIO_RECORD_PLAYBACK_SAURABH_BUFFER( 3885): ===== Entering Loop =====
D/AUDIO_RECORD_PLAYBACK_SAURABH_BUFFER( 3885): =========== Initializing Record API =======
E/ACDB-LOADER( 213): Error: ACDB AudProc vol returned = -19
D/AUDIO_RECORD_PLAYBACK_SAURABH_BUFFER( 3885): ===== Read : Sizeof Buffer:640=== readbytes: [640]=====
D/AUDIO_RECORD_PLAYBACK_SAURABH_BUFFER( 3885): ========= Reading Completed =========
D/AUDIO_RECORD_PLAYBACK_SAURABH_BUFFER( 3885): ========== Initializing Playing API ========
D/AUDIO_RECORD_PLAYBACK_SAURABH_BUFFER( 3885): ========= AudioTrack ==> bufferSize : 640=========
D/AUDIO_RECORD_PLAYBACK_SAURABH_BUFFER( 3885): ===== Write : Sizeof Buffer:640==== writebytes: [640]========
D/AUDIO_RECORD_PLAYBACK_SAURABH_BUFFER( 3885): =========Initialising Record API =========
E/ACDB-LOADER( 213): Error: ACDB AudProc vol returned = -19
我需要验证E/ACDB-LOADER( 213): Error: ACDB AudProc vol returned = -19
是否对此负责
以上音频配置适用于Google Nexus 5
。可能无法在其他设备上初始化。
Android GUI包含两个按钮Start
和Stop
。
请帮我解决上述问题。
答案 0 :(得分:0)
上述问题已修复。
问题不在于:
E/ACDB-LOADER( 213): Error: ACDB AudProc vol returned = -19
我更正了代码并在此答案中更新了它: Audio Recording and Streaming in Android
代码更改:
AudioRecord
和AudioTrack
对象
(不得成为循环的一部分)。通过这种方式,我可以使用缓冲区在循环中录制音频并播放相同内容。