[Vorbis-dev] RE: encode, decode and encode again

Aleksey Surkov Aleksey_S at abbyy.com
Mon Sep 11 08:17:04 PDT 2006


Hi, Ian!	

Thank you for your response. Here is some details...

> Well, without the code we can't say much.  Since the problem occurs
with 
> large numbers of files I'd suggest there's some kind of memory leak 
> somewhere, or some buffer is being filled up and never emptied.

Not exactly so. It works correctly with other files (even with a big
number of files) and fails just for several "bad" files.

>Your problem with round trippping the files may be related or entirely 
> separate.  Are you sure the .wav files being produced at the
intermediate 
> step are valid?

Yes, they are valid. I can play it. More, after converting (changing
frequency) by CDex the files can be compressed again correctly. I just
can't compress it immediately after decompressing, without any
intermediate actions like frequency changing via third-party utility.

> Final aside: this is just a test isn't it?  Round tripping audio
through
> the encode/decode is probably a bad idea.

No, unfortunately it`s not a test. It`s a real problem (we've lost  the
source files that are compressed into archive... And now the only way to
make some changes in this archive is decompressing-compressing). 

And this problem occurs not only with recompressed files.

For example, I have a test wav file (88 kb), the described bug occurs
with it:
http://rapidshare.de/files/32738670/0008.wav.html or I can send it by
email, just write me to Aleksey_S(at)abbyy.com

The Code I use is almost the same as in example below (it's a part that
encodes files):


void COggArchive::addFileToStream(CWAVFile & wavFile)
{
	char readBuffer[ReadBufferSize];
	int bytesRead;

	int channels = pcmDefaultSettings.channels;
	int bytesPerSample = wavFile.GetWaveFormat().nBitsPerSample / 8;
	int bytesPerChannel = bytesPerSample / channels;
	int totalSamples = wavFile.getDataChunkSize() / bytesPerSample;

	while( bytesRead = wavFile.ReadData( readBuffer, ReadBufferSize
) ) {
		int samplesRead = bytesRead / bytesPerSample;
		float **buffer = vorbis_analysis_buffer( &oggState.vd,
samplesRead );

		for (int ch = 0; ch < channels; ch++) {
			for (int i = 0; i < samplesRead; i++) {
				if ( bytesPerChannel == 2 ) {
					short ampl;
					int sampleChannelOffset = i *
bytesPerSample + ch * 2/*bytesPerChannel*/;
					ampl = ( ( 0x00ff &
(short)readBuffer[sampleChannelOffset] ) |
						(
readBuffer[sampleChannelOffset + 1] << 8 ) );
					buffer[ch][i] = ampl / 32768.f;
				} else {
					buffer[ch][i] =
readBuffer[i*bytesPerSample + ch/* *bytesPerChannel=1*/] / 255.f;
				}
			}
		}

		vorbis_analysis_wrote( &oggState.vd, samplesRead );
		EncodeReadSamples();
	}

}

void COggArchive::EncodeReadSamples()
{
	int eos = 0;

	while( vorbis_analysis_blockout( &oggState.vd, &oggState.vb ) ==
1 ) {

		/* analysis, assume we want to use bitrate management */
		vorbis_analysis( &oggState.vb, 0 );
		vorbis_bitrate_addblock( &oggState.vb );

		while( vorbis_bitrate_flushpacket( &oggState.vd,
&oggState.op ) ) {

			/* weld the packet into the bitstream */
			ogg_stream_packetin( &oggState.os, &oggState.op
);

			/* write out pages (if any) */
//			int eos = 0;
			while( !eos ) {
				if ( !ogg_stream_pageout( &oggState.os,
&oggState.og ) )
					break;
				streamBuffer->Write( oggState.og.header,
oggState.og.header_len );
				streamBuffer->Write( oggState.og.body,
oggState.og.body_len );

				if( ogg_page_eos( &oggState.og ) )
					eos = 1;
			}
		}
	}
}


More information about the Vorbis-dev mailing list