【问题标题】:How can I play a sound from the asset catalog using AVAudioPlayerNode?如何使用 AVAudioPlayerNode 从资产目录播放声音?
【发布时间】:2018-01-20 16:02:54
【问题描述】:

我正在尝试使用 AVAudioPlayerNode 播放来自 Assets.xcassets 资产目录的声音,但我不知道该怎么做。

我一直在使用AVAudioPlayer,可以像这样使用NSDataAsset 进行初始化:

let sound = NSDataAsset(name: "beep")!
do {
    let player = try AVAudioPlayer(data: sound.data, fileTypeHint: AVFileTypeWAVE)
    player.prepareToPlay()
    player.play()
} catch {
    print("Failed to create AVAudioPlayer")
}

我想改用AVAudioPlayerNode(出于音高转换和其他原因)。我可以创建引擎并连接节点 OK:

var engine = AVAudioEngine()
func playSound(named name: String) {
    let mixer = engine.mainMixerNode
    let playerNode = AVAudioPlayerNode()
    engine.attach(playerNode)
    engine.connect(playerNode, to: mixer, format: mixer.outputFormat(forBus: 0))

    // play the file (this is what I don't know how to do)
}

播放文件的方法好像是playerNode.scheduleFile()。它需要一个AVAudioFile,所以我想我会尝试制作一个。但是AVAudioFile 的初始化程序需要一个 URL。据我所知,资产目录中的资产不能通过 URL 获得。我可以使用NSDataAsset 直接获取数据,但似乎没有任何方法可以使用它来填充AVAudioFile

是否可以使用AVAudioPlayerNode 播放资产目录中的声音?如果有,怎么做?

【问题讨论】:

    标签: swift avfoundation avaudioplayer avaudioplayernode avaudiofile


    【解决方案1】:

    好的,所以您的问题是您想从资产目录中的文件中获取URL,对吗?

    我环顾四周,但只找到this answer

    正如它所说的

    它基本上只是从资产中获取图像,将其数据保存到磁盘并返回文件 URL

    您可能应该更改它以查找 MP3 文件(或 WAV 或任何您喜欢的,也许这可能是一个输入参数)

    所以你最终可能会得到这样的结果:

    enum SoundType: String {
        case mp3 = "mp3"
        case wav = "wav"
    }
    
    class AssetExtractor {
    
        static func createLocalUrl(forSoundNamed name: String, ofType type: SoundType = .mp3) -> URL? {
    
            let fileManager = FileManager.default
            let cacheDirectory = fileManager.urls(for: .cachesDirectory, in: .userDomainMask)[0]
            let url = cacheDirectory.appendingPathComponent("\(name).\(type)")
    
            guard fileManager.fileExists(atPath: url.path) else {
                guard
                    let image = UIImage(named: name),
                    let data = UIImagePNGRepresentation(image)
                else { return nil }
    
                fileManager.createFile(atPath: url.path, contents: data, attributes: nil)
                return url
            }
            return url
        }
    }
    

    可能有点牵强,但我没有找到任何其他选择。

    希望对你有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-03-18
      • 2012-06-13
      • 1970-01-01
      • 2015-02-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多