无法在 Android 中播放使用 AudioRecord 录制的 pcm 文件

Posted

技术标签:

【中文标题】无法在 Android 中播放使用 AudioRecord 录制的 pcm 文件【英文标题】:Unable to play the pcm file recorded using AudioRecord in Android 【发布时间】:2016-09-22 15:30:05 【问题描述】:

我正在开发一个 android 应用程序。在我的应用程序中,我需要使用 AudionRecord 录制音频并需要播放它。但是在播放录制的 pcm 文件时抛出错误。主要问题是我也无法记录错误,因为我必须在真实设备上进行测试并且无法在模拟器上运行。因为当我在模拟器上运行并录制时,我的应用程序崩溃了。

这是我的活动

public class MainActivity extends AppCompatActivity 

    Boolean recording;
    private Thread recordingThread = null;
    DataOutputStream dataOutputStream;
    short[] audioData;


    private Button btnPlay,btnStop,btnRecord;
    private String outputFile = null;
    //outputFile = Environment.getExternalStorageDirectory().getAbsolutePath()+"/recording.3gp";
    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initialize();
        initViews();
        setUpViews();
    

    private void initialize()
    

    

    private void initViews()
    
        btnPlay = (Button)findViewById(R.id.btn_play);
        btnRecord = (Button)findViewById(R.id.btn_record);
        btnStop = (Button)findViewById(R.id.btn_stop);
    

    private void setUpViews()
    
        btnRecord.setOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View v) 
                startRecord();
            
        );

        btnStop.setOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View v) 
                recording = false;
                Toast.makeText(getBaseContext(),"Stopped",Toast.LENGTH_SHORT).show();
            
        );

        btnPlay.setOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View v) 
                playRecord();
            
        );
    

    private void startRecord()

        File file = new File(Environment.getExternalStorageDirectory(), "test.pcm");

        try 
            file.createNewFile();

            OutputStream outputStream = new FileOutputStream(file);
            BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream);
            dataOutputStream = new DataOutputStream(bufferedOutputStream);

            final int minBufferSize = AudioRecord.getMinBufferSize(11025,
                    AudioFormat.CHANNEL_CONFIGURATION_MONO,
                    AudioFormat.ENCODING_PCM_16BIT);

            audioData = new short[minBufferSize];

            final AudioRecord audioRecord = new AudioRecord(MediaRecorder.Audiosource.MIC,
                    11025,
                    AudioFormat.CHANNEL_CONFIGURATION_MONO,
                    AudioFormat.ENCODING_PCM_16BIT,
                    minBufferSize);

            audioRecord.startRecording();

            Toast.makeText(getBaseContext(),"Recording",Toast.LENGTH_SHORT).show();


            recordingThread = new Thread(new Runnable() 
                public void run() 
                    while(recording)
                        int numberOfShort = audioRecord.read(audioData, 0, minBufferSize);
                        for(int i = 0; i < numberOfShort; i++)
                            try
                                dataOutputStream.writeShort(audioData[i]);
                            
                            catch (IOException e)
                            
                                Toast.makeText(getBaseContext(),e.getMessage(),Toast.LENGTH_SHORT).show();
                            
                        
                    
                
            , "AudioRecorder Thread");

            audioRecord.stop();
            dataOutputStream.close();

         catch (IOException e) 
            e.printStackTrace();
        

    

    private void playRecord()

        File file = new File(Environment.getExternalStorageDirectory(), "test.pcm");

        int shortSizeInBytes = Short.SIZE/Byte.SIZE;

        int bufferSizeInBytes = (int)(file.length()/shortSizeInBytes);
        short[] audioData = new short[bufferSizeInBytes];

        try 
            InputStream inputStream = new FileInputStream(file);
            BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
            DataInputStream dataInputStream = new DataInputStream(bufferedInputStream);

            int i = 0;
            while(dataInputStream.available() > 0)
                audioData[i] = dataInputStream.readShort();
                i++;
            

            dataInputStream.close();

            AudioTrack audioTrack = new AudioTrack(
                    AudioManager.STREAM_MUSIC,
                    11025,
                    AudioFormat.CHANNEL_CONFIGURATION_MONO,
                    AudioFormat.ENCODING_PCM_16BIT,
                    bufferSizeInBytes,
                    AudioTrack.MODE_STREAM);

            audioTrack.play();
            audioTrack.write(audioData, 0, bufferSizeInBytes);


         catch (FileNotFoundException e) 
            e.printStackTrace();
         catch (IOException e) 
            e.printStackTrace();
        
    


问题在于播放录制的 pcm。当我单击播放按钮时,应用程序抛出致命错误并停止。我也无法记录错误。 pcm 文件也确实存在于定义的路径中。我的代码有什么问题?为什么不能播放?

如下图所示,pcm文件录制完成后创建成功

【问题讨论】:

audioRecord.startRecording(); ... 几个 CPU 周期后 ... audioRecord.stop(); ... recordingThread 永远不会启动 ... 等等... 【参考方案1】:

没有看到 Logcat,很难在代码中找出问题所在。看看这个关于“如何使用 AudioTrack 播放 pcm 文件”的工作代码:

private void PlayAudioFileViaAudioTrack(String filePath) throws IOException

// We keep temporarily filePath globally as we have only two sample sounds now..
if (filePath==null)
return;

int intSize = android.media.AudioTrack.getMinBufferSize(44100, AudioFormat.CHANNEL_CONFIGURATION_STEREO,
AudioFormat.ENCODING_PCM_16BIT); 

AudioTrack at = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_CONFIGURATION_STEREO,
AudioFormat.ENCODING_PCM_16BIT, intSize, AudioTrack.MODE_STREAM); 


if (at==null) 
Log.d("TCAudio", "audio track is not initialised ");
return; 


int count = 512 * 1024; // 512 kb
//Reading the file..
byte[] byteData = null; 
File file = null; 
file = new File(filePath);

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

 catch (FileNotFoundException e) 
// TODO Auto-generated catch block
e.printStackTrace();


int bytesread = 0, ret = 0;
int size = (int) file.length();
at.play();
while (bytesread < size)  
   ret = in.read( byteData,0, count); 
   if (ret != -1)  // Write the byte array to the track 
    at.write(byteData,0, ret); 
    bytesread += ret; 
     

    else break; 
 
    in.close();    
    at.stop(); 
    at.release(); 

来自http://jongladwin.blogspot.co.uk/2010/03/android-play-pcmwav-audio-buffer-using.html的代码

【讨论】:

以上是关于无法在 Android 中播放使用 AudioRecord 录制的 pcm 文件的主要内容,如果未能解决你的问题,请参考以下文章

无法使用 MediaPlayer 对象在 Android 中播放许多音频文件

在android中使用listview无法正常播放视频

无法在 android 中使用 MediaPlayer 播放 MediaStore.Audio 歌曲

无法在对话框中使用 android MediaPlayer 播放声音?

无法在 Android 中使用 React Native Video DRM Fork 播放 DRM 视频

无法使用 LibGDX 在 Android 上播放 2 个音乐实例