N
N
nuclear_kote2020-06-02 15:45:34
Android
nuclear_kote, 2020-06-02 15:45:34

Why is no sound playing?

public class VoicePlayer extends Plugin {

    private AudioTrack track;
    private final BlockingDeque<byte[]> queue = new LinkedBlockingDeque<>();

    MediaCodec decoder = null;

    @PluginMethod
    public void init(PluginCall call) {
        Context context = getContext();

        int bufferLength = call.getInt("bufferLength", 16384);
        AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
        audioManager.setMode(AudioManager.STREAM_MUSIC);

        AudioFormat.Builder audioFormatBuilder = new AudioFormat.Builder();
        audioFormatBuilder.setSampleRate(Parameters.SAMPLE_RATE);
        audioFormatBuilder.setChannelMask(AudioFormat.CHANNEL_OUT_DEFAULT);
        audioFormatBuilder.setEncoding(AudioFormat.ENCODING_PCM_16BIT);

        AudioAttributes.Builder aBuilder = new AudioAttributes.Builder();
        aBuilder.setContentType(AudioAttributes.CONTENT_TYPE_SPEECH);
        track =
                new AudioTrack(aBuilder.build(), audioFormatBuilder.build(),
                        bufferLength*10, AudioTrack.MODE_STREAM, AudioManager.AUDIO_SESSION_ID_GENERATE);

        track.play();
        try {
            decoder = makeDecoder();
            decoder.start();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    @PluginMethod
    public void destroy(PluginCall call) {
        if (track != null) {
            track.stop();
            track.release();
        }
    }

    @PluginMethod()
    public void play(PluginCall call) {
        try {

            byte[] base64s = readBase64AsByteArray(call.getString("base64"));
            queue.add(base64s);
            call.resolve(ResponseGenerator.successResponse());
        } catch (Exception e) {
            call.reject("PLAY_ERROR", e);
        } finally {
           // if (decoder != null) {
             //   decoder.stop();
              //  decoder.release();
            //}
        }

    }


    private MediaCodec makeDecoder() throws IOException {
        MediaCodec decoder = MediaCodec.createDecoderByType("audio/mp4a-latm");
        MediaFormat format = new MediaFormat();
        format.setString(MediaFormat.KEY_MIME, "audio/mp4a-latm");
        format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, Parameters.CHANNELS);
        format.setInteger(MediaFormat.KEY_SAMPLE_RATE, Parameters.SAMPLE_RATE);
        format.setInteger(MediaFormat.KEY_BIT_RATE, Parameters.BIT_RATE);
        //AAC-HE 64kbps
        format.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectHE);
        decoder.configure(format, null, null, 0);
        decoder.setCallback(new MediaCodec.Callback() {
            @Override
            public void onInputBufferAvailable(MediaCodec mediaCodec, int i) {
                //One InputBuffer is available to decode
                try {
//                    while (true) {
                        byte[] data = queue.takeFirst();
                        ByteBuffer buffer = mediaCodec.getInputBuffer(i);
                        buffer.put(data, 0, data.length);
                        mediaCodec.queueInputBuffer(i, 0, data.length, 0, 0);
//                        break;
//                    }
                } catch (Exception ignored) {
                    ignored.printStackTrace();
                }
            }

            @Override
            public void onOutputBufferAvailable(MediaCodec mediaCodec, int i, MediaCodec.BufferInfo info) {
                //DECODING PACKET ENDED
                ByteBuffer outBuffer = mediaCodec.getOutputBuffer(i);
                byte[] chunk = new byte[info.size];
                outBuffer.get(chunk); // Read the buffer all at once
                outBuffer.clear();
                track.write(chunk, info.offset, info.offset + info.size); // AudioTrack write data
                mediaCodec.releaseOutputBuffer(i, false);
            }

            @Override
            public void onError(MediaCodec mediaCodec, MediaCodec.CodecException e) {
                notifyListeners("playError", ResponseGenerator.failResponse(e));
            }

            @Override
            public void onOutputFormatChanged(MediaCodec mediaCodec, MediaFormat mediaFormat) {
            }
        });

        return decoder;
    }


    private byte[] readBase64AsByteArray(String base64) {
        return Base64.decode(base64, Base64.DEFAULT);
    }

}


In general, I am making a plugin for ionic (capacitor), a base64 string containing aac arrives in play, after which it is decoded to pcm and played through AudioTrack. The problem is that MediaCodec.Callback()::onInputBufferAvailable is not called, or rather it is called occasionally, it is not clear under what conditions and throws an IllegalStateException, if called,
onOutputBufferAvailable is never called

Answer the question

In order to leave comments, you need to log in

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question