5

I want to play very basic sounds using the AudioKit oscillator at a given frequency.

For example: play a simple sine wave at 400Hz for 50 miliseconds, then 100 ms of silence, then play 600Hz for 50ms …

I have a metal view where I render some visual stimuli. My intention was to use the basic AKOscillator and the render function of the CADisplayLink to play/stop the sound at some frames.

I tried using oscillator.play() and oscillator.stop() or changing the amplitude with oscillator.amplitude = 0 and oscillator.amplitude = 1 but the result in both cases is a jittering of about 10 ms.

If I first create .wav files and then played them with AKPlayer.play() the timing is correct.

I want the flexibility to use any frequency at any time. How can I do something similar to the first approach? Wrapping the oscillator in an midi instrument is the way to go?

bienqueda
  • 89
  • 5
  • Have you tried setting the rampTime (rampDuration in the develop branch) to zero? – Aurelius Prochazka May 17 '18 at 11:40
  • Yes the rampTime is set to zero. I am measuring both changes of the screen and changes of the sound with an oscilloscope so for the moment I wasn’t taking care of the pops and clicks. The screen is behaving very accurately with an error less than 1ms but the sound is not. – bienqueda May 18 '18 at 09:50

1 Answers1

3

CADisplayLink runs in the UI thread, so will have some sub-frame-time jitter, as the UI thread has lower priority than audio (and perhaps other OS) threads.

The only way I've succeeded in reliable sub-millisecond accurate real-time synthesis of arbitrary frequency audio is to put a sinewave oscillator (or waveform generator or table look-up) inside an Audio Unit callback (RemoteIO for iOS), and count samples, before dynamically inserting the stop/start of the desired sinewave (or other waveform) into the callback buffer(s), starting at the correct sample buffer offset index.

At first, I pre-generated sinewave look-up tables; but later did some profiling; and found that just calling the sin() function with a rotating phase, at audio sample rates, took a barely measurable fraction of a percent of CPU time on any contemporary iOS device. If you do use an incrementing phase, make sure to keep the phase in a reasonable numeric range by occasionally adding/subtracting multiples of 2*pi.

hotpaw2
  • 70,107
  • 14
  • 90
  • 153
  • Wow, I didn’t know that it would be so complex. I don’t think I have enough knowledge in Core Audio or audio processing so I would need to study the subject more. Any recommendations of documentation or code examples to read more about it? Thanks in advance. – bienqueda May 18 '18 at 09:53
  • This Swift iOS example code on github plays a tone of an exact length in samples, could probably adapted for exact start/stop times: https://github.com/hotpaw2/auv3test5 – hotpaw2 May 18 '18 at 14:54