2011-04-19 7 views
4

Je audio PCM enregistré dans un tableau d'octets. C'est 16 bits par échantillon. Je veux faire 8 bits par échantillon audio.Autre 16 bits PCM à 8 bits

Quelqu'un peut-il suggérer un bon algorithme pour le faire?

Je n'ai pas mentionné le débit car je pense que ce n'est pas important pour l'algorithme - non?

+1

Le débit peut être important (mais pas nécessairement) - par ex. quand vous traitez avec des convertisseurs A/N (quand vous traitez avec l'audio vous le sortez finalement par A/D) vous pourriez augmenter la fréquence d'échantillonnage d'un facteur de 65k (si je calculais correctement) pour obtenir la plus haute résolution avec moins de bits). – flolo

+1

Ce n'est pas Java, mais regardez comment ffmpeg l'implémente. Parcourir le code ici: http://ffmpeg.org/doxygen/0.5/pcm_8c-source.html – Aleadam

+0

@gosho_ot_pochivka Pouvez-vous me faire savoir comment convertir 16bit pcm en 24 bits. Merci – ravi

Répondre

7

Je ne vois pas pourquoi il ne suffit pas de prendre l'octet supérieur, c'est-à-dire de jeter les 8 bits inférieurs de chaque échantillon.

Ce suppose bien entendu que les échantillons sont linéaires; Si ce n'est pas le cas, vous devrez peut-être faire quelque chose pour les linéariser avant de laisser tomber des morceaux.

short sixteenBit = 0xfeed; 
byte eightBit = sixteenBit >> 8; 
// eightBit is now 0xfe. 

Comme suggéré par AShelly dans un commentaire, il pourrait être une bonne idée de compléter, à savoir ajouter 1 si l'octet nous jeter est supérieure à la moitié maximum:

eightBit += eightBit < 0xff && ((sixteenBit & 0xff) > 0x80); 

Le test contre 0xff implémente le serrage, donc nous ne risquons pas d'ajouter 1 à 0xff et d'envelopper cela à 0x00 ce qui serait mauvais.

+1

Vous pouvez également vouloir arrondir au lieu de tronquer. Ajoutez 'eightbit + = (seizebit & 0x80) >> 7;' ajouter 1 si l'octet inférieur est plus de la moitié de sa portée. – AShelly

+1

@AShelly: vrai, ce pourrait être une bonne idée ... Votre code va provoquer des valeurs dans la plage 0xff00 à 0xffff pour renvoyer à 0x00, ce qui est probablement pire que de ne pas arrondir du tout. Je vais éditer. – unwind

+0

merci. Si mon entrée est dans un tableau d'octets (octet [] arr n'est pas court) cela signifie-t-il simplement laisser tomber la moitié des octets, c'est-à-dire arr [0], arr [2], arr [4] etc. –

1

Normalise les échantillons de 16 bits, puis redimensionne la valeur maximale de votre échantillon de 8 bits. Cela donne une conversion plus précise car les 8 bits inférieurs de chaque échantillon ne sont pas rejetés. Cependant, ma solution est plus coûteuse en calcul que la réponse sélectionnée.

6

Les échantillons de 16 bits sont généralement signés et les échantillons de 8 bits sont généralement non signés. La réponse la plus simple est de convertir les échantillons de 16 bits en échantillons signés (les échantillons de 16 bits sont presque toujours stockés de -32768 à +32767) à unsigned et ensuite prendre les 8 premiers bits du résultat. En C, cela pourrait être exprimé comme output = (unsigned char) ((unsigned short) (entrée + 32768) >> 8). C'est un bon début, et pourrait être assez bon pour vos besoins, mais cela ne vous semblera pas très agréable. Cela semble rugueux à cause du "bruit de quantification".

Le bruit de quantification est la différence entre l'entrée d'origine et la sortie de votre algorithme. Peu importe ce que vous faites, vous allez avoir du bruit, et le bruit sera "un demi-bit" en moyenne. Il n'y a rien que vous puissiez faire à ce sujet, mais il existe des moyens de rendre le bruit moins perceptible.

Le principal problème avec le bruit de quantification est qu'il a tendance à former des motifs. Si la différence entre l'entrée et la sortie était complètement aléatoire, les choses sembleraient bien, mais la sortie sera à plusieurs reprises trop élevée pour une certaine partie de la forme d'onde et trop faible pour la partie suivante. Votre oreille capte ce motif.

Pour avoir un résultat qui sonne bien, vous devez ajouter tramage. Le dithering est une technique qui essaie de lisser le bruit de quantification. Le tramage le plus simple supprime simplement les motifs du bruit de sorte que les motifs de bruit ne distraient pas des motifs de signal réels. Mieux tramage peut aller plus loin et prendre des mesures pour réduire le bruit en additionnant les valeurs d'erreur à partir de plusieurs échantillons, puis en ajoutant une correction lorsque l'erreur totale devient assez grand pour être utile de corriger.

Vous trouverez des explications et des exemples de code pour les différents algorithmes de tramage en ligne. Un bon domaine à étudier pourrait être l'outil SoX, http://en.wikipedia.org/wiki/SoX. Vérifiez l'origine de son effet de tramage et expérimentez la conversion de différents sons de 16 bits à 8 bits avec et sans tramage activé. Vous serez surpris par la différence de qualité que le tramage peut faire lors de la conversion en son 8 bits.

1
byteData = (byte) (((shortData +32768)>>8)& 0xFF) 

cela a fonctionné pour moi.

Questions connexes