2014-07-19 11 views
15

Ich habe eine Brückenfunktion in Swift, eine der Argumente in C ist AudioBufferList *. In Swift wird ein UnsafePointer<AudioBufferList> generiert. Ich habe es geschafft, den Zeiger durch Aufruf von audioData[0] zu unterscheiden (gibt es einen besseren Weg?). Aber ich kämpfe mit den nächsten 2 Stufen: die .mBuffers Reihe von AudioBuffer 's und ihre void */UnsafePointer<()>.mData Mitglieder.Verwenden von AudioBufferList mit Swift

In C wäre es einfach

sein
Float32 *audioData = (Float 32*)abl->mBuffers[0]->mData; 
output = audioData[sampleNum]... 

In Swift die erste Seltsame ist, dass es mir die Elemente mBuffers Zugriff nicht zulassen, ist aber vollkommen glücklich, wenn ich es als eine Eigenschaft zuzugreifen. Mit anderen Worten, das funktioniert und auch korrekte Daten (für das erste Mitglied mBuffers nehme ich an) ...

println(abl[0].mBuffers.mNumberChannels) // But .mBuffers should be an []! 

Zweitens hat mich mal .mData Indizes drucken, aber der Wert ist immer ()

println(abl[0].mBuffers.mData[10]) // Prints '()' 

Ich habe verschiedene Casting Ops ausprobiert und mit mehreren Indizes zugreifen, aber ohne Erfolg ... irgendwelche Ideen?

Hier sind die C und Swift-Definitionen für AudioBufferList und AudioBuffer für Komfort ...

// C 
struct AudioBufferList 
{ 
    UInt32  mNumberBuffers; 
    AudioBuffer mBuffers[1]; // this is a variable length array of mNumberBuffers elements 
    // ...and a bit more for c++ 
} 


struct AudioBuffer 
{ 
    UInt32 mNumberChannels; 
    UInt32 mDataByteSize; 
    void* mData; 
}; 

...

// SWIFT 

struct AudioBufferList { 
    var mNumberBuffers: UInt32 
    var mBuffers: (AudioBuffer) 
} 

struct AudioBuffer { 
    var mNumberChannels: UInt32 
    var mDataByteSize: UInt32 
    var mData: UnsafePointer<()> 
} 

Antwort

9

Edit: Antwort Adam Ritenauer das ist wahrscheinlich das beste jetzt . Um es zu erweitern, können Sie sich die neuen Funktionen/Typen des Dienstes in the iOS 8.3 Core Audio changes ansehen.

UnsafeMutableAudioBufferListPointer kann verwendet werden, um einige gegebenen Daten zu lesen/Zugang:

struct UnsafeMutableAudioBufferListPointer { 
    init(_ p: UnsafeMutablePointer<AudioBufferList>) 
    var count: Int 
    subscript (index: Int) -> AudioBuffer { get nonmutating set } 
} 

Und Sie die Erweiterungen auf Audiobuffer verwenden können & AudioBufferList Ihre eigene zuzuteilen:

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) 
} 

Alt antwort:

Das ist ein bisschen schwierig, weil AudioBufferList eigentlich eine Struktur variabler Größe ist. Dies bedeutet, dass es als eine einzige AudioBuffer deklariert wurde, aber es hat wirklich so viele, wie von der mNumberBuffers Mitglied angegeben. Dieser Begriff übersetzt sich nicht sehr gut zu Swift, weshalb Sie var mBuffers: (AudioBuffer) sehen.

Also der kanonische Weg, auf diese Puffer und ihre Daten zuzugreifen, wäre UnsafeArray. Der folgende Code bietet einige Ideen, aber UnsafePointer und UnsafeArray sind nicht gut dokumentiert, so könnte dies falsch sein.

Das scheint auf dem Spielplatz zu funktionieren, aber es ist schwer für mich, mit echten Audiodaten zu testen. Insbesondere bin ich nicht 100% sicher, dass die Verwendung von start: &foo.memory.mBuffers wie erwartet funktioniert.(Es gibt einen anderen Zeiger vom Original zurück, obwohl die Daten dort zu sein scheinen.) Geben Sie eine Chance und melden Sie sich zurück!

Edit: diese debuggen, nebenbei gesagt, können Sie zum Beispiel:

(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 
... 
+0

Hallo, zum Schweigen zu bringen hat keine Chance, zu versuchen, dies hatte die in mein Projekt wollte aber nur schnell sagen, dass 'reininterpretCast' auch helfen könnte ... –

+0

Das ist ein guter Punkt, aber ich bin mir nicht sicher, wie ich es hier benutzen soll. Es ist undokumentiert, also weiß ich nicht, ob es am selben Ort im Speicher agiert, Dinge kopiert oder was ... – jtbandes

+0

thx. entschied, Ihnen das Guthaben zu geben, selbst wenn Adam's besser ist :) –

1

Ich habe festgestellt, das OK funktioniert. abl ist eine AudioBufferList, die beim Laden einer 16-Bit-AIFF-Audiodatei erstellt wurde.

let mBuffers=abl.memory.mBuffers 

let data=UnsafePointer<Int16>(mBuffers.mData) 
let dataArray=UnsafeBufferPointer<Int16>(start:data, count: Int(mBuffers.mDataByteSize)/sizeof(Int16)) 

//checking resulting array 
let count=dataArray.count //this matches the expected number of samples in my case 
for i in 0..<count 
{ 
    print(dataArray[i]) //values look OK in my case 
    print(" ") 
} 
14

Ich habe dies zufällig gefunden. Seltsamerweise arbeitete der Typ voraus mit Swift, als es UnsafeMutableAudioBufferListPointer vorschlug. Was Sie mit einem UnsafeMutablePointer-Argument initialisieren können. Dieser Typ ist ein MutableCollectionType und bietet Subscript- und Generatorzugriff auf die enthaltenen Audio-Puffer.

Zum Beispiel können Sie eine ABL einstellen können mit dem folgenden Code

func renderCallback(ioData: UnsafeMutablePointer<AudioBufferList>) -> OSStatus { 

    let abl = UnsafeMutableAudioBufferListPointer(ioData) 

    for buffer in abl { 

     memset(buffer.mData, 0, Int(buffer.mDataByteSize)) 
    } 

    return noErr 
} 
+0

Tolles Ergebnis! :) –

+0

Schön, das scheint ziemlich neu zu sein. – jtbandes

+0

Frage: Ich habe einen 'UnsafePointer ' aber der UnsafeMutableAudioBufferListPointer benötigt einen 'UnsafeMutablePointer '. Weißt du, wie man es konvertiert? – Georg

1

Dies funktioniert für mich mit Swift 1,2

 var ddata: NSData 
     buf = AudioBuffer(mNumberChannels: 1, mDataByteSize: numberOfFrames * UInt32(sizeof(Float32)), mData: &ddata) 
     var audioBuffers = AudioBufferList(mNumberBuffers: 1, mBuffers: buf!) 
Verwandte Themen