2010-11-25 7 views
2

Ich verwende Speex, um einige Audiodaten zu kodieren und es über UDP zu senden und es auf der anderen Seite zu decodieren. Ich habe ein paar Tests mit Speex durchgeführt und festgestellt, dass, wenn ich ein Paket dekodiere, direkt nachdem ich es codiert habe, die decodierten Daten in keiner Weise nah an den ursprünglichen Daten sind. Die meisten Bytes am Anfang des Puffers sind 0. Also, wenn ich das über UDP gesendete Audio dekodiere, bekomme ich nur Rauschen. Dies ist, wie ich das Audio-bin kodiert:speex Decodierung geht falsch

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

das ist, wie ich das Audio-Decodierung am:

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

Ich habe die Dokumentation überprüfen, und die meisten meinen Code stammt aus dem Beispiel Codieren/Decodieren eines Samples von der Speex-Website. Ich bin mir nicht sicher, was ich hier vermisse.

+0

speex ist ein verlustbehafteter Codec, der resultierende Stream wird anders sein als original, weil Sie Informationen verlieren, um eine bessere Komprimierung zu erreichen. –

+1

@Paulo Scardine Wenn ich ein Array mit den Werten einer Sinuswelle kodiere, sind die 20 ~ ersten Floats (einmal decodiert) alle gleich 0. Ich weiß, dass es verlustreich ist, aber da verliere ich die meisten Daten. Ich bekomme auch einige negative Werte, wo ich positive Werte habe. – dotminic

+0

scheint wie ein signed/unsigned-Datentyp-Problem. –

Antwort

1

Ich fand den Grund, warum die codierten Daten so unterschiedlich waren. Es ist die Tatsache, dass es eine verlustbehaftete Komprimierung ist, wie Paulo Scardine sagte, und auch, dass speex nur mit 160 Frames arbeitet, wenn also Daten von portaudio zu speex kommen, muss es durch "Pakete" von 160 Frames sein.

+1

was meinst du mit 160 frames? ein Rahmen sollte 160 kurze oder 320 Bytes enthalten, oder? – guness

+0

Framegröße bezieht sich immer auf die decodierte Datenrahmengröße in Samples. Framegröße ist abhängig vom Codiermodus Schmalband (8 kHz): Rahmengröße = 160 Abtastwerte = 320 Bytes PCM Breitband (16 kHz): Rahmengröße = 320 Abtastwerte = 640 Byte PCM Ultra-Breitband (32 kHz): Rahmengröße = 640 Abtastungen = 1280 Bytes PCM –

0

Sie möchten vielleicht einen Blick hier für einige einfache Codierung/Decodierung haben: http://www.speex.org/docs/manual/speex-manual/node13.html#SECTION001310000000000000000

Da Sie UDP verwenden Sie auch mit einem Jitter-Puffer arbeiten können Pakete und so neu zu ordnen.

+0

Ich habe diesen Link gesehen, und nein, ich benutze noch keinen Jitter-Puffer, da ich noch nicht einmal ein Paket codieren/senden/decodieren/abspielen kann. Ich ziehe mir die Haare aus! – dotminic

1

Eigentlich spricht führt eine zusätzliche Verzögerung auf die Audiodaten, fand ich durch reverse enginiering aus:

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 

Da der Look-Ahead mit zereos initialisiert ist, können Sie die ersten paar Proben beobachten „nahe Null“ zu sein .

Um das richtige Timing zu erhalten, müssen Sie diese Samples überspringen, bevor Sie die tatsächlichen Audiodaten, die Sie in den Codec eingegeben haben, erhalten. Warum das ist, weiß ich nicht. Probalby der Autor von speex kümmerte sich nie darum, da speex zum streamen dient, nicht primär zum Speichern und Wiederherstellen von Audiodaten. Eine weitere Problemumgehung (um Platz zu sparen) ist, dass Sie Nullen in den Codec einspeisen, bevor Sie Ihre eigentlichen Audiodaten einspeisen und dann den gesamten ersten Speer-Rahmen löschen.

Ich hoffe, dass dies alles klarstellt. Wenn jemand, der mit Speex vertraut ist, dies liest, kannst du mich korrigieren, wenn ich falsch liege.

EDIT: Eigentlich haben Decoder und Encoder beide eine vorausschauende Zeit. Die tatsächliche Formel für die Verzögerung ist:

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