PdAudio::init() fails on specific devices
rpattabi opened this issue · 5 comments
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
- Lenovo Vibe P1– P1a42
- Lenovo A680– A680
- Samsung Galaxy Core Prime – SM-G360H
- 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
@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.
@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.
Since API23, RECORD_AUDIO requires getting the permission at Runtime.
@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).
- Moto G4
- GT-I8262
- XT1068
- MI 4W
- C6603
- SM-T113
- GT-I8552
- SM-J200H
- Lenovo A6
I wonder how I can get to the bottom of this problem. I could only retry with different sample rates.
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
- suggested sample rate was 48k
- playback crackling happens at 48k only if we init audio with input channel.
- no crackling at 48k if no input channel was initialized.
- no crackling at 44.1k even if we init audio with input channel.
- the android pd app, MobMuPlat, which helps to run pd patches directly on android devices, had 44.1k as hard coded sample rate. So hard coding may be okay.
Solution
- Use 44.1k everywhere.
- android takes care of up or down sampling. Refer: https://developer.android.com/ndk/guides/audio/sampling-audio.html
- if device sample rate is 48k, android up samples for playback and down samples while recording.
- trade off: up or down sampling adds a bit of latency
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.