Question

The following code should record audio and store it in to SD card in PCM format. the code is working with me ,but the PCM file doesn't play !!!!

I got this code from this link.... Android : recording audio using audiorecord class play as fast forwarded

I need to play the PCM file How can i do that ??????

public class Audio_Record 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);
    System.out.println("Short wirting to file" + sData.toString());
    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);
 }
}
Was it helpful?

Solution

Android's media player by default doesn't play PCM files. Either

  1. Copy it from your SD card to your computer and play it there
  2. Write your own player using AudioTrack
  3. Install an app that plays PCM

Here's a tutorial on how to play PCM using the AudioTrack class: (http://jongladwin.blogspot.co.uk/2010/03/android-play-pcmwav-audio-buffer-using.html)

Windows Media Player should be able to play PCM, some alternatives are mentioned here: (http://www.makeuseof.com/answers/play-pcm-file-pc/)

I guess most of the big music player apps on Android will support PCM.

OTHER TIPS

I also used your code, but my voice record was like a "zzzzz" record. So I changed a little the code and now I can listen without problems and distortions the record both by smartphone and by PC (in this case with Audacity). This is my code:

public class VoiceActivity extends Activity {
private static final String TAG = "VoiceRecord";

private static final int RECORDER_SAMPLERATE = 8000;     
private static final int RECORDER_CHANNELS_IN = AudioFormat.CHANNEL_IN_MONO;
private static final int RECORDER_CHANNELS_OUT = AudioFormat.CHANNEL_OUT_MONO;
private static final int RECORDER_AUDIO_ENCODING = AudioFormat.ENCODING_PCM_16BIT;

private static final int AUDIO_SOURCE = MediaRecorder.AudioSource.MIC;

// Initialize minimum buffer size in bytes.
private int bufferSize = AudioRecord.getMinBufferSize(RECORDER_SAMPLERATE, RECORDER_CHANNELS_IN, RECORDER_AUDIO_ENCODING);

private AudioRecord recorder = null;
private Thread recordingThread = null;
private boolean isRecording = false;

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

    ((Button) findViewById(R.id.start_button)).setOnClickListener(btnClick);
    ((Button) findViewById(R.id.stop_button)).setOnClickListener(btnClick);
    enableButtons(false);   
}

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

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

private void startRecording() {
    if( bufferSize == AudioRecord.ERROR_BAD_VALUE)
        Log.e( TAG, "Bad Value for \"bufferSize\", recording parameters are not supported by the hardware");

    if( bufferSize == AudioRecord.ERROR )
        Log.e( TAG, "Bad Value for \"bufferSize\", implementation was unable to query the hardware for its output properties");

    Log.e( TAG, "\"bufferSize\"="+bufferSize);

    // Initialize Audio Recorder.    
    recorder = new AudioRecord(AUDIO_SOURCE, RECORDER_SAMPLERATE, RECORDER_CHANNELS_IN, RECORDER_AUDIO_ENCODING, bufferSize);
    // Starts recording from the AudioRecord instance.
    recorder.startRecording();

    isRecording = true;

    recordingThread = new Thread(new Runnable() {
        public void run() {
            writeAudioDataToFile();
        }
    }, "AudioRecorder Thread");
    recordingThread.start();
}

private void writeAudioDataToFile() {
    //Write the output audio in byte
    String filePath = "/sdcard/8k16bitMono.pcm";
    byte saudioBuffer[] = new byte[bufferSize];

    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(saudioBuffer, 0, bufferSize);
        try {
            //  writes the data to file from buffer stores the voice buffer
            os.write(saudioBuffer, 0, bufferSize);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    try {
        os.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

private void stopRecording() throws IOException {
    //  stops the recording activity
    if (null != recorder) {
        isRecording = false;  
        recorder.stop();
        recorder.release();
        recorder = null;
        recordingThread = null;
        PlayShortAudioFileViaAudioTrack("/sdcard/8k16bitMono.pcm");
    }   
}

private void PlayShortAudioFileViaAudioTrack(String filePath) throws IOException{
    // We keep temporarily filePath globally as we have only two sample sounds now..
    if (filePath==null)
        return;

    //Reading the file.. 
    File file = new File(filePath); // for ex. path= "/sdcard/samplesound.pcm" or "/sdcard/samplesound.wav"
    byte[] byteData = new byte[(int) file.length()];
    Log.d(TAG, (int) file.length()+"");

    FileInputStream in = null;
    try {
        in = new FileInputStream( file );
        in.read( byteData );
        in.close(); 
    } catch (FileNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    // Set and push to audio track..
    int intSize = android.media.AudioTrack.getMinBufferSize(RECORDER_SAMPLERATE, RECORDER_CHANNELS_OUT, RECORDER_AUDIO_ENCODING); 
    Log.d(TAG, intSize+"");

    AudioTrack at = new AudioTrack(AudioManager.STREAM_MUSIC, RECORDER_SAMPLERATE, RECORDER_CHANNELS_OUT, RECORDER_AUDIO_ENCODING, intSize, AudioTrack.MODE_STREAM); 
    if (at!=null) { 
        at.play();
        // Write the byte array to the track
        at.write(byteData, 0, byteData.length); 
        at.stop();
        at.release();
    }
    else
        Log.d(TAG, "audio track is not initialised ");

}

private View.OnClickListener btnClick = new View.OnClickListener() {
    public void onClick(View v) {
        switch (v.getId()) {
        case R.id.start_button: {
            enableButtons(true);
            startRecording();
            break;
        }
        case R.id.stop_button: {
            enableButtons(false);
            try {
                stopRecording();
            } catch (IOException e) {
                //  TODO Auto-generated catch block
                e.printStackTrace();
            }
            break;
        }
        }
    }   
};

    // onClick of backbutton finishes the activity.
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_BACK) {
        finish();
    }
    return super.onKeyDown(keyCode, event);
}
}

it's my solution

public class AudioTrackPlayer {
    private String pathAudio;
    private AudioTrack audioPlayer;
    private Thread mThread;
    private int bytesread = 0, ret = 0;
    private int size;
    private FileInputStream in = null;
    private byte[] byteData = null;
    private int count = 512 * 1024; // 512 kb
    private boolean isPlay = true;
    private boolean isLooping = false;
    private static Handler mHandler;

    public AudioTrackPlayer() {

    }

    public void prepare(String pathAudio){
        this.pathAudio = pathAudio;
        mHandler = new Handler();
    }

    public void play(){
        stop();

        isPlay = true;
        bytesread = 0;
        ret = 0;
        if (pathAudio == null)
            return;

        audioPlayer = createAudioPlayer();
        if (audioPlayer == null) return;
        audioPlayer.play();

        mThread = new Thread(new PlayerProcess());
        mThread.start();
    }

    private final Runnable mLopingRunnable = new Runnable() {
        @Override
        public void run() {
            play();
        }
    };

    private AudioTrack createAudioPlayer(){
        int intSize = android.media.AudioTrack.getMinBufferSize(16000, AudioFormat.CHANNEL_CONFIGURATION_MONO,
                AudioFormat.ENCODING_PCM_16BIT);
        AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, 16000, AudioFormat.CHANNEL_CONFIGURATION_MONO,
                AudioFormat.ENCODING_PCM_16BIT, intSize, AudioTrack.MODE_STREAM);
        if (audioTrack == null) {
            Log.d("TCAudio", "audio track is not initialised ");
            return null;
        }

        File file = null;
        file = new File(pathAudio);

        byteData = new byte[(int) count];
        try {
            in = new FileInputStream(file);

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

        size = (int) file.length();
        return  audioTrack;
    }

    private class PlayerProcess implements Runnable{

        @Override
        public void run() {
            while (bytesread < size && isPlay) {
                if (Thread.currentThread().isInterrupted()) {
                    break;
                }
                try {
                    ret = in.read(byteData, 0, count);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                if (ret != -1) { // Write the byte array to the track
                    audioPlayer.write(byteData,0, ret);
                    bytesread += ret;
                } else break;
            }
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (audioPlayer!=null){
                if (audioPlayer.getState()!=AudioTrack.PLAYSTATE_STOPPED){
                    audioPlayer.stop();
                    audioPlayer.release();
                    mThread = null;
                }
            }
            if (isLooping && isPlay ) mHandler.postDelayed(mLopingRunnable,100);
        }
    }

    public void setLooping(){
        isLooping = !isLooping;
    }

    public void pause(){

    }

    public void stop(){
        isPlay = false;
        if (mThread != null) {
            mThread.interrupt();
            mThread = null;
        }
        if (audioPlayer != null) {
            audioPlayer.stop();
            audioPlayer.release();
            audioPlayer = null;
        }
    }

    public void reset(){

    }
}

private void startRecording() { if( bufferSize == AudioRecord.ERROR_BAD_VALUE) Log.e( TAG, "Bad Value for \"bufferSize\", recording parameters are not supported by the hardware");

if( bufferSize == AudioRecord.ERROR )
    Log.e( TAG, "Bad Value for \"bufferSize\", implementation was unable to query the hardware for its output properties");

Log.e( TAG, "\"bufferSize\"="+bufferSize);

// Initialize Audio Recorder.    
recorder = new AudioRecord(AUDIO_SOURCE, RECORDER_SAMPLERATE, AudioFormat.CHANNEL_CONFIGURATION_MONO, RECORDER_AUDIO_ENCODING, bufferSize);
// Starts recording from the AudioRecord instance.
recorder.startRecording();

isRecording = true;

recordingThread = new Thread(new Runnable() {
    public void run() {
        writeAudioDataToFile();
    }
}, "AudioRecorder Thread");
recordingThread.start();

}

Replace Recording Code...

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top