2015-05-19 98 views
5

我已經在我的android應用程序中實現了錄製音頻的功能。我的應用程序在Linux上正常工作。但是當我在mac osx中運行相同的應用程序並記錄音頻時,它會崩潰我的應用程序。Android - 如何將音頻的原始數據轉換爲wav?

 private AudioRecordingThread recordingThread; 

     recordingThread = new AudioRecordingThread(fileName, 
      new AudioRecordingHandler() { 
       @Override 
       public void onFftDataCapture(final byte[] bytes) { 
        runOnUiThread(new Runnable() { 
         public void run() { 
          if (visualizerView != null) { 
           visualizerView.updateVisualizerFFT(bytes); 
          } 
         } 
        }); 
       } 

       @Override 
       public void onRecordSuccess() { 
       } 

       @Override 
       public void onRecordingError() { 
        runOnUiThread(new Runnable() { 
         public void run() { 
          recordStop(); 
          NotificationUtils.showInfoDialog(
            ActivityCropImage.this, 
            "Error in saving"); 
         } 
        }); 
       } 

       @Override 
       public void onRecordSaveError() { 
        runOnUiThread(new Runnable() { 
         public void run() { 
          recordStop(); 
          NotificationUtils.showInfoDialog(
            ActivityCropImage.this, 
            "Error in recording"); 
         } 
        }); 
       } 
      }); 
     PcmAudioHelper.convertRawToWav(WavAudioFormat.mono16Bit(SAMPLING_RATE), file_raw, file_wav); 

這是我的應用程序崩潰的代碼行。我在我的項目中使用了https://github.com/steelkiwi/AndroidRecording庫。

+0

以下權限你解決這個問題。對於你的問題,我測試過了,它可以記錄下來。但是,如果我改變可視化類型如circlerenderer。這是行不通的。你有同樣的問題嗎? – Jame

回答

7
package com.record.util; 

import android.media.AudioFormat; 
import android.media.AudioRecord; 
import android.media.MediaRecorder; 
import android.os.Environment; 
import android.text.format.Time; 
import android.util.Log; 

import java.io.BufferedOutputStream; 
import java.io.DataInputStream; 
import java.io.DataOutputStream; 
import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.nio.ByteBuffer; 
import java.nio.ByteOrder; 

public class RecordWavMaster { 
    private static final int samplingRates[] = {16000, 11025, 11000, 8000, 6000}; 
    public static int SAMPLE_RATE = 16000; 
    private AudioRecord mRecorder; 
    private File mRecording; 
    private short[] mBuffer; 
    private String audioFilePath; 
    private boolean mIsRecording = false; 
    private String RECORD_WAV_PATH = Environment.getExternalStorageDirectory() + File.separator + "AudioRecord"; 

    /* Initializing AudioRecording MIC */ 
    public RecordWavMaster() { 
     initRecorder(); 
    } 

    /* Get Supported Sample Rate */ 
    public static int getValidSampleRates() { 
     for (int rate : samplingRates) { 
      int bufferSize = AudioRecord.getMinBufferSize(rate, AudioFormat.CHANNEL_CONFIGURATION_DEFAULT, AudioFormat.ENCODING_PCM_16BIT); 
      if (bufferSize > 0) { 
       return rate; 
      } 
     } 
     return SAMPLE_RATE; 
    } 

    /* Start AudioRecording */ 
    public void recordWavStart() { 
     mIsRecording = true; 
     mRecorder.startRecording(); 
     mRecording = getFile("raw"); 
     startBufferedWrite(mRecording); 
    } 

    /* Stop AudioRecording */ 
    public String recordWavStop() { 
     try { 
      mIsRecording = false; 
      mRecorder.stop(); 
      File waveFile = getFile("wav"); 
      rawToWave(mRecording, waveFile); 
      Log.e("path_audioFilePath",audioFilePath); 
      return audioFilePath; 
     } catch (Exception e) { 
      Log.e("Error saving file : ", e.getMessage()); 
     } 
     return null; 
    } 

    /* Release device MIC */ 
    public void releaseRecord() { 
     mRecorder.release(); 
    } 

    /* Initializing AudioRecording MIC */ 
    private void initRecorder() { 
     SAMPLE_RATE = getValidSampleRates(); 
     int bufferSize = AudioRecord.getMinBufferSize(SAMPLE_RATE, AudioFormat.CHANNEL_IN_MONO, 
       AudioFormat.ENCODING_PCM_16BIT); 
     mBuffer = new short[bufferSize]; 
     mRecorder = new AudioRecord(MediaRecorder.AudioSource.MIC, SAMPLE_RATE, AudioFormat.CHANNEL_IN_MONO, 
       AudioFormat.ENCODING_PCM_16BIT, bufferSize); 
     new File(RECORD_WAV_PATH).mkdir(); 
    } 

    /* Writing RAW file */ 
    private void startBufferedWrite(final File file) { 
     new Thread(new Runnable() { 
      @Override 
      public void run() { 
       DataOutputStream output = null; 
       try { 
        output = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(file))); 
        while (mIsRecording) { 
         double sum = 0; 
         int readSize = mRecorder.read(mBuffer, 0, mBuffer.length); 
         for (int i = 0; i < readSize; i++) { 
          output.writeShort(mBuffer[i]); 
          sum += mBuffer[i] * mBuffer[i]; 
         } 
         if (readSize > 0) { 
          final double amplitude = sum/readSize; 
         } 
        } 
       } catch (IOException e) { 
        Log.e("Error writing file : ", e.getMessage()); 
       } finally { 

        if (output != null) { 
         try { 
          output.flush(); 
         } catch (IOException e) { 
          Log.e("Error writing file : ", e.getMessage()); 
         } finally { 
          try { 
           output.close(); 
          } catch (IOException e) { 
           Log.e("Error writing file : ", e.getMessage()); 
          } 
         } 
        } 
       } 
      } 
     }).start(); 
    } 

    /* Converting RAW format To WAV Format*/ 
    private void rawToWave(final File rawFile, final File waveFile) throws IOException { 

     byte[] rawData = new byte[(int) rawFile.length()]; 
     DataInputStream input = null; 
     try { 
      input = new DataInputStream(new FileInputStream(rawFile)); 
      input.read(rawData); 
     } finally { 
      if (input != null) { 
       input.close(); 
      } 
     } 
     DataOutputStream output = null; 
     try { 
      output = new DataOutputStream(new FileOutputStream(waveFile)); 
      // WAVE header 
      writeString(output, "RIFF"); // chunk id 
      writeInt(output, 36 + rawData.length); // chunk size 
      writeString(output, "WAVE"); // format 
      writeString(output, "fmt "); // subchunk 1 id 
      writeInt(output, 16); // subchunk 1 size 
      writeShort(output, (short) 1); // audio format (1 = PCM) 
      writeShort(output, (short) 1); // number of channels 
      writeInt(output, SAMPLE_RATE); // sample rate 
      writeInt(output, SAMPLE_RATE * 2); // byte rate 
      writeShort(output, (short) 2); // block align 
      writeShort(output, (short) 16); // bits per sample 
      writeString(output, "data"); // subchunk 2 id 
      writeInt(output, rawData.length); // subchunk 2 size 
      // Audio data (conversion big endian -> little endian) 
      short[] shorts = new short[rawData.length/2]; 
      ByteBuffer.wrap(rawData).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().get(shorts); 
      ByteBuffer bytes = ByteBuffer.allocate(shorts.length * 2); 
      for (short s : shorts) { 
       bytes.putShort(s); 
      } 
      output.write(bytes.array()); 
     } finally { 
      if (output != null) { 
       output.close(); 
       rawFile.delete(); 
      } 
     } 


    } 

    /* Get file name */ 
    private File getFile(final String suffix) { 
     Time time = new Time(); 
     time.setToNow(); 
     audioFilePath = time.format("%Y%m%d%H%M%S"); 
     return new File(RECORD_WAV_PATH, time.format("%Y%m%d%H%M%S") + "." + suffix); 
    } 

    private void writeInt(final DataOutputStream output, final int value) throws IOException { 
     output.write(value >> 0); 
     output.write(value >> 8); 
     output.write(value >> 16); 
     output.write(value >> 24); 
    } 

    private void writeShort(final DataOutputStream output, final short value) throws IOException { 
     output.write(value >> 0); 
     output.write(value >> 8); 
    } 

    private void writeString(final DataOutputStream output, final String value) throws IOException { 
     for (int i = 0; i < value.length(); i++) { 
      output.write(value.charAt(i)); 
     } 
    } 

    public String getFileName (final String time_suffix) { 
     return (RECORD_WAV_PATH+time_suffix+ "." + "wav"); 
    } 

    public Boolean getRecordingState() { 
     if( mRecorder.getRecordingState() == AudioRecord.RECORDSTATE_STOPPED) { 
     return false; 
     } 
     return true; 
    } 
} 

使用清單中

<!--Permission record--> 
    <uses-permission android:name="android.permission.RECORD_AUDIO" /> 
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> 
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> 
+3

這是AudioRecord在整個SO中保存爲WAV文件的最佳示例。此代碼正常工作。恥辱,它埋在這樣一個可憐的,低調的問題。 – ktorn

+0

感謝您的回答,我使用'rawToWave'方法來評論'.order(ByteOrder.LITTLE_ENDIAN)',它對我而言完全適用。 –

相關問題