4

我正在尝试使用 anAVAudioPlayerNode来播放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")
}

我想使用 anAVAudioPlayerNode代替(出于音高转换和其他原因)。我可以创建引擎并连接节点 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?如果是这样,怎么办?

4

1 回答 1

0

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

我环顾四周,但只找到了这个答案

正如它所说

它基本上只是从资产中获取图像,将其数据保存到磁盘并返回文件 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
    }
}

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

希望对您有所帮助。

于 2017-08-14T06:47:09.040 回答