2012-07-02 38 views
5

Tôi đã viết mã để ghi tệp âm thanh bằng cách sử dụng AudioRecord và trong khi ghi tệp trên thẻ SD, tôi đang tạo hai phiên bản.AudioRecord with Gain Adjustment không hoạt động trên Thiết bị Samsung

Phiên bản 1 Tệp đã ghi được lưu trên thẻ SD như cũ.

Phiên bản 2 Tôi đang áp dụng tính năng tăng trên tệp được ghi và lưu trên thẻ SD.

Điều này hoạt động tuyệt vời trên điện thoại di động Sony Ericson. Âm lượng âm thanh cũng được tăng lên ở mức độ lớn.

Nhưng tôi đang đấu tranh để làm cho nó hoạt động trên các thiết bị Samsung.

khi tôi chơi tập tin âm thanh như Talking Tom ghi: P

Ban đầu tôi nghĩ rằng thiết bị Samusung không thích hợp tôi đã sử dụng để tạo AudioRecorder.

Vì vậy, tôi đã sử dụng phương pháp tiếp cận sau, trong đó tôi lặp thành cấu hình có sẵn và sử dụng cấu hình tốt nhất để khởi tạo AudioRecord.

public AudioRecord findAudioRecord() { 
    for (int rate: mSampleRates) { 
     for (short audioFormat: new short[] { 
      AudioFormat.ENCODING_PCM_8BIT, AudioFormat.ENCODING_PCM_16BIT 
     }) { 
      for (short channelConfig: new short[] { 
       AudioFormat.CHANNEL_IN_MONO, AudioFormat.CHANNEL_IN_STEREO 
      }) { 
       try { 
        Log.i("vipul", "Attempting rate " + rate + "Hz, bits: " + audioFormat + ", channel: " + channelConfig); 
        int bufferSize = AudioRecord.getMinBufferSize(rate, channelConfig, audioFormat); 

        if (bufferSize != AudioRecord.ERROR_BAD_VALUE) { 
         // check if we can instantiate and have a success 
         AudioRecord recorder = new AudioRecord(
         AudioSource.DEFAULT, rate, channelConfig, audioFormat, bufferSize); 

         if (recorder.getState() == AudioRecord.STATE_INITIALIZED) return recorder; 
        } 
       } catch (Exception e) { 
        e.printStackTrace(); 
       } 
      } 
     } 
    } 
    return null; 
} 

Dưới đây là mã hoạt động tốt trên điện thoại di động Sony.But Đấu tranh để hoạt động trên các thiết bị Samsung.

public class EnvironmentRecorder extends Activity implements OnClickListener { 

    private static final int RECORDER_BPP = 16; 
    private static final String AUDIO_RECORDER_FILE_EXT_WAV = ".wav"; 
    private static final String AUDIO_RECORDER_FOLDER = "MyRecorder"; 
    private static final String AUDIO_RECORDER_TEMP_FILE = "record_temp.raw"; 
    private static final int RECORDER_SAMPLERATE = 44100; 
    private static final int RECORDER_CHANNELS = AudioFormat.CHANNEL_IN_STEREO; 
    private static final int RECORDER_AUDIO_ENCODING = AudioFormat.ENCODING_PCM_16BIT; 
    private Button start, stop; 
    private AudioRecord recorder = null; 
    private int bufferSize = 0; 
    private Thread recordingThread = null; 
    private boolean isRecording = false; 
    private static int[] mSampleRates = new int[] { 
     8000, 11025, 22050, 44100 
    }; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 
     start = (Button) findViewById(R.id.start); 
     stop = (Button) findViewById(R.id.stop); 
     start.setOnClickListener(this); 
     stop.setOnClickListener(this); 
    } 

    @Override 
    public void onClick(View view) { 
     switch (view.getId()) { 
     case R.id.start: 
      startRecord(); 
      break; 
     case R.id.stop: 
      stopRecording(); 
      break; 
     } 
    } 

    public EnvironmentRecorder() { 

     try { 
      bufferSize = AudioRecord.getMinBufferSize(RECORDER_SAMPLERATE, RECORDER_CHANNELS, RECORDER_AUDIO_ENCODING); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 

    } 

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

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

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

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

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

     return (file.getAbsolutePath() + "/" + "Gained" + 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); 
    } 

    public AudioRecord findAudioRecord() { 
     for (int rate: mSampleRates) { 
      for (short audioFormat: new short[] { 
       AudioFormat.ENCODING_PCM_8BIT, AudioFormat.ENCODING_PCM_16BIT 
      }) { 
       for (short channelConfig: new short[] { 
        AudioFormat.CHANNEL_IN_MONO, AudioFormat.CHANNEL_IN_STEREO 
       }) { 
        try { 
         Log.v("vipul", "Attempting rate " + rate + "Hz, bits: " + audioFormat + ", channel: " + channelConfig); 
         int bufferSize = AudioRecord.getMinBufferSize(rate, channelConfig, audioFormat); 

         if (bufferSize != AudioRecord.ERROR_BAD_VALUE) { 
          // check if we can instantiate and have a success 
          AudioRecord recorder = new AudioRecord(
          AudioSource.DEFAULT, rate, channelConfig, audioFormat, bufferSize); 

          if (recorder.getState() == AudioRecord.STATE_INITIALIZED) return recorder; 
         } 
        } catch (Exception e) { 
         e.printStackTrace(); 
        } 
       } 
      } 
     } 
     return null; 
    } 

    public void startRecord() { 
     /* 
     * recorder = new AudioRecord(MediaRecorder.AudioSource.MIC, 
     * RECORDER_SAMPLERATE, RECORDER_CHANNELS, RECORDER_AUDIO_ENCODING, 
     * bufferSize); 
     */ 

     recorder = findAudioRecord(); 

     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) { 
      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(); 
      } 
     } 
    } 

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

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

      recorder = null; 
      recordingThread = null; 
      copyWaveFile(getTempFilename(), getFilename1(), getFilename2()); 
      deleteTempFile(); 
     } 

    } 

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

     file.delete(); 
    } 

    private void copyWaveFile(String inFilename, String outFileName1, String outFileName2) { 
     FileInputStream in = null; 
     FileOutputStream out1 = null, out2 = 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); 
      out1 = new FileOutputStream(outFileName1); 
      out2 = new FileOutputStream(outFileName2); 
      totalAudioLen = in .getChannel().size(); 
      totalDataLen = totalAudioLen + 36; 

      WriteWaveFileHeader(out1, totalAudioLen, totalDataLen, longSampleRate, channels, byteRate); 
      WriteWaveFileHeader(out2, totalAudioLen, totalDataLen, longSampleRate, channels, byteRate); 

      while (in .read(data) != -1) { 

       out1.write(data); // Writing Non-Gained Data 

       float rGain = 2.5f; 
       for (int i = 0; i < data.length/2; i++) { 

        short curSample = getShort(data[i * 2], data[i * 2 + 1]); 
        if (rGain != 1) { 
         // apply gain 
         curSample *= rGain; 
         // convert back from short sample that was "gained" to 
         // byte data 
         byte[] a = getByteFromShort(curSample); 
         // modify buffer to contain the gained sample 
         data[i * 2] = a[0]; 
         data[i * 2 + 1] = a[1]; 
        } 

       } 

       out2.write(data); // Writing Gained Data 
      } 
      out1.close(); 
      out2.close(); in .close(); 

      Toast.makeText(this, "Done!!", Toast.LENGTH_LONG).show(); 
     } catch (FileNotFoundException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

    private short getShort(byte argB1, byte argB2) { 
     return (short)((argB1 & 0xff) | (argB2 << 8)); 

    } 

    private byte[] getByteFromShort(short x) { 
     // variant 1 - noise 
     byte[] a = new byte[2]; 
     a[0] = (byte)(x & 0xff); 
     a[1] = (byte)((x >> 8) & 0xff); 

     // variant 2 - noise and almost broke my ears - very loud 
     // ByteBuffer buffer = ByteBuffer.allocate(2); 
     // buffer.putShort(x); 
     // buffer.flip(); 

     return a; 
    } 

    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'; 
     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'; 
     header[13] = 'm'; 
     header[14] = 't'; 
     header[15] = ' '; 
     header[16] = 16; 
     header[17] = 0; 
     header[18] = 0; 
     header[19] = 0; 
     header[20] = 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); 
     header[33] = 0; 
     header[34] = RECORDER_BPP; 
     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); 
    } 

} 

Tôi muốn biết liệu tôi có cần thêm bất kỳ vị trí bổ sung nào để làm cho AudioRecord của tôi thoải mái với Thiết bị Samsung hay không.

+0

Hi Vipul, bạn đã tìm thấy giải pháp chưa? Chúng tôi có cùng một vấn đề trên Galaxy S3 và chúng tôi tin rằng nó giống như của bạn. – Giuseppe

Trả lời

6

Chúng tôi cũng đang đấu tranh với việc ghi âm trên một số thiết bị Android của Samsung. Thật không may nó có vẻ rất bị hỏng, vì ngay cả các phiên bản khác nhau của cùng một kiểu điện thoại đang hoạt động khác nhau với cùng một codebase.

Dưới đây là những phát hiện hiện tại của tôi, hy vọng bạn tìm thấy một cái gì đó hữu ích:

1. Khởi tạo bị hỏng:

Thật không may, chiến lược bạn đang sử dụng để truy vấn cho các cấu hình ghi hợp lệ sẽ thất bại ít nhất là trên Samsung Các mô hình Galaxy Young và Ace chạy Android 2.3 Vấn đề là một số cấu hình AudioRecord không hợp lệ thay vì đơn giản là không thành công, sẽ hoàn toàn gạch hệ thống phụ thu âm nếu được thử. Bạn cần đặt lại điện thoại để khôi phục từ trạng thái này.

2. Lấy mẫu không nhất quán-Rate hỗ trợ cùng phiên bản của cùng một mô hình điện thoại

Trên cũ Điện thoại Galaxy Ace, ghi @ 11025Hz, 16-bit mono sẽ thành công. Trên phiên bản Ace mới hơn, cấu hình AudioRecord này sẽ được chấp nhận là hợp lệ, nhưng bản ghi kết quả sẽ bị méo, với hiệu ứng "chipmunk". Một ứng dụng tuner guitar rất phổ biến đã hardcoded tỷ lệ lấy mẫu này là không cung cấp cho đọc đúng điều chỉnh trên các điện thoại này chính xác vì vấn đề này!

3. Thu âm âm lượng cực thấp trên một số cấu hình.

Trong Galaxy Young và Galaxy Ace, ghi âm từ mic hoặc nguồn âm thanh mặc định @ 44,100Hz (tốc độ được cho là chuẩn khi mọi thứ hoạt động tốt) tạo ra bản ghi âm không bị phân loại nhưng cực nhỏ. Tôi chưa tìm được cách nào để sửa lỗi này ngoài khuếch đại phần mềm (tương đương với việc phóng đại một hình ảnh có độ phân giải rất thấp, với sự kết hợp "jageddnes" của kết quả).

4. Không hỗ trợ tỷ lệ lấy mẫu 44,100Hz chuẩn trên mọi nguồn thu âm.

Trong Galaxy Young và Galaxy Ace, ghi từ nguồn máy quay không thành công @ 44,100Hz. (một lần nữa, cấu hình sẽ được chấp nhận là hợp lệ) tạo ra rác hoàn chỉnh. Tuy nhiên, ghi âm @ 8,000Hz, 16.000Hz và 48,000Hz hoạt động tốt và tạo ra một bản ghi âm với mức âm lượng rất có thể chấp nhận được. Điều bực bội là theo tài liệu Android, 44,100Hz là tốc độ lấy mẫu mà tất cả các thiết bị NÊN hỗ trợ.

5. OpenSL không khắc phục bất kỳ sự cố nào được báo cáo.

Làm việc với NDK và OpenSL tạo ra cùng một kết quả được mô tả. Có vẻ như lớp AudioRecorder chỉ đơn giản là gói các cuộc gọi đến OpenSL, và vấn đề là dựa trên phần cứng, hoặc được chôn ở tầng mức thấp hơn trong mã hạt nhân.

Tình trạng này thực sự rất không may, vì các mô hình này đang trở nên rất phổ biến - ít nhất là ở Mexico.

Chúc may mắn - và vui lòng báo cáo nếu bạn may mắn hơn khi làm việc với những điện thoại này. =)

+0

Dường như bạn biết khá nhiều về vấn đề này. Tôi đang đối mặt với cùng một vấn đề ngay bây giờ. Bạn có thể biết nếu có một sửa chữa nào được nêu ra bởi Samsung? Tôi hỏi vì tôi không có thiết bị, tôi cần 44100Hz và tôi không có ý tưởng phải làm gì bây giờ. – stefple

+0

... xin lỗi quên để nói: Đó là người dùng ofc có vấn đề bây giờ mà ứng dụng của tôi không hoạt động. Giải pháp duy nhất tôi thấy bây giờ là, tôi loại trừ các thiết bị đó. – stefple

+0

Xin chào @stefple, không, tôi không biết liệu có khắc phục được không. Hiện tại chúng tôi đang xử lý 44.100 trên mô hình Ace và Young bằng cách sử dụng nguồn âm thanh MIC và áp dụng khuếch đại phần mềm (nhân các mẫu bằng một hằng số và cắt bớt giá trị nếu nó tràn) để bù cho các mức thấp. Chất lượng bị ảnh hưởng, nhưng nó là đủ tốt bốn mục đích DSP của chúng tôi. Ghi bằng cách sử dụng các công trình CAMCORDER @ 48000Hz với mức âm lượng rất tốt. Nếu bạn có thể đủ khả năng thêm một thói quen chuyển đổi tỷ lệ mẫu, bạn có thể đi từ 48000Hz đến 44100Hz với ít tổn thất chất lượng. –

1

Tăng tốc âm thanh Để tăng biên độ của âm thanh, bạn cần tính hệ số tăng và nhân hệ số tăng tính với mỗi mẫu được chụp. Đoạn mã sau thực hiện điều đó. P.S. Bỏ qua mã không liên quan

public class MainActivity extends Activity { 

public static final int SAMPLE_RATE = 16000; 

private AudioRecord mRecorder; 
private File mRecording; 
private short[] mBuffer; 
private final String startRecordingLabel = "Start recording"; 
private final String stopRecordingLabel = "Stop recording"; 
private boolean mIsRecording = false; 
private ProgressBar mProgressBar; 
float iGain = 1.0f; 
CheckBox gain; 

protected int bitsPerSamples = 16; 

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

    initRecorder(); 

    Button bluetooth = (Button)findViewById(R.id.blue); 
    gain = (CheckBox) findViewById(R.id.checkBox1); 
    mProgressBar = (ProgressBar) findViewById(R.id.progressBar); 

    final Button button = (Button) findViewById(R.id.start); 
    button.setText(startRecordingLabel); 

    bluetooth.setOnClickListener(new View.OnClickListener() { 

     @Override 
     public void onClick(View v) { 
      // TODO Auto-generated method stub 
      Intent i = new Intent(""); 
     } 
    }); 
    gain.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 

     @Override 
     public void onCheckedChanged(CompoundButton buttonView, 
       boolean isChecked) { 

      if (gain.isChecked()) { 
       iGain = 5.0f; 

      } else { 
       iGain = 2.0f; 
      } 
     } 
    }); 

    button.setOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(final View v) { 
      if (!mIsRecording) { 
       button.setText(stopRecordingLabel); 
       mIsRecording = true; 
       mRecorder.startRecording(); 
       mRecording = getFile("raw"); 
       startBufferedWrite(mRecording); 
      } else { 
       button.setText(startRecordingLabel); 
       mIsRecording = false; 
       mRecorder.stop(); 
       File waveFile = getFile("wav"); 
       try { 
        rawToWave(mRecording, waveFile); 
       } catch (IOException e) { 
        Toast.makeText(MainActivity.this, e.getMessage(), 
          Toast.LENGTH_SHORT).show(); 
       } 
       Toast.makeText(MainActivity.this, 
         "Recorded to " + waveFile.getName(), 
         Toast.LENGTH_SHORT).show(); 
      } 
     } 
    }); 
} 

@Override 
public void onDestroy() { 
    mRecorder.release(); 
    super.onDestroy(); 
} 

private void initRecorder() { 
    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); 
} 

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); 

        final int bytesPerSample = bitsPerSamples/8; 
        final int emptySpace = 64 - bitsPerSamples; 
        int byteIndex = 0; 
        int byteIndex2 = 0; 
        int temp = 0; 
        int mLeftTemp = 0; 
        int mRightTemp = 0; 
        int a = 0; 
        int x = 0; 

        for (int frameIndex = 0; frameIndex < readSize; frameIndex++) { 

         for (int c = 0; c < 1; c++) { 

          if (iGain != 1) { 

           long accumulator = 0; 
           for (int b = 0; b < bytesPerSample; b++) { 

            accumulator += ((long) (mBuffer[byteIndex++] & 0xFF)) << (b * 8 + emptySpace); 
           } 

           double sample = ((double) accumulator/(double) Long.MAX_VALUE); 
           sample *= iGain; 
           int intValue = (int) ((double) sample * (double) Integer.MAX_VALUE); 

           for (int i = 0; i < bytesPerSample; i++) { 
            mBuffer[i + byteIndex2] = (byte) (intValue >>> ((i + 2) * 8) & 0xff); 
           } 
           byteIndex2 += bytesPerSample; 

          } 
         }// end for(channel) 

         // mBuffer[frameIndex] *=iGain; 
         if (mBuffer[frameIndex] > 32765) { 
          mBuffer[frameIndex] = 32767; 

         } else if (mBuffer[frameIndex] < -32767) { 
          mBuffer[frameIndex] = -32767; 
         } 
         output.writeShort(mBuffer[frameIndex]); 
         sum += mBuffer[frameIndex] * mBuffer[frameIndex]; 

        } 

        if (readSize > 0) { 
         final double amplitude = sum/readSize; 
         mProgressBar.setProgress((int) Math.sqrt(amplitude)); 
        } 
       } 
      } catch (IOException e) { 
       Toast.makeText(MainActivity.this, e.getMessage(), 
         Toast.LENGTH_SHORT).show(); 
      } finally { 
       mProgressBar.setProgress(0); 
       if (output != null) { 
        try { 
         output.flush(); 
        } catch (IOException e) { 
         Toast.makeText(MainActivity.this, e.getMessage(), 
           Toast.LENGTH_SHORT).show(); 
        } finally { 
         try { 
          output.close(); 
         } catch (IOException e) { 
          Toast.makeText(MainActivity.this, e.getMessage(), 
            Toast.LENGTH_SHORT).show(); 
         } 
        } 
       } 
      } 
     } 
    }).start(); 
} 

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 
     // see http://ccrma.stanford.edu/courses/422/projects/WaveFormat/ 
     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) { 

      // Apply Gain 
      /* 
      * s *= iGain; if(s>32767) { s=32767; } else if(s<-32768) { 
      * s=-32768; } 
      */ 
      bytes.putShort(s); 
     } 
     output.write(bytes.array()); 
    } finally { 
     if (output != null) { 
      output.close(); 
     } 
    } 
} 

private File getFile(final String suffix) { 
    Time time = new Time(); 
    time.setToNow(); 
    return new File(Environment.getExternalStorageDirectory(), 
      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)); 
    } 
} 
}