2010-11-26 4 views
1

Ma question est liée à cette question mais elle est à l'envers.représente 2 échantillons sint16s comme un seul échantillon uint32

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

Dans la liaison au-dessus du op souhaitée pour diviser une trame de 32 bits en 2 16 échantillons de bit (gauche et droite).

J'ai 2 échantillons de 16 bits et je voudrais les exprimer comme une seule trame entrelacée de 32 bits. Ce que j'ai tenté jusqu'à présent ressemble à ceci.

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; 

Est-ce légitime et correct? Je ne suis pas sûr en raison de mon inexpérience. Ma sortie audio sonne un peu particulier et j'essaie par processus d'élimination de déterminer ce qui ne va pas.

Il serait utile que quelqu'un puisse soit confirmer que ce que je fais est la bonne façon d'exprimer 2 échantillons de 16 bits comme une trame de 32 bits ou suggérer une manière correcte. J'ai le sentiment que ce que j'ai fait est faux. Je pense que c'est parce que les 16 premiers bits de la trame 32 bits devraient être à gauche et les 16 bits restants devraient être les bons. Le tout ne devrait pas être la somme des deux ... Je pense.

+0

Peut-être que vos échantillons l et r devraient avoir le type const UInt16? – unwind

Répondre

4

Vous devez changer ::

UInt32 t = (UInt32) l + r; 

à:

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

Cela met l dans les 16 bits les plus significatifs de t et r dans les moins 16 bits significatifs.

Explication détaillée

Si vous avez deux 16 échantillons de bits, l et r, qui ressemblent à ceci en binaire:

l: LLLLLLLLLLLLLLLL 
r: RRRRRRRRRRRRRRRR 

nous allons d'abord les étendre à de 32 bits:

l: 0000000000000000LLLLLLLLLLLLLLLL 
r: 0000000000000000RRRRRRRRRRRRRRRR 

Passons maintenant l laissé par 16 bits (l << 16)

l: LLLLLLLLLLLLLLLL0000000000000000 
r: 0000000000000000RRRRRRRRRRRRRRRR 

Maintenant, nous allons OU (|) les ensemble:

t: LLLLLLLLLLLLLLLLRRRRRRRRRRRRRRRR 

Voilà! Maintenant vous avez l et r combinés dans une valeur de 32 bits à partir de laquelle ils peuvent facilement être extraits à nouveau plus tard.

+1

excellente explication! – dubbeat

+0

Cela ne fonctionne que si vous avez deux * 16 bits non signés. Les échantillons 16 bits négatifs et signés sont convertis en nombres 32 bits non signés avec tous les 16 bits supérieurs étant '1'. – caf

+0

@caf: true - J'ai omis le masquage pour garder l'exemple simple mais je suppose que je devrais l'ajouter - réponse mise à jour maintenant. –

2

Je vais prendre cela comme un complément à la réponse de Paul R, mais c'était un peu long à mettre en commentaire.

Une solution alternative qui peut être plus "évidente" consiste à définir explicitement les valeurs supérieures ou inférieures de 16 bits dans la valeur de 32 bits. Vous pouvez le faire avec une union, c'est-à-dire

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

Utilisation:

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; 

Cependant, cette approche nécessite de connaître un peu plus sur la plate-forme sous-jacente, car elle repose sur la façon dont les données sont effectivement stockées dans la mémoire. Selon la plate-forme cible et le compilateur, cependant, cela pourrait être plus efficace.

+0

c'est très utile. "union" est nouveau pour moi. Je n'ai vu que struct avant – dubbeat

Questions connexes