twilio / twilio-video-ios

Programmable Video SDK by Twilio
http://twilio.com/video
Other
65 stars 22 forks source link

Cannot get Twilio to route Audio to Bluetooth headphones #181

Open dericpr opened 3 years ago

dericpr commented 3 years ago

I've been working on integrating the ExampleAVAudioEngineDevice with mixed results, it's mostly working for what we need it for, which is mixing local audio into the stream for both local playback and playing back into the stream going to the remote client.

We have a few issues though which are still causing some problems.

1) Cannot get bluetooth headsets to work.

Here is the setup for our audioSession. `- (void)setupAVAudioSession { AVAudioSession session = [AVAudioSession sharedInstance]; NSError error = nil;

if (![session setPreferredSampleRate:kPreferredSampleRate error:&error]) {
    NSLog(@"Error setting sample rate: %@", error);
}

if (![session setPreferredOutputNumberOfChannels:kPreferredNumberOfChannels error:&error]) {
    NSLog(@"Error setting number of output channels: %@", error);
}

/*
 * We want to be as close as possible to the 10 millisecond buffer size that the media engine needs. If there is
 * a mismatch then TwilioVideo will ensure that appropriately sized audio buffers are delivered.
 */
if (![session setPreferredIOBufferDuration:kPreferredIOBufferDuration error:&error]) {
    NSLog(@"Error setting IOBuffer duration: %@", error);
}

if (![session setCategory:AVAudioSessionCategoryPlayAndRecord           
    withOptions:AVAudioSessionCategoryOptionMixWithOthers|AVAudioSessionCategoryOptionAllowBluetooth
    error:&error]) {
    NSLog(@"Error setting session category: %@", error);
}

if (![session setMode:AVAudioSessionModeVideoChat error:&error]) {
    NSLog(@"Error setting session category: %@", error);
}

[self registerAVAudioSessionObservers];

if (![session setActive:YES error:&error]) {
    NSLog(@"Error activating AVAudioSession: %@", error);
}

if (session.maximumInputNumberOfChannels > 0) {
    if (![session setPreferredInputNumberOfChannels:TVIAudioChannelsMono error:&error]) {
        NSLog(@"Error setting number of input channels: %@", error);
    }
}

}`

When I connect a bluetooth headset to my ipad, it works for all other apps on the device, but the Twilio audio only comes out the speakers. If I plug a wired pair of headphones into the device it seems to work. Any ideas on how I can make it use bluetooth if bluetooth is connected and available?

  1. We have an application that listens to the local microphone input using the following code.

let format = audioEngine?.mainMixerNode.outputFormat(forBus: 0) outputNode.removeTap(onBus: 0) outputNode.installTap(onBus: 0, bufferSize: bufferSize, format: format) { buffer, time in

In this case audioEngine is a reference to the _playoutEngine object from ExampleAVAudioEngineDevice, this tap will then process the input data and attempt to determine the note that is being played. We use this to implement a simplified guitar tuner. The tuner module returns a note frequency, and prior to switching to the ExampleAVAudioEngineDevice this worked reliably for tuning a guitar, verifying against a physical tuner attached. When we switched to the new ExampleAVAudioEngineDevice for the mixing audio problems we were having the values coming back from the Tuner module were suddenly to low by anywhere from 13 to 25Hz which throws the tuning off as you can imagine. The weird thing is, sometimes the values will work perfectly, but when the app is restarted it starts outputting incorrect values again. I also notice that when we start the tuner application the audio often changes, it get's noiser with more white noise and a higher level for some reason. This sticks around even after the Tuner app is closed.

Is there anything we can do here? I suspect it might have something to do with a sample rate mismatch, we had a crash in the ExampleAVAudioDevice that we could only resolve by removing the code that validated the sample rates were matching. The call audio seems to continue to work regardless of that check, but it seems to have killed the Tuner functionality.

Thanks. Deric

dericpr commented 3 years ago

Discovered that even though the AVAudioSession is being setup in ExampleAVAudioEngineDevice we still have to use the AVAudioSession.sharedInstance().setCategory call from within our Swift application as well to get this to work.

 try AVAudioSession.sharedInstance().setCategory(
                .playAndRecord, mode: .videoChat,
                options: [.mixWithOthers,
                          .allowAirPlay,
                          .allowBluetoothA2DP,
                          .allowBluetooth])

in our init handler before the application finishes allows bluetooth connections to function.