AVAudioSession从未停止过

时间:2017-04-12 15:14:25

标签: ios swift swift3 avaudiosession

我正在尝试将AVAudioSession设置为无效以恢复正常状态。

我的话语功能:

class SSpeech : NSObject, AVSpeechSynthesizerDelegate {

    var group = DispatchGroup();
    var queue = DispatchQueue(label: "co.xxxx.speech", attributes: [])

    class var sharedInstance: SSpeech {
        struct Static {
            static var instance: SSpeech?
        }
        if !(Static.instance != nil) {
            Static.instance = SSpeech()
        }
       return Static.instance!
    }

   required override init() {
       super.init();
       self.speechsynt.delegate = self;
   }

   deinit {
      print("deinit SSpeech")
   }

   let audioSession = AVAudioSession.sharedInstance();
   var speechsynt: AVSpeechSynthesizer = AVSpeechSynthesizer()
   var queueTalks = SQueue<String>();

   func pause() {
        speechsynt.pauseSpeaking(at: .word)
   }

   func talk(_ sentence: String, languageCode code:String = SUtils.selectedLanguage.code, withEndPausing: Bool = false) {
       if SUser.sharedInstance.currentUser.value!.speechOn != 1 {
           return
        }

        queue.async{            
            self.queueTalks.enQueue(sentence)
            do {
                let category = AVAudioSessionCategoryPlayback;
                var categoryOptions = AVAudioSessionCategoryOptions.duckOthers
                if #available(iOS 9.0, *) {
                    categoryOptions.formUnion(AVAudioSessionCategoryOptions.interruptSpokenAudioAndMixWithOthers)
                 }
                try self.audioSession.setCategory(category, with: categoryOptions)
                try self.audioSession.setActive(true);
            } catch _ {
                return;
            }

            self.utteranceTalk(sentence, initSentence: false, speechsynt: self.speechsynt, languageCode:code, withEndPausing: withEndPausing)

            do {
                try self.audioSession.setCategory(AVAudioSessionCategoryPlayback, with: AVAudioSessionCategoryOptions.mixWithOthers)
            } catch _ {
                return;
            }
        }
    }

    func utteranceTalk(_ sentence: String, initSentence: Bool, speechsynt: AVSpeechSynthesizer, languageCode:String = "en-US", withEndPausing: Bool = false){
        if SUser.sharedInstance.currentUser.value!.speechOn != 1 {
            return
        }

        let nextSpeech:AVSpeechUtterance = AVSpeechUtterance(string: sentence)
        nextSpeech.voice = AVSpeechSynthesisVoice(language: languageCode)
        if !initSentence {
            nextSpeech.rate = 0.4;
        }

        if(withEndPausing){
            nextSpeech.postUtteranceDelay = 0.2;
        }
        speechsynt.speak(nextSpeech)
    }


    func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didFinish utterance:AVSpeechUtterance) {
        print("Speaker has finished to talk")

        queue.async {
               do {
                   try self.audioSession.setActive(false, with: AVAudioSessionSetActiveOptions.notifyOthersOnDeactivation)
               }
               catch {}
           }
       }
    }
}

我的方法被正确调用,但audioSession完成后utterance仍处于活动状态。我已经尝试了很多东西,但没有任何效果:(。

3 个答案:

答案 0 :(得分:1)

来自documentation of AVAudioSession的部分:

  

<强>讨论

     

如果另一个活动音频会话的优先级高于您的优先级(for   例如,电话),音频会话都不允许混音,   尝试激活您的音频会话失败。 停用你的   如果任何相关的音频对象(如队列,   转换器,播放器或刻录机)目前正在运行。

我的猜测是,无法停用会话是queue的正在运行的过程,正如我在文档引用中所强调的那样。

可能您应该停用进程同步而不是异步确保queue下的所有正在运行的操作都已处理< / em>的

尝试一下:

func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didFinish utterance:AVSpeechUtterance) {
        print("Speaker has finished to talk")

        queue.sync { // <---- `async` changed to `sync`
               do {
                   try self.audioSession.setActive(false, with: AVAudioSessionSetActiveOptions.notifyOthersOnDeactivation)
               }
               catch {}
           }
       }
    }

答案 1 :(得分:0)

我建议使用AvAudioPlayer。它们具有非常简单的启动和停止命令。

首先将音频播放器声明为变量

var SoundEffect: AVAudioPlayer!

然后选择您需要的文件

    let path = Bundle.main.path(forResource: "Untitled2.wav", ofType:nil)!
                    let url = URL(fileURLWithPath: path)
    let sound = try AVAudioPlayer(contentsOf: url)
                        SoundEffect = sound
                        sound.numberOfLoops = -1
                        sound.play()

并停止音频播放器

if SoundEffect != nil {
            SoundEffect.stop()
            SoundEffect = nil
        }

答案 2 :(得分:0)

您无法停止或停用AudioSession,您的应用会在启动时获取它。 Documentation

  

音频会话是您的应用和iOS之间的中介,用于配置应用的音频行为。启动后,您的应用会自动单个音频会话。

因此方法-setActive:不会使您的AudioSession“处于活动状态”,只需将其类别和模式配置付诸实践。要恢复“正常状态”,您可以设置default settings或只调用setActive(false, with:.notifyOthersOnDeactivation),这就足够了。