--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/msLPC10encoder.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,251 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + +#include <stdlib.h> +#include "msLPC10encoder.h" +#include <lpc10.h> + + +extern MSCodecInfo LPC10info; + +/* The return value of each of these calls is the same as that + returned by fread/fwrite, which should be the number of samples + successfully read/written, not the number of bytes. */ + +int +read_16bit_samples(INT16 int16samples[], float speech[], int n) +{ + int i; + + /* Convert 16 bit integer samples to floating point values in the + range [-1,+1]. */ + + for (i = 0; i < n; i++) { + speech[i] = ((float) int16samples[i]) / 32768.0; + } + + return (n); +} + + + +int +write_16bit_samples(INT16 int16samples[], float speech[], int n) +{ + int i; + float real_sample; + + /* Convert floating point samples in range [-1,+1] to 16 bit + integers. */ + for (i = 0; i < n; i++) { + real_sample = 32768.0 * speech[i]; + if (real_sample < -32768.0) { + int16samples[i] = -32768; + } else if (real_sample > 32767.0) { + int16samples[i] = 32767; + } else { + int16samples[i] = real_sample; + } + } + return (n); +} + +/* + +Write the bits in bits[0] through bits[len-1] to file f, in "packed" +format. + +bits is expected to be an array of len integer values, where each +integer is 0 to represent a 0 bit, and any other value represents a 1 +bit. This bit string is written to the file f in the form of several +8 bit characters. If len is not a multiple of 8, then the last +character is padded with 0 bits -- the padding is in the least +significant bits of the last byte. The 8 bit characters are "filled" +in order from most significant bit to least significant. + +*/ + +void +write_bits(unsigned char *data, INT32 *bits, int len) +{ + int i; /* generic loop variable */ + unsigned char mask; /* The next bit position within the + variable "data" to place the next + bit. */ + + + /* Fill in the array bits. + * The first compressed output bit will be the most significant + * bit of the byte, so initialize mask to 0x80. The next byte of + * compressed data is initially 0, and the desired bits will be + * turned on below. + */ + mask = 0x80; + *data = 0; + + for (i = 0; i < len; i++) { + /* Turn on the next bit of output data, if necessary. */ + if (bits[i]) { + (*data) |= mask; + } + /* + * If the byte data is full, determined by mask becoming 0, + * then write the byte to the output file, and reinitialize + * data and mask for the next output byte. Also add the byte + * if (i == len-1), because if len is not a multiple of 8, + * then mask won't yet be 0. */ + mask >>= 1; + if ((mask == 0) || (i == len-1)) { + data++; + *data = 0; + mask = 0x80; + } + } +} + + + +/* + +Read bits from file f into bits[0] through bits[len-1], in "packed" +format. + +Read ceiling(len/8) characters from file f, if that many are available +to read, otherwise read to the end of the file. The first character's +8 bits, in order from MSB to LSB, are used to fill bits[0] through +bits[7]. The second character's bits are used to fill bits[8] through +bits[15], and so on. If ceiling(len/8) characters are available to +read, and len is not a multiple of 8, then some of the least +significant bits of the last character read are completely ignored. +Every entry of bits[] that is modified is changed to either a 0 or a +1. + +The number of bits successfully read is returned, and is always in the +range 0 to len, inclusive. If it is less than len, it will always be +a multiple of 8. + +*/ + +int +read_bits(unsigned char *data, INT32 *bits, int len) +{ + int i,ind=0; /* generic loop variable */ + int c=0; + + /* Unpack the array bits into coded_frame. */ + for (i = 0; i < len; i++) { + if ((i % 8) == 0) { + c = (int)(data[ind]); + ind++; + } + if (c & (0x80 >> (i & 7))) { + bits[i] = 1; + } else { + bits[i] = 0; + } + } + return (len); +} + + + + +static MSLPC10EncoderClass *ms_LPC10encoder_class=NULL; + +MSFilter * ms_LPC10encoder_new(void) +{ + MSLPC10Encoder *r; + + r=g_new(MSLPC10Encoder,1); + ms_LPC10encoder_init(r); + if (ms_LPC10encoder_class==NULL) + { + ms_LPC10encoder_class=g_new(MSLPC10EncoderClass,1); + ms_LPC10encoder_class_init(ms_LPC10encoder_class); + } + MS_FILTER(r)->klass=MS_FILTER_CLASS(ms_LPC10encoder_class); + return(MS_FILTER(r)); +} + + +/* FOR INTERNAL USE*/ +void ms_LPC10encoder_init(MSLPC10Encoder *r) +{ + ms_filter_init(MS_FILTER(r)); + MS_FILTER(r)->infifos=r->f_inputs; + MS_FILTER(r)->outfifos=r->f_outputs; + MS_FILTER(r)->r_mingran=LPC10_SAMPLES_PER_FRAME*2; + memset(r->f_inputs,0,sizeof(MSFifo*)*MSLPC10ENCODER_MAX_INPUTS); + memset(r->f_outputs,0,sizeof(MSFifo*)*MSLPC10ENCODER_MAX_INPUTS); + r->lpc10_enc=create_lpc10_encoder_state(); +} + +void ms_LPC10encoder_class_init(MSLPC10EncoderClass *klass) +{ + ms_filter_class_init(MS_FILTER_CLASS(klass)); + ms_filter_class_set_name(MS_FILTER_CLASS(klass),"LPC10Enc"); + MS_FILTER_CLASS(klass)->max_finputs=MSLPC10ENCODER_MAX_INPUTS; + MS_FILTER_CLASS(klass)->max_foutputs=MSLPC10ENCODER_MAX_INPUTS; + MS_FILTER_CLASS(klass)->r_maxgran=LPC10_SAMPLES_PER_FRAME*2; + MS_FILTER_CLASS(klass)->w_maxgran=7; + MS_FILTER_CLASS(klass)->destroy=(MSFilterDestroyFunc)ms_LPC10encoder_destroy; + MS_FILTER_CLASS(klass)->process=(MSFilterProcessFunc)ms_LPC10encoder_process; + MS_FILTER_CLASS(klass)->info=(MSFilterInfo*)&LPC10info; +} + +void ms_LPC10encoder_process(MSLPC10Encoder *r) +{ + MSFifo *fi,*fo; + int err1; + void *s,*d; + float speech[LPC10_SAMPLES_PER_FRAME]; + INT32 bits[LPC10_BITS_IN_COMPRESSED_FRAME]; + + /* process output fifos, but there is only one for this class of filter*/ + + fi=r->f_inputs[0]; + fo=r->f_outputs[0]; + if (fi!=NULL) + { + err1=ms_fifo_get_read_ptr(fi,LPC10_SAMPLES_PER_FRAME*2,&s); + if (err1>0) + { + err1=ms_fifo_get_write_ptr(fo,7,&d); + if (d!=NULL) + { + read_16bit_samples((INT16*)s, speech, LPC10_SAMPLES_PER_FRAME); + lpc10_encode(speech, bits, r->lpc10_enc); + write_bits(d, bits, LPC10_BITS_IN_COMPRESSED_FRAME); + } + } + + } +} + +void ms_LPC10encoder_uninit(MSLPC10Encoder *obj) +{ + free(obj->lpc10_enc); +} + +void ms_LPC10encoder_destroy( MSLPC10Encoder *obj) +{ + ms_LPC10encoder_uninit(obj); + g_free(obj); +}