moved functions conv8() and conv16() to class Util (as conv())

added resampling functionality
added support for variable bitrates
This commit is contained in:
darkeye 2002-03-28 16:47:38 +00:00
parent a50598add0
commit 38dc041a4b
2 changed files with 173 additions and 168 deletions

View File

@ -72,13 +72,38 @@ VorbisLibEncoder :: open ( void )
} }
vorbis_info_init( &vorbisInfo); vorbis_info_init( &vorbisInfo);
if ( (ret = vorbis_encode_init( &vorbisInfo,
getInChannel(), if ( isVBR() ) {
getInSampleRate(),
getOutBitrate() * 1000, if ( (ret = vorbis_encode_init_vbr( &vorbisInfo,
getOutBitrate() * 1000, getInChannel(),
-1 )) ) { getOutSampleRate(),
throw Exception( __FILE__, __LINE__, "vorbis encode init error", ret); getOutQuality() )) ) {
throw Exception( __FILE__, __LINE__,
"vorbis encode init error", ret);
}
} else {
#ifdef VORBIS_LIB_RC3
if ( (ret = vorbis_encode_init( &vorbisInfo,
getInChannel(),
getOutSampleRate(),
getOutBitrate() * 1024,
getOutBitrate() * 1024,
-1 )) ) {
throw Exception( __FILE__, __LINE__,
"vorbis encode init error", ret);
}
#else
if ( (ret = vorbis_encode_init( &vorbisInfo,
getInChannel(),
getOutSampleRate(),
-1,
getOutBitrate() * 1024,
-1 )) ) {
throw Exception( __FILE__, __LINE__,
"vorbis encode init error", ret);
}
#endif
} }
if ( (ret = vorbis_analysis_init( &vorbisDspState, &vorbisInfo)) ) { if ( (ret = vorbis_analysis_init( &vorbisDspState, &vorbisInfo)) ) {
@ -100,8 +125,6 @@ VorbisLibEncoder :: open ( void )
} }
// create an empty vorbis_comment structure // create an empty vorbis_comment structure
vorbis_comment vorbisComment;
vorbis_comment_init( &vorbisComment); vorbis_comment_init( &vorbisComment);
// create the vorbis stream headers and send them to the underlying sink // create the vorbis stream headers and send them to the underlying sink
@ -117,8 +140,6 @@ VorbisLibEncoder :: open ( void )
throw Exception( __FILE__, __LINE__, "vorbis header init error", ret); throw Exception( __FILE__, __LINE__, "vorbis header init error", ret);
} }
vorbis_comment_init( &vorbisComment);
ogg_stream_packetin( &oggStreamState, &header); ogg_stream_packetin( &oggStreamState, &header);
ogg_stream_packetin( &oggStreamState, &commentHeader); ogg_stream_packetin( &oggStreamState, &commentHeader);
ogg_stream_packetin( &oggStreamState, &codeHeader); ogg_stream_packetin( &oggStreamState, &codeHeader);
@ -131,116 +152,16 @@ VorbisLibEncoder :: open ( void )
vorbis_comment_clear( &vorbisComment ); vorbis_comment_clear( &vorbisComment );
// initialize the resampling coverter if needed
if ( converter ) {
converter->initialize( resampleRatio, getInChannel());
}
encoderOpen = true; encoderOpen = true;
return true; return true;
} }
/*------------------------------------------------------------------------------
* Convert an unsigned char buffer holding 8 bit PCM values with channels
* interleaved to two float buffers (one for each channel)
*----------------------------------------------------------------------------*/
void
VorbisLibEncoder :: conv8 ( unsigned char * pcmBuffer,
unsigned int lenPcmBuffer,
float * leftBuffer,
float * rightBuffer,
unsigned int channels )
{
if ( channels == 1 ) {
unsigned int i, j;
for ( i = 0, j = 0; i < lenPcmBuffer; ) {
short int value;
value = pcmBuffer[i++];
leftBuffer[j] = ((float) value) / 128.f;
++j;
}
} else {
unsigned int i, j;
for ( i = 0, j = 0; i < lenPcmBuffer; ) {
short int value;
value = pcmBuffer[i++];
leftBuffer[j] = ((float) value) / 128.f;
value = pcmBuffer[i++];
rightBuffer[j] = ((float) value) / 128.f;
++j;
}
}
}
/*------------------------------------------------------------------------------
* Convert an unsigned char buffer holding 16 bit PCM values with channels
* interleaved to two float buffers (one for each channel)
*----------------------------------------------------------------------------*/
void
VorbisLibEncoder :: conv16 ( unsigned char * pcmBuffer,
unsigned int lenPcmBuffer,
float * leftBuffer,
float * rightBuffer,
unsigned int channels )
{
if ( isInBigEndian() ) {
if ( channels == 1 ) {
unsigned int i, j;
for ( i = 0, j = 0; i < lenPcmBuffer; ) {
short int value;
value = pcmBuffer[i++] << 8;
value |= pcmBuffer[i++];
leftBuffer[j] = ((float) value) / 32768.f;
++j;
}
} else {
unsigned int i, j;
for ( i = 0, j = 0; i < lenPcmBuffer; ) {
short int value;
value = pcmBuffer[i++] << 8;
value |= pcmBuffer[i++];
leftBuffer[j] = ((float) value) / 32768.f;
value = pcmBuffer[i++] << 8;
value |= pcmBuffer[i++];
rightBuffer[j] = ((float) value) / 32768.f;
++j;
}
}
} else {
if ( channels == 1 ) {
unsigned int i, j;
for ( i = 0, j = 0; i < lenPcmBuffer; ) {
short int value;
value = pcmBuffer[i++];
value |= pcmBuffer[i++] << 8;
leftBuffer[j] = ((float) value) / 32768.f;
++j;
}
} else {
unsigned int i, j;
for ( i = 0, j = 0; i < lenPcmBuffer; ) {
short int value;
value = pcmBuffer[i++];
value |= pcmBuffer[i++] << 8;
leftBuffer[j] = ((float) value) / 32768.f;
value = pcmBuffer[i++];
value |= pcmBuffer[i++] << 8;
rightBuffer[j] = ((float) value) / 32768.f;
++j;
}
}
}
}
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
* Write data to the encoder * Write data to the encoder
@ -268,19 +189,37 @@ VorbisLibEncoder :: write ( const void * buf,
unsigned int nSamples = processed / sampleSize; unsigned int nSamples = processed / sampleSize;
float ** vorbisBuffer; float ** vorbisBuffer;
vorbisBuffer = vorbis_analysis_buffer( &vorbisDspState, nSamples);
if ( bitsPerSample == 8 ) { // convert the byte-based raw input into a short buffer
conv8( b, processed, vorbisBuffer[0], vorbisBuffer[1], channels); // with channels still interleaved
} else if ( bitsPerSample == 16 ) { unsigned int totalSamples = nSamples * channels;
conv16( b, processed, vorbisBuffer[0], vorbisBuffer[1], channels); short int shortBuffer[totalSamples];
Util::conv( bitsPerSample, b, processed, shortBuffer, isInBigEndian());
if ( converter ) {
// resample if needed
int inCount = totalSamples;
int outCount = (int) (inCount * resampleRatio);
short int resampledBuffer[outCount * channels];
int converted;
converted = converter->resample( inCount,
outCount,
shortBuffer,
resampledBuffer );
vorbisBuffer = vorbis_analysis_buffer( &vorbisDspState,
converted / channels);
Util::conv( resampledBuffer, converted, vorbisBuffer, channels);
vorbis_analysis_wrote( &vorbisDspState, converted / channels);
} else { } else {
throw Exception( __FILE__, __LINE__,
"unsupported number of bits per sample for the encoder", vorbisBuffer = vorbis_analysis_buffer( &vorbisDspState, nSamples);
bitsPerSample ); Util::conv( shortBuffer, totalSamples, vorbisBuffer, channels);
vorbis_analysis_wrote( &vorbisDspState, nSamples);
} }
vorbis_analysis_wrote( &vorbisDspState, nSamples);
vorbisBlocksOut(); vorbisBlocksOut();
return processed; return processed;
@ -315,9 +254,11 @@ VorbisLibEncoder :: vorbisBlocksOut ( void ) throw ()
ogg_page oggPage; ogg_page oggPage;
vorbis_analysis( &vorbisBlock, &oggPacket); vorbis_analysis( &vorbisBlock, &oggPacket);
#ifdef VORBIS_LIB_RC3
vorbis_bitrate_addblock( &vorbisBlock); vorbis_bitrate_addblock( &vorbisBlock);
while ( vorbis_bitrate_flushpacket( &vorbisDspState, &oggPacket) ) { while ( vorbis_bitrate_flushpacket( &vorbisDspState, &oggPacket) ) {
#endif
ogg_stream_packetin( &oggStreamState, &oggPacket); ogg_stream_packetin( &oggStreamState, &oggPacket);
@ -334,7 +275,9 @@ VorbisLibEncoder :: vorbisBlocksOut ( void ) throw ()
oggPage.header_len + oggPage.body_len - written); oggPage.header_len + oggPage.body_len - written);
} }
} }
#ifdef VORBIS_LIB_RC3
} }
#endif
} }
} }
@ -351,6 +294,7 @@ VorbisLibEncoder :: close ( void ) throw ( Exception )
ogg_stream_clear( &oggStreamState); ogg_stream_clear( &oggStreamState);
vorbis_block_clear( &vorbisBlock); vorbis_block_clear( &vorbisBlock);
vorbis_dsp_clear( &vorbisDspState); vorbis_dsp_clear( &vorbisDspState);
vorbis_comment_clear( &vorbisComment);
vorbis_info_clear( &vorbisInfo); vorbis_info_clear( &vorbisInfo);
encoderOpen = false; encoderOpen = false;
@ -366,6 +310,11 @@ VorbisLibEncoder :: close ( void ) throw ( Exception )
$Source$ $Source$
$Log$ $Log$
Revision 1.7 2002/03/28 16:47:38 darkeye
moved functions conv8() and conv16() to class Util (as conv())
added resampling functionality
added support for variable bitrates
Revision 1.6 2002/02/20 10:35:35 darkeye Revision 1.6 2002/02/20 10:35:35 darkeye
updated to work with Ogg Vorbis libs rc3 and current IceCast2 cvs updated to work with Ogg Vorbis libs rc3 and current IceCast2 cvs

View File

@ -52,6 +52,7 @@
#include "Reporter.h" #include "Reporter.h"
#include "AudioEncoder.h" #include "AudioEncoder.h"
#include "Sink.h" #include "Sink.h"
#include "aflibConverter.h"
/* ================================================================ constants */ /* ================================================================ constants */
@ -93,6 +94,11 @@ class VorbisLibEncoder : public AudioEncoder, public virtual Reporter
*/ */
vorbis_block vorbisBlock; vorbis_block vorbisBlock;
/**
* Ogg Vorbis library global comment
*/
vorbis_comment vorbisComment;
/** /**
* Ogg library global stream state * Ogg library global stream state
*/ */
@ -103,6 +109,16 @@ class VorbisLibEncoder : public AudioEncoder, public virtual Reporter
*/ */
Ref<Sink> sink; Ref<Sink> sink;
/**
* Resample ratio
*/
double resampleRatio;
/**
* aflibConverter object for possible resampling
*/
aflibConverter * converter;
/** /**
* Initialize the object. * Initialize the object.
* *
@ -120,9 +136,17 @@ class VorbisLibEncoder : public AudioEncoder, public virtual Reporter
getInBitsPerSample() ); getInBitsPerSample() );
} }
if ( getOutSampleRate() != getInSampleRate() ) { if ( getOutSampleRate() == getInSampleRate() ) {
throw Exception( __FILE__, __LINE__, resampleRatio = 1;
"different in and out sample rate not supported"); converter = 0;
} else {
resampleRatio = ( (double) getOutSampleRate() /
(double) getInSampleRate() );
// open the aflibConverter in
// - high quality
// - not linear (quadratic) interpolation
// - not filter interpolation
converter = new aflibConverter( true, true, false);
} }
if ( getInChannel() != getOutChannel() ) { if ( getInChannel() != getOutChannel() ) {
@ -143,42 +167,6 @@ class VorbisLibEncoder : public AudioEncoder, public virtual Reporter
{ {
} }
/**
* Convert a char buffer holding 8 bit PCM values to a short buffer
*
* @param pcmBuffer buffer holding 8 bit PCM audio values,
* channels are interleaved
* @param lenPcmBuffer length of pcmBuffer
* @param leftBuffer put the left channel here (must be big enough)
* @param rightBuffer put the right channel here (if mono, not
* touched, must be big enough)
* @param channels number of channels (1 = mono, 2 = stereo)
*/
void
conv8 ( unsigned char * pcmBuffer,
unsigned int lenPcmBuffer,
float * leftBuffer,
float * rightBuffer,
unsigned int channels );
/**
* Convert a char buffer holding 16 bit PCM values to a short buffer
*
* @param pcmBuffer buffer holding 16 bit PCM audio values,
* channels are interleaved
* @param lenPcmBuffer length of pcmBuffer
* @param leftBuffer put the left channel here (must be big enough)
* @param rightBuffer put the right channel here (if mono, not
* touched, must be big enough)
* @param channels number of channels (1 = mono, 2 = stereo)
*/
void
conv16 ( unsigned char * pcmBuffer,
unsigned int lenPcmBuffer,
float * leftBuffer,
float * rightBuffer,
unsigned int channels );
/** /**
* Send pending Vorbis blocks to the underlying stream * Send pending Vorbis blocks to the underlying stream
*/ */
@ -203,13 +191,13 @@ class VorbisLibEncoder : public AudioEncoder, public virtual Reporter
public: public:
/** /**
* Constructor. * Constructor for fixed bitrate encoding.
* *
* @param sink the sink to send mp3 output to * @param sink the sink to send mp3 output to
* @param inSampleRate sample rate of the input. * @param inSampleRate sample rate of the input.
* @param inBitsPerSample number of bits per sample of the input. * @param inBitsPerSample number of bits per sample of the input.
* @param inChannel number of channels of the input. * @param inChannel number of channels of the input.
* @param outBitrate bit rate of the output (bits/sec). * @param outBitrate bit rate of the output (kbits/sec).
* @param outSampleRate sample rate of the output. * @param outSampleRate sample rate of the output.
* If 0, inSampleRate is used. * If 0, inSampleRate is used.
* @param outChannel number of channels of the output. * @param outChannel number of channels of the output.
@ -237,12 +225,46 @@ class VorbisLibEncoder : public AudioEncoder, public virtual Reporter
} }
/** /**
* Constructor. * Constructor for variable bitrate encoding.
*
* @param sink the sink to send mp3 output to
* @param inSampleRate sample rate of the input.
* @param inBitsPerSample number of bits per sample of the input.
* @param inChannel number of channels of the input.
* @param outQuality the quality of the stream (0.0 .. 1.0).
* @param outSampleRate sample rate of the output.
* If 0, inSampleRate is used.
* @param outChannel number of channels of the output.
* If 0, inChannel is used.
* @exception Exception
*/
inline
VorbisLibEncoder ( Sink * sink,
unsigned int inSampleRate,
unsigned int inBitsPerSample,
unsigned int inChannel,
double outQuality,
unsigned int outSampleRate = 0,
unsigned int outChannel = 0 )
throw ( Exception )
: AudioEncoder ( inSampleRate,
inBitsPerSample,
inChannel,
outQuality,
outSampleRate,
outChannel )
{
init( sink);
}
/**
* Constructor for fixed bitrate encoding.
* *
* @param sink the sink to send mp3 output to * @param sink the sink to send mp3 output to
* @param as get input sample rate, bits per sample and channels * @param as get input sample rate, bits per sample and channels
* from this AudioSource. * from this AudioSource.
* @param outBitrate bit rate of the output (bits/sec). * @param outBitrate bit rate of the output (kbits/sec).
* @param outSampleRate sample rate of the output. * @param outSampleRate sample rate of the output.
* If 0, input sample rate is used. * If 0, input sample rate is used.
* @param outChannel number of channels of the output. * @param outChannel number of channels of the output.
@ -265,6 +287,35 @@ class VorbisLibEncoder : public AudioEncoder, public virtual Reporter
init( sink); init( sink);
} }
/**
* Constructor for variable bitrate encoding.
*
* @param sink the sink to send mp3 output to
* @param as get input sample rate, bits per sample and channels
* from this AudioSource.
* @param outQuality the quality of the stream (0.0 .. 1.0).
* @param outSampleRate sample rate of the output.
* If 0, input sample rate is used.
* @param outChannel number of channels of the output.
* If 0, input channel is used.
* @exception Exception
*/
inline
VorbisLibEncoder ( Sink * sink,
const AudioSource * as,
double outQuality,
unsigned int outSampleRate = 0,
unsigned int outChannel = 0 )
throw ( Exception )
: AudioEncoder ( as,
outQuality,
outSampleRate,
outChannel )
{
init( sink);
}
/** /**
* Copy constructor. * Copy constructor.
* *
@ -442,6 +493,11 @@ class VorbisLibEncoder : public AudioEncoder, public virtual Reporter
$Source$ $Source$
$Log$ $Log$
Revision 1.4 2002/03/28 16:47:38 darkeye
moved functions conv8() and conv16() to class Util (as conv())
added resampling functionality
added support for variable bitrates
Revision 1.3 2001/10/19 12:39:42 darkeye Revision 1.3 2001/10/19 12:39:42 darkeye
created configure options to compile with or without lame / Ogg Vorbis created configure options to compile with or without lame / Ogg Vorbis