Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.1k views
in Technique[技术] by (71.8m points)

audio - Android Play PCM byte array from Converted from Base64 String Slow Sounds

As the very long title suggests, I'm having trouble playing the audio from a audio that I send over the network through PubNunb. What I do is I send the audio while recording from AudioRecord using this code:

 AudioConfig audioConfig = getValidSampleRates(AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT);
    buffer = new byte[audioConfig.getBufferSize()];

    recorder = new AudioRecord(MediaRecorder.AudioSource.MIC, audioConfig.getSampleSize(), AudioFormat.CHANNEL_IN_MONO, AUDIO_FORMAT, audioConfig.getBufferSize());

Recorded data is sent when the user holds the button down:

   private class RecorderRunnable implements Runnable {
    @Override
    public void run() {
        while(mRecording) {
            Log.d("RECORDER_STATE", "Recording LOOP");
            recorder.read(buffer, 0, buffer.length);

            String base64EncodedBuffer = Base64.encodeToString(buffer, Base64.NO_WRAP);

            pubnub.publish(MainActivity.CHANNEL_ID, base64EncodedBuffer, new Callback() {
                @Override
                public void successCallback(String channel, Object message) {
                    super.successCallback(channel, message);
                }
            });
        }
    }
}

Receive code:

       @Override
                    public void successCallback(String channel, final Object message) {


                        byte[] decodedBase64 = Base64.decode(message.toString(), Base64.NO_WRAP);

                        speaker.write(decodedBase64, 0, decodedBase64.length);
                    }

Issue: I get the audio, but I get sounds that are really slow. "Hello" would sound like: "Hee-*static*-ll-*static*-oo"

To rule out possible causes, I tried immediately playing the audio like this (without the network):

 while(mRecording) {
            Log.d("RECORDER_STATE", "Recording LOOP");
            recorder.read(buffer, 0, buffer.length);

            String base64EncodedBuffer = Base64.encodeToString(buffer, Base64.NO_WRAP);

            byte[] decodedBase64 = Base64.decode(base64EncodedBuffer, Base64.NO_WRAP);

            speaker.write(decodedBase64, 0, decodedBase64.length);
        }

(Note: I did the convert to base64 and back to byte array on purpose.)

The result for the code above (directly playing it after recording) is pretty good. So I'm wondering what I'm doing wrong when handling it over the network.

Any suggestion is appreciated. Thank you.

Edit: 08/28/2015 Found a good explanation for this here. But now the question is, what's the best way of handling network jitter/buffering and packetloss using my current implementation.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

pubnub delivers data through tcp (not udp). http://www.pubnub.com/knowledge-base/discussion/263/does-pubnub-support-the-udp-protocol

There should be no need to handle packet loss in your application.

You may need to handle jitter by creating a buffer of some sort. Since there would be no rigid realtime constraint, I will discuss an approach rather than pasting code.

You can make a buffer using a queue. I suggest having two threads. One for your reader (your player) and one for writer (the network stream). Let the writer queue up some data (maybe a few seconds of data) before letting the reader read. On paper, with a very simply proof of concept, you should not have issues with simultaneous reads and writes since the writer is writing to the end of the queue and the reader is reading at the beginning of the queue.

Think of it as a bucket that is halfway full. You pour water in and let water leak out at the same rate.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...