AudioKit, экспорт массива AVAudioPCMBuffer в аудиофайл с постепенным исчезновением - PullRequest
0 голосов
/ 08 октября 2018

Я записываю звук из AKLazyTap и рендеринг накопленного [AVAudioPCMBuffer] в аудиофайл в фоновом режиме, пока звук моего приложения работает.Это прекрасно работает, но я хочу добавить fade in / out, чтобы очистить результат.Я вижу удобное расширение для добавления затуханий в один AVAudioPCMBuffer, но я не уверен, как бы я это сделал в массиве.Я подумал объединить буферы, но, похоже, это не поддерживается.Кто-нибудь знает, возможно ли это в настоящее время?По сути, для этого потребуется нечто похожее на copy(from:readOffset:frames), но также потребуется смещение записи ...

Или, может быть, есть более простой способ?

  • ОБНОВЛЕНИЕ

Хорошо, после изучения некоторого связанного кода АК, я попытался напрямую скопировать данные буфера в один длинный буфер, затем применил вспомогательную функцию затухания.Но это дает мне пустой (ну, 4к) файл.Есть ли какая-то очевидная ошибка, которую я просто не вижу?

func renderBufferedAudioToFile(_ audioBuffers: [AVAudioPCMBuffer], withStartOffset startOffset: Int, endOffset: Int, fadeIn: Float64, fadeOut: Float64, atURL url: URL) {
    // strip off the file name
    let name = String(url.lastPathComponent.split(separator: ".")[0])

    var url = self.module.stateManager.audioCacheDirectory

    // UNCOMPRESSED
    url = url.appendingPathComponent("\(name).caf")
    let format = Conductor.sharedInstance.sourceMixer.avAudioNode.outputFormat(forBus: 0)
    var settings = format.settings
    settings["AVLinearPCMIsNonInterleaved"] = false

    // temp buffer for fades
    let totalFrameCapacity = audioBuffers.reduce(0) { $0 + $1.frameLength }
    guard let tempAudioBufferForFades = AVAudioPCMBuffer(pcmFormat: format, frameCapacity: totalFrameCapacity) else {
        print("Failed to create fade buffer!")
        return
    }

    // write ring buffer to file.
    let file = try! AVAudioFile(forWriting: url, settings: settings)

    var writeOffset: AVAudioFrameCount = 0
    for i in 0 ..< audioBuffers.count {
        var buffer = audioBuffers[i]
        let channelCount = Int(buffer.format.channelCount)
        if i == 0 && startOffset != 0 {
            // copy a subset of samples in the buffer
            if let subset = buffer.copyFrom(startSample: AVAudioFrameCount(startOffset)) {
                buffer = subset
            }
        } else if i == audioBuffers.count - 1 && endOffset != 0 {
            if let subset = buffer.copyTo(count: AVAudioFrameCount(endOffset)) {
                buffer = subset
            }
        }
        // write samples into single, long buffer
        for i in 0 ..< buffer.frameLength {
            for n in 0 ..< channelCount {
                tempAudioBufferForFades.floatChannelData?[n][Int(i + writeOffset)] = (buffer.floatChannelData?[n][Int(i)])!
            }
        }
        print("buffer \(i), writeOffset = \(writeOffset)")
        writeOffset = writeOffset + buffer.frameLength
    }
    // update!
    tempAudioBufferForFades.frameLength = totalFrameCapacity 

    if let bufferWithFades = tempAudioBufferForFades.fade(inTime: fadeIn, outTime: fadeOut) {
        try! file.write(from: bufferWithFades)
    }
}
...