快速需要关闭音频层

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了快速需要关闭音频层相关的知识,希望对你有一定的参考价值。

我正在使用多个视图控制器构建应用程序。我需要控制所有音乐,所以我创建了一个专门的音乐课程,用于设置/播放/停止/暂停。

我已经录制了音频问题和答案,我需要能够播放问题然后回答mp3文件。

所以我相信这里有一些方法来完成这个委托和协议,使用func audioPlayerDidFinishPlaying并使用闭包。根据我的理解,闭包是我想要实现的目标的最佳选择。

我在MakeMusic类中的起点是:

class MakeMusicClass : NSObject, AVAudioPlayerDelegate {
    static let shared = MakeMusicClass()
    var audioPlayer = AVAudioPlayer()

    override init() { }

    func setup(Selection: String) {
        do {
            audioPlayer =  try AVAudioPlayer(contentsOf: URL.init(fileURLWithPath: Bundle.main.path(forResource: Selection, ofType: "mp3")!))
            audioPlayer.prepareToPlay()
            audioPlayer.delegate=self
        } catch {
            print (error)
        }
    }

    func play() {
        audioPlayer.play()
    }

我的调用文件是:

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        MakeMusicClass.shared.setup(Selection: "Question11")
        MakeMusicClass.shared.play()

        MakeMusicClass.shared.setup(Selection: "Answer11")
        MakeMusicClass.shared.play()

为了实现这一点,我理解我需要为被调用的类添加一个闭包:

func play() {
    var closure = { in
        audioPlayer.play()
    }
}

我需要更新我需要调用函数的地方:

override func viewDidLoad() {
    super.viewDidLoad()
    MakeMusicClass.shared.setup(Selection: "Question11")
    MakeMusicClass.shared.play() {

    MakeMusicClass.shared.setup(Selection: "Answer11")
    MakeMusicClass.shared.play()
}

我花了很多年时间试图解决这个问题,但我很挣扎。我的代码显然不起作用,因为我缺少一些基本的东西。我试过传递void和参数,但我不明白应该传递什么参数。我最接近的是使用makemusic类中的audioPlayerDidFinishPlaying触发下一个音频文件,但我不知道这是理想的。

答案

我认为你最好的选择是在你的MakeMusicClass中将Array作为初始化者,例如一个问题和答案,然后使用AVAudioPlayerDelegate来触发下一个文件,我认为这是你想要得到的(并且非常接近^ ________ *)。

例如:

class AudioLooper: NSObject, AVAudioPlayerDelegate {

var debugView = true

var audioLoopPlayer: AVAudioPlayer!

var audioFileIndex: Int = 0

var audioFileArray: [String] = []

//-------------------------------------------------
//MARK: Audio Player Initialisation & Functionality
//-------------------------------------------------

/// Function To Initialise The Audio Loop Player
///
/// - Parameter audioFiles: [String] - The Array Of Audio Files To Play
func initAudioPlayerWith(audioFiles: [String]) {

    audioFileArray = audioFiles

    if debugView { print("Audio Files To Play In Sequence == (audioFileArray)") }

}

/// Function To Play An Array Of Audio Files
///
/// - Parameter index: (Int) - The Current Index Of The Audio Sequence
func playAudioLoopAt(index: Int) {

    let currentAudioFile = "(audioFileArray[audioFileIndex])"

    if let audioFilePath = Bundle.main.path(forResource: currentAudioFile, ofType: "mp3"){

        do {
            let audioFileUrl = NSURL.fileURL(withPath: audioFilePath)

            // Set An Instance Of AVAudiosession Which Allows Playback Even When Device Is Muted
            try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
            try AVAudioSession.sharedInstance().setActive(true)

            audioLoopPlayer = try AVAudioPlayer(contentsOf: audioFileUrl)
            audioLoopPlayer.prepareToPlay()
            audioLoopPlayer.delegate = self
            audioLoopPlayer.play()
            if debugView { print("Playing (currentAudioFile) ") }
            audioFileIndex += 1

        } catch {
            print("Error Playing Audio")
        }

    } else {

        print("Error Finding File: (currentAudioFile)")
    }

}

/// Function To Continue The Audio Sequence
@objc func continueAudioLoop(){

    playAudioLoopAt(index: audioFileIndex)
}

/// Function To Stop The Audio Looop Player
func stopAudioPlayer() {

    if audioLoopPlayer != nil {
        audioFileIndex=0
        audioLoopPlayer.stop()
        audioLoopPlayer = nil
    }

}

//-----------------------------
//MARK: AVAudio Player Delegate
//-----------------------------

func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {

    if audioFileIndex < audioFileArray.count {

        self.perform(#selector(continueAudioLoop), with: self, afterDelay: 0.5)

    }else{

        audioFileIndex=0

      }
  }
}

在我的例子中,你只需像这样初始化:

    audioLooper = AudioLooper()
    audioLooper?.initAudioPlayerWith(audioFiles: ["question", "answer"])
    audioLooper?.playAudioLoopAt(index: 0)

audioLooper声明如下:var audioLooper:AudioLooper?

显然我的例子不是单身人士,但它应该让你知道如何调整你的MakeMusicClass使其适合...

您也可以像这样添加Delegate方法来通知ViewController音频已完成或执行其他任务,例如更新下一个问题等,例如:

@objc protocol AudioLooperDelegate {

   @objc optional func update()
}

然后在你的ViewController

var delegate: AudioLooperDelegate?

然后在AudioLooper类中,您可以在需要的地方添加委托方法,例如:

func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {

if audioFileIndex < audioFileArray.count {

    self.perform(#selector(continueAudioLoop), with: self, afterDelay: 0.5)

}else{

    audioFileIndex=0
   delegate?.updateUI!()

  }
 }
}

以上是关于快速需要关闭音频层的主要内容,如果未能解决你的问题,请参考以下文章

如何以毫秒为单位获取javaFX音频片段的长度[关闭]

在 IOS 中,如何乱序播放音频片段的一部分?

在后台和屏幕关闭时在 WatchKit 锻炼应用程序中播放音频

关于在各浏览器中插入音频文件的html代码片段

使用导致内存泄漏的音频片段

如何对H.265视频播放器EasyPlayer.js实现音频开启与关闭控制?附代码