我怎么能播放pcm文件

时间:2013-06-09 16:33:03

标签: android audio-recording voice-recording

以下代码应录制音频并以PCM格式存储到SD卡中。 代码正在与我合作,但PCM文件无法播放!!!!

我从此链接获得此代码.... Android : recording audio using audiorecord class play as fast forwarded

我需要播放PCM文件我该怎么做??????

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

4 个答案:

答案 0 :(得分:4)

Android的媒体播放器默认不播放PCM文件。任

  1. 将其从SD卡复制到计算机并在那里播放
  2. 使用AudioTrack
  3. 编写自己的播放器
  4. 安装播放PCM的应用
  5. 以下是有关如何使用AudioTrack课程播放PCM的教程:(http://jongladwin.blogspot.co.uk/2010/03/android-play-pcmwav-audio-buffer-using.html

    Windows Media Player应该能够播放PCM,这里提到了一些替代方案:(http://www.makeuseof.com/answers/play-pcm-file-pc/

    我猜Android上大多数大型音乐播放器应用都支持PCM。

答案 1 :(得分:3)

我也使用了你的代码,但我的语音记录就像一个&#34; zzzzz&#34;记录。所以我改变了一点代码,现在我可以通过智能手机和PC(在这种情况下使用Audacity)可以毫无问题地收听并歪曲记录。 这是我的代码:

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

答案 2 :(得分:2)

这是我的解决方案

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

    }
}

答案 3 :(得分:0)

private void startRecording(){     if(bufferSize == AudioRecord.ERROR_BAD_VALUE)         Log.e(标签,“错误值为”bufferSize \“,硬件不支持录制参数”);

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

}

替换录制代码......