1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226
|
#include "gvSpeexSpu.h"
#include <speex.h>
#include "gvCodec.h"
#define GVI_SPEEX_ENCODED_BUFFER 128 //dma has trouble when smaller than
struct SpursSpeexTaskOutput gSpeexTaskOutput;
char *gviSpeexEncoderStateBuffer;
static GVBool gviSpeexEncoderInitialized;
static int gviSpeexEncodedFrameSize;
static int gviSpeexSamplesPerFrame;
char *gviSpeexEncodedBuffer;
short *gviSpeexDecodedBuffer;
// used for decoding if SPU decoding isn't used
#if defined(GVI_NOT_USING_SPURS_DECODE_TASK)
static float * gviSpeexBuffer;
static SpeexBits gviSpeexBits;
#endif
GVBool gviSpeexInitialize(int quality, GVRate sampleRate)
{
// we shouldn't already be initialized
if(gviSpeexEncoderInitialized)
return GVFalse;
// align on a 128 byte boundary to make DMA in spurs task easier
gviSpeexEncoderStateBuffer = (char *)gsimemalign(128,SPEEX_ENCODER_STATE_BUFFER_SIZE);
gSpeexTaskOutput.mSpeexReturnCode = -1;
// initialize the bits struct
#if defined(GVI_NOT_USING_SPURS_DECODE_TASK)
speex_bits_init(&gviSpeexBits);
#endif
if (initializeSpursSampleTask() != 0)
return GVFalse;
// initialize the encoder given the the buffer used to keep track of state
if (issueSampleTaskEncodeInit(quality, sampleRate, &gSpeexTaskOutput,gviSpeexEncoderStateBuffer,SPEEX_ENCODER_STATE_BUFFER_SIZE) != 0)
return GVFalse;
assert(gSpeexTaskOutput.mSpeexReturnCode == 0);
if (gSpeexTaskOutput.mSpeexInitialized != GVTrue)
{
return GVFalse;
}
gviSpeexSamplesPerFrame = gSpeexTaskOutput.mSpeexSamplesPerFrame;
gviSpeexEncodedFrameSize = gSpeexTaskOutput.mSpeexEncodedFrameSize;
#if defined(GVI_NOT_USING_SPURS_DECODE_TASK)
gviSpeexBuffer = (float *)gsimalloc(gviSpeexSamplesPerFrame * sizeof(float));
#endif
gviSpeexEncodedBuffer = (char *)gsimemalign(128, GVI_SPEEX_ENCODED_BUFFER);
gviSpeexDecodedBuffer = (short *)gsimemalign(128, gviSpeexSamplesPerFrame*sizeof(short));
// we're now initialized
gviSpeexEncoderInitialized = GVTrue;
return GVTrue;
}
void gviSpeexCleanup(void)
{
// make sure there is something to cleanup
if(!gviSpeexEncoderInitialized)
return;
#ifdef GVI_NOT_USING_SPURS_DECODE_TASK
// free up encoding and decoding buffer.
gsifree(gviSpeexBuffer);
// destroy the bits struct
speex_bits_destroy(&gviSpeexBits);
#endif
// destroy speex state buffer
gsifree(gviSpeexEncoderStateBuffer);
gsifree(gviSpeexEncodedBuffer);
gsifree(gviSpeexDecodedBuffer);
// cleanup spu
shutdownSpursTask();
// no longer initialized
gviSpeexEncoderInitialized = GVFalse;
}
int gviSpeexGetSamplesPerFrame(void)
{
return gviSpeexSamplesPerFrame;
}
int gviSpeexGetEncodedFrameSize(void)
{
return gviSpeexEncodedFrameSize;
}
GVBool gviSpeexNewDecoder(GVDecoderData * data)
{
#ifdef GVI_NOT_USING_SPURS_DECODE_TASK
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;
#else
char *decoder = (char *)gsimemalign(128, SPEEX_DECODER_STATE_BUFFER_SIZE);
gSpeexTaskOutput.mSpeexReturnCode = -1;
if (issueSampleTaskDecodeInit(decoder, SPEEX_DECODER_STATE_BUFFER_SIZE, gviGetSampleRate(), &gSpeexTaskOutput) != 0)
return GVFalse;
if (gSpeexTaskOutput.mSpeexReturnCode != 0)
return GVFalse;
*data = decoder;
return GVTrue;
#endif // USE SPU ENCODING
}
void gviSpeexFreeDecoder(GVDecoderData data)
{
#ifdef GVI_NOT_USING_SPURS_DECODE_TASK
// destroy the decoder state
speex_decoder_destroy((void *)data);
#else
gsifree(data);
#endif
}
void gviSpeexEncode(GVByte * out, const GVSample * in)
{
int immediateReturn = 0;
gSpeexTaskOutput.mSpeexInitialized = 1;
gSpeexTaskOutput.mSpeexReturnCode = -1;
memset(gviSpeexEncodedBuffer, 0, GVI_SPEEX_ENCODED_BUFFER);
immediateReturn = issueSampleTaskEncode((short *)in, gviSpeexSamplesPerFrame, gviSpeexEncodedFrameSize, (char *)gviSpeexEncodedBuffer,
GVI_SPEEX_ENCODED_BUFFER, &gSpeexTaskOutput,gviSpeexEncoderStateBuffer,SPEEX_ENCODER_STATE_BUFFER_SIZE);
assert(immediateReturn == 0);
assert(gSpeexTaskOutput.mSpeexReturnCode == 0);
memcpy(out, gviSpeexEncodedBuffer, gviSpeexEncodedFrameSize);
assert(gSpeexTaskOutput.mSpeexOutBufferSize == gviSpeexEncodedFrameSize);
}
void gviSpeexDecodeAdd(GVSample * out, const GVByte * in, GVDecoderData data)
{
#ifdef GVI_NOT_USING_SPURS_DECODE_TASK
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];
#else
int immediateReturn = 0, i;
gSpeexTaskOutput.mSpeexInitialized = 1;
gSpeexTaskOutput.mSpeexReturnCode = -1;
memset(gviSpeexEncodedBuffer, 0, GVI_SPEEX_ENCODED_BUFFER);
memcpy(gviSpeexEncodedBuffer, in, gviSpeexEncodedFrameSize);
immediateReturn = issueSampleTaskDecodeAdd(data, SPEEX_DECODER_STATE_BUFFER_SIZE, gviSpeexEncodedBuffer, GVI_SPEEX_ENCODED_BUFFER,
gviSpeexEncodedFrameSize, gviSpeexDecodedBuffer, gviSpeexSamplesPerFrame, &gSpeexTaskOutput);
for (i = 0; i < gviSpeexSamplesPerFrame; i++)
out[i] = out[i] + (GVSample)gviSpeexDecodedBuffer[i];
assert(immediateReturn == 0);
assert(gSpeexTaskOutput.mSpeexReturnCode == 0);
#endif
}
void gviSpeexDecodeSet(GVSample * out, const GVByte * in, GVDecoderData data)
{
#ifdef GVI_USE_SPURS_DECODE_TASK
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];
#else
int immediateReturn = 0;
gSpeexTaskOutput.mSpeexInitialized = 1;
gSpeexTaskOutput.mSpeexReturnCode = -1;
memset(gviSpeexEncodedBuffer, 0, GVI_SPEEX_ENCODED_BUFFER);
memcpy(gviSpeexEncodedBuffer, in, gviSpeexEncodedFrameSize);
immediateReturn = issueSampleTaskDecodeSet(data, SPEEX_DECODER_STATE_BUFFER_SIZE, gviSpeexEncodedBuffer, GVI_SPEEX_ENCODED_BUFFER,
gviSpeexEncodedFrameSize, out, gviSpeexSamplesPerFrame, &gSpeexTaskOutput);
assert(immediateReturn == 0);
assert(gSpeexTaskOutput.mSpeexReturnCode == 0);
#endif
}
void gviSpeexResetEncoder(void)
{
speex_encoder_ctl((void *)gviSpeexEncoderStateBuffer, SPEEX_RESET_STATE, NULL);
}
|