Android:java.lang.IllegalArgumentException:音频缓冲区大小无效

问题描述:

我试图在使用audiorecord类立即录制音频后播放音频。我搜索谷歌& *我dint发现任何解决方案。任何帮助? 这里是Audio_Record代码....Android:java.lang.IllegalArgumentException:音频缓冲区大小无效

public class Audio_RecordActivity extends Activity { 
private static final int RECORDER_BPP = 16; 
private static final String AUDIO_RECORDER_FILE_EXT_WAV = ".wav"; 
private static final String AUDIO_RECORDER_FOLDER = "AudioRecorder"; 
private static final String AUDIO_RECORDER_TEMP_FILE = "record_temp.raw"; 
private static final int RECORDER_SAMPLERATE = 16000; 
private static final int RECORDER_CHANNELS = AudioFormat.CHANNEL_IN_STEREO; 
private static final int RECORDER_AUDIO_ENCODING = AudioFormat.ENCODING_PCM_16BIT; 

private AudioRecord recorder = null; 
private int bufferSize = 0; 
private Thread recordingThread = null; 
private boolean isRecording = false; 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 

    setButtonHandlers(); 
    enableButtons(false); 

    bufferSize = AudioRecord.getMinBufferSize(RECORDER_SAMPLERATE, 
      RECORDER_CHANNELS, RECORDER_AUDIO_ENCODING); 
} 

private void setButtonHandlers() { 
    ((Button) findViewById(R.id.btnStart)).setOnClickListener(btnClick); 
    ((Button) findViewById(R.id.btnStop)).setOnClickListener(btnClick); 
} 

private void enableButton(int id, boolean isEnable) { 
    ((Button) findViewById(id)).setEnabled(isEnable); 
} 

private void enableButtons(boolean isRecording) { 
    enableButton(R.id.btnStart, !isRecording); 
    enableButton(R.id.btnStop, isRecording); 
} 

private String getFilename() { 
    String filepath = Environment.getExternalStorageDirectory().getPath(); 
    File file = new File(filepath, AUDIO_RECORDER_FOLDER); 

    if (!file.exists()) { 
     file.mkdirs(); 
    } 

    return (file.getAbsolutePath() + "/" + System.currentTimeMillis() + AUDIO_RECORDER_FILE_EXT_WAV); 
} 

private String getTempFilename() { 
    String filepath = Environment.getExternalStorageDirectory().getPath(); 
    File file = new File(filepath, AUDIO_RECORDER_FOLDER); 

    if (!file.exists()) { 
     file.mkdirs(); 
    } 

    File tempFile = new File(filepath, AUDIO_RECORDER_TEMP_FILE); 

    if (tempFile.exists()) 
     tempFile.delete(); 

    return (file.getAbsolutePath() + "/" + AUDIO_RECORDER_TEMP_FILE); 
} 

private void startRecording() { 
    recorder = new AudioRecord(MediaRecorder.AudioSource.MIC, 
      RECORDER_SAMPLERATE, RECORDER_CHANNELS, 
      RECORDER_AUDIO_ENCODING, bufferSize); 

    recorder.startRecording(); 

    isRecording = true; 

    recordingThread = new Thread(new Runnable() { 

     @Override 
     public void run() { 
      writeAudioDataToFile(); 
     } 
    }, "AudioRecorder Thread"); 

    recordingThread.start(); 
} 

private void writeAudioDataToFile() { 
    byte data[] = new byte[bufferSize]; 
    String filename = getTempFilename(); 
    FileOutputStream os = null; 

    try { 
     os = new FileOutputStream(filename); 
    } catch (FileNotFoundException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 

    int read = 0; 

    if (null != os) { 
     while (isRecording) { 
      read = recorder.read(data, 0, bufferSize); 

      if (AudioRecord.ERROR_INVALID_OPERATION != read) { 
       try { 
        os.write(data); 
       } catch (IOException e) { 
        e.printStackTrace(); 
       } 
      } 
     } 

     try { 
      os.close(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

private void stopRecording() { 
    if (null != recorder) { 
     isRecording = false; 

     recorder.stop(); 
     recorder.release(); 

     recorder = null; 
     recordingThread = null; 
    } 

    copyWaveFile(getTempFilename(), getFilename()); 
    deleteTempFile(); 
} 

private void deleteTempFile() { 
    File file = new File(getTempFilename()); 

    file.delete(); 
} 

private void copyWaveFile(String inFilename, String outFilename) { 
    FileInputStream in = null; 
    FileOutputStream out = null; 
    long totalAudioLen = 0; 
    long totalDataLen = totalAudioLen + 36; 
    long longSampleRate = RECORDER_SAMPLERATE; 
    int channels = 2; 
    long byteRate = RECORDER_BPP * RECORDER_SAMPLERATE * channels/8; 

    byte[] data = new byte[bufferSize]; 

    try { 
     in = new FileInputStream(inFilename); 
     out = new FileOutputStream(outFilename); 
     totalAudioLen = in.getChannel().size(); 
     totalDataLen = totalAudioLen + 36; 

     AppLog.logString("File size: " + totalDataLen); 

     WriteWaveFileHeader(out, totalAudioLen, totalDataLen, 
       longSampleRate, channels, byteRate); 

     while (in.read(data) != -1) { 
      out.write(data); 
     } 

     in.close(); 
     out.close(); 
    } catch (FileNotFoundException e) { 
     e.printStackTrace(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
} 

private void WriteWaveFileHeader(FileOutputStream out, long totalAudioLen, 
     long totalDataLen, long longSampleRate, int channels, long byteRate) 
     throws IOException { 

    byte[] header = new byte[44]; 

    header[0] = 'R'; // RIFF/WAVE header 
    header[1] = 'I'; 
    header[2] = 'F'; 
    header[3] = 'F'; 
    header[4] = (byte) (totalDataLen & 0xff); 
    header[5] = (byte) ((totalDataLen >> 8) & 0xff); 
    header[6] = (byte) ((totalDataLen >> 16) & 0xff); 
    header[7] = (byte) ((totalDataLen >> 24) & 0xff); 
    header[8] = 'W'; 
    header[9] = 'A'; 
    header[10] = 'V'; 
    header[11] = 'E'; 
    header[12] = 'f'; // 'fmt ' chunk 
    header[13] = 'm'; 
    header[14] = 't'; 
    header[15] = ' '; 
    header[16] = 16; // 4 bytes: size of 'fmt ' chunk 
    header[17] = 0; 
    header[18] = 0; 
    header[19] = 0; 
    header[20] = 1; // format = 1 
    header[21] = 0; 
    header[22] = (byte) channels; 
    header[23] = 0; 
    header[24] = (byte) (longSampleRate & 0xff); 
    header[25] = (byte) ((longSampleRate >> 8) & 0xff); 
    header[26] = (byte) ((longSampleRate >> 16) & 0xff); 
    header[27] = (byte) ((longSampleRate >> 24) & 0xff); 
    header[28] = (byte) (byteRate & 0xff); 
    header[29] = (byte) ((byteRate >> 8) & 0xff); 
    header[30] = (byte) ((byteRate >> 16) & 0xff); 
    header[31] = (byte) ((byteRate >> 24) & 0xff); 
    header[32] = (byte) (2 * 16/8); // block align 
    header[33] = 0; 
    header[34] = RECORDER_BPP; // bits per sample 
    header[35] = 0; 
    header[36] = 'd'; 
    header[37] = 'a'; 
    header[38] = 't'; 
    header[39] = 'a'; 
    header[40] = (byte) (totalAudioLen & 0xff); 
    header[41] = (byte) ((totalAudioLen >> 8) & 0xff); 
    header[42] = (byte) ((totalAudioLen >> 16) & 0xff); 
    header[43] = (byte) ((totalAudioLen >> 24) & 0xff); 

    out.write(header, 0, 44); 
} 

private View.OnClickListener btnClick = new View.OnClickListener() { 
    @Override 
    public void onClick(View v) { 
     switch (v.getId()) { 
     case R.id.btnStart: { 
      AppLog.logString("Start Recording"); 

      enableButtons(true); 
      startRecording(); 

      break; 
     } 
     case R.id.btnStop: { 
      AppLog.logString("Start Recording"); 

      enableButtons(false); 
      stopRecording(); 

      break; 
     } 
     } 
    } 
}; 
} 

如下图所示logcat的文件,我得到的错误。

logcat的错误

05-18 16:51:04.656: E/AndroidRuntime(1974): FATAL EXCEPTION: main 
05-18 16:51:04.656: E/AndroidRuntime(1974): java.lang.IllegalArgumentException: Invalid audio buffer size. 
05-18 16:51:04.656: E/AndroidRuntime(1974):  at android.media.AudioRecord.audioBuffSizeCheck(AudioRecord.java:333) 
05-18 16:51:04.656: E/AndroidRuntime(1974):  at android.media.AudioRecord.<init>(AudioRecord.java:230) 
05-18 16:51:04.656: E/AndroidRuntime(1974):  at audio.xxx.Audio_RecordActivity.startRecording(Audio_RecordActivity.java:88) 
05-18 16:51:04.656: E/AndroidRuntime(1974):  at audio.xxx.Audio_RecordActivity.access$1(Audio_RecordActivity.java:85) 
05-18 16:51:04.656: E/AndroidRuntime(1974):  at audio.xxx.Audio_RecordActivity$1.onClick(Audio_RecordActivity.java:258) 
05-18 16:51:04.656: E/AndroidRuntime(1974):  at android.view.View.performClick(View.java:3511) 
05-18 16:51:04.656: E/AndroidRuntime(1974):  at android.view.View$PerformClick.run(View.java:14105) 
05-18 16:51:04.656: E/AndroidRuntime(1974):  at android.os.Handler.handleCallback(Handler.java:605) 
05-18 16:51:04.656: E/AndroidRuntime(1974):  at android.os.Handler.dispatchMessage(Handler.java:92) 
05-18 16:51:04.656: E/AndroidRuntime(1974):  at android.os.Looper.loop(Looper.java:137) 
05-18 16:51:04.656: E/AndroidRuntime(1974):  at android.app.ActivityThread.main(ActivityThread.java:4424) 
05-18 16:51:04.656: E/AndroidRuntime(1974):  at java.lang.reflect.Method.invokeNative(Native Method) 
05-18 16:51:04.656: E/AndroidRuntime(1974):  at java.lang.reflect.Method.invoke(Method.java:511) 
05-18 16:51:04.656: E/AndroidRuntime(1974):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784) 
05-18 16:51:04.656: E/AndroidRuntime(1974):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551) 
05-18 16:51:04.656: E/AndroidRuntime(1974):  at dalvik.system.NativeStart.main(Native Method) 

请帮我..我应该使用什么样的缓冲区大小。我使用4096,然后也显示相同的错误。

您尝试使用此代码其能正常工作..

public class Audio_RecordActivity extends Activity { 
private static final int RECORDER_SAMPLERATE = 8000; 
private static final int RECORDER_CHANNELS = AudioFormat.CHANNEL_IN_MONO; 
private static final int RECORDER_AUDIO_ENCODING = AudioFormat.ENCODING_PCM_16BIT; 
private AudioRecord recorder = null; 
private Thread recordingThread = null; 
private boolean isRecording = false; 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 
    setButtonHandlers(); 
    enableButtons(false); 

    int bufferSize = AudioRecord.getMinBufferSize(RECORDER_SAMPLERATE, 
      RECORDER_CHANNELS, RECORDER_AUDIO_ENCODING); 

    System.out.println("BUFFER SIZE VALUE IS " + bufferSize); 

} 
private void setButtonHandlers() { 
    ((Button) findViewById(R.id.btnStart)).setOnClickListener(btnClick); 
    ((Button) findViewById(R.id.btnStop)).setOnClickListener(btnClick); 
} 

private void enableButton(int id, boolean isEnable) { 
    ((Button) findViewById(id)).setEnabled(isEnable); 
} 

private void enableButtons(boolean isRecording) { 
    enableButton(R.id.btnStart, !isRecording); 
    enableButton(R.id.btnStop, isRecording); 
} 

int BufferElements2Rec = 1024; // want to play 2048 (2K) since 2 bytes we use only 1024 
int BytesPerElement = 2; // 2 bytes in 16bit format 

private void startRecording() { 

    recorder = new AudioRecord(MediaRecorder.AudioSource.MIC, 
      RECORDER_SAMPLERATE, RECORDER_CHANNELS, 
      RECORDER_AUDIO_ENCODING, BufferElements2Rec*BytesPerElement); 

    recorder.startRecording(); 
    isRecording = true; 

    recordingThread = new Thread(new Runnable() { 

     public void run() { 

      writeAudioDataToFile(); 

     } 
    }, "AudioRecorder Thread"); 
    recordingThread.start(); 
} 

private byte[] short2byte(short[] sData) 
{ 
    int shortArrsize= sData.length; 
    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; 

} 

    private void writeAudioDataToFile() { 
    // Write the output audio in byte 

    String filePath = "/sdcard/voice8K16bitmono.pcm"; 
    short sData[] = new short[BufferElements2Rec]; 

    FileOutputStream os = null; 
    try { 
     os = new FileOutputStream(filePath); 
    } catch (FileNotFoundException e) { 
     e.printStackTrace(); 
    } 

    while (isRecording) { 
     // gets the voice output from microphone to byte format 

     recorder.read(sData, 0, BufferElements2Rec); 

     try { 
      // // writes the data to file from buffer 
      // // stores the voice buffer 
      byte bData[] = short2byte(sData); 
      os.write(bData, 0, BufferElements2Rec*BytesPerElement); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

    try { 
     os.close(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
    } 

     private void stopRecording() { 
    // stops the recording activity 

    if (null != recorder) { 
     isRecording = false; 

     recorder.stop(); 
     recorder.release(); 

     recorder = null; 
     recordingThread = null; 
    } 
} 

private View.OnClickListener btnClick = new View.OnClickListener() { 
    public void onClick(View v) { 
     switch (v.getId()) { 
     case R.id.btnStart: { 
      enableButtons(true); 
      startRecording(); 
      break; 
     } 
     case R.id.btnStop: { 
      enableButtons(false); 
      stopRecording(); 
      break; 
     } 
     } 
    } 
    }; 

    @Override 
    public boolean onKeyDown(int keyCode, KeyEvent event) { 

    if (keyCode == KeyEvent.KEYCODE_BACK) { 

     finish(); 
    } 
    return super.onKeyDown(keyCode, event); 
    } 
    } 

对于音频录制和播放请参阅此链接Samples 下载样本并使用音频编码代码。它运作良好。

+1

我想只有你说这个示例代码..它不是和我一起工作..你自己看着办吧,我在做什么他们错了。 –

+0

如果它工作让我知道请。 –