moved functions conv8() and conv16() to class Util (as conv())
added resampling functionality added support for variable bitrates
This commit is contained in:
parent
a50598add0
commit
38dc041a4b
|
@ -72,13 +72,38 @@ VorbisLibEncoder :: open ( void )
|
|||
}
|
||||
|
||||
vorbis_info_init( &vorbisInfo);
|
||||
if ( (ret = vorbis_encode_init( &vorbisInfo,
|
||||
getInChannel(),
|
||||
getInSampleRate(),
|
||||
getOutBitrate() * 1000,
|
||||
getOutBitrate() * 1000,
|
||||
-1 )) ) {
|
||||
throw Exception( __FILE__, __LINE__, "vorbis encode init error", ret);
|
||||
|
||||
if ( isVBR() ) {
|
||||
|
||||
if ( (ret = vorbis_encode_init_vbr( &vorbisInfo,
|
||||
getInChannel(),
|
||||
getOutSampleRate(),
|
||||
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)) ) {
|
||||
|
@ -100,8 +125,6 @@ VorbisLibEncoder :: open ( void )
|
|||
}
|
||||
|
||||
// create an empty vorbis_comment structure
|
||||
vorbis_comment vorbisComment;
|
||||
|
||||
vorbis_comment_init( &vorbisComment);
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
vorbis_comment_init( &vorbisComment);
|
||||
|
||||
ogg_stream_packetin( &oggStreamState, &header);
|
||||
ogg_stream_packetin( &oggStreamState, &commentHeader);
|
||||
ogg_stream_packetin( &oggStreamState, &codeHeader);
|
||||
|
@ -131,116 +152,16 @@ VorbisLibEncoder :: open ( void )
|
|||
|
||||
vorbis_comment_clear( &vorbisComment );
|
||||
|
||||
// initialize the resampling coverter if needed
|
||||
if ( converter ) {
|
||||
converter->initialize( resampleRatio, getInChannel());
|
||||
}
|
||||
|
||||
encoderOpen = 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
|
||||
|
@ -268,19 +189,37 @@ VorbisLibEncoder :: write ( const void * buf,
|
|||
unsigned int nSamples = processed / sampleSize;
|
||||
float ** vorbisBuffer;
|
||||
|
||||
vorbisBuffer = vorbis_analysis_buffer( &vorbisDspState, nSamples);
|
||||
|
||||
if ( bitsPerSample == 8 ) {
|
||||
conv8( b, processed, vorbisBuffer[0], vorbisBuffer[1], channels);
|
||||
} else if ( bitsPerSample == 16 ) {
|
||||
conv16( b, processed, vorbisBuffer[0], vorbisBuffer[1], channels);
|
||||
// convert the byte-based raw input into a short buffer
|
||||
// with channels still interleaved
|
||||
unsigned int totalSamples = nSamples * 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 {
|
||||
throw Exception( __FILE__, __LINE__,
|
||||
"unsupported number of bits per sample for the encoder",
|
||||
bitsPerSample );
|
||||
|
||||
vorbisBuffer = vorbis_analysis_buffer( &vorbisDspState, nSamples);
|
||||
Util::conv( shortBuffer, totalSamples, vorbisBuffer, channels);
|
||||
vorbis_analysis_wrote( &vorbisDspState, nSamples);
|
||||
}
|
||||
|
||||
vorbis_analysis_wrote( &vorbisDspState, nSamples);
|
||||
vorbisBlocksOut();
|
||||
|
||||
return processed;
|
||||
|
@ -315,9 +254,11 @@ VorbisLibEncoder :: vorbisBlocksOut ( void ) throw ()
|
|||
ogg_page oggPage;
|
||||
|
||||
vorbis_analysis( &vorbisBlock, &oggPacket);
|
||||
#ifdef VORBIS_LIB_RC3
|
||||
vorbis_bitrate_addblock( &vorbisBlock);
|
||||
|
||||
while ( vorbis_bitrate_flushpacket( &vorbisDspState, &oggPacket) ) {
|
||||
#endif
|
||||
|
||||
ogg_stream_packetin( &oggStreamState, &oggPacket);
|
||||
|
||||
|
@ -334,7 +275,9 @@ VorbisLibEncoder :: vorbisBlocksOut ( void ) throw ()
|
|||
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);
|
||||
vorbis_block_clear( &vorbisBlock);
|
||||
vorbis_dsp_clear( &vorbisDspState);
|
||||
vorbis_comment_clear( &vorbisComment);
|
||||
vorbis_info_clear( &vorbisInfo);
|
||||
|
||||
encoderOpen = false;
|
||||
|
@ -366,6 +310,11 @@ VorbisLibEncoder :: close ( void ) throw ( Exception )
|
|||
$Source$
|
||||
|
||||
$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
|
||||
updated to work with Ogg Vorbis libs rc3 and current IceCast2 cvs
|
||||
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
#include "Reporter.h"
|
||||
#include "AudioEncoder.h"
|
||||
#include "Sink.h"
|
||||
#include "aflibConverter.h"
|
||||
|
||||
|
||||
/* ================================================================ constants */
|
||||
|
@ -93,6 +94,11 @@ class VorbisLibEncoder : public AudioEncoder, public virtual Reporter
|
|||
*/
|
||||
vorbis_block vorbisBlock;
|
||||
|
||||
/**
|
||||
* Ogg Vorbis library global comment
|
||||
*/
|
||||
vorbis_comment vorbisComment;
|
||||
|
||||
/**
|
||||
* Ogg library global stream state
|
||||
*/
|
||||
|
@ -103,6 +109,16 @@ class VorbisLibEncoder : public AudioEncoder, public virtual Reporter
|
|||
*/
|
||||
Ref<Sink> sink;
|
||||
|
||||
/**
|
||||
* Resample ratio
|
||||
*/
|
||||
double resampleRatio;
|
||||
|
||||
/**
|
||||
* aflibConverter object for possible resampling
|
||||
*/
|
||||
aflibConverter * converter;
|
||||
|
||||
/**
|
||||
* Initialize the object.
|
||||
*
|
||||
|
@ -120,9 +136,17 @@ class VorbisLibEncoder : public AudioEncoder, public virtual Reporter
|
|||
getInBitsPerSample() );
|
||||
}
|
||||
|
||||
if ( getOutSampleRate() != getInSampleRate() ) {
|
||||
throw Exception( __FILE__, __LINE__,
|
||||
"different in and out sample rate not supported");
|
||||
if ( getOutSampleRate() == getInSampleRate() ) {
|
||||
resampleRatio = 1;
|
||||
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() ) {
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -203,13 +191,13 @@ class VorbisLibEncoder : public AudioEncoder, public virtual Reporter
|
|||
public:
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* Constructor for fixed 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 outBitrate bit rate of the output (bits/sec).
|
||||
* @param outBitrate bit rate of the output (kbits/sec).
|
||||
* @param outSampleRate sample rate of the output.
|
||||
* If 0, inSampleRate is used.
|
||||
* @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 as get input sample rate, bits per sample and channels
|
||||
* 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.
|
||||
* If 0, input sample rate is used.
|
||||
* @param outChannel number of channels of the output.
|
||||
|
@ -265,6 +287,35 @@ class VorbisLibEncoder : public AudioEncoder, public virtual Reporter
|
|||
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.
|
||||
*
|
||||
|
@ -442,6 +493,11 @@ class VorbisLibEncoder : public AudioEncoder, public virtual Reporter
|
|||
$Source$
|
||||
|
||||
$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
|
||||
created configure options to compile with or without lame / Ogg Vorbis
|
||||
|
||||
|
|
Loading…
Reference in New Issue