如何使用AVAudioPlayerNode从资源目录播放声音?

4
我正在尝试使用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(用于调音等原因)。我可以创建引擎并连接节点:
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从资产目录播放声音?如果可以,该怎么做?
1个回答

0

好的,你的问题是想从资产目录中的文件获取一个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
    }
}

也许有点牵强,但我没有找到其他的选择。

希望这能帮到你。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接