2010-11-26 5 views
1

Meine Frage bezieht sich auf diese Frage, aber es ist in umgekehrter Reihenfolge.repräsentieren 2 sint16s Proben als eine einzige Uint32 Probe

Split UInt32 (audio frame) into two SInt16s (left and right)?

In der Verbindung über dem op wollte einen 32-Bit-Rahmen in 2 16-Bit-Abtastwerte (links und rechts) spalten.

Ich habe 2 16-Bit-Samples und möchte sie als 32-Bit-Interleaved-Frame ausdrücken.

Was ich bisher versucht habe, sieht so aus.

UInt32* ar = malloc(totalFramesInFile * sizeof (ar)); 

for (int b=0; b < totalFramesInFile; b++) 
{ 
    UInt32 l = soundStructArray[audioFile].audioDataLeft[b]; 
    UInt32 r = soundStructArray[audioFile].audioDataRight[b]; 

    UInt32 t = (UInt32) l + r; 

    ar[b] = t; 
} 
soundStructArray[audioFile].audioData = ar; 

Ist das legitim und korrekt? Ich bin mir aufgrund meiner Unerfahrenheit nicht sicher. Mein Audio-Ausgang klingt etwas eigenartig und ich versuche durch Eliminierung festzustellen, was schief geht.

Es wäre hilfreich, wenn jemand bestätigen könnte, dass das, was ich mache, der richtige Weg ist, um 2 16-Bit-Samples als 32-Bit-Frame auszudrücken oder einen korrekten Weg vorzuschlagen.

Ich habe das Gefühl, dass das, was ich getan habe, falsch ist. Ich denke dies, weil die ersten 16 Bits des 32-Bit-Rahmens die linke und die zweiten 16 Bits die richtige sein sollten. Das Ganze sollte nicht die Summe der beiden sein ...... denke ich.

+0

Vielleicht sollten Ihre l und r Proben Typ const UInt16 haben? – unwind

Antwort

4

Sie müssen sich ändern ::

UInt32 t = (UInt32) l + r; 

zu:

UInt32 t = (l << 16) | (r & 0xffff); 

Dies stellt l in den höchstwertigen 16 Bits von t und r in den am wenigsten signifikanten 16 Bits.

Ausführliche Erklärung

Wenn Sie zwei 16-Bit-Proben haben, l und r, die in binärer wie folgt aussehen:

l: LLLLLLLLLLLLLLLL 
r: RRRRRRRRRRRRRRRR 

Lassen Sie uns zunächst, sie erstrecken sich bis zu 32 Bit:

l: 0000000000000000LLLLLLLLLLLLLLLL 
r: 0000000000000000RRRRRRRRRRRRRRRR 

Jetzt verschieben wir l um 16 Bits (l << 16)

l: LLLLLLLLLLLLLLLL0000000000000000 
r: 0000000000000000RRRRRRRRRRRRRRRR 

Lassen Sie uns jetzt OR (|) sie zusammen:

t: LLLLLLLLLLLLLLLLRRRRRRRRRRRRRRRR 

Voilà! Jetzt haben Sie l und r kombiniert in einem 32-Bit-Wert, aus dem sie später wieder leicht extrahiert werden können.

+1

ausgezeichnete Erklärung! – dubbeat

+0

Dies funktioniert nur, wenn Sie zwei * unsigned * 16 Bit Samples haben. Negative, vorzeichenbehaftete 16-Bit-Abtastwerte würden in vorzeichenlose 32-Bit-Zahlen umgewandelt, wobei alle oberen 16 Bits "1" sind. – caf

+0

@caf: true - Ich habe die Maskierung weggelassen, um das Beispiel einfach zu halten, aber ich schätze, ich sollte es hinzufügen - antworten Sie jetzt aktualisiert. –

2

Ich nehme das als Ergänzung zu Paul Rs Antwort auf, aber es war ein bisschen zu lang, um einen Kommentar abzugeben.

Eine alternative Lösung, die "offensichtlich" sein kann, ist das explizite Festlegen der oberen oder unteren 16-Bit-Werte im 32-Bit-Wert. Sie können dies mit einer Vereinigung tun, d.

typedef union { 
    struct { 
     SInt16 high; 
     SInt16 low; 
    } parts; 
    UInt32 word; 
} IntConverter; 

Verbrauch:

IntConverter * ar = malloc(totalFramesInFile * sizeof (IntConverter)); 

for (int b=0; b < totalFramesInFile; b++) 
{ 
    ar[b].parts.high = soundStructArray[audioFile].audioDataLeft[b]; 
    ar[b].parts.low = soundStructArray[audioFile].audioDataRight[b]; 
} 
soundStructArray[audioFile].audioData = (UInt32 *) ar; 

Doch dieser Ansatz erfordert, dass Sie ein bisschen mehr über die zugrunde liegende Plattform zu wissen, da es auf beruht, wie die Daten tatsächlich gespeichert. Abhängig von der Zielplattform und dem Compiler könnte es jedoch effizienter sein.

+0

das ist ziemlich nützlich. "Union" ist neu für mich. Ich habe Struct bisher nur einmal gesehen – dubbeat

Verwandte Themen