2

I can't find method how i can play sound real with low latency.

I try use AVFoundation audio player huge latency around 500ms

So i try create system sound, and too without luck latency around 200ms it's not much but not useful for me. I need 50ms max.

Be sure my sound sample is clear tone without silence.

SystemSoundID cID;
BOOL spinitialized;

-(IBAction)doInit
{
    if (spinitialized){
        AudioServicesPlaySystemSound (cID);

        return;
    }



    NSURL *uref = [[NSURL alloc] initFileURLWithPath: [NSString stringWithFormat:@"%@/soundlib/1.wav", [[NSBundle mainBundle] resourcePath]]];

    OSStatus error = AudioServicesCreateSystemSoundID ((__bridge CFURLRef)uref, &cID);
    if (error) NSLog(@"SoundPlayer doInit Error is %d",(int)error);


    AudioServicesPlaySystemSound (cID);

    spinitialized = YES;
}

So i try call by button press down.

Dmitriy Pushkarev
  • 390
  • 2
  • 5
  • 26
  • 1
    Did you try AVAudioEngine? I have not experimented with latency, but if you watch the WWDC video, low latency is one of their big claims. — Also, don't forget that the _first_ sound your app produces is _always_ likely to be subject to latency. For this reason, you should consider playing a "silent" sound just after launch, to tickle the audio server. – matt Feb 28 '16 at 23:54
  • i generally prefer `AVFoundation` in my apps, but my advantage is that i have total of 10 - 20 sounds max with small sizes, and at the launch of my app, i call `prepareToPlay` method of each sounds. It may help you if you have limited number of sounds in your app. – meth Feb 29 '16 at 00:36

4 Answers4

3

Using an already running RemoteIO Audio Unit (or AVAudioUnit) with PCM waveform data that is already loaded into memory provides the lowest latency method to produce sound on iOS devices.

Zero latency is impossible due to buffering, but on all current iOS devices, the buffer size is usually 5.3 to 5.8 milliseconds or lower. On the newest iOS devices you can get audio callbacks even more often. Your audio callback code has to ready to manually copy the proper sequential slice of the desired waveform data into an audio buffer. It will be called in a non-UI thread, so the callback needs to be thread safe, and do no locks, memory management or even Objective C messaging.

Using other AV audio playing methods may result in far higher latency due to the time it takes to load the sound into memory (including potential unpacking or decompression) and to power up the audio hardware (etc.), as well as typically using longer audio buffers. Even starting the RemoteIO Audio Unit has its own latency; but it can be started ahead of time, potentially playing silence, until your app needs to play a sound with the lowest possible (but non-zero) latency, upon receiving some event.

hotpaw2
  • 70,107
  • 14
  • 90
  • 153
1

AVAudioEngine with AVAudioUnitSampler is a really easy way to get low latency audio file triggering.

dave234
  • 4,793
  • 1
  • 14
  • 29
  • I've suggested some code which uses AVAudioEngine here: https://stackoverflow.com/questions/34680007/simple-low-latency-audio-playback-in-ios-swift – CKP78 Dec 08 '17 at 21:01
0

I would suggest looking into incorporating The Amazing Audio Engine into your project http://theamazingaudioengine.com/

It has very nice tools for buffering audio files and playback. As hotpaw2 has mentioned, you're running into an issue with the system starting the buffer when you press the button. you will need to buffer the audio before the button is pressed to reduce your latency.

Michael at TAAE has create this class AEAudioFilePlayer http://theamazingaudioengine.com/doc/interface_a_e_audio_file_player.html

Initializing an AEAudioFilePlayer will load the buffer for you. You can then ask the Player to play the audio back when the button is pressed.

Mgill404
  • 115
  • 1
  • 9
0

Configure AVAudioSession's preferredIOBufferDuration property.

preferredIOBufferDuration

The preferred I/O buffer duration, in seconds. (read-only)
kvr
  • 573
  • 2
  • 8