📄 hvdi.c
字号:
init_openlpc_encoder_state((openlpc_encoder_state *)st->state, OPENLPC_FRAMESIZE_1_8);
frame = OPENLPC_FRAMESIZE_1_8;
break;
case HV_4_5K_CODEC:
st->state = create_celp_encoder_state();
init_celp_encoder_state(st->state, CELP_4_5_FRAMESIZE);
if(st->state == NULL)
{
return NL_INVALID;
}
frame = CELP_4_5_FRAMESIZE;
break;
case HV_3_0K_CODEC:
st->state = create_celp_encoder_state();
init_celp_encoder_state(st->state, CELP_3_0_FRAMESIZE);
if(st->state == NULL)
{
return NL_INVALID;
}
frame = CELP_3_0_FRAMESIZE;
break;
case HV_2_3K_CODEC:
st->state = create_celp_encoder_state();
init_celp_encoder_state(st->state, CELP_2_3_FRAMESIZE);
if(st->state == NULL)
{
return NL_INVALID;
}
frame = CELP_2_3_FRAMESIZE;
break;
default:
break;
}
st->codec = codec;
return frame;
}
HL_EXP unsigned char HL_APIENTRY hvdiDecStateGetCodec(hvdi_dec_state *state)
{
return state->codec;
}
HL_EXP int HL_APIENTRY hvdiPacketIsVoice(unsigned char *packet, int paclen)
{
int count = 0;
unsigned char codec;
unsigned short sequence;
/* paclen must be at least 3 for the header */
if(paclen < 3)
{
return NL_FALSE;
}
/* read the packet header */
readByte(packet, count, codec);
if((codec&HVDI_SEQUENCE_BIT) != (unsigned char)0)
{
readShort(packet, count, sequence);
}
if((codec&HVDI_ENCRYPT_BIT) != (unsigned char)0)
{
/* adjust the paclen to remove the 4 byte MAC */
paclen -= 4;
}
/* remove HVDI_ENCRYPT_BIT and HVDI_SEQUENCE_BIT */
codec &= 0x3F;
paclen -= count;
/* check for valid codec and length */
switch(codec){
case HV_2_4K_CODEC:
if((paclen % LPC10_ENCODED_FRAME_SIZE) != 0)
{
return NL_FALSE;
}
break;
case HV_4_8K_CODEC:
if((paclen % LPC_ENCODED_FRAME_SIZE) != 0)
{
return NL_FALSE;
}
break;
case HV_13_2K_CODEC:
if((paclen % GSM_ENCODED_FRAME_SIZE) != 0)
{
return NL_FALSE;
}
break;
case HV_32K_CODEC:
case HV_64K_CODEC:
/* no real size limitation hear */
break;
case HV_1_4K_CODEC:
case HV_1_8K_CODEC:
if((paclen % OPENLPC_ENCODED_FRAME_SIZE) != 0)
{
return NL_FALSE;
}
break;
case HV_4_5K_CODEC:
case HV_3_0K_CODEC:
case HV_2_3K_CODEC:
if((paclen % CELP_ENCODED_FRAME_SIZE) != 0)
{
return NL_FALSE;
}
break;
case HV_SILENCE_CODEC:
if(paclen != 2)
{
return NL_FALSE;
}
break;
case HV_VBR_2_4K_CODEC:
/* we need a way to check variable length packets */
break;
default:
return NL_FALSE;
}
return NL_TRUE;
}
/* hvdiDecodePacket() is in decpacket.c */
/* hvdiEncodePacket() is in encpacket.c */
/*
* Basic VOX algorithm adapted from SpeakFreely
*
* Returns 1 if buffer passes VOX, and 0 if it does not
*/
HL_EXP hvdi_vox* HL_APIENTRY hvdiNewVOX(int voxspeed, int noisethreshold)
{
hvdi_vox *vox;
vox = malloc(sizeof(hvdi_vox));
if(vox == NULL)
{
return NULL;
}
vox->rate = voxspeed;
vox->noisethreshold = (int) exp(log(32767.0) * ((1000 - noisethreshold) / 1000.0));
vox->samplecount = 0;
return vox;
}
HL_EXP int HL_APIENTRY hvdiVOX(hvdi_vox *vox, short *buffer, int buflen)
{
int i;
long level = 0;
for(i=0;i<buflen;i++)
{
long sample = buffer[i];
if(sample < 0)
{
level -= sample;
}
else
{
level += sample;
}
}
level /= buflen;
if(level < vox->noisethreshold)
{
if (vox->samplecount <= 0)
{
return 0;
}
vox->samplecount -= buflen;
}
else
{
vox->samplecount = vox->rate;
}
return 1;
}
HL_EXP void HL_APIENTRY hvdiDeleteVOX(hvdi_vox *vox)
{
free(vox);
}
/*
* This AGC algorithm was taken from isdn2h323 (http://www.telos.de). It was
* converted from C++ to C, and modified to add control over the recording level.
* Converted to fixed point by Phil Frisbie, Jr. 4/12/2003
*/
HL_EXP hvdi_agc* HL_APIENTRY hvdiNewAGC(float level)
{
hvdi_agc *agc = malloc(sizeof(hvdi_agc));
if(agc == NULL)
{
return NULL;
}
agc->sample_max = 1;
agc->counter = 0;
agc->igain = 65536;
if(level > 1.0f)
{
level = 1.0f;
}
else if(level < 0.5f)
{
level = 0.5f;
}
agc->ipeak = (int)(SHRT_MAX * level * 65536);
agc->silence_counter = 0;
return agc;
}
HL_EXP void HL_APIENTRY hvdiAGC(hvdi_agc *agc, short *buffer, int len)
{
int i;
for(i=0;i<len;i++)
{
long gain_new;
int sample;
/* get the abs of buffer[i] */
sample = buffer[i];
sample = (sample < 0 ? -(sample):sample);
if(sample > (int)agc->sample_max)
{
/* update the max */
agc->sample_max = (unsigned int)sample;
}
agc->counter ++;
/* Will we get an overflow with the current gain factor? */
if (((sample * agc->igain) >> 16) > agc->ipeak)
{
/* Yes: Calculate new gain. */
agc->igain = ((agc->ipeak / agc->sample_max) * 62259) >> 16;
agc->silence_counter = 0;
buffer[i] = (short) ((buffer[i] * agc->igain) >> 16);
continue;
}
/* Calculate new gain factor 10x per second */
if (agc->counter >= 8000/10)
{
if (agc->sample_max > 800) /* speaking? */
{
gain_new = ((agc->ipeak / agc->sample_max) * 62259) >> 16;
if (agc->silence_counter > 40) /* pause -> speaking */
agc->igain += (gain_new - agc->igain) >> 2;
else
agc->igain += (gain_new - agc->igain) / 20;
agc->silence_counter = 0;
}
else /* silence */
{
agc->silence_counter++;
/* silence > 2 seconds: reduce gain */
if ((agc->igain > 65536) && (agc->silence_counter >= 20))
agc->igain = (agc->igain * 62259) >> 16;
}
agc->counter = 0;
agc->sample_max = 1;
}
buffer[i] = (short) ((buffer[i] * agc->igain) >> 16);
}
}
HL_EXP void HL_APIENTRY hvdiDeleteAGC(hvdi_agc *agc)
{
free(agc);
}
HL_EXP void HL_APIENTRY hvdiMix(short *outbuf, short **inbuf, int number, int inlen)
{
int i, j;
for(i=0;i<inlen;i++)
{
long total = 0;
for(j=0;j<number;j++)
{
total += *(inbuf[j] + i);
}
if(total > SHRT_MAX)
{
*outbuf++ = (short)SHRT_MAX;
}
else if(total < SHRT_MIN)
{
*outbuf++ = (short)SHRT_MIN;
}
else
{
*outbuf++ = (short)total;
}
}
}
HL_EXP void HL_APIENTRY hvdiHint(int name, int arg)
{
switch (name) {
case HVDI_NORMAL:
hvdi_state.celp_codebook = 256;
hvdi_state.gsm_lpt = 0;
hvdi_state.celp_fast_gain = 0;
break;
case HVDI_FAST:
hvdi_state.celp_codebook = 128;
hvdi_state.gsm_lpt = 1;
hvdi_state.celp_fast_gain = 1;
break;
case HVDI_FASTEST:
hvdi_state.celp_codebook = 32;
hvdi_state.gsm_lpt = 1;
hvdi_state.celp_fast_gain = 1;
break;
case HVDI_CELP_CODEBOOK:
hvdi_state.celp_codebook = min(max(arg, 32), 256);
break;
case HVDI_SEQUENCE:
hvdi_state.sequence = arg;
break;
case HVDI_AUTO_VOX:
hvdi_state.autoVOX = arg;
break;
case HVDI_VOX_LEVEL:
hvdi_state.VOXlevel = (int) exp(log(32767.0) * ((1000 - min(max(arg, 0), 1000)) / 1000.0));;
break;
case HVDI_VOX_SPEED:
hvdi_state.VOXspeed = arg;
break;
case HVDI_COMFORT_NOISE:
hvdi_state.comfortnoise = arg;
break;
case HVDI_NOISE_LEVEL:
hvdi_state.noiselevel = (int) exp(log(32767.0) * ((min(max(arg, 0), 1000) + 1000 ) / 2000.0));
break;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -