libpd / pd-for-android

Pure Data for Android
353 stars 91 forks source link

PdAudio::init() fails on specific devices #54

Closed rpattabi closed 6 years ago

rpattabi commented 8 years ago

I have the following code to initialize PdAudio

    private void configureAudioGlue() throws IOException {
        AudioParameters.init(mContext);

        int sampleRate = AudioParameters.suggestSampleRate();
        final int inputChannels = AudioParameters.suggestInputChannels(); // or 1
        final int outputChannels = AudioParameters.suggestOutputChannels();
        final int ticksPerBuffer = 8; // ignored from android 2.3 / openSL
        final boolean restart = true;

        PdAudio.initAudio(sampleRate, inputChannels, outputChannels, 
                                          ticksPerBuffer, restart);
    }

I find that this fails with IOException on the following devices, as per my app's crash reports

  1. Lenovo Vibe P1– P1a42
  2. Lenovo A680– A680
  3. Samsung Galaxy Core Prime – SM-G360H
  4. Samsung I9505 Galaxy S4 – GT-I9505

I suspected the suggested sample rate may be incorrect, so tried with other known sample rates. None of them work.

44100, 48000, 32000, 24000, 22050, 16000, 12000, 11025, 8000
tkirshboim commented 8 years ago

@rpattabi can you attach the stack trace that is being produced by the IOException? Is the stack trace identical on all of those devices? I've been testing pd-for-android apps on a Samsung Galaxy S4 mini device for a long time and never had any special issues with it.

rpattabi commented 8 years ago

@tkirshboim Sorry about the delay in responding. The stack traces are identical. The exception always comes from here ===> for these devices:

File: PdAudio.java

    public synchronized static void initAudio(int sampleRate, int inChannels, int outChannels, final int ticksPerBuffer, boolean restart)
            throws IOException {
        if (isRunning() && !restart) return;
        stopAudio();
        if (PdBase.openAudio(inChannels, outChannels, sampleRate, null) != 0) {
===>            throw new IOException("unable to open Pd audio: " + sampleRate + ", " + inChannels + ", " + outChannels);
        }
        if (!PdBase.implementsAudio()) {
            if (!AudioParameters.checkParameters(sampleRate, inChannels, outChannels) || ticksPerBuffer <= 0) {
                throw new IOException("bad Java audio parameters: " + sampleRate + ", " + inChannels + ", " + outChannels + ", " + ticksPerBuffer);
            }
            int bufferSizePerChannel = ticksPerBuffer * PdBase.blockSize();
            audioWrapper = new AudioWrapper(sampleRate, inChannels, outChannels, bufferSizePerChannel) {
                @Override
                protected int process(short[] inBuffer, short[] outBuffer) {
                    Arrays.fill(outBuffer, (short) 0);
                    int err = PdBase.process(ticksPerBuffer, inBuffer, outBuffer);
                    PdBase.pollMidiQueue();
                    PdBase.pollPdMessageQueue();
                    return err;
                }
            };
        }
    }

I feel, this information is not enough to understand the root cause. Unfortunately, that's all the information I have.

By the way, I am using PdAudio, not PdService if that matters. I believe, it is unrelated. I don't have a way to see if PdService solves the problem.

rayalu commented 7 years ago

Since API23, RECORD_AUDIO requires getting the permission at Runtime.

rpattabi commented 7 years ago

@rayalu Right, I already made sure I got record audio permission on 23+ on app launch.

What I noticed recently is, there are newer devices showing the same problem. On some of these devices the initAudio succeeds most of the times though (e.g. Moto G4).

  1. Moto G4
  2. GT-I8262
  3. XT1068
  4. MI 4W
  5. C6603
  6. SM-T113
  7. GT-I8552
  8. SM-J200H
  9. Lenovo A6

I wonder how I can get to the bottom of this problem. I could only retry with different sample rates.

rpattabi commented 6 years ago

Workaround

Instead of going by the suggested sample rate, use 44100.

Explanation

Suggested sample rate causes crackling sound during playback on Xiaomi devices (only on Marshmallow+).

Investigation

Solution

Got confirmation from Android Audio's Don Turner (@donturner https://twitter.com/rpattabi/status/915578976868876289) that 44.1k can be expected to be supported on all android devices.