Android - 音频轨道噪音

时间:2017-11-15 14:44:40

标签: android mp3 pcm audiotrack

我在Android App上通过WebSocketClient接收了一些字节[]。那些字节是MP3字节: 第III层帧单信道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();
}

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

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信号。

1 个答案:

答案 0 :(得分:0)

AFAIK,如果输入已经是PCM,你的代码就可以工作了,所以你需要某种第三方代码。

如果您不想使用本机代码(C / C ++)和JNI网桥,我建议您使用JLayer

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

代码示例:

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