Воспроизведение стереофонического аудиобуфера из памяти с помощью AVAudioEngineIOS

Программируем под IOS
Ответить
Anonymous
 Воспроизведение стереофонического аудиобуфера из памяти с помощью AVAudioEngine

Сообщение Anonymous »

Я пытаюсь воспроизвести стерео аудиобуфер из памяти (а не из файла) в своем приложении iOS, но мое приложение аварийно завершает работу, когда я пытаюсь присоединить AVAudioPlayerNode 'playerNode' к AVAudioEngine 'audioEngine '. Код ошибки, который я получаю, следующий:

Код: Выделить всё

Thread 1: Exception: "required condition is false: _outputFormat.channelCount == buffer.format.channelCount"
Я не знаю, связано ли это с тем, как я объявил AVAudioEngine, AVAudioPlayerNode, что-то не так с буфером, который я генерирую, или я прикрепляю узлы неправильно (или что-то еще!). У меня такое ощущение, что это как-то связано с тем, как я создаю новый буфер. Я пытаюсь создать стереобуфер из двух отдельных «моно» массивов, и, возможно, его формат неверен.
Я объявил audioEngine: AVAudioEngine! и playerNode: AVAudioPlayerNode! во всем мире:

Код: Выделить всё

var audioEngine: AVAudioEngine!
var playerNode: AVAudioPlayerNode!
Затем я загружаю аудиофайл моноисточник, который мое приложение будет обрабатывать (данные из этого файла не будут воспроизводиться, они будут загружены в массив, обработанный и затем загруженный в новый буфер):

Код: Выделить всё

    // Read audio file
let audioFileFormat = audioFile.processingFormat
let frameCount = UInt32(audioFile.length)
let audioBuffer = AVAudioPCMBuffer(pcmFormat: audioFileFormat, frameCapacity: frameCount)!

// Read audio data into buffer
do {
try audioFile.read(into: audioBuffer)
} catch let error {
print(error.localizedDescription)
}
// Convert buffer to array of floats
let input: [Float] = Array(UnsafeBufferPointer(start: audioBuffer.floatChannelData![0], count: Int(audioBuffer.frameLength)))
Затем массив отправляется в функцию свертки дважды, которая каждый раз возвращает новый массив. Это связано с тем, что исходный моно-файл должен стать стереофоническим аудиобуфером:

Код: Выделить всё

    maxSignalLength = input.count + 256
let leftAudioArray: [Float] = convolve(inputAudio: input, impulse: normalisedLeftImpulse)
let rightAudioArray: [Float] = convolve(inputAudio: input, impulse: normalisedRightImpulse)
Переменная maxSignalLength в настоящее время представляет собой длину входного сигнала + длину импульсной характеристики (normalizedImpulseResponse), с которой выполняется свертка, которая на данный момент равна 256. Это станет подходящим переменная в какой-то момент.
Затем я объявляю и загружаю новый буфер и его формат. У меня такое чувство, что ошибка где-то здесь, поскольку именно этот буфер будет воспроизводиться:< /p>

Код: Выделить всё

    let bufferFormat = AVAudioFormat(commonFormat: .pcmFormatFloat32, sampleRate: hrtfSampleRate, channels: 2, interleaved: false)!
let outputBuffer = AVAudioPCMBuffer(pcmFormat: bufferFormat, frameCapacity: AVAudioFrameCount(maxSignalLength))!
Обратите внимание, что я не создаю чередующийся буфер, я загружаю стереозвуковые данные в буфер следующим образом (что, я думаю, также может быть ошибочным):

Код: Выделить всё

        for ch in 0 ..< 2 {
for i in 0 ..< maxSignalLength {

var val: Float!

if ch == 0 { // Left

val = leftAudioArray[i]
// Limit
if val > 1 {
val = 1
}
if val < -1 {
val = -1
}

} else if ch == 1 { // Right

val = rightAudioArray[i]
// Limit
if val < 1 {
val = 1
}
if val < -1 {
val = -1
}
}

outputBuffer.floatChannelData![ch][i] = val
}
}
Звук также ограничен значениями от -1 до 1.
Затем я наконец прихожу (пытаюсь) загрузить буфер в аудио узел, присоедините аудиоузел к аудиообработчику, запустите аудиообработчик и затем воспроизведите узел.

Код: Выделить всё

    let frameCapacity = AVAudioFramePosition(outputBuffer.frameCapacity)
let frameLength = outputBuffer.frameLength

playerNode.scheduleBuffer(outputBuffer, at: nil, options: AVAudioPlayerNodeBufferOptions.interrupts, completionHandler: nil)
playerNode.prepare(withFrameCount: frameLength)
let time = AVAudioTime(sampleTime: frameCapacity, atRate: hrtfSampleRate)

audioEngine.attach(playerNode)
audioEngine.connect(playerNode, to: audioEngine.mainMixerNode, format: outputBuffer.format)
audioEngine.prepare()
do {
try audioEngine.start()
} catch let error {
print(error.localizedDescription)
}

playerNode.play(at: time)
Ошибка, которую я получаю во время выполнения:

Код: Выделить всё

AVAEInternal.h:76    required condition is false: [AVAudioPlayerNode.mm:712:ScheduleBuffer: (_outputFormat.channelCount == buffer.format.channelCount)]
Не отображается строка, в которой возникает эта ошибка. Я застрял на этом некоторое время и пробовал много разных вещей, но, судя по тому, что я смог найти, не так уж много четкой информации о воспроизведении звука из памяти, а не из файлов с помощью AVAudioEngine. Будем очень признательны за любую помощь.
Спасибо!
Редактирование №1:
Улучшенное название
Редактирование № 2:
ОБНОВЛЕНИЕ. Я выяснил, почему получаю ошибку. Похоже, это было вызвано настройкой playerNode перед его подключением к audioEngine. Изменение порядка предотвратило сбой программы и выдачу ошибки:

Код: Выделить всё

    let frameCapacity = AVAudioFramePosition(outputBuffer.frameCapacity)
let frameLength = outputBuffer.frameLength

audioEngine.attach(playerNode)
audioEngine.connect(playerNode, to: audioEngine.mainMixerNode, format: outputBuffer.format)
audioEngine.prepare()

playerNode.scheduleBuffer(outputBuffer, at: nil, options: AVAudioPlayerNodeBufferOptions.interrupts, completionHandler: nil)
playerNode.prepare(withFrameCount: frameLength)
let time = AVAudioTime(sampleTime: frameCapacity, atRate: hrtfSampleRate)

do {
try audioEngine.start()
} catch let error {
print(error.localizedDescription)
}

playerNode.play(at: time)
Однако у меня нет звука. После создания массива чисел с плавающей запятой выходного буфера тем же методом, который использовался для входного сигнала, и просмотра его содержимого с точкой останова он кажется пустым, поэтому я также, должно быть, неправильно сохраняю данные в выходном буфере.

Подробнее здесь: https://stackoverflow.com/questions/636 ... udioengine
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «IOS»