音频播放令人头痛

发布于 2024-11-03 02:37:43 字数 4608 浏览 1 评论 0原文

我希望有人能指出我正确的方向。我已经能够让录音和电平表正常工作。我已经开始播放音频,这让我有些头疼。我阅读了有关 MediaPlayer 和 AudioTrack 的各种文章以及这两个类之间的一些差异。我读到的一件事是这两个类都支持 PCM,这是我录制的音频的格式。

在音频录制中,我使用 AudioRecord 类来捕获 16 位 PCM 单声道数据。我正在捕获数据,然后将数据写入保存到 SD 卡的文件中。这是写入文件的代码的核心:

        totalAudioLen = in.getChannel().size();
        totalDataLen = totalAudioLen + 36;

        WriteWaveFileHeader(out, totalAudioLen, totalDataLen,
                longSampleRate, channels, byteRate);

        while (dis.available() > 0 )
        {
            dos.writeShort(dis.readShort());
        }

这是写入 WAVE 标头的代码:

    byte[] header = new byte[44];

    header[0] = 'R';  // RIFF/WAVE header
    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';  // 'fmt ' chunk
    header[13] = 'm';
    header[14] = 't';
    header[15] = ' ';
    header[16] = 16;  // 4 bytes: size of 'fmt ' chunk
    header[17] = 0;
    header[18] = 0;
    header[19] = 0;
    header[20] = 1;  // format = 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);  // block align
    header[33] = 0;
    header[34] = RECORDER_BPP;  // bits per sample
    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);

问题出在音频文件的播放上。 MediaPlayer 的播放速度确实很快,但结果是噪音很大。我正在获取使用上面的代码创建的文件,并尝试通过 MediaPlayer 推送它进行播放。据我所知,MediaPlayer 支持 16 位 PCM 音频,我相信我已经在上面创建了它。

    mPlayer = new MediaPlayer();
    mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
    File file = new File(mFileName);
    FileInputStream fis = new FileInputStream(file);
    mPlayer.setDataSource(mFileName);
    mPlayer.prepare();
    mPlayer.start();

当我使用AudioTrack时,音频播放正常,这意味着音频与录制时的一样。使用此类的一个大问题是我在尝试开始播放时遇到的延迟。我使用的是 Stream 模式,音频需要 5-15 秒才能开始播放,这是完全不可接受的。

以下是我用于调用 AudioTrack 类的代码:

    int intSize = android.media.AudioTrack.getMinBufferSize(RECORDER_SAMPLERATE, 
           AudioFormat.CHANNEL_CONFIGURATION_MONO,
           AudioFormat.ENCODING_PCM_16BIT);

    audioPlayer = new AudioTrack(AudioManager.STREAM_MUSIC,RECORDER_SAMPLERATE, 
                      AudioFormat.CHANNEL_CONFIGURATION_MONO,
                       AudioFormat.ENCODING_PCM_16BIT, 
                       intSize, 
                       AudioTrack.MODE_STREAM);

    short[] byteData = null;
    File file = null;
    file = new File(mFileName);

    InputStream is  = null;
    BufferedInputStream bis = null;
DataInputStream dis = null;

    try 
    {
        is = new FileInputStream( file );
        bis = new BufferedInputStream(is);
        dis = new DataInputStream(bis);
    } 
    catch (FileNotFoundException e) 
    {
        e.printStackTrace();
    }

    try
    {
        int bytesread = 0, ret = 0;
        int size = (int) file.length();
        audioPlayer.play();

        byteData = new short[size/2];

    while (dis.available() > 0 )
    {
        byteData[ret] = dis.readShort();
        ret++;
    }
    if (byteData != null ) 
    { 
        //  Write the byte array to the track 
        audioPlayer.write(byteData,0, ret); 
        bytesread += ret; 
    } 

    dis.close();

    is.close(); 
    audioPlayer.stop(); 
    audioPlayer.release();
    }
    catch(IOException e)
    {
        e.printStackTrace();
    }
    catch(Exception e)
    {
        e.printStackTrace();
    }

关于使用 MediaPlayer 时可能导致静态的原因有什么想法吗?或者关于如何提高使用 AudioTrack 时的性能的任何想法?

I am hoping someone can point me in the right direction. I have been able to get the audio recording to work good, as well as level meters. I have moved onto playback of audio, which is causing me some headaches. I have read various articles relating to MediaPlayer and AudioTrack and some of the differences between the two classes. One thing that I did read was that both classes support PCM, which is the format of my recorded audio.

In the recording of audio, I am using the AudioRecord class to capture 16-bit PCM mono data. I am capturing the data and then writing the data to a file that is saved to the SD card. Here is the core of the code to write to the file:

        totalAudioLen = in.getChannel().size();
        totalDataLen = totalAudioLen + 36;

        WriteWaveFileHeader(out, totalAudioLen, totalDataLen,
                longSampleRate, channels, byteRate);

        while (dis.available() > 0 )
        {
            dos.writeShort(dis.readShort());
        }

and here is the code for writing the WAVE header:

    byte[] header = new byte[44];

    header[0] = 'R';  // RIFF/WAVE header
    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';  // 'fmt ' chunk
    header[13] = 'm';
    header[14] = 't';
    header[15] = ' ';
    header[16] = 16;  // 4 bytes: size of 'fmt ' chunk
    header[17] = 0;
    header[18] = 0;
    header[19] = 0;
    header[20] = 1;  // format = 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);  // block align
    header[33] = 0;
    header[34] = RECORDER_BPP;  // bits per sample
    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);

The problem is with the playback of the audio file. MediaPlayer is really quick when it comes to playback but the result is loud static. I am taking the file that was created with the code above and trying to push it through MediaPlayer for playback. From what I have read, MediaPlayer supports 16-bit PCM audio, which I believe I have created above.

    mPlayer = new MediaPlayer();
    mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
    File file = new File(mFileName);
    FileInputStream fis = new FileInputStream(file);
    mPlayer.setDataSource(mFileName);
    mPlayer.prepare();
    mPlayer.start();

When I use AudioTrack, the audio playback is normal, meaning the audio is as it was recorded. The big problem with using this class is the latency that I am experiencing when trying to start the playback. I am using Stream mode and it is taking 5-15 seconds for the audio to start the playback, which is totally unacceptable.

Here is the code that I have for calling the AudioTrack class:

    int intSize = android.media.AudioTrack.getMinBufferSize(RECORDER_SAMPLERATE, 
           AudioFormat.CHANNEL_CONFIGURATION_MONO,
           AudioFormat.ENCODING_PCM_16BIT);

    audioPlayer = new AudioTrack(AudioManager.STREAM_MUSIC,RECORDER_SAMPLERATE, 
                      AudioFormat.CHANNEL_CONFIGURATION_MONO,
                       AudioFormat.ENCODING_PCM_16BIT, 
                       intSize, 
                       AudioTrack.MODE_STREAM);

    short[] byteData = null;
    File file = null;
    file = new File(mFileName);

    InputStream is  = null;
    BufferedInputStream bis = null;
DataInputStream dis = null;

    try 
    {
        is = new FileInputStream( file );
        bis = new BufferedInputStream(is);
        dis = new DataInputStream(bis);
    } 
    catch (FileNotFoundException e) 
    {
        e.printStackTrace();
    }

    try
    {
        int bytesread = 0, ret = 0;
        int size = (int) file.length();
        audioPlayer.play();

        byteData = new short[size/2];

    while (dis.available() > 0 )
    {
        byteData[ret] = dis.readShort();
        ret++;
    }
    if (byteData != null ) 
    { 
        //  Write the byte array to the track 
        audioPlayer.write(byteData,0, ret); 
        bytesread += ret; 
    } 

    dis.close();

    is.close(); 
    audioPlayer.stop(); 
    audioPlayer.release();
    }
    catch(IOException e)
    {
        e.printStackTrace();
    }
    catch(Exception e)
    {
        e.printStackTrace();
    }

Any ideas on what might be causing the static when using MediaPlayer? Or any ideas on how to improve the performance when using AudioTrack?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文