Android audio : change pitch

Patrick picture Patrick · Oct 29, 2011 · Viewed 11.6k times · Source

The Android documentation for SoundPool says "the application can also alter the pitch by adjusting the playback rate in real-time for doppler or synthesis effects". So I tried to do this, using the setRate method to vary smoothly from one note to another, but the result is awful: the sound variation is very ragged. Here is the code I tried. Please tell me if there is a better way.

int streamId = soundPool.play (soundId, 1, 1, 1, 0, 1.0f);
for (float x = 0; x < 1; x += 0.005) {
  SystemClock.sleep (10);
  soundPool.setRate (streamId, 1 + x);
}

Answer

MBober picture MBober · Nov 18, 2011

Even though the Androids documentation suggests that you can use setRate() to produce doppler effects, I would not rely on a fast or good enough implementation on every android device.

Affordable audio ICs require a fixed sample rate of 44kHz or 48kHz. Sample rate conversion (i.e. pitch modification) therefore has to be done in software. Because this includes low-level number crunching I am sure that this is implemented by the device manufacturer and not by Google. Given the wide variety of Android device manufacturers and the often low-cost hardware used, there are certainly many sample rate conversion implementations out there. Some faster, some slower. Some smooth, some ragged.

What happens when changing the conversion rate during playback? If the algorithm doesn't match the pieces precisely together, there might be a short crack in your audio playback. You change the conversion rate every 10 milliseconds. If there is a crack every 10ms, that corresponds to a frequency of 100Hz which is a tone itself. This is likely to be what you hear as "ragged".

All in all I don't think that it is possible to emulate musical instruments in real-time on a wide range of Android devices using high-level Android API. A native application might be fast enough though.