123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564 |
- #include <asterisk/lock.h>
- #include <asterisk/logger.h>
- #include <asterisk/module.h>
- #include <asterisk/translate.h>
- #include <asterisk/channel.h>
- #include <fcntl.h>
- #include <netinet/in.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #define BUFFER_SIZE 8096
- AST_MUTEX_DEFINE_STATIC(localuser_lock);
- static int localusecnt = 0;
- static char *tdesc = "Adaptive Differential PCM Coder/Decoder";
- #include "slin_adpcm_ex.h"
- #include "adpcm_slin_ex.h"
- static short indsft[8] = { -1, -1, -1, -1, 2, 4, 6, 8 };
- static short stpsz[49] = {
- 16, 17, 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, 50, 55, 60, 66, 73,
- 80, 88, 97, 107, 118, 130, 143, 157, 173, 190, 209, 230, 253, 279,
- 307, 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, 876, 963,
- 1060, 1166, 1282, 1411, 1552
- };
- static short nbl2bit[16][4] = {
- {1, 0, 0, 0}, {1, 0, 0, 1}, {1, 0, 1, 0}, {1, 0, 1, 1},
- {1, 1, 0, 0}, {1, 1, 0, 1}, {1, 1, 1, 0}, {1, 1, 1, 1},
- {-1, 0, 0, 0}, {-1, 0, 0, 1}, {-1, 0, 1, 0}, {-1, 0, 1, 1},
- {-1, 1, 0, 0}, {-1, 1, 0, 1}, {-1, 1, 1, 0}, {-1, 1, 1, 1}
- };
- static inline void
- decode (unsigned char encoded, short *ssindex, short *signal, unsigned char *rkey, unsigned char *next)
- {
- short diff, step;
- step = stpsz[*ssindex];
- diff = step * nbl2bit[encoded][1] +
- (step >> 1) * nbl2bit[encoded][2] +
- (step >> 2) * nbl2bit[encoded][3] +
- (step >> 3);
- if (nbl2bit[encoded][2] && (step & 0x1))
- diff++;
- diff *= nbl2bit[encoded][0];
- if ( *next & 0x1 )
- *signal -= 8;
- else if ( *next & 0x2 )
- *signal += 8;
- *signal += diff;
- if (*signal > 2047)
- *signal = 2047;
- else if (*signal < -2047)
- *signal = -2047;
- *next = 0;
- #ifdef AUTO_RETURN
- if( encoded & 0x7 )
- *rkey = 0;
- else if ( ++(*rkey) == 24 ) {
- *rkey = 0;
- if (*signal > 0)
- *next = 0x1;
- else if (*signal < 0)
- *next = 0x2;
- }
- #endif
- *ssindex = *ssindex + indsft[(encoded & 7)];
- if (*ssindex < 0)
- *ssindex = 0;
- else if (*ssindex > 48)
- *ssindex = 48;
- }
- static inline unsigned char
- adpcm (short csig, short *ssindex, short *signal, unsigned char *rkey, unsigned char *next)
- {
- short diff, step;
- unsigned char encoded;
- step = stpsz[*ssindex];
-
-
- csig >>= 4;
- diff = csig - *signal;
-
- if (diff < 0)
- {
- encoded = 8;
- diff = -diff;
- }
- else
- encoded = 0;
- if (diff >= step)
- {
- encoded |= 4;
- diff -= step;
- }
- step >>= 1;
- if (diff >= step)
- {
- encoded |= 2;
- diff -= step;
- }
- step >>= 1;
- if (diff >= step)
- encoded |= 1;
-
- decode (encoded, ssindex, signal, rkey, next);
- return (encoded);
- }
- struct adpcm_encoder_pvt
- {
- struct ast_frame f;
- char offset[AST_FRIENDLY_OFFSET];
- short inbuf[BUFFER_SIZE];
- unsigned char outbuf[BUFFER_SIZE];
- short ssindex;
- short signal;
- unsigned char zero_count;
- unsigned char next_flag;
- int tail;
- };
- struct adpcm_decoder_pvt
- {
- struct ast_frame f;
- char offset[AST_FRIENDLY_OFFSET];
- short outbuf[BUFFER_SIZE];
- short ssindex;
- short signal;
- unsigned char zero_count;
- unsigned char next_flag;
- int tail;
- };
- static struct ast_translator_pvt *
- adpcmtolin_new (void)
- {
- struct adpcm_decoder_pvt *tmp;
- tmp = malloc (sizeof (struct adpcm_decoder_pvt));
- if (tmp)
- {
- memset(tmp, 0, sizeof(*tmp));
- tmp->tail = 0;
- localusecnt++;
- ast_update_use_count ();
- }
- return (struct ast_translator_pvt *) tmp;
- }
- static struct ast_translator_pvt *
- lintoadpcm_new (void)
- {
- struct adpcm_encoder_pvt *tmp;
- tmp = malloc (sizeof (struct adpcm_encoder_pvt));
- if (tmp)
- {
- memset(tmp, 0, sizeof(*tmp));
- localusecnt++;
- ast_update_use_count ();
- tmp->tail = 0;
- }
- return (struct ast_translator_pvt *) tmp;
- }
- static int
- adpcmtolin_framein (struct ast_translator_pvt *pvt, struct ast_frame *f)
- {
- struct adpcm_decoder_pvt *tmp = (struct adpcm_decoder_pvt *) pvt;
- int x;
- unsigned char *b;
- if (f->datalen * 4 > sizeof(tmp->outbuf)) {
- ast_log(LOG_WARNING, "Out of buffer space\n");
- return -1;
- }
- b = f->data;
- for (x=0;x<f->datalen;x++) {
- decode((b[x] >> 4) & 0xf, &tmp->ssindex, &tmp->signal, &tmp->zero_count, &tmp->next_flag);
- tmp->outbuf[tmp->tail++] = tmp->signal << 4;
- decode(b[x] & 0x0f, &tmp->ssindex, &tmp->signal, &tmp->zero_count, &tmp->next_flag);
- tmp->outbuf[tmp->tail++] = tmp->signal << 4;
- }
- return 0;
- }
- static struct ast_frame *
- adpcmtolin_frameout (struct ast_translator_pvt *pvt)
- {
- struct adpcm_decoder_pvt *tmp = (struct adpcm_decoder_pvt *) pvt;
- if (!tmp->tail)
- return NULL;
- tmp->f.frametype = AST_FRAME_VOICE;
- tmp->f.subclass = AST_FORMAT_SLINEAR;
- tmp->f.datalen = tmp->tail *2;
- tmp->f.samples = tmp->tail;
- tmp->f.mallocd = 0;
- tmp->f.offset = AST_FRIENDLY_OFFSET;
- tmp->f.src = __PRETTY_FUNCTION__;
- tmp->f.data = tmp->outbuf;
- tmp->tail = 0;
- return &tmp->f;
- }
- static int
- lintoadpcm_framein (struct ast_translator_pvt *pvt, struct ast_frame *f)
- {
- struct adpcm_encoder_pvt *tmp = (struct adpcm_encoder_pvt *) pvt;
- if ((tmp->tail + f->datalen / 2) < (sizeof (tmp->inbuf) / 2))
- {
- memcpy (&tmp->inbuf[tmp->tail], f->data, f->datalen);
- tmp->tail += f->datalen / 2;
- }
- else
- {
- ast_log (LOG_WARNING, "Out of buffer space\n");
- return -1;
- }
- return 0;
- }
- static struct ast_frame *
- lintoadpcm_frameout (struct ast_translator_pvt *pvt)
- {
- struct adpcm_encoder_pvt *tmp = (struct adpcm_encoder_pvt *) pvt;
- unsigned char adpcm0, adpcm1;
- int i_max, i;
-
- if (tmp->tail < 2) return NULL;
- i_max = (tmp->tail / 2) * 2;
- tmp->outbuf[0] = tmp->ssindex & 0xff;
- tmp->outbuf[1] = (tmp->signal >> 8) & 0xff;
- tmp->outbuf[2] = (tmp->signal & 0xff);
- tmp->outbuf[3] = tmp->zero_count;
- tmp->outbuf[4] = tmp->next_flag;
- for (i = 0; i < i_max; i+=2)
- {
- adpcm0 = adpcm (tmp->inbuf[i], &tmp->ssindex, &tmp->signal, &tmp->zero_count, &tmp->next_flag);
- adpcm1 = adpcm (tmp->inbuf[i+1], &tmp->ssindex, &tmp->signal, &tmp->zero_count, &tmp->next_flag);
- tmp->outbuf[i/2] = (adpcm0 << 4) | adpcm1;
- };
- tmp->f.frametype = AST_FRAME_VOICE;
- tmp->f.subclass = AST_FORMAT_ADPCM;
- tmp->f.samples = i_max;
- tmp->f.mallocd = 0;
- tmp->f.offset = AST_FRIENDLY_OFFSET;
- tmp->f.src = __PRETTY_FUNCTION__;
- tmp->f.data = tmp->outbuf;
- tmp->f.datalen = i_max / 2;
-
- if (tmp->tail == i_max)
- tmp->tail = 0;
- else
- {
- tmp->inbuf[0] = tmp->inbuf[tmp->tail];
- tmp->tail = 1;
- }
- return &tmp->f;
- }
- static struct ast_frame *
- adpcmtolin_sample (void)
- {
- static struct ast_frame f;
- f.frametype = AST_FRAME_VOICE;
- f.subclass = AST_FORMAT_ADPCM;
- f.datalen = sizeof (adpcm_slin_ex);
- f.samples = sizeof(adpcm_slin_ex) * 2;
- f.mallocd = 0;
- f.offset = 0;
- f.src = __PRETTY_FUNCTION__;
- f.data = adpcm_slin_ex;
- return &f;
- }
- static struct ast_frame *
- lintoadpcm_sample (void)
- {
- static struct ast_frame f;
- f.frametype = AST_FRAME_VOICE;
- f.subclass = AST_FORMAT_SLINEAR;
- f.datalen = sizeof (slin_adpcm_ex);
-
- f.samples = sizeof (slin_adpcm_ex) / 2;
- f.mallocd = 0;
- f.offset = 0;
- f.src = __PRETTY_FUNCTION__;
- f.data = slin_adpcm_ex;
- return &f;
- }
- static void
- adpcm_destroy (struct ast_translator_pvt *pvt)
- {
- free (pvt);
- localusecnt--;
- ast_update_use_count ();
- }
- static struct ast_translator adpcmtolin = {
- "adpcmtolin",
- AST_FORMAT_ADPCM,
- AST_FORMAT_SLINEAR,
- adpcmtolin_new,
- adpcmtolin_framein,
- adpcmtolin_frameout,
- adpcm_destroy,
-
- adpcmtolin_sample
- };
- static struct ast_translator lintoadpcm = {
- "lintoadpcm",
- AST_FORMAT_SLINEAR,
- AST_FORMAT_ADPCM,
- lintoadpcm_new,
- lintoadpcm_framein,
- lintoadpcm_frameout,
- adpcm_destroy,
-
- lintoadpcm_sample
- };
- int
- unload_module (void)
- {
- int res;
- ast_mutex_lock (&localuser_lock);
- res = ast_unregister_translator (&lintoadpcm);
- if (!res)
- res = ast_unregister_translator (&adpcmtolin);
- if (localusecnt)
- res = -1;
- ast_mutex_unlock (&localuser_lock);
- return res;
- }
- int
- load_module (void)
- {
- int res;
- res = ast_register_translator (&adpcmtolin);
- if (!res)
- res = ast_register_translator (&lintoadpcm);
- else
- ast_unregister_translator (&adpcmtolin);
- return res;
- }
- char *
- description (void)
- {
- return tdesc;
- }
- int
- usecount (void)
- {
- int res;
- STANDARD_USECOUNT (res);
- return res;
- }
- char *
- key ()
- {
- return ASTERISK_GPL_KEY;
- }
|