Как воспроизвести звук из каталога ресурсов с помощью AVAudioPlayerNode?

Я пытаюсь использовать 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 ответ

Итак, ваша проблема в том, что вы хотели бы получить 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
    }
}

Возможно, немного надуманно, но я не нашел других вариантов.

Надеюсь, это поможет вам.

Другие вопросы по тегам