【问题标题】:Android - Audio Track noises [duplicate]Android - 音轨噪音[重复]
【发布时间】:2017-11-15 14:44:39
【问题描述】:

我正在通过我的 Android 应用程序上的 WebSocketClient 接收一些字节 []。这些字节是 MP3 字节: 第三层帧 单通道 MPEG-1 无校验和 48 kHz, 32 kbit/s 我要做的是在收到每个字节[] 后立即将其写入 AudioTrack。问题是,这些 bytes[] 是 MP3,这是一种 AudioTrack 类不接受的压缩格式。我正在尝试将它们解码为 PCM。 以下是我创建音轨的方法:

final AudioTrack player = new AudioTrack.Builder()
            .setAudioAttributes(new AudioAttributes.Builder()
                    .setUsage(AudioAttributes.USAGE_MEDIA)
                    .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
                    .build())
            .setAudioFormat(new AudioFormat.Builder()
                    .setEncoding(AudioFormat.ENCODING_PCM_16BIT)
                    .setSampleRate(48000)
                    .setChannelMask(AudioFormat.CHANNEL_OUT_STEREO)
                    .build())
            .setBufferSizeInBytes(AudioTrack.getMinBufferSize(48000, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT))
            .build();

最后这是服务器发送给我的内容。我不知道我应该如何构建我的音轨以匹配这种格式。采样率设置为 48000 Hz,我尝试了 CHANNEL_OUT_STEREO 和 MONO。我尝试了所有的 ENCODING 参数,但我的音质仍然很差,而且声音高。不知道我做错了什么。

流 #0:0:音频:mp3 (libmp3lame),48000 Hz,单声道,s16p,32 kb/s

编辑: 正如我在评论中所说,我尝试了在相关帖子中找到的有关 JLayer 解码的内容,这是新代码:

public void addSample(byte[] data) throws BitstreamException, DecoderException {
    Decoder decoder = new Decoder();
    InputStream bis = new ByteArrayInputStream(data);
    ByteArrayOutputStream outStream = new ByteArrayOutputStream();
    Bitstream bits = new Bitstream(bis);
    SampleBuffer pcmBuffer = (SampleBuffer) decoder.decodeFrame(bits.readFrame(), bits);

    for (int i = 0; i < pcmBuffer.getBufferLength(); i++) {
        if (pcmBuffer.getBuffer()[i] != 0) {
            outStream.write(pcmBuffer.getBuffer()[i] & 0xff);
            outStream.write((pcmBuffer.getBuffer()[i] >> 8) & 0xff);
        }
    }
    System.out.println("--------");
    for (int j = 0; j < outStream.toByteArray().length; j++) {
        System.out.println(outStream.toByteArray()[j]);
    }
    System.out.println("--------");
    mTrack.write(outStream.toByteArray(), 0, outStream.toByteArray().length);
    bits.closeFrame();
}

我没有直接写入 pcmBuffer 中包含的 short[] 数据,而是通过 outStream 和一些掩码操作将它们解码为 byte[]。我得到完全相同的结果(机器人声音)。但是,正如您所看到的,我尝试在写入 AudioTrack 的 byteArray 内循环,并尝试打印每个数据。以下是结果示例:

11-20 10:18:42.331 1749-2268/? I/System.out: 0
11-20 10:18:42.331 1749-2268/? I/System.out: 48
11-20 10:18:42.331 1749-2268/? I/System.out: 0
11-20 10:18:42.331 1749-2268/? I/System.out: 46
11-20 10:18:42.331 1749-2268/? I/System.out: 0
11-20 10:18:42.331 1749-2268/? I/System.out: 44
11-20 10:18:42.331 1749-2268/? I/System.out: 0
11-20 10:18:42.331 1749-2268/? I/System.out: 44
11-20 10:18:42.331 1749-2268/? I/System.out: 0
11-20 10:18:42.331 1749-2268/? I/System.out: 45
11-20 10:18:42.331 1749-2268/? I/System.out: 0
11-20 10:18:42.331 1749-2268/? I/System.out: 48
11-20 10:18:42.331 1749-2268/? I/System.out: 0

正如我所怀疑的,数据实际上写成(左,右,左,右)......我不知道如何从中获得真正的单声道 MP3 信号。

【问题讨论】:

  • @rckrd 我在研究中偶然发现了这篇文章,但它只是说 JLayer 可能是一个解决方案。我现在的问题是我无法让 JLayer 工作

标签: android mp3 pcm audiotrack


【解决方案1】:

AFAIK,如果输入已经是 PCM,您的代码就可以工作,因此您需要某种第 3 方代码。

如果你不想搞乱原生代码 (C/C++) 和 JNI 桥接,我建议你使用JLayer

编辑:您的编辑似乎没问题。您是否尝试过直接播放 MP3 样本(使用 JLayer),而不是使用 AudioTrack?

代码示例:

Player player;
/* create your input stream, bis in your code */     
player = new Player(bis);
player.play();

【讨论】:

  • 非常感谢!我有点迷路了,因为我以为我在这个示例中使用 JLayer 将我的 MP3 解码为 PCM。除非“buff = (SampleBuffer) decoder.decodeFrame(frameHeader, bits);”并没有真正解码我的 MP3
  • 很高兴您注意到它,请尝试看看是否有帮助。如果您在 JLayer 上需要更多帮助,请随时更新您的问题
  • 刚刚按照您的建议进行了更新。好像我没有正确使用 JLayer
  • 首先,非常感谢您的帮助,我终于使用另一个 AudioTrack 实例实现了它,我的已被弃用。我终于收到并播放声音。问题是现在它已经完全散列了。一切都是高音而不是连续的
  • @jineb92 很高兴你成功了。不知道那个高音,srry
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-08-26
  • 2015-10-01
  • 1970-01-01
  • 2018-09-25
  • 2018-10-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多