Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Performing vibration in recording app

I am trying to perform a vibration in an app similar to Snapchat, that uses both audio output and input as well as supports audio mixing from other apps, but this seems to be a harder task that I initially thought it would be. Important to know is that I am not trying to vibrate during playback or recording. From reading all the documentation I could find on the subject, this is what I have come to understand:

  • In order to support both playback and recording (output and input), I need to use AVAudioSessionCategoryPlayAndRecord
  • Making the phone vibrate through AudioServicesPlaySystemSound (kSystemSoundID_Vibrate) is not supported in any of the recording categories, including AVAudioSessionCategoryPlayAndRecord.
  • Enabling other apps to play audio can be done by adding the option AVAudioSessionCategoryOptionMixWithOthers.

Therefore, I do this in my app delegate:

NSError *error = nil;
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker | AVAudioSessionCategoryOptionMixWithOthers error:&error];

The possible solutions to doing the vibration that I have tried but failed at are:

  • Deactivating the shared AVAudioSession before vibrating, and then activate it straight after.

    [[AVAudioSession sharedInstance] setActive:NO error:nil];         
    AudioServicesPlaySystemSound (kSystemSoundID_Vibrate);
    [[AVAudioSession sharedInstance] setActive:YES error:nil];
    

    This successfully performs the vibration, but afterwards, when I try to record a movie, the audio is ducked (or something else is causing it to be very silent). It also gives me an error saying that I am not allowed to deactivate a session without removing its I/O devices first.

  • Changing category before vibrating, and then changing it back.

    [[AVAudioSession sharedInstance] setActive:NO error:nil];
    [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:nil];
    [[AVAudioSession sharedInstance] setActive:YES error:nil];
    
    AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
    
    [[AVAudioSession sharedInstance] setActive:NO error:nil];
    [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker | AVAudioSessionCategoryOptionMixWithOthers error:nil];
    [[AVAudioSession sharedInstance] setActive:YES error:nil];
    

    This solution comes up every now and then, but does not seem to work for me. No vibration occurs, even though the categories seems to be set. This might still be a valid solution if I set usesApplicationAudioSession = YES on my AVCaptureSession, but I haven't made it work yet.

Sources:

  • https://developer.apple.com/library/ios/documentation/Audio/Conceptual/AudioSessionProgrammingGuide/ConfiguringanAudioSession/ConfiguringanAudioSession.html

  • https://developer.apple.com/library/ios/documentation/Audio/Conceptual/AudioSessionProgrammingGuide/AudioSessionBasics/AudioSessionBasics.html

  • https://developer.apple.com/library/ios/documentation/Audio/Conceptual/AudioSessionProgrammingGuide/AudioGuidelinesByAppType/AudioGuidelinesByAppType.html#//apple_ref/doc/uid/TP40007875-CH11-SW1

like image 308
Daniel Larsson Avatar asked Aug 15 '16 09:08

Daniel Larsson


People also ask

What is vibration in sound?

Vibration is the backward and forward movement of a body. Sound is caused by vibration that makes particles in the air form sound waves. A damper is used to reduce vibration. Vibration is the backward and forward movement of a body.

How do I control the vibration intensity on my iPhone?

Set sound and vibration optionsGo to Settings > Sounds & Haptics. To set the volume for all sounds, drag the slider below Ringtone and Alert Volume. To set the tones and vibration patterns for sounds, tap a sound type, such as ringtone or text tone.


2 Answers

So, I've been recently trying to play a simple beep in my app and one of the methods of doing so I stumbled upon is:

AudioServicesPlaySystemSound(SystemSoundID inSystemSoundID);

It's a function that plays a system sound from /System/Library/Audio/UISounds/ it's supported on all iOS versions.

The sound 1350 equals to RingerVibeChanged (vibration). So..

AudioServicesPlaySystemSound(1350);

...vibrates for about 0.5 seconds.

Incase you're interested in more sounds here is a link to all the playable sounds and what iOS versions they've been added in: http://iphonedevwiki.net/index.php/AudioServices

like image 108
Adam Svestka Avatar answered Sep 28 '22 03:09

Adam Svestka


For reference, I'm not using AVCaptureSession but an AVAudioEngine to record something, and for my case I pinpointed it down to having to pause the input in order to play the vibration properly with AudioServicesPlaySystemSound during a record session.

So in my case, I did something like this

audioEngine?.pause()
AudioServicesPlaySystemSound(1519)
do {
  try audioEngine.start()
} catch let error {
  print("An error occurred starting audio engine. \(error.localizedDescription)")
}

I'm not sure if it would also work with doing something similar for AVCaptureSession (i.e., stopRunning() and startRunning()), but leaving this here in case someone wants to give it a try.

like image 23
jayOrange Avatar answered Sep 28 '22 03:09

jayOrange