Nathaniel Meyer
2004-Sep-12 16:04 UTC
[Speex-dev] Speex encoding/decoding producing garbled audio
I'm getting garbled playback with decoded fragments and I'm hoping
someone
here can point me in the right direction to correcting the problem.
Essentially I'm capturing audio from the microphone. I stream it over the
net, but for testing purposes with this API I'm just grabbing the whole
chunk and encoding / decoding it right away and then updating the sound
buffer for playback. The playback sounds very scratchy with a bit of a buzz
sound and some skipping; yet I can still make it out somewhat. At first I
though maybe I was doing data conversion between bytes and shorts
incorrectly, so I temporarily moved over to a short-based system. Still the
problem persisted, so perhaps it could be a setting or two I'm missing? I
posted my code below, demonstrating how I'm encoding and decoding the
buffers. I can't see anything wrong with it, so I'm guessing my problem
lies
elsewhere. If anyone experienced a similar problem beforehand, it would be
nice to know what I could be doing wrong. As far as the system itself, I can
perfectly record audio at any channel setting, sample rate, or bit-rate and
play it back fine.
- I'm using Speex version 1.1.6. I've also used 1.0.4 beforehand and
experienced the same problem with it.
1) I initialize the bits, encoder, and decoder as normal (default settings
seemed appropriate):
speex_bits_init(&mBits);
mEncode = speex_encoder_init(&speex_nb_mode);
mDecode = speex_decoder_init(&speex_nb_mode);
2) I record my audio at mono 8000Hz, 16bits per sample.
3) I encode frame-sized (320 bytes) fragments. Since I deal only with char
data types, I convert to 2-byte short values first and then set the float
buffer.
char *CSpeex::encode (char *buffer, int size, int &encodeSize)
{
char *encodedBuffer = new char[160];
short speexShort;
float *speexFloat = new float[160];
// Convert the audio to a short then to a float buffer
for (int i = 0; i < 160; i++)
{
memcpy(&speexShort, &buffer[i*2], sizeof(short));
speexFloat[i] = speexShort;
}
// Encode the sound data using the float buffer
speex_bits_reset(&mBits);
speex_encode(mEncode, speexFloat, &mBits);
encodeSize = speex_bits_write(&mBits, encodedBuffer, 160);
delete[] speexFloat;
// Return the encoded buffer
return encodedBuffer;
}
4) I immediately decode the encoded buffer. Encoded size is always 38 bytes
for this sample set and expected decoded size is 320 bytes
char *CSpeex::decode (char *buffer, int encodeSize)
{
char *decodedBuffer = new char[320];
short speexShort;
float *speexFloat = new float[160];
// Decode the sound data into a float buffer
speex_bits_reset(&mBits);
speex_bits_read_from(&mBits, buffer, encodeSize);
speex_decode(mDecode, &mBits, speexFloat);
// Convert from float to short to char
for (int i = 0; i < 160; i++)
{
speexShort = speexFloat[i];
memcpy(&decodedBuffer[i*2], &speexShort, sizeof(short));
}
delete[] speexFloat;
// Return the buffer
return decodedBuffer;
}
Hope no one minds the source post. I'm really stumped on this one, but the
benefits of using Speex versus the bloat offered in the competitors are well
worth the hassle. I'm looking forward to incorporating this into several
games for VoIP support.
Thanks.
Jean-Marc Valin
2004-Sep-12 19:53 UTC
[Speex-dev] Speex encoding/decoding producing garbled audio
Hi, If you're having problems with simple encoding/decoding with Speex, I strongly suggest starting with the sampleenc.c/sampledec.c programs that are included in the appendix of the manual. From there, you can start adding more stuff, but at least you start from something that works. If you need a more complicated example, see speexenc.c and speexdec.c . Jean-Marc On dim, 2004-09-12 at 19:03 -0400, Nathaniel Meyer wrote:> I'm getting garbled playback with decoded fragments and I'm hoping someone > here can point me in the right direction to correcting the problem. > > > > Essentially I'm capturing audio from the microphone. I stream it over the > net, but for testing purposes with this API I'm just grabbing the whole > chunk and encoding / decoding it right away and then updating the sound > buffer for playback. The playback sounds very scratchy with a bit of a buzz > sound and some skipping; yet I can still make it out somewhat. At first I > though maybe I was doing data conversion between bytes and shorts > incorrectly, so I temporarily moved over to a short-based system. Still the > problem persisted, so perhaps it could be a setting or two I'm missing? I > posted my code below, demonstrating how I'm encoding and decoding the > buffers. I can't see anything wrong with it, so I'm guessing my problem lies > elsewhere. If anyone experienced a similar problem beforehand, it would be > nice to know what I could be doing wrong. As far as the system itself, I can > perfectly record audio at any channel setting, sample rate, or bit-rate and > play it back fine. > > > > - I'm using Speex version 1.1.6. I've also used 1.0.4 beforehand and > experienced the same problem with it. > > > > 1) I initialize the bits, encoder, and decoder as normal (default settings > seemed appropriate): > > speex_bits_init(&mBits); > > mEncode = speex_encoder_init(&speex_nb_mode); > > mDecode = speex_decoder_init(&speex_nb_mode); > > > > 2) I record my audio at mono 8000Hz, 16bits per sample. > > > > 3) I encode frame-sized (320 bytes) fragments. Since I deal only with char > data types, I convert to 2-byte short values first and then set the float > buffer. > > char *CSpeex::encode (char *buffer, int size, int &encodeSize) > > { > > char *encodedBuffer = new char[160]; > > short speexShort; > > float *speexFloat = new float[160]; > > > > // Convert the audio to a short then to a float buffer > > for (int i = 0; i < 160; i++) > > { > > memcpy(&speexShort, &buffer[i*2], sizeof(short)); > > speexFloat[i] = speexShort; > > } > > > > // Encode the sound data using the float buffer > > speex_bits_reset(&mBits); > > speex_encode(mEncode, speexFloat, &mBits); > > encodeSize = speex_bits_write(&mBits, encodedBuffer, 160); > > delete[] speexFloat; > > > > // Return the encoded buffer > > return encodedBuffer; > > } > > > > 4) I immediately decode the encoded buffer. Encoded size is always 38 bytes > for this sample set and expected decoded size is 320 bytes > > char *CSpeex::decode (char *buffer, int encodeSize) > > { > > char *decodedBuffer = new char[320]; > > short speexShort; > > float *speexFloat = new float[160]; > > > > // Decode the sound data into a float buffer > > speex_bits_reset(&mBits); > > speex_bits_read_from(&mBits, buffer, encodeSize); > > speex_decode(mDecode, &mBits, speexFloat); > > > > // Convert from float to short to char > > for (int i = 0; i < 160; i++) > > { > > speexShort = speexFloat[i]; > > memcpy(&decodedBuffer[i*2], &speexShort, sizeof(short)); > > } > > delete[] speexFloat; > > > > // Return the buffer > > return decodedBuffer; > > } > > > > > > Hope no one minds the source post. I'm really stumped on this one, but the > benefits of using Speex versus the bloat offered in the competitors are well > worth the hassle. I'm looking forward to incorporating this into several > games for VoIP support. > > > > > > Thanks. > _______________________________________________ > Speex-dev mailing list > Speex-dev@xiph.org > http://lists.xiph.org/mailman/listinfo/speex-dev
Reed Hedges
2004-Sep-13 05:12 UTC
[Speex-dev] Speex encoding/decoding producing garbled audio
Nathaniel Meyer wrote:> I'm getting garbled playback with decoded fragments and I'm hoping > someone here can point me in the right direction to correcting the problem.What format does your playback require-- both datatypes and ranges? I wasn't sure why I was getting garbled noise until I realized that Speex samples range from 0.0f to 32768.0f (Is this documented anywhere in the Speex docs?), while my audio IO library (PortAudio) uses 0.0f to 1.0f :D Reed