00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "codec_alaw.h"
00015 #include "iaxclient_lib.h"
00016
00017 #if defined(_MSC_VER)
00018 #define INLINE __inline
00019 #else
00020 #define INLINE inline
00021 #endif
00022
00023 struct state {
00024 plc_state_t plc;
00025 };
00026
00027 static INLINE short int alawdecode (unsigned char alaw)
00028 {
00029 int value;
00030 int segment;
00031
00032
00033 alaw ^= 0x55;
00034
00035
00036 value = (alaw & 0x0f) << 4;
00037
00038
00039 segment = (alaw & 0x70) >> 4;
00040
00041
00042 switch (segment) {
00043 case 0:
00044 break;
00045 case 1:
00046 value += 0x100;
00047 break;
00048 default:
00049 value += 0x100;
00050 value <<= segment - 1;
00051 }
00052
00053
00054 return (alaw & 0x80) ? value : -value;
00055 }
00056
00057 static INLINE unsigned char alawencode (short int linear)
00058 {
00059 int mask = 0x55;
00060 int segment;
00061 unsigned char alaw;
00062
00063 static int segments[8] = {0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF};
00064
00065 if (linear >= 0)
00066 {
00067
00068 mask |= 0x80;
00069 }
00070 else
00071 {
00072
00073 linear = -linear;
00074 }
00075
00076
00077 for (segment = 0;segment < 8;segment++)
00078 if (linear <= segments[segment])
00079 break;
00080
00081
00082
00083 if (segment < 8)
00084 {
00085 if (segment < 2)
00086 alaw = (linear >> 4) & 0x0F;
00087 else
00088 alaw = (linear >> (segment + 3)) & 0x0F;
00089
00090 return ((alaw | (segment << 4)) ^ mask);
00091 }
00092 else
00093
00094 return (0x7F ^ mask);
00095 }
00096
00097 static int decode ( struct iaxc_audio_codec *c,
00098 int *inlen, unsigned char *in, int *outlen, short *out ) {
00099 struct state *state = (struct state *)(c->decstate);
00100 short *orig_out = out;
00101 short sample;
00102
00103
00104 if(*inlen == 0) {
00105 int interp_len = 160;
00106 if(*outlen < interp_len) interp_len = *outlen;
00107 plc_fillin(&state->plc,out,interp_len);
00108 *outlen -= interp_len;
00109 return 0;
00110 }
00111
00112
00113 while ((*inlen > 0) && (*outlen > 0)) {
00114 sample = alawdecode((unsigned char)*(in++));
00115 *(out++) = sample;
00116 (*inlen)--; (*outlen)--;
00117 }
00118 plc_rx(&state->plc, orig_out, (int)(out - orig_out));
00119
00120 return 0;
00121 }
00122
00123 static int encode ( struct iaxc_audio_codec *c,
00124 int *inlen, short *in, int *outlen, unsigned char *out ) {
00125
00126 while ((*inlen > 0) && (*outlen > 0)) {
00127 *(out++) = alawencode(*(in++));
00128 (*inlen)--; (*outlen)--;
00129 }
00130
00131 return 0;
00132 }
00133
00134 static void destroy ( struct iaxc_audio_codec *c) {
00135 free(c);
00136 }
00137
00138 struct iaxc_audio_codec *codec_audio_alaw_new() {
00139
00140 struct iaxc_audio_codec *c = (struct iaxc_audio_codec *)calloc(1, sizeof(struct iaxc_audio_codec));
00141
00142 if(!c) return c;
00143
00144 strcpy(c->name,"alaw");
00145 c->format = IAXC_FORMAT_ALAW;
00146 c->encode = encode;
00147 c->decode = decode;
00148 c->destroy = destroy;
00149
00150
00151 c->minimum_frame_size = 160;
00152
00153
00154 c->decstate = calloc(sizeof(struct state),1);
00155 plc_init(&((struct state *)c->decstate)->plc);
00156
00157 return c;
00158 }
00159