dosse91214
dosse91214

Reputation: 561

Android sound synthesis

I am trying to play a synthesized sound (basically 2 sine waves and some noise) using the AudioTrack class. It doesn't seem to be any different than the SourceDataLine in javax.sound.sampled, BUT the synthesis is REALLY SLOW. Even for ARM standards, it's unrealistic to think that 32768 samples (16 bit, stereo, for a total of 65536) take over 1 second to render on a Nexus 4 (measured with System.nanotime(), write to AudioTrack excluded). The synthesis part is almost identical to this http://audioprograming.wordpress.com/2012/10/18/a-simple-synth-in-android-step-by-step-guide-using-the-java-sdk/, the only difference is that I play stereo sound (I can't reduce it to mono because it's a binaural tone).

Any ideas? what can I do?

Thanks in advance

Upvotes: 5

Views: 5478

Answers (4)

philburk
philburk

Reputation: 711

You should be able render multiple oscillators with filters and envelopes and still have CPU time left over. Check your inner loops to make sure that there are no system calls.

Are you on a very old phone? You did not mention the hardware or OS version.

You might want to try using JSyn. It is a free modular Java synthesizer that runs on any Java platform including desktops, Raspberry Pi and Android.

https://github.com/philburk/jsyn

Upvotes: 1

DigCamara
DigCamara

Reputation: 5578

Marko's answer seems very good. But if you're still in the experimental/investigational phase of your project, you might want to consider using Pure Data, which already is implemented as a combination Android library/NDK library and which would allow you to synthesize many sounds and interact with them in a relatively simple manner.

The libpd distribution is the Android implementation of Pure Data. Some good starting references can be found at the SoundOnSound site and also at this site.

Addendum: I found a basic but functional implementation of an Android Midi Driver through this discussion link. The relevant code can be found here (github, project by billthefarmer, named mididriver).

You can view how I use it in my Android app (imSynt link leads you to Google Play), or on YouTube.

Upvotes: 6

marko
marko

Reputation: 9169

The performance of audio synthesis on ARM is actually very respectable with native code that makes good use of the NEON unit. The Dalvik's JIT compiler is never going to get close to this level of performance for floating-point intensive code.
A look at the enormous number of soft-synth apps for iOS provides ample evidence of what should be possible on ARM devices with similar levels of performance.

However, the performance you are reporting is several orders of magnitude short of what I would expect. You might consider the following:

  1. Double precision float-point arithmetic is particularly expensive on ARM Cortex A-x NEON units, where as single precision is very fast and highly parallelizable. Math.sin() returns a double, so is unnecessarily precise, and liable to be slow. The 24-mantissa provided by single precision floating point value is substantially larger than the 16-bit int used by the audio subsystem.
  2. You could precompute sin(x) and then perform a table-lookup in your render loop.
  3. There is a previous post on SO concerning Math.sin(x) on android suggesting degrading performance as x becomes large, as it's likely to in this case over time.
  4. For a more advanced table-based synthesiser, you might consider using a DDS Oscillator.

Ultimately, you might consider using native code for synthesis, with the NDK.

Upvotes: 4

Mike Jones
Mike Jones

Reputation: 111

Have you tried profiling your code? It sounds like something else is possibly causing your slow down, profiling would help to highlight the cause.

Mike

Upvotes: 0

Related Questions