AKAudioPlayer: No sound in speakers, only with hea

2019-07-23 15:15发布

问题:

Using AudioKit for sound management, I noticed an issue (bug?) with this very simple piece of code.

import AudioKit

class MainViewController: UIViewController {

var audioFile: AKAudioFile?
var audioPlayer: AKAudioPlayer?

override func viewDidLoad() {
    super.viewDidLoad()
}

@IBAction func onPlayButtonClick(_ sender: Any) {

    do {
        audioFile = try AKAudioFile(forReading: Bundle.main.url(forResource: "3e", withExtension: "mp3")!)

        audioPlayer = try AKAudioPlayer(file: audioFile!)

        AudioKit.output = audioPlayer
        AudioKit.start()

        audioPlayer!.play()


    } catch {
        print(error)
    }
}
}

When launching the playback with play() method, everything is normal in logs and in the process (player duration, currentTime). BUT I do not hear the audio in speakers (only a kind of wind noise). As soon as I plug my headphones and tap the button again, I normally hear the audio. Then, I unplug my headphones and tap the button, I don’t hear audio (only that wind noise).

I face this on iPhone 5S.

I do not face this on iPad5, I do not face this on simulators. I don’t have the other devices to try to reproduce.

Both devices: iOS 11.1.2 and AudioKit : v4.0.4

NB: my speakers works normally with any other app and I’ve checked the volume. The default outputDevice is set to Speakers when headphones are not plugged.

回答1:

According to the Configuring an Audio Session guide, by default, the AVAudioSessionCategory is set so that

In iOS, setting the Ring/Silent switch to silent mode silences any audio being played by the app.

Since iPads and the simulator don't have this switch they will always play to the speaker, but in the case of hardware iPhones, they will only play to the headphones and not to the speakers when in silent mode, unless the session category is changed.

You can change the session category directly with AVAudioSession:

do {
    try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
catch {
    print("failed to set category")
}

or you can use AudioKit's AKSettings wrapper:

AudioKit.start()
do {
    try AKSettings.setSession(category: AKSettings.SessionCategory.playback)
} catch {
    print("failed to set category")
}

According to the AVSessionCategory docs, the Playback category is

The category for playing recorded music or other sounds that are central to the successful use of your app.

so it will assume the user wants the silent mode to be overridden when using the app.