Игровой сегмент AVAudioPCMBuffer - PullRequest
0 голосов
/ 06 ноября 2018

Я создаю этот простой аудио-рекордер и интерфейс редактора для приложения для iOS:

Screenshot of the recorder/editor interface

Звук записывается в массив с плавающей точкой, который используется для создания формы волны. После записи я копирую данные с плавающей точкой в ​​AVAudioPCMBuffer для игры с AVAudioPlayerNode. Я могу воспроизвести буфер с самого начала, но не могу понять, как я могу воспроизвести только сегмент буфера. Функция scheduleSegment работает только для файлов.

1 Ответ

0 голосов
/ 06 ноября 2018

Вы можете создать новый буфер, который является сегментом оригинала. AVAudioPCMBuffer и AudioBufferlist являются своего рода болью в Swift. Есть несколько способов сделать это, если вы используете float, вы можете получить доступ к AVAUdioPCMBuffer.floatChannelData, но вот метод, который работает как для образцов float, так и для int.

func segment(of buffer: AVAudioPCMBuffer, from startFrame: AVAudioFramePosition, to endFrame: AVAudioFramePosition) -> AVAudioPCMBuffer? {
    let framesToCopy = AVAudioFrameCount(endFrame - startFrame)
    guard let segment = AVAudioPCMBuffer(pcmFormat: buffer.format, frameCapacity: framesToCopy) else { return nil }

    let sampleSize = buffer.format.streamDescription.pointee.mBytesPerFrame

    let srcPtr = UnsafeMutableAudioBufferListPointer(buffer.mutableAudioBufferList)
    let dstPtr = UnsafeMutableAudioBufferListPointer(segment.mutableAudioBufferList)
    for (src, dst) in zip(srcPtr, dstPtr) {
        memcpy(dst.mData, src.mData?.advanced(by: Int(startFrame) * Int(sampleSize)), Int(framesToCopy) * Int(sampleSize))
    }

    segment.frameLength = framesToCopy
    return segment
}
...