2010-11-25 4 views
2

J'utilise speex pour encoder des données audio et les envoyer via UDP, et les décoder de l'autre côté. J'ai effectué quelques tests avec speex, et j'ai remarqué que si je décode un paquet directement après l'avoir encodé, les données décodées ne sont en aucun cas proches des données d'origine. La plupart des octets au début de la mémoire tampon sont 0. Donc, quand je décode l'audio envoyé sur UDP, tout ce que je reçois, c'est du bruit. Voilà comment je suis l'encodage audio:Le décodage de speex se passe mal

bool AudioEncoder::encode(float *raw, char *encoded_bits) 
{ 
    for (size_t i = 0; i < 256; i++) 
     this->_rfdata[i] = raw[i]; 
    speex_bits_reset(&this->_bits); 
    speex_encode(this->_state, this->_rfdata, &this->_bits); 
    int bytesWritten = speex_bits_write(&this->_bits, encoded_bits, 512); 
    if (bytesWritten) 
     return true; 
    return false; 
} 

c'est ainsi que je décoder les audio:

float *f = new float[256]; 
// recvbuf is the buffer I pass to my recv function on the socket 
speex_bits_read_from(&this->_bits, recvbuf, 512); 
speex_decode(this->state, &this->_bits, f); 

J'ai vérifier les documents, et la plupart de mon code provient de l'exemple échantillon d'encodage/décodage du site web de speex. Je ne suis pas sûr de ce qui me manque ici.

+0

speex est un codec avec perte, le flux résultant sera différent de l'original car vous perdez des informations afin d'obtenir une meilleure compression. –

+1

@Paulo Scardine si je code un tableau avec les valeurs d'une onde sinusoïdale, les 20 ~ premiers flotteurs (une fois décodés) sont tous égaux à 0. Je sais que c'est un problème, mais je perds la plupart des données. J'ai aussi des valeurs neg où j'avais des valeurs positives. – dotminic

+0

semble être un problème de type de données signé/non signé. –

Répondre

1

J'ai trouvé la raison pour laquelle les données codées étaient si différentes. Il y a le fait que c'est une compression avec perte, comme l'a dit Paulo Scardine, et aussi que speex ne fonctionne qu'avec 160 images, donc quand on obtient des données de portaudio vers speex, il faut des paquets de 160 images.

+1

que voulez-vous dire par 160 images? un cadre devrait inclure 160 courts ou 320 octets à droite? – guness

+0

Framesize fait toujours référence à la taille de trame de données décodée dans les échantillons. Framesize dépend du mode de codage Bande étroite (8kHz): taille de trame = 160 échantillons = 320 octets de PCM Large bande (16kHz): taille de trame = 320 échantillons = 640 octets de PCM Ultra Wideband (32kHz): taille de trame = 640 échantillons = 1280 octets de PCM –

0

Vous pouvez jeter un oeil ici pour quelques simples encodage/décodage: http://www.speex.org/docs/manual/speex-manual/node13.html#SECTION001310000000000000000

Puisque vous utilisez UDP, vous pouvez également travailler avec un tampon de gigue aux paquets réordonner et des choses.

+0

J'ai vu ce lien, et non, n'utilisant pas encore de tampon de gigue, car je ne peux même pas encore obtenir un paquet codé/envoyé/décodé/lu correctement. Je m'arrache les cheveux pour ça! – dotminic

1

parle fait introduit un délai supplémentaire aux données audio, j'ai découvert par enginiering inverse:

narrow band : delay = 200 - framesize + lookahead = 200 - 160 + 40 = 80 samples 

wide band : delay = 400 - framesize + lookahead = 400 - 320 + 143 = 223 samples 

uwide band : delay = 800 - framesize + lookahead = 800 - 640 + 349 = 509 samples 

Depuis le préanalyse est initialisé avec zereos, vous observez les premiers échantillons à être « proche de zéro » . Pour obtenir le bon timing, vous devez ignorer ces échantillons avant d'obtenir les données audio réelles que vous avez alimentées dans le codec. Pourquoi c'est, je ne sais pas. Probalby l'auteur de speex ne s'est jamais soucié de cela puisque speex est pour le streaming, pas principalement pour stocker et restaurer des données audio. Une autre solution de contournement (pour ne pas gaspiller d'espace) est que vous alimentez (codifiez-retarder) des zéros dans le codec, avant d'alimenter vos données audio réelles, puis de laisser tomber toute la première trame speex.

J'espère que cela clarifie tout. Si quelqu'un qui connaît Speex lit ceci, n'hésitez pas à me corriger si je me trompe.

EDIT: En fait, le décodeur et le codeur ont tous les deux un temps d'anticipation. La formule actuelle du délai est la suivante:

narrow band : delay = decoder_lh + encoder_lh = 40 + 40 = 80 samples 

wide band : delay = decoder_lh + encoder_lh = 80 + 143 = 223 samples 

uwide band : delay = decoder_lh + encoder_lh = 160 + 349 = 509 samples