Воспроизвести сегмент AVAudioPCMBuffer

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

Скриншот интерфейса рекордера/редактора

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


person torof    schedule 05.11.2018    source источник


Ответы (1)


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

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
}
person dave234    schedule 06.11.2018