mirror of
https://github.com/openmoh/openmohaa.git
synced 2025-05-06 19:01:04 +03:00
187 lines
4.5 KiB
C
187 lines
4.5 KiB
C
#include "gvSpeex.h"
|
|
#include <speex.h>
|
|
#include "gvCodec.h"
|
|
|
|
|
|
static GVBool gviSpeexInitialized;
|
|
static void * gviSpeexEncoderState;
|
|
static SpeexBits gviSpeexBits;
|
|
static int gviSpeexEncodedFrameSize;
|
|
static int gviSpeexSamplesPerFrame;
|
|
|
|
//Encode/Decode buffer.
|
|
static float * gviSpeexBuffer;
|
|
|
|
GVBool gviSpeexInitialize(int quality, GVRate sampleRate)
|
|
{
|
|
int rate;
|
|
int bitsPerFrame;
|
|
int samplesPerSecond;
|
|
|
|
// we shouldn't already be initialized
|
|
if(gviSpeexInitialized)
|
|
return GVFalse;
|
|
|
|
// create a new encoder state
|
|
if (sampleRate == GVRate_8KHz)
|
|
gviSpeexEncoderState = speex_encoder_init(&speex_nb_mode);
|
|
else if (sampleRate == GVRate_16KHz)
|
|
gviSpeexEncoderState = speex_encoder_init(&speex_wb_mode);
|
|
else
|
|
return GVFalse;
|
|
|
|
if(!gviSpeexEncoderState)
|
|
return GVFalse;
|
|
|
|
// set the sampling rate
|
|
samplesPerSecond = sampleRate;
|
|
speex_encoder_ctl(gviSpeexEncoderState, SPEEX_SET_SAMPLING_RATE, &samplesPerSecond);
|
|
|
|
// Get the samples per frame setting.
|
|
speex_encoder_ctl(gviSpeexEncoderState, SPEEX_GET_FRAME_SIZE, &gviSpeexSamplesPerFrame);
|
|
|
|
// set the quality
|
|
speex_encoder_ctl(gviSpeexEncoderState, SPEEX_SET_QUALITY, &quality);
|
|
|
|
// initialize the bits struct
|
|
speex_bits_init(&gviSpeexBits);
|
|
|
|
// get the bitrate
|
|
speex_encoder_ctl(gviSpeexEncoderState, SPEEX_GET_BITRATE, &rate);
|
|
|
|
// convert to bits per frame
|
|
bitsPerFrame = (rate / (sampleRate / gviSpeexSamplesPerFrame));
|
|
|
|
// convert to bytes per frame and store, round up to allocate more space than needed.
|
|
gviSpeexEncodedFrameSize = (bitsPerFrame / 8);
|
|
if (bitsPerFrame % 8)
|
|
gviSpeexEncodedFrameSize++;
|
|
|
|
// create our encoding and decoding buffer.
|
|
gviSpeexBuffer = (float *)gsimalloc(gviSpeexSamplesPerFrame * sizeof(float));
|
|
|
|
// we're now initialized
|
|
gviSpeexInitialized = GVTrue;
|
|
|
|
return GVTrue;
|
|
}
|
|
|
|
void gviSpeexCleanup(void)
|
|
{
|
|
// make sure there is something to cleanup
|
|
if(!gviSpeexInitialized)
|
|
return;
|
|
|
|
// free up encoding and decoding buffer.
|
|
gsifree(gviSpeexBuffer);
|
|
|
|
// destroy the encoder state
|
|
speex_encoder_destroy(gviSpeexEncoderState);
|
|
gviSpeexEncoderState = NULL;
|
|
|
|
// destroy the bits struct
|
|
speex_bits_destroy(&gviSpeexBits);
|
|
|
|
// no longer initialized
|
|
gviSpeexInitialized = GVFalse;
|
|
}
|
|
|
|
int gviSpeexGetSamplesPerFrame(void)
|
|
{
|
|
return gviSpeexSamplesPerFrame;
|
|
}
|
|
|
|
int gviSpeexGetEncodedFrameSize(void)
|
|
{
|
|
return gviSpeexEncodedFrameSize;
|
|
}
|
|
|
|
GVBool gviSpeexNewDecoder(GVDecoderData * data)
|
|
{
|
|
void * decoder;
|
|
int perceptualEnhancement = 1;
|
|
|
|
// create a new decoder state
|
|
if (gviGetSampleRate() == GVRate_8KHz)
|
|
decoder = speex_decoder_init(&speex_nb_mode);
|
|
else if (gviGetSampleRate() == GVRate_16KHz)
|
|
decoder = speex_decoder_init(&speex_wb_mode);
|
|
else
|
|
return GVFalse;
|
|
|
|
if(!decoder)
|
|
return GVFalse;
|
|
|
|
// turn on the perceptual enhancement
|
|
speex_decoder_ctl(decoder, SPEEX_SET_ENH, &perceptualEnhancement);
|
|
|
|
*data = decoder;
|
|
return GVTrue;
|
|
}
|
|
|
|
void gviSpeexFreeDecoder(GVDecoderData data)
|
|
{
|
|
// destory the decoder state
|
|
speex_decoder_destroy((void *)data);
|
|
}
|
|
|
|
void gviSpeexEncode(GVByte * out, const GVSample * in)
|
|
{
|
|
int bytesWritten;
|
|
int i;
|
|
|
|
// convert the input to floats for encoding
|
|
for(i = 0 ; i < gviSpeexSamplesPerFrame ; i++)
|
|
gviSpeexBuffer[i] = in[i];
|
|
|
|
// flush the bits
|
|
speex_bits_reset(&gviSpeexBits);
|
|
|
|
// encode the frame
|
|
speex_encode(gviSpeexEncoderState, gviSpeexBuffer, &gviSpeexBits);
|
|
|
|
// write the bits to the output
|
|
bytesWritten = speex_bits_write(&gviSpeexBits, (char *)out, gviSpeexEncodedFrameSize);
|
|
assert(bytesWritten == gviSpeexEncodedFrameSize);
|
|
}
|
|
|
|
void gviSpeexDecodeAdd(GVSample * out, const GVByte * in, GVDecoderData data)
|
|
{
|
|
int rcode;
|
|
int i;
|
|
|
|
// read the data into the bits
|
|
speex_bits_read_from(&gviSpeexBits, (char *)in, gviSpeexEncodedFrameSize);
|
|
|
|
// decode it
|
|
rcode = speex_decode((void *)data, &gviSpeexBits, gviSpeexBuffer);
|
|
assert(rcode == 0);
|
|
|
|
// convert the output from floats
|
|
for(i = 0 ; i < gviSpeexSamplesPerFrame ; i++)
|
|
// Expanded to remove warnings in VS2K5
|
|
out[i] = out[i] + (GVSample)gviSpeexBuffer[i];
|
|
}
|
|
|
|
void gviSpeexDecodeSet(GVSample * out, const GVByte * in, GVDecoderData data)
|
|
{
|
|
int rcode;
|
|
int i;
|
|
|
|
// read the data into the bits
|
|
speex_bits_read_from(&gviSpeexBits, (char *)in, gviSpeexEncodedFrameSize);
|
|
|
|
// decode it
|
|
rcode = speex_decode((void *)data, &gviSpeexBits, gviSpeexBuffer);
|
|
assert(rcode == 0);
|
|
|
|
// convert the output from floats
|
|
for(i = 0 ; i < gviSpeexSamplesPerFrame ; i++)
|
|
out[i] = (GVSample)gviSpeexBuffer[i];
|
|
}
|
|
|
|
void gviSpeexResetEncoder(void)
|
|
{
|
|
// reset the encoder's state
|
|
speex_encoder_ctl(gviSpeexEncoderState, SPEEX_RESET_STATE, NULL);
|
|
}
|