Ответ 1
Изменить: Адам Ритенауэр ответ, вероятно, самый лучший. Чтобы расширить его, вы можете посмотреть новые функции/типы функций в изменениях IOS 8.3 Core Audio.
UnsafeMutableAudioBufferListPointer
может использоваться для чтения/доступа к некоторым данным:
struct UnsafeMutableAudioBufferListPointer {
init(_ p: UnsafeMutablePointer<AudioBufferList>)
var count: Int
subscript (index: Int) -> AudioBuffer { get nonmutating set }
}
И вы можете использовать расширения для AudioBuffer и AudioBufferList, чтобы выделить свои собственные:
extension AudioBufferList {
static func sizeInBytes(maximumBuffers maximumBuffers: Int) -> Int
static func allocate(maximumBuffers maximumBuffers: Int) -> UnsafeMutableAudioBufferListPointer
}
extension AudioBuffer {
init<Element>(_ typedBuffer: UnsafeMutableBufferPointer<Element>, numberOfChannels: Int)
}
Старый ответ:
Это немного сложно, потому что AudioBufferList
на самом деле является структурой с переменным размером. Это означает, что он объявлен как имеющий один AudioBuffer
, но на самом деле он имеет столько, сколько указано членом mNumberBuffers
. Это понятие не очень хорошо переводится в Swift, поэтому вы видите var mBuffers: (AudioBuffer)
.
Таким образом, канонический способ доступа к этим буферам и их данным будет использовать UnsafeArray
. В приведенном ниже коде представлены некоторые идеи, но UnsafePointer
и UnsafeArray
недостаточно хорошо документированы, поэтому это может быть неправильно.
// ***WARNING: UNTESTED CODE AHEAD***
let foo: UnsafePointer<AudioBufferList> // from elsewhere...
// This looks intuitive, but accessing `foo.memory` may be doing a copy.
let bufs = UnsafeArray<AudioBuffer>(start: &foo.memory.mBuffers, length: Int(foo.memory.mNumberBuffers))
// This is another alternative that should work...
let bufsStart = UnsafePointer<AudioBuffer>(UnsafePointer<UInt32>(foo) + 1) // Offset to mBuffers member
let bufs = UnsafeArray<AudioBuffer>(start: bufsStart, length: Int(foo.memory.mNumberBuffers))
// Hopefully this isn't doing a copy, but it shouldn't be too much of a problem anyway.
let buf: AudioBuffer = bufs[0] // or you could use a for loop over bufs, etc.
typealias MySample = Float32
let numSamples = Int(buf.mDataByteSize / UInt32(sizeof(MySample)))
let samples = UnsafeArray<MySample>(start: UnsafePointer<MySample>(buf.mData), length: numSamples)
// Now use the samples array...
Это, похоже, работает на игровой площадке, но мне сложно проверить настоящие аудиоданные. В частности, я не уверен на 100%, что использование start: &foo.memory.mBuffers
будет работать должным образом. (Он возвращает другой указатель из оригинала, хотя данные, похоже, там.) Сделайте снимок и сообщите об этом!
Изменить: чтобы отладить это, кстати, вы можете, например:
(lldb) p foo
(UnsafePointer<AudioBufferList>) $R1 = (value = Builtin.RawPointer = 0x0000000100700740)
(lldb) expr -lc -- ((int*)0x0000000100700740)[0]
(int) $2 = 42
(lldb) expr -lc -- ((int*)0x0000000100700740)[1]
(int) $3 = 43
...