/* HawkVoice Direct Interface (HVDI) cross platform network voice library Copyright (C) 2001-2004 Phil Frisbie, Jr. (phil@hawksoft.com) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. Or go to http://www.gnu.org/copyleft/lgpl.html */ #ifndef MACOSX #include #endif #include #include "hvdint.h" static int openlpcencode(short *in, unsigned char *out, int buflen, int paclen, void *state, int framesize) { if(paclen >= (int)(buflen / framesize * OPENLPC_ENCODED_FRAME_SIZE)) { openlpc_encoder_state *st = (openlpc_encoder_state *)state; int len = 0; int i; /* make sure buflen is a multiple of the frame length */ buflen = ((int)(buflen / framesize) * framesize); for(i = 0;i= (int)(buflen / LPC10_SAMPLES_PER_FRAME * LPC10_ENCODED_FRAME_SIZE)) { lpc10_encoder_state *st = (lpc10_encoder_state *)state; int len = 0; int i; /* make sure buflen is a multiple of the frame length */ buflen = ((int)(buflen / LPC10_SAMPLES_PER_FRAME) * LPC10_SAMPLES_PER_FRAME); /* the LPC10 codec needs to process in LPC10_SAMPLES_PER_FRAME chunks */ for(i = 0;i= (int)(buflen / LPC_SAMPLES_PER_FRAME * LPC_ENCODED_FRAME_SIZE)) { lpc_encoder_state *st = (lpc_encoder_state *)state; int len = 0; int i; /* make sure buflen is a multiple of the frame length */ buflen = ((int)(buflen / LPC_SAMPLES_PER_FRAME) * LPC_SAMPLES_PER_FRAME); /* the LPC codec needs to process in LPC_FRAMESIZE chunks */ for(i = 0;i= (int)(buflen / GSM_SAMPLES_PER_FRAME * GSM_ENCODED_FRAME_SIZE)) { struct gsm_state *st = (struct gsm_state *)state; int len = 0; int i; int gsm_lpt = hvdi_state.gsm_lpt; /* make sure buflen is a multiple of the frame length */ buflen = ((int)(buflen / GSM_SAMPLES_PER_FRAME) * GSM_SAMPLES_PER_FRAME); /* set the GSM_OPT_LTP_CUT option */ (void)gsm_option(st, GSM_OPT_LTP_CUT, &gsm_lpt); /* the GSM codec needs to process in 160 sample chunks */ for(i = 0;i= (int)(buflen / 2 + sizeof(st->valprev) + sizeof(st->index))) { int len; int count = 0; /* write out the previous codec state */ writeShort(out, count, st->valprev); writeByte(out, count, st->index); len = count; len += adpcm_coder(in, &out[count], buflen, st); return len; } return 0; } static int ulawencode(short *in, unsigned char *out, int buflen, int paclen) { if(paclen >= buflen) { return ulawEncode(in, out, buflen); } return 0; } static int celpencode(short *in, unsigned char *out, int buflen, int paclen, void *state, int framesize) { if(paclen >= (int)(buflen / framesize * CELP_ENCODED_FRAME_SIZE)) { celp_encoder_state *st = (celp_encoder_state *)state; int len = 0; int i; /* make sure buflen is a multiple of the frame length */ buflen = ((int)(buflen / framesize) * framesize); /* set the options */ celp_set_encoder_option(st, CELP_CODEBOOK_LEN, hvdi_state.celp_codebook); celp_set_encoder_option(st, CELP_FAST_GAIN, hvdi_state.celp_fast_gain); for(i = 0;i= (int)(buflen / LPC10_SAMPLES_PER_FRAME * LPC10_ENCODED_FRAME_SIZE)) { lpc10_encoder_state *st = (lpc10_encoder_state *)state; int len = 0; int i; /* make sure buflen is a multiple of the frame length */ buflen = ((int)(buflen / LPC10_SAMPLES_PER_FRAME) * LPC10_SAMPLES_PER_FRAME); /* the VBR-LPC-10 codec needs to process in VBR_LPC10_SAMPLES_PER_FRAME chunks */ for(i = 0;icodec; if(paclen < 3) { return 0; } /* check for auto VOX state */ if(hvdi_state.autoVOX != 0) { /* check for NULL VOX state */ if(state->vox == NULL) { state->vox = hvdiNewVOX(hvdi_state.VOXspeed, 300); } /* update from global state */ state->vox->rate = hvdi_state.VOXspeed; state->vox->noisethreshold = hvdi_state.VOXlevel; /* now run VOX */ if(hvdiVOX(state->vox, buffer, buflen) == 0) { if(hvdi_state.comfortnoise != 0) { /* encode a silence packet */ codec = (unsigned char)HV_SILENCE_CODEC; if(hvdi_state.sequence != 0) { codec |= HVDI_SEQUENCE_BIT; } if(key != NULL) { codec |= HVDI_ENCRYPT_BIT; } /* write the header */ writeByte(packet, count, codec); if(hvdi_state.sequence != 0) { writeShort(packet, count, state->sequence); } writeShort(packet, count, buflen); /* We are going to skip encryption for silence packets */ /* but we will authenticate */ if(key != NULL) { /* sign the entire packet */ hcryptSignPacket(packet, count, key); count += 4; } state->sequence++; return count; } else { return 0; } } } if(key != NULL) { codec |= HVDI_ENCRYPT_BIT; } if(hvdi_state.sequence != 0) { codec |= HVDI_SEQUENCE_BIT; } /* write the header */ writeByte(packet, count, codec); if(hvdi_state.sequence != 0) { writeShort(packet, count, state->sequence); } len = count; /* data points to the start of the encoded speech */ data = &packet[count]; /* encode the speech */ switch (state->codec) { case HV_1_4K_CODEC: result = openlpcencode(buffer, data, buflen, paclen, state->state, OPENLPC_FRAMESIZE_1_4); break; case HV_1_8K_CODEC: result = openlpcencode(buffer, data, buflen, paclen, state->state, OPENLPC_FRAMESIZE_1_8); break; case HV_2_4K_CODEC: result = lpc10encode(buffer, data, buflen, paclen, state->state); break; case HV_4_8K_CODEC: result = lpcencode(buffer, data, buflen, paclen, state->state); break; case HV_13_2K_CODEC: result = gsmencode(buffer, data, buflen, paclen, state->state); break; case HV_32K_CODEC: result = adpcmencode(buffer, data, buflen, paclen, state->state); break; case HV_64K_CODEC: result = ulawencode(buffer, data, buflen, paclen); break; case HV_4_5K_CODEC: result = celpencode(buffer, data, buflen, paclen, state->state, CELP_4_5_FRAMESIZE); break; case HV_3_0K_CODEC: result = celpencode(buffer, data, buflen, paclen, state->state, CELP_3_0_FRAMESIZE); break; case HV_2_3K_CODEC: result = celpencode(buffer, data, buflen, paclen, state->state, CELP_2_3_FRAMESIZE); break; case HV_VBR_2_4K_CODEC: result = vbrlpc10encode(buffer, data, buflen, paclen, state->state); break; default: /* invalid codec */ return 0; } if(result <= 0) { return 0; } len += result; /* encrypt the packet if needed */ if(key != NULL) { if((len + 4) > paclen) { /* packet not long enough */ return 0; } /* encrypt only the encoded speech */ hcryptEncryptPacket(data, data, result, key); /* sign the entire packet */ hcryptSignPacket(packet, len, key); len += 4; } state->sequence++; return len; }