On Saturday 10 April 2010 21.51.55 Jean-Marc Valin wrote:> All version after 1.0 are compatible with each other and with 1.0.Hi Jean-Marc and thanks for the quick reply. I have now looked at this further and got the idea to hard code the number of frames in the decoder temporarily as a test and voil?, it works! The problem seem to be some incompatibility in the termination handling. After processing exactly four frames the number of remaining bits can be anything from zero to seven which I guess is normal. However, if I use the while loop below, speex_decode will get called one more time (a total of five times) and that seem to mess up the decoder state. The decoded audio get sort of "bubbly". while ((speex_decode(dec_state,&bits, samples) == 0) && (speex_bits_remaining(&bits) >= 0)) {} As far as I can see, the termination handling is not compatible when encoding with, in this case, Speex ver 1.2rc1 and decoding with ver 1.0.5. Do you agree or have I done something wrong in my code? The full code can be found here: http://svxlink.svn.sf.net/viewvc/svxlink/trunk/src/async/audio/AsyncAudioDecoderSpeex.cpp?view=markup http://svxlink.svn.sf.net/viewvc/svxlink/trunk/src/async/audio/AsyncAudioEncoderSpeex.cpp?view=markup I guess I could solve this problem by transmitting the frame count out-of-band but if Speex can handle it, it's better. Regards, Tobias> > Jean-Marc > > On 2010-04-10 15:44, Tobias wrote: > > Hi list, > > > > I'm trying to figure out how to do the most compatible implementation > > that will work with as many versions of Speex as possible. I am > > streaming multi frame Speex blocks over a TCP connection which works > > fine as long as the version of Speex is the same on both sides. When > > using a newer Speex (1.1.?) to encode and an older version to decode > > (1.0.5), it does not work. > > > > The encoder code look like this: > > > > int AudioEncoderSpeex::writeSamples(const float *samples, int count) > > { > > > > for (int i=0; i<count; ++i) > > { > > > > sample_buf[buf_len++] = samples[i] * 32767.0; > > > > if (buf_len == frame_size) > > { > > > > speex_encode(enc_state, sample_buf,&bits); > > buf_len = 0; > > > > if (++frame_cnt == 4) // Four frames per packet > > { > > > > speex_bits_insert_terminator(&bits); > > int nbytes = speex_bits_nbytes(&bits); > > char output_buf[nbytes]; > > nbytes = speex_bits_write(&bits, output_buf, nbytes); > > writeEncodedSamples(output_buf, nbytes); > > speex_bits_reset(&bits); > > frame_cnt = 0; > > > > } > > > > } > > > > } > > > > return count; > > > > } /* AudioEncoderSpeex::writeSamples */ > > > > > > > > The decoder have looked like this for quite a while: > > > > void AudioDecoderSpeex::writeEncodedSamples(void *buf, int size) > > { > > > > char *ptr = (char *)buf; > > > > speex_bits_read_from(&bits, ptr, size); > > float samples[frame_size]; > > > > #if SPEEX_MAJOR> 1 || (SPEEX_MAJOR == 1&& SPEEX_MINOR>= 1) > > > > while (speex_decode(dec_state,&bits, samples) == 0) > > > > #else > > > > while ((speex_decode(dec_state,&bits, samples) == 0)&& > > > > (speex_bits_remaining(&bits)> 0)) > > > > #endif > > > > { > > > > for (int i=0; i<frame_size; ++i) > > { > > > > samples[i] = samples [i] / 32767.0; > > > > } > > sinkWriteSamples(samples, frame_size); > > > > } > > > > } /* AudioDecoderSpeex::writeEncodedSamples */ > > > > > > This have worked well when using the same version of Speex on both sides. > > When using 1.1 on the encoder and 1.0 on the decoder, the number of > > frames decoded varies between three and four even though four frames are > > always sent. The use of speex_bits_remaining is one I have found by > > Googling. I started to wonder if it's wrong now though. If I change the > > comparison to read > > "speex_bits_remaining(&bits)>= 0" I always get four frames decoded. > > However, it still does not sound correctly. The change from ">" to">=" > > makes sense though. It should be OK for speex_decode to consume all bits > > so zero bits remaining should be OK (or?). > > > > The original question was if versions 1.0 and>= 1.1 is compatible. Can I > > make the code work in all cases or am I on a "mission impossible"? > > > > Regards, > > Tobias
The main difference is not that much in the bit-stream but in the API. In earlier versions you had to append the terminator manually, whereas I modifed later versions to do it automatically in case programmers forgot (there was no reason not to do so). Jean-Marc On 2010-04-11 05:23, Tobias wrote:> On Saturday 10 April 2010 21.51.55 Jean-Marc Valin wrote: >> All version after 1.0 are compatible with each other and with 1.0. > > Hi Jean-Marc and thanks for the quick reply. > > I have now looked at this further and got the idea to hard code the number of > frames in the decoder temporarily as a test and voil?, it works! The problem > seem to be some incompatibility in the termination handling. After processing > exactly four frames the number of remaining bits can be anything from zero to > seven which I guess is normal. However, if I use the while loop below, > speex_decode will get called one more time (a total of five times) and that > seem to mess up the decoder state. The decoded audio get sort of "bubbly". > > while ((speex_decode(dec_state,&bits, samples) == 0)&& > (speex_bits_remaining(&bits)>= 0)) {} > > As far as I can see, the termination handling is not compatible when encoding > with, in this case, Speex ver 1.2rc1 and decoding with ver 1.0.5. Do you agree > or have I done something wrong in my code? The full code can be found here: > > http://svxlink.svn.sf.net/viewvc/svxlink/trunk/src/async/audio/AsyncAudioDecoderSpeex.cpp?view=markup > http://svxlink.svn.sf.net/viewvc/svxlink/trunk/src/async/audio/AsyncAudioEncoderSpeex.cpp?view=markup > > I guess I could solve this problem by transmitting the frame count out-of-band > but if Speex can handle it, it's better. > > Regards, > Tobias > > >> >> Jean-Marc >> >> On 2010-04-10 15:44, Tobias wrote: >>> Hi list, >>> >>> I'm trying to figure out how to do the most compatible implementation >>> that will work with as many versions of Speex as possible. I am >>> streaming multi frame Speex blocks over a TCP connection which works >>> fine as long as the version of Speex is the same on both sides. When >>> using a newer Speex (1.1.?) to encode and an older version to decode >>> (1.0.5), it does not work. >>> >>> The encoder code look like this: >>> >>> int AudioEncoderSpeex::writeSamples(const float *samples, int count) >>> { >>> >>> for (int i=0; i<count; ++i) >>> { >>> >>> sample_buf[buf_len++] = samples[i] * 32767.0; >>> >>> if (buf_len == frame_size) >>> { >>> >>> speex_encode(enc_state, sample_buf,&bits); >>> buf_len = 0; >>> >>> if (++frame_cnt == 4) // Four frames per packet >>> { >>> >>> speex_bits_insert_terminator(&bits); >>> int nbytes = speex_bits_nbytes(&bits); >>> char output_buf[nbytes]; >>> nbytes = speex_bits_write(&bits, output_buf, nbytes); >>> writeEncodedSamples(output_buf, nbytes); >>> speex_bits_reset(&bits); >>> frame_cnt = 0; >>> >>> } >>> >>> } >>> >>> } >>> >>> return count; >>> >>> } /* AudioEncoderSpeex::writeSamples */ >>> >>> >>> >>> The decoder have looked like this for quite a while: >>> >>> void AudioDecoderSpeex::writeEncodedSamples(void *buf, int size) >>> { >>> >>> char *ptr = (char *)buf; >>> >>> speex_bits_read_from(&bits, ptr, size); >>> float samples[frame_size]; >>> >>> #if SPEEX_MAJOR> 1 || (SPEEX_MAJOR == 1&& SPEEX_MINOR>= 1) >>> >>> while (speex_decode(dec_state,&bits, samples) == 0) >>> >>> #else >>> >>> while ((speex_decode(dec_state,&bits, samples) == 0)&& >>> >>> (speex_bits_remaining(&bits)> 0)) >>> >>> #endif >>> >>> { >>> >>> for (int i=0; i<frame_size; ++i) >>> { >>> >>> samples[i] = samples [i] / 32767.0; >>> >>> } >>> sinkWriteSamples(samples, frame_size); >>> >>> } >>> >>> } /* AudioDecoderSpeex::writeEncodedSamples */ >>> >>> >>> This have worked well when using the same version of Speex on both sides. >>> When using 1.1 on the encoder and 1.0 on the decoder, the number of >>> frames decoded varies between three and four even though four frames are >>> always sent. The use of speex_bits_remaining is one I have found by >>> Googling. I started to wonder if it's wrong now though. If I change the >>> comparison to read >>> "speex_bits_remaining(&bits)>= 0" I always get four frames decoded. >>> However, it still does not sound correctly. The change from ">" to">=" >>> makes sense though. It should be OK for speex_decode to consume all bits >>> so zero bits remaining should be OK (or?). >>> >>> The original question was if versions 1.0 and>= 1.1 is compatible. Can I >>> make the code work in all cases or am I on a "mission impossible"? >>> >>> Regards, >>> Tobias > _______________________________________________ > Speex-dev mailing list > Speex-dev at xiph.org > http://lists.xiph.org/mailman/listinfo/speex-dev > >
On Sunday 11 April 2010 15.52.54 Jean-Marc Valin wrote:> The main difference is not that much in the bit-stream but in the API. > In earlier versions you had to append the terminator manually, whereas I > modifed later versions to do it automatically in case programmers forgot > (there was no reason not to do so).Yes, thanks. I know about that change and I am calling the speex_bits_insert_terminator function which make the encoder work on both older and newer versions of Speex. I even made a test where I removed the call to the speex_bits_insert_terminator when using version 1.2rc1 to encode since it is unnecessary. There were no difference in the decoder using version 1.0.5. It still did not detect the terminator properly. That is, the decoder state was still messed up when calling speex_decode an extra (fifth) time. It will exit the decode loop properly though. Hard coding the number of frames or getting this information out-of-band to the remote side seem to be the only viable solutions. Regards, Tobias> > Jean-Marc > > On 2010-04-11 05:23, Tobias wrote: > > On Saturday 10 April 2010 21.51.55 Jean-Marc Valin wrote: > >> All version after 1.0 are compatible with each other and with 1.0. > > > > Hi Jean-Marc and thanks for the quick reply. > > > > I have now looked at this further and got the idea to hard code the > > number of frames in the decoder temporarily as a test and voil?, it > > works! The problem seem to be some incompatibility in the termination > > handling. After processing exactly four frames the number of remaining > > bits can be anything from zero to seven which I guess is normal. > > However, if I use the while loop below, speex_decode will get called one > > more time (a total of five times) and that seem to mess up the decoder > > state. The decoded audio get sort of "bubbly". > > > > while ((speex_decode(dec_state,&bits, samples) == 0)&& > > > > (speex_bits_remaining(&bits)>= 0)) {} > > > > As far as I can see, the termination handling is not compatible when > > encoding with, in this case, Speex ver 1.2rc1 and decoding with ver > > 1.0.5. Do you agree or have I done something wrong in my code? The full > > code can be found here: > > > > http://svxlink.svn.sf.net/viewvc/svxlink/trunk/src/async/audio/AsyncAudio > > DecoderSpeex.cpp?view=markup > > http://svxlink.svn.sf.net/viewvc/svxlink/trunk/src/async/audio/AsyncAudi > > oEncoderSpeex.cpp?view=markup > > > > I guess I could solve this problem by transmitting the frame count > > out-of-band but if Speex can handle it, it's better. > > > > Regards, > > Tobias > > > >> Jean-Marc > >> > >> On 2010-04-10 15:44, Tobias wrote: > >>> Hi list, > >>> > >>> I'm trying to figure out how to do the most compatible implementation > >>> that will work with as many versions of Speex as possible. I am > >>> streaming multi frame Speex blocks over a TCP connection which works > >>> fine as long as the version of Speex is the same on both sides. When > >>> using a newer Speex (1.1.?) to encode and an older version to decode > >>> (1.0.5), it does not work. > >>> > >>> The encoder code look like this: > >>> > >>> int AudioEncoderSpeex::writeSamples(const float *samples, int count) > >>> { > >>> > >>> for (int i=0; i<count; ++i) > >>> { > >>> > >>> sample_buf[buf_len++] = samples[i] * 32767.0; > >>> > >>> if (buf_len == frame_size) > >>> { > >>> > >>> speex_encode(enc_state, sample_buf,&bits); > >>> buf_len = 0; > >>> > >>> if (++frame_cnt == 4) // Four frames per packet > >>> { > >>> > >>> speex_bits_insert_terminator(&bits); > >>> int nbytes = speex_bits_nbytes(&bits); > >>> char output_buf[nbytes]; > >>> nbytes = speex_bits_write(&bits, output_buf, nbytes); > >>> writeEncodedSamples(output_buf, nbytes); > >>> speex_bits_reset(&bits); > >>> frame_cnt = 0; > >>> > >>> } > >>> > >>> } > >>> > >>> } > >>> > >>> return count; > >>> > >>> } /* AudioEncoderSpeex::writeSamples */ > >>> > >>> > >>> > >>> The decoder have looked like this for quite a while: > >>> > >>> void AudioDecoderSpeex::writeEncodedSamples(void *buf, int size) > >>> { > >>> > >>> char *ptr = (char *)buf; > >>> > >>> speex_bits_read_from(&bits, ptr, size); > >>> float samples[frame_size]; > >>> > >>> #if SPEEX_MAJOR> 1 || (SPEEX_MAJOR == 1&& SPEEX_MINOR>= 1) > >>> > >>> while (speex_decode(dec_state,&bits, samples) == 0) > >>> > >>> #else > >>> > >>> while ((speex_decode(dec_state,&bits, samples) == 0)&& > >>> > >>> (speex_bits_remaining(&bits)> 0)) > >>> > >>> #endif > >>> > >>> { > >>> > >>> for (int i=0; i<frame_size; ++i) > >>> { > >>> > >>> samples[i] = samples [i] / 32767.0; > >>> > >>> } > >>> sinkWriteSamples(samples, frame_size); > >>> > >>> } > >>> > >>> } /* AudioDecoderSpeex::writeEncodedSamples */ > >>> > >>> > >>> This have worked well when using the same version of Speex on both > >>> sides. When using 1.1 on the encoder and 1.0 on the decoder, the > >>> number of frames decoded varies between three and four even though > >>> four frames are always sent. The use of speex_bits_remaining is one I > >>> have found by Googling. I started to wonder if it's wrong now though. > >>> If I change the comparison to read > >>> "speex_bits_remaining(&bits)>= 0" I always get four frames decoded. > >>> However, it still does not sound correctly. The change from ">" to">=" > >>> makes sense though. It should be OK for speex_decode to consume all > >>> bits so zero bits remaining should be OK (or?). > >>> > >>> The original question was if versions 1.0 and>= 1.1 is compatible. Can > >>> I make the code work in all cases or am I on a "mission impossible"? > >>> > >>> Regards, > >>> Tobias