Mon, 27 Apr 2009 12:19:05 +0200
Import new package spec for introduction into repository.
michael@202 | 1 | Index: cdr/cdr_sqlite.c |
michael@202 | 2 | diff -Nau cdr/cdr_sqlite.c.orig cdr/cdr_sqlite.c |
michael@202 | 3 | --- cdr/cdr_sqlite.c.orig 2007-06-14 23:50:40.000000000 +0200 |
michael@202 | 4 | +++ cdr/cdr_sqlite.c 2009-04-24 00:30:33.000000000 +0200 |
michael@202 | 5 | @@ -58,7 +58,7 @@ |
michael@202 | 6 | #define DATE_FORMAT "%Y-%m-%d %T" |
michael@202 | 7 | |
michael@202 | 8 | static char *name = "sqlite"; |
michael@202 | 9 | -static sqlite* db = NULL; |
michael@202 | 10 | +static sqlite3 *db = NULL; |
michael@202 | 11 | |
michael@202 | 12 | AST_MUTEX_DEFINE_STATIC(sqlite_lock); |
michael@202 | 13 | |
michael@202 | 14 | @@ -92,10 +92,10 @@ |
michael@202 | 15 | static int sqlite_log(struct ast_cdr *cdr) |
michael@202 | 16 | { |
michael@202 | 17 | int res = 0; |
michael@202 | 18 | - char *zErr = 0; |
michael@202 | 19 | struct tm tm; |
michael@202 | 20 | time_t t; |
michael@202 | 21 | char startstr[80], answerstr[80], endstr[80]; |
michael@202 | 22 | + char *cdrsql = 0; |
michael@202 | 23 | int count; |
michael@202 | 24 | |
michael@202 | 25 | ast_mutex_lock(&sqlite_lock); |
michael@202 | 26 | @@ -113,7 +113,7 @@ |
michael@202 | 27 | strftime(endstr, sizeof(endstr), DATE_FORMAT, &tm); |
michael@202 | 28 | |
michael@202 | 29 | for(count=0; count<5; count++) { |
michael@202 | 30 | - res = sqlite_exec_printf(db, |
michael@202 | 31 | + cdrsql = sqlite3_mprintf( |
michael@202 | 32 | "INSERT INTO cdr (" |
michael@202 | 33 | "clid,src,dst,dcontext," |
michael@202 | 34 | "channel,dstchannel,lastapp,lastdata, " |
michael@202 | 35 | @@ -138,8 +138,7 @@ |
michael@202 | 36 | # if LOG_USERFIELD |
michael@202 | 37 | ",'%q'" |
michael@202 | 38 | # endif |
michael@202 | 39 | - ")", NULL, NULL, &zErr, |
michael@202 | 40 | - cdr->clid, cdr->src, cdr->dst, cdr->dcontext, |
michael@202 | 41 | + ")", cdr->clid, cdr->src, cdr->dst, cdr->dcontext, |
michael@202 | 42 | cdr->channel, cdr->dstchannel, cdr->lastapp, cdr->lastdata, |
michael@202 | 43 | startstr, answerstr, endstr, |
michael@202 | 44 | cdr->duration, cdr->billsec, cdr->disposition, cdr->amaflags, |
michael@202 | 45 | @@ -151,16 +150,13 @@ |
michael@202 | 46 | ,cdr->userfield |
michael@202 | 47 | # endif |
michael@202 | 48 | ); |
michael@202 | 49 | + res = sqlite3_exec(db, cdrsql, 0, 0, 0); |
michael@202 | 50 | + sqlite3_free(cdrsql); |
michael@202 | 51 | if (res != SQLITE_BUSY && res != SQLITE_LOCKED) |
michael@202 | 52 | break; |
michael@202 | 53 | usleep(200); |
michael@202 | 54 | } |
michael@202 | 55 | |
michael@202 | 56 | - if (zErr) { |
michael@202 | 57 | - ast_log(LOG_ERROR, "cdr_sqlite: %s\n", zErr); |
michael@202 | 58 | - free(zErr); |
michael@202 | 59 | - } |
michael@202 | 60 | - |
michael@202 | 61 | ast_mutex_unlock(&sqlite_lock); |
michael@202 | 62 | return res; |
michael@202 | 63 | } |
michael@202 | 64 | @@ -168,7 +164,7 @@ |
michael@202 | 65 | static int unload_module(void) |
michael@202 | 66 | { |
michael@202 | 67 | if (db) |
michael@202 | 68 | - sqlite_close(db); |
michael@202 | 69 | + sqlite3_close(db); |
michael@202 | 70 | ast_cdr_unregister(name); |
michael@202 | 71 | return 0; |
michael@202 | 72 | } |
michael@202 | 73 | @@ -181,17 +177,16 @@ |
michael@202 | 74 | |
michael@202 | 75 | /* is the database there? */ |
michael@202 | 76 | snprintf(fn, sizeof(fn), "%s/cdr.db", ast_config_AST_LOG_DIR); |
michael@202 | 77 | - db = sqlite_open(fn, 0660, &zErr); |
michael@202 | 78 | + sqlite3_open(fn, &db); |
michael@202 | 79 | if (!db) { |
michael@202 | 80 | - ast_log(LOG_ERROR, "cdr_sqlite: %s\n", zErr); |
michael@202 | 81 | - free(zErr); |
michael@202 | 82 | + ast_log(LOG_ERROR, "cdr_sqlite: %s\n", sqlite3_errmsg(db)); |
michael@202 | 83 | return -1; |
michael@202 | 84 | } |
michael@202 | 85 | |
michael@202 | 86 | /* is the table there? */ |
michael@202 | 87 | - res = sqlite_exec(db, "SELECT COUNT(AcctId) FROM cdr;", NULL, NULL, NULL); |
michael@202 | 88 | + res = sqlite3_exec(db, "SELECT COUNT(AcctId) FROM cdr;", NULL, NULL, NULL); |
michael@202 | 89 | if (res) { |
michael@202 | 90 | - res = sqlite_exec(db, sql_create_table, NULL, NULL, &zErr); |
michael@202 | 91 | + res = sqlite3_exec(db, sql_create_table, NULL, NULL, &zErr); |
michael@202 | 92 | if (res) { |
michael@202 | 93 | ast_log(LOG_ERROR, "cdr_sqlite: Unable to create table 'cdr': %s\n", zErr); |
michael@202 | 94 | free(zErr); |
michael@202 | 95 | @@ -210,7 +205,7 @@ |
michael@202 | 96 | |
michael@202 | 97 | err: |
michael@202 | 98 | if (db) |
michael@202 | 99 | - sqlite_close(db); |
michael@202 | 100 | + sqlite3_close(db); |
michael@202 | 101 | return -1; |
michael@202 | 102 | } |
michael@202 | 103 | |
michael@202 | 104 | Index: channels/chan_sip.c |
michael@202 | 105 | diff -Nau channels/chan_sip.c.orig channels/chan_sip.c |
michael@202 | 106 | --- channels/chan_sip.c.orig 2009-04-02 19:20:22.000000000 +0200 |
michael@202 | 107 | +++ channels/chan_sip.c 2009-04-24 00:30:33.000000000 +0200 |
michael@202 | 108 | @@ -7469,7 +7469,7 @@ |
michael@202 | 109 | |
michael@202 | 110 | ast_copy_string(from, get_header(&p->initreq, "From"), sizeof(from)); |
michael@202 | 111 | c = get_in_brackets(from); |
michael@202 | 112 | - if (strncasecmp(c, "sip:", 4)) { |
michael@202 | 113 | + if (strncasecmp(c, "sip:", 4) && strncasecmp(c, "sips:", 5)) { |
michael@202 | 114 | ast_log(LOG_WARNING, "Huh? Not a SIP header (%s)?\n", c); |
michael@202 | 115 | return -1; |
michael@202 | 116 | } |
michael@202 | 117 | @@ -7477,7 +7477,7 @@ |
michael@202 | 118 | |
michael@202 | 119 | ast_copy_string(to, get_header(&p->initreq, "To"), sizeof(to)); |
michael@202 | 120 | c = get_in_brackets(to); |
michael@202 | 121 | - if (strncasecmp(c, "sip:", 4)) { |
michael@202 | 122 | + if (strncasecmp(c, "sip:", 4) && strncasecmp(c, "sips:", 5)) { |
michael@202 | 123 | ast_log(LOG_WARNING, "Huh? Not a SIP header (%s)?\n", c); |
michael@202 | 124 | return -1; |
michael@202 | 125 | } |
michael@202 | 126 | @@ -8004,7 +8004,10 @@ |
michael@202 | 127 | of = get_in_brackets(from); |
michael@202 | 128 | ast_string_field_set(p, from, of); |
michael@202 | 129 | if (strncasecmp(of, "sip:", 4)) |
michael@202 | 130 | - ast_log(LOG_NOTICE, "From address missing 'sip:', using it anyway\n"); |
michael@202 | 131 | + if (strncasecmp(of, "sips:", 5)) |
michael@202 | 132 | + ast_log(LOG_NOTICE, "From address missing 'sip:' or 'sips:', using it anyway\n"); |
michael@202 | 133 | + else |
michael@202 | 134 | + of += 5; |
michael@202 | 135 | else |
michael@202 | 136 | of += 4; |
michael@202 | 137 | /* Get just the username part */ |
michael@202 | 138 | @@ -8280,7 +8283,10 @@ |
michael@202 | 139 | |
michael@202 | 140 | /* Make sure it's a SIP URL */ |
michael@202 | 141 | if (strncasecmp(contact, "sip:", 4)) { |
michael@202 | 142 | - ast_log(LOG_NOTICE, "'%s' is not a valid SIP contact (missing sip:) trying to use anyway\n", contact); |
michael@202 | 143 | + if (strncasecmp(contact, "sips:", 5)) |
michael@202 | 144 | + ast_log(LOG_NOTICE, "'%s' is not a valid SIP contact (missing sip: or sips:) trying to use anyway\n", contact); |
michael@202 | 145 | + else |
michael@202 | 146 | + contact += 5; |
michael@202 | 147 | } else |
michael@202 | 148 | contact += 4; |
michael@202 | 149 | |
michael@202 | 150 | @@ -8409,7 +8415,10 @@ |
michael@202 | 151 | |
michael@202 | 152 | /* Make sure it's a SIP URL */ |
michael@202 | 153 | if (strncasecmp(curi, "sip:", 4)) { |
michael@202 | 154 | - ast_log(LOG_NOTICE, "'%s' is not a valid SIP contact (missing sip:) trying to use anyway\n", curi); |
michael@202 | 155 | + if (strncasecmp(curi, "sips:", 5)) |
michael@202 | 156 | + ast_log(LOG_NOTICE, "'%s' is not a valid SIP contact (missing sip: or sips:) trying to use anyway\n", curi); |
michael@202 | 157 | + else |
michael@202 | 158 | + curi += 5; |
michael@202 | 159 | } else |
michael@202 | 160 | curi += 4; |
michael@202 | 161 | /* Ditch q */ |
michael@202 | 162 | @@ -9000,9 +9009,12 @@ |
michael@202 | 163 | |
michael@202 | 164 | if (!strncasecmp(c, "sip:", 4)) { |
michael@202 | 165 | name = c + 4; |
michael@202 | 166 | + } |
michael@202 | 167 | + else if (!strncasecmp(c, "sips:", 5)) { |
michael@202 | 168 | + name = c + 5; |
michael@202 | 169 | } else { |
michael@202 | 170 | name = c; |
michael@202 | 171 | - ast_log(LOG_NOTICE, "Invalid to address: '%s' from %s (missing sip:) trying to use anyway...\n", c, ast_inet_ntoa(sin->sin_addr)); |
michael@202 | 172 | + ast_log(LOG_NOTICE, "Invalid to address: '%s' from %s (missing sip: or sips:) trying to use anyway...\n", c, ast_inet_ntoa(sin->sin_addr)); |
michael@202 | 173 | } |
michael@202 | 174 | |
michael@202 | 175 | /* Strip off the domain name */ |
michael@202 | 176 | @@ -9162,10 +9174,15 @@ |
michael@202 | 177 | return 0; |
michael@202 | 178 | c = get_in_brackets(tmp); |
michael@202 | 179 | if (strncasecmp(c, "sip:", 4)) { |
michael@202 | 180 | - ast_log(LOG_WARNING, "Huh? Not an RDNIS SIP header (%s)?\n", c); |
michael@202 | 181 | - return -1; |
michael@202 | 182 | + if (strncasecmp(c, "sips:", 5)) { |
michael@202 | 183 | + ast_log(LOG_WARNING, "Huh? Not an RDNIS SIP header (%s)?\n", c); |
michael@202 | 184 | + return -1; |
michael@202 | 185 | + } |
michael@202 | 186 | + else |
michael@202 | 187 | + c += 5; |
michael@202 | 188 | } |
michael@202 | 189 | - c += 4; |
michael@202 | 190 | + else |
michael@202 | 191 | + c += 4; |
michael@202 | 192 | a = c; |
michael@202 | 193 | strsep(&a, "@;"); /* trim anything after @ or ; */ |
michael@202 | 194 | if (sip_debug_test_pvt(p)) |
michael@202 | 195 | @@ -9200,10 +9217,15 @@ |
michael@202 | 196 | uri = get_in_brackets(tmp); |
michael@202 | 197 | |
michael@202 | 198 | if (strncasecmp(uri, "sip:", 4)) { |
michael@202 | 199 | - ast_log(LOG_WARNING, "Huh? Not a SIP header (%s)?\n", uri); |
michael@202 | 200 | - return -1; |
michael@202 | 201 | + if (strncasecmp(uri, "sips:", 5)) { |
michael@202 | 202 | + ast_log(LOG_WARNING, "Huh? Not a SIP header (%s)?\n", uri); |
michael@202 | 203 | + return -1; |
michael@202 | 204 | + } |
michael@202 | 205 | + else |
michael@202 | 206 | + uri += 5; |
michael@202 | 207 | } |
michael@202 | 208 | - uri += 4; |
michael@202 | 209 | + else |
michael@202 | 210 | + uri += 4; |
michael@202 | 211 | |
michael@202 | 212 | /* Now find the From: caller ID and name */ |
michael@202 | 213 | ast_copy_string(tmpf, get_header(req, "From"), sizeof(tmpf)); |
michael@202 | 214 | @@ -9217,10 +9239,15 @@ |
michael@202 | 215 | |
michael@202 | 216 | if (!ast_strlen_zero(from)) { |
michael@202 | 217 | if (strncasecmp(from, "sip:", 4)) { |
michael@202 | 218 | - ast_log(LOG_WARNING, "Huh? Not a SIP header (%s)?\n", from); |
michael@202 | 219 | - return -1; |
michael@202 | 220 | + if (strncasecmp(from, "sips:", 5)) { |
michael@202 | 221 | + ast_log(LOG_WARNING, "Huh? Not a SIP header (%s)?\n", from); |
michael@202 | 222 | + return -1; |
michael@202 | 223 | + } |
michael@202 | 224 | + else |
michael@202 | 225 | + from += 5; |
michael@202 | 226 | } |
michael@202 | 227 | - from += 4; |
michael@202 | 228 | + else |
michael@202 | 229 | + from += 4; |
michael@202 | 230 | if ((a = strchr(from, '@'))) |
michael@202 | 231 | *a++ = '\0'; |
michael@202 | 232 | else |
michael@202 | 233 | @@ -9397,10 +9424,15 @@ |
michael@202 | 234 | ast_uri_decode(refer_to); |
michael@202 | 235 | |
michael@202 | 236 | if (strncasecmp(refer_to, "sip:", 4)) { |
michael@202 | 237 | - ast_log(LOG_WARNING, "Can't transfer to non-sip: URI. (Refer-to: %s)?\n", refer_to); |
michael@202 | 238 | - return -3; |
michael@202 | 239 | + if (strncasecmp(refer_to, "sips:", 5)) { |
michael@202 | 240 | + ast_log(LOG_WARNING, "Can't transfer to non-sip: URI. (Refer-to: %s)?\n", refer_to); |
michael@202 | 241 | + return -3; |
michael@202 | 242 | + } |
michael@202 | 243 | + else |
michael@202 | 244 | + refer_to += 5; /* Skip sips: */ |
michael@202 | 245 | } |
michael@202 | 246 | - refer_to += 4; /* Skip sip: */ |
michael@202 | 247 | + else |
michael@202 | 248 | + refer_to += 4; /* Skip sip: */ |
michael@202 | 249 | |
michael@202 | 250 | /* Get referred by header if it exists */ |
michael@202 | 251 | p_referred_by = get_header(req, "Referred-By"); |
michael@202 | 252 | @@ -9417,9 +9449,13 @@ |
michael@202 | 253 | } |
michael@202 | 254 | |
michael@202 | 255 | referred_by_uri = get_in_brackets(h_referred_by); |
michael@202 | 256 | - if(strncasecmp(referred_by_uri, "sip:", 4)) { |
michael@202 | 257 | - ast_log(LOG_WARNING, "Huh? Not a sip: header (Referred-by: %s). Skipping.\n", referred_by_uri); |
michael@202 | 258 | - referred_by_uri = (char *) NULL; |
michael@202 | 259 | + if (strncasecmp(referred_by_uri, "sip:", 4)) { |
michael@202 | 260 | + if (strncasecmp(referred_by_uri, "sips:", 5)) { |
michael@202 | 261 | + ast_log(LOG_WARNING, "Huh? Not a sip: header (Referred-by: %s). Skipping.\n", referred_by_uri); |
michael@202 | 262 | + referred_by_uri = (char *) NULL; |
michael@202 | 263 | + } |
michael@202 | 264 | + else |
michael@202 | 265 | + referred_by_uri += 5; /* Skip sips: */ |
michael@202 | 266 | } else { |
michael@202 | 267 | referred_by_uri += 4; /* Skip sip: */ |
michael@202 | 268 | } |
michael@202 | 269 | @@ -9547,10 +9583,15 @@ |
michael@202 | 270 | ast_uri_decode(c); |
michael@202 | 271 | |
michael@202 | 272 | if (strncasecmp(c, "sip:", 4)) { |
michael@202 | 273 | - ast_log(LOG_WARNING, "Huh? Not a SIP header in Also: transfer (%s)?\n", c); |
michael@202 | 274 | - return -1; |
michael@202 | 275 | + if (strncasecmp(c, "sips:", 5)) { |
michael@202 | 276 | + ast_log(LOG_WARNING, "Huh? Not a SIP header in Also: transfer (%s)?\n", c); |
michael@202 | 277 | + return -1; |
michael@202 | 278 | + } |
michael@202 | 279 | + else |
michael@202 | 280 | + c += 5; |
michael@202 | 281 | } |
michael@202 | 282 | - c += 4; |
michael@202 | 283 | + else |
michael@202 | 284 | + c += 4; |
michael@202 | 285 | if ((a = strchr(c, ';'))) /* Remove arguments */ |
michael@202 | 286 | *a = '\0'; |
michael@202 | 287 | |
michael@202 | 288 | @@ -9761,6 +9802,8 @@ |
michael@202 | 289 | t = uri2; |
michael@202 | 290 | if (!strncasecmp(t, "sip:", 4)) |
michael@202 | 291 | t+= 4; |
michael@202 | 292 | + else if (!strncasecmp(t, "sips:", 5)) |
michael@202 | 293 | + t+= 5; |
michael@202 | 294 | ast_string_field_set(p, exten, t); |
michael@202 | 295 | t = strchr(p->exten, '@'); |
michael@202 | 296 | if (t) |
michael@202 | 297 | @@ -9771,7 +9814,10 @@ |
michael@202 | 298 | /* save the URI part of the From header */ |
michael@202 | 299 | ast_string_field_set(p, from, of); |
michael@202 | 300 | if (strncasecmp(of, "sip:", 4)) { |
michael@202 | 301 | - ast_log(LOG_NOTICE, "From address missing 'sip:', using it anyway\n"); |
michael@202 | 302 | + if (strncasecmp(of, "sips:", 5)) |
michael@202 | 303 | + ast_log(LOG_NOTICE, "From address missing 'sip:' or 'sips:', using it anyway\n"); |
michael@202 | 304 | + else |
michael@202 | 305 | + of += 5; |
michael@202 | 306 | } else |
michael@202 | 307 | of += 4; |
michael@202 | 308 | /* Get just the username part */ |
michael@202 | 309 | @@ -12379,6 +12425,8 @@ |
michael@202 | 310 | if (ast_test_flag(&p->flags[0], SIP_PROMISCREDIR)) { |
michael@202 | 311 | if (!strncasecmp(s, "sip:", 4)) |
michael@202 | 312 | s += 4; |
michael@202 | 313 | + else if (!strncasecmp(s, "sips:", 5)) |
michael@202 | 314 | + s += 5; |
michael@202 | 315 | e = strchr(s, ';'); |
michael@202 | 316 | if (e) |
michael@202 | 317 | *e = '\0'; |
michael@202 | 318 | @@ -12404,6 +12452,8 @@ |
michael@202 | 319 | |
michael@202 | 320 | if (!strncasecmp(s, "sip:", 4)) |
michael@202 | 321 | s += 4; |
michael@202 | 322 | + else if (!strncasecmp(s, "sips:", 5)) |
michael@202 | 323 | + s += 5; |
michael@202 | 324 | if (option_debug > 1) |
michael@202 | 325 | ast_log(LOG_DEBUG, "Received 302 Redirect to extension '%s' (domain %s)\n", s, domain); |
michael@202 | 326 | if (p->owner) { |
michael@202 | 327 | Index: codecs/codec_g722.c |
michael@202 | 328 | diff -Nau codecs/codec_g722.c.orig codecs/codec_g722.c |
michael@202 | 329 | --- codecs/codec_g722.c.orig 1970-01-01 01:00:00.000000000 +0100 |
michael@202 | 330 | +++ codecs/codec_g722.c 2009-04-24 00:30:33.000000000 +0200 |
michael@202 | 331 | @@ -0,0 +1,306 @@ |
michael@202 | 332 | +/* |
michael@202 | 333 | + * Asterisk -- An open source telephony toolkit. |
michael@202 | 334 | + * |
michael@202 | 335 | + * Copyright (C) 1999 - 2008, Digium, Inc. |
michael@202 | 336 | + * |
michael@202 | 337 | + * Matthew Fredrickson <creslin@digium.com> |
michael@202 | 338 | + * Russell Bryant <russell@digium.com> |
michael@202 | 339 | + * |
michael@202 | 340 | + * Special thanks to Steve Underwood for the implementation |
michael@202 | 341 | + * and for doing the 8khz<->g.722 direct translation code. |
michael@202 | 342 | + * |
michael@202 | 343 | + * See http://www.asterisk.org for more information about |
michael@202 | 344 | + * the Asterisk project. Please do not directly contact |
michael@202 | 345 | + * any of the maintainers of this project for assistance; |
michael@202 | 346 | + * the project provides a web site, mailing lists and IRC |
michael@202 | 347 | + * channels for your use. |
michael@202 | 348 | + * |
michael@202 | 349 | + * This program is free software, distributed under the terms of |
michael@202 | 350 | + * the GNU General Public License Version 2. See the LICENSE file |
michael@202 | 351 | + * at the top of the source tree. |
michael@202 | 352 | + */ |
michael@202 | 353 | + |
michael@202 | 354 | +/*! \file |
michael@202 | 355 | + * |
michael@202 | 356 | + * \brief codec_g722.c - translate between signed linear and ITU G.722-64kbps |
michael@202 | 357 | + * |
michael@202 | 358 | + * \author Matthew Fredrickson <creslin@digium.com> |
michael@202 | 359 | + * \author Russell Bryant <russell@digium.com> |
michael@202 | 360 | + * |
michael@202 | 361 | + * \arg http://soft-switch.org/downloads/non-gpl-bits.tgz |
michael@202 | 362 | + * \arg http://lists.digium.com/pipermail/asterisk-dev/2006-September/022866.html |
michael@202 | 363 | + * |
michael@202 | 364 | + * \ingroup codecs |
michael@202 | 365 | + */ |
michael@202 | 366 | + |
michael@202 | 367 | +#include "asterisk.h" |
michael@202 | 368 | + |
michael@202 | 369 | +ASTERISK_FILE_VERSION(__FILE__, "$Revision: 106501 $") |
michael@202 | 370 | + |
michael@202 | 371 | +#include "asterisk/linkedlists.h" |
michael@202 | 372 | +#include "asterisk/module.h" |
michael@202 | 373 | +#include "asterisk/config.h" |
michael@202 | 374 | +#include "asterisk/options.h" |
michael@202 | 375 | +#include "asterisk/translate.h" |
michael@202 | 376 | +#include "asterisk/utils.h" |
michael@202 | 377 | + |
michael@202 | 378 | +#define BUFFER_SAMPLES 8096 /* size for the translation buffers */ |
michael@202 | 379 | +#define BUF_SHIFT 5 |
michael@202 | 380 | + |
michael@202 | 381 | +/* Sample frame data */ |
michael@202 | 382 | + |
michael@202 | 383 | +#include "g722/g722.h" |
michael@202 | 384 | +#include "slin_g722_ex.h" |
michael@202 | 385 | +#include "g722_slin_ex.h" |
michael@202 | 386 | + |
michael@202 | 387 | +struct g722_encoder_pvt { |
michael@202 | 388 | + g722_encode_state_t g722; |
michael@202 | 389 | +}; |
michael@202 | 390 | + |
michael@202 | 391 | +struct g722_decoder_pvt { |
michael@202 | 392 | + g722_decode_state_t g722; |
michael@202 | 393 | +}; |
michael@202 | 394 | + |
michael@202 | 395 | +/*! \brief init a new instance of g722_encoder_pvt. */ |
michael@202 | 396 | +static int lintog722_new(struct ast_trans_pvt *pvt) |
michael@202 | 397 | +{ |
michael@202 | 398 | + struct g722_encoder_pvt *tmp = pvt->pvt; |
michael@202 | 399 | + |
michael@202 | 400 | + g722_encode_init(&tmp->g722, 64000, G722_SAMPLE_RATE_8000); |
michael@202 | 401 | + |
michael@202 | 402 | + return 0; |
michael@202 | 403 | +} |
michael@202 | 404 | + |
michael@202 | 405 | +static int lin16tog722_new(struct ast_trans_pvt *pvt) |
michael@202 | 406 | +{ |
michael@202 | 407 | + struct g722_encoder_pvt *tmp = pvt->pvt; |
michael@202 | 408 | + |
michael@202 | 409 | + g722_encode_init(&tmp->g722, 64000, 0); |
michael@202 | 410 | + |
michael@202 | 411 | + return 0; |
michael@202 | 412 | +} |
michael@202 | 413 | + |
michael@202 | 414 | +/*! \brief init a new instance of g722_encoder_pvt. */ |
michael@202 | 415 | +static int g722tolin_new(struct ast_trans_pvt *pvt) |
michael@202 | 416 | +{ |
michael@202 | 417 | + struct g722_decoder_pvt *tmp = pvt->pvt; |
michael@202 | 418 | + |
michael@202 | 419 | + g722_decode_init(&tmp->g722, 64000, G722_SAMPLE_RATE_8000); |
michael@202 | 420 | + |
michael@202 | 421 | + return 0; |
michael@202 | 422 | +} |
michael@202 | 423 | + |
michael@202 | 424 | +static int g722tolin16_new(struct ast_trans_pvt *pvt) |
michael@202 | 425 | +{ |
michael@202 | 426 | + struct g722_decoder_pvt *tmp = pvt->pvt; |
michael@202 | 427 | + |
michael@202 | 428 | + g722_decode_init(&tmp->g722, 64000, 0); |
michael@202 | 429 | + |
michael@202 | 430 | + return 0; |
michael@202 | 431 | +} |
michael@202 | 432 | + |
michael@202 | 433 | +static int g722tolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f) |
michael@202 | 434 | +{ |
michael@202 | 435 | + struct g722_decoder_pvt *tmp = pvt->pvt; |
michael@202 | 436 | + int out_samples; |
michael@202 | 437 | + int in_samples; |
michael@202 | 438 | + |
michael@202 | 439 | + /* g722_decode expects the samples to be in the invalid samples / 2 format */ |
michael@202 | 440 | + in_samples = f->samples / 2; |
michael@202 | 441 | + |
michael@202 | 442 | + out_samples = g722_decode(&tmp->g722, (int16_t *) &pvt->outbuf[pvt->samples * sizeof(int16_t)], |
michael@202 | 443 | + (uint8_t *) f->data, in_samples); |
michael@202 | 444 | + |
michael@202 | 445 | + pvt->samples += out_samples; |
michael@202 | 446 | + |
michael@202 | 447 | + pvt->datalen += (out_samples * sizeof(int16_t)); |
michael@202 | 448 | + |
michael@202 | 449 | + return 0; |
michael@202 | 450 | +} |
michael@202 | 451 | + |
michael@202 | 452 | +static int lintog722_framein(struct ast_trans_pvt *pvt, struct ast_frame *f) |
michael@202 | 453 | +{ |
michael@202 | 454 | + struct g722_encoder_pvt *tmp = pvt->pvt; |
michael@202 | 455 | + int outlen; |
michael@202 | 456 | + |
michael@202 | 457 | + outlen = g722_encode(&tmp->g722, (uint8_t *) (&pvt->outbuf[pvt->datalen]), |
michael@202 | 458 | + (int16_t *) f->data, f->samples); |
michael@202 | 459 | + |
michael@202 | 460 | + pvt->samples += outlen * 2; |
michael@202 | 461 | + |
michael@202 | 462 | + pvt->datalen += outlen; |
michael@202 | 463 | + |
michael@202 | 464 | + return 0; |
michael@202 | 465 | +} |
michael@202 | 466 | + |
michael@202 | 467 | +static struct ast_frame *g722tolin_sample(void) |
michael@202 | 468 | +{ |
michael@202 | 469 | + static struct ast_frame f = { |
michael@202 | 470 | + .frametype = AST_FRAME_VOICE, |
michael@202 | 471 | + .subclass = AST_FORMAT_G722, |
michael@202 | 472 | + .datalen = sizeof(g722_slin_ex), |
michael@202 | 473 | + .samples = sizeof(g722_slin_ex) * 2, |
michael@202 | 474 | + .src = __PRETTY_FUNCTION__, |
michael@202 | 475 | + .data = g722_slin_ex, |
michael@202 | 476 | + }; |
michael@202 | 477 | + |
michael@202 | 478 | + return &f; |
michael@202 | 479 | +} |
michael@202 | 480 | + |
michael@202 | 481 | +static struct ast_frame *g722tolin16_sample(void) |
michael@202 | 482 | +{ |
michael@202 | 483 | + static struct ast_frame f = { |
michael@202 | 484 | + .frametype = AST_FRAME_VOICE, |
michael@202 | 485 | + .subclass = AST_FORMAT_G722, |
michael@202 | 486 | + .datalen = sizeof(slin_g722_ex), |
michael@202 | 487 | + .samples = sizeof(slin_g722_ex) * 2, |
michael@202 | 488 | + .src = __PRETTY_FUNCTION__, |
michael@202 | 489 | + .data = slin_g722_ex, |
michael@202 | 490 | + }; |
michael@202 | 491 | + |
michael@202 | 492 | + return &f; |
michael@202 | 493 | +} |
michael@202 | 494 | + |
michael@202 | 495 | +static struct ast_frame *lintog722_sample (void) |
michael@202 | 496 | +{ |
michael@202 | 497 | + static struct ast_frame f = { |
michael@202 | 498 | + .frametype = AST_FRAME_VOICE, |
michael@202 | 499 | + .subclass = AST_FORMAT_SLINEAR, |
michael@202 | 500 | + .datalen = sizeof(slin_g722_ex), |
michael@202 | 501 | + .samples = sizeof(slin_g722_ex) / sizeof(slin_g722_ex[0]), |
michael@202 | 502 | + .src = __PRETTY_FUNCTION__, |
michael@202 | 503 | + .data = slin_g722_ex, |
michael@202 | 504 | + }; |
michael@202 | 505 | + |
michael@202 | 506 | + return &f; |
michael@202 | 507 | +} |
michael@202 | 508 | + |
michael@202 | 509 | +static struct ast_frame *lin16tog722_sample (void) |
michael@202 | 510 | +{ |
michael@202 | 511 | + static struct ast_frame f = { |
michael@202 | 512 | + .frametype = AST_FRAME_VOICE, |
michael@202 | 513 | + .subclass = AST_FORMAT_SLINEAR16, |
michael@202 | 514 | + .datalen = sizeof(slin_g722_ex), |
michael@202 | 515 | + .samples = sizeof(slin_g722_ex) / sizeof(slin_g722_ex[0]), |
michael@202 | 516 | + .src = __PRETTY_FUNCTION__, |
michael@202 | 517 | + .data = slin_g722_ex, |
michael@202 | 518 | + }; |
michael@202 | 519 | + |
michael@202 | 520 | + return &f; |
michael@202 | 521 | +} |
michael@202 | 522 | + |
michael@202 | 523 | +static struct ast_translator g722tolin = { |
michael@202 | 524 | + .name = "g722tolin", |
michael@202 | 525 | + .srcfmt = AST_FORMAT_G722, |
michael@202 | 526 | + .dstfmt = AST_FORMAT_SLINEAR, |
michael@202 | 527 | + .newpvt = g722tolin_new, /* same for both directions */ |
michael@202 | 528 | + .framein = g722tolin_framein, |
michael@202 | 529 | + .sample = g722tolin_sample, |
michael@202 | 530 | + .desc_size = sizeof(struct g722_decoder_pvt), |
michael@202 | 531 | + .buffer_samples = BUFFER_SAMPLES / sizeof(int16_t), |
michael@202 | 532 | + .buf_size = BUFFER_SAMPLES, |
michael@202 | 533 | + .plc_samples = 160, |
michael@202 | 534 | +}; |
michael@202 | 535 | + |
michael@202 | 536 | +static struct ast_translator lintog722 = { |
michael@202 | 537 | + .name = "lintog722", |
michael@202 | 538 | + .srcfmt = AST_FORMAT_SLINEAR, |
michael@202 | 539 | + .dstfmt = AST_FORMAT_G722, |
michael@202 | 540 | + .newpvt = lintog722_new, /* same for both directions */ |
michael@202 | 541 | + .framein = lintog722_framein, |
michael@202 | 542 | + .sample = lintog722_sample, |
michael@202 | 543 | + .desc_size = sizeof(struct g722_encoder_pvt), |
michael@202 | 544 | + .buffer_samples = BUFFER_SAMPLES * 2, |
michael@202 | 545 | + .buf_size = BUFFER_SAMPLES, |
michael@202 | 546 | +}; |
michael@202 | 547 | + |
michael@202 | 548 | +static struct ast_translator g722tolin16 = { |
michael@202 | 549 | + .name = "g722tolin16", |
michael@202 | 550 | + .srcfmt = AST_FORMAT_G722, |
michael@202 | 551 | + .dstfmt = AST_FORMAT_SLINEAR16, |
michael@202 | 552 | + .newpvt = g722tolin16_new, /* same for both directions */ |
michael@202 | 553 | + .framein = g722tolin_framein, |
michael@202 | 554 | + .sample = g722tolin16_sample, |
michael@202 | 555 | + .desc_size = sizeof(struct g722_decoder_pvt), |
michael@202 | 556 | + .buffer_samples = BUFFER_SAMPLES / sizeof(int16_t), |
michael@202 | 557 | + .buf_size = BUFFER_SAMPLES, |
michael@202 | 558 | + .plc_samples = 160, |
michael@202 | 559 | +}; |
michael@202 | 560 | + |
michael@202 | 561 | +static struct ast_translator lin16tog722 = { |
michael@202 | 562 | + .name = "lin16tog722", |
michael@202 | 563 | + .srcfmt = AST_FORMAT_SLINEAR16, |
michael@202 | 564 | + .dstfmt = AST_FORMAT_G722, |
michael@202 | 565 | + .newpvt = lin16tog722_new, /* same for both directions */ |
michael@202 | 566 | + .framein = lintog722_framein, |
michael@202 | 567 | + .sample = lin16tog722_sample, |
michael@202 | 568 | + .desc_size = sizeof(struct g722_encoder_pvt), |
michael@202 | 569 | + .buffer_samples = BUFFER_SAMPLES * 2, |
michael@202 | 570 | + .buf_size = BUFFER_SAMPLES, |
michael@202 | 571 | +}; |
michael@202 | 572 | + |
michael@202 | 573 | +static int parse_config(int reload) |
michael@202 | 574 | +{ |
michael@202 | 575 | + struct ast_variable *var; |
michael@202 | 576 | + struct ast_config *cfg = ast_config_load("codecs.conf"); |
michael@202 | 577 | + |
michael@202 | 578 | + if (cfg == NULL) |
michael@202 | 579 | + return 0; |
michael@202 | 580 | + if (cfg == CONFIG_STATUS_FILEUNCHANGED) |
michael@202 | 581 | + return 0; |
michael@202 | 582 | + for (var = ast_variable_browse(cfg, "plc"); var; var = var->next) { |
michael@202 | 583 | + if (!strcasecmp(var->name, "genericplc")) { |
michael@202 | 584 | + g722tolin.useplc = ast_true(var->value) ? 1 : 0; |
michael@202 | 585 | + if (option_verbose > 2) |
michael@202 | 586 | + ast_verbose(VERBOSE_PREFIX_3 "codec_g722: %susing generic PLC\n", |
michael@202 | 587 | + g722tolin.useplc ? "" : "not "); |
michael@202 | 588 | + } |
michael@202 | 589 | + } |
michael@202 | 590 | + ast_config_destroy(cfg); |
michael@202 | 591 | + return 0; |
michael@202 | 592 | +} |
michael@202 | 593 | + |
michael@202 | 594 | +static int reload(void) |
michael@202 | 595 | +{ |
michael@202 | 596 | + if (parse_config(1)) |
michael@202 | 597 | + return AST_MODULE_LOAD_DECLINE; |
michael@202 | 598 | + return AST_MODULE_LOAD_SUCCESS; |
michael@202 | 599 | +} |
michael@202 | 600 | + |
michael@202 | 601 | +static int unload_module(void) |
michael@202 | 602 | +{ |
michael@202 | 603 | + int res = 0; |
michael@202 | 604 | + |
michael@202 | 605 | + res |= ast_unregister_translator(&g722tolin); |
michael@202 | 606 | + res |= ast_unregister_translator(&lintog722); |
michael@202 | 607 | + res |= ast_unregister_translator(&g722tolin16); |
michael@202 | 608 | + res |= ast_unregister_translator(&lin16tog722); |
michael@202 | 609 | + |
michael@202 | 610 | + return res; |
michael@202 | 611 | +} |
michael@202 | 612 | + |
michael@202 | 613 | +static int load_module(void) |
michael@202 | 614 | +{ |
michael@202 | 615 | + int res = 0; |
michael@202 | 616 | + |
michael@202 | 617 | + if (parse_config(0)) |
michael@202 | 618 | + return AST_MODULE_LOAD_DECLINE; |
michael@202 | 619 | + |
michael@202 | 620 | + res |= ast_register_translator(&g722tolin); |
michael@202 | 621 | + res |= ast_register_translator(&lintog722); |
michael@202 | 622 | + res |= ast_register_translator(&g722tolin16); |
michael@202 | 623 | + res |= ast_register_translator(&lin16tog722); |
michael@202 | 624 | + |
michael@202 | 625 | + if (res) { |
michael@202 | 626 | + unload_module(); |
michael@202 | 627 | + return AST_MODULE_LOAD_FAILURE; |
michael@202 | 628 | + } |
michael@202 | 629 | + |
michael@202 | 630 | + return AST_MODULE_LOAD_SUCCESS; |
michael@202 | 631 | +} |
michael@202 | 632 | + |
michael@202 | 633 | +AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "ITU G.722-64kbps G722 Transcoder", |
michael@202 | 634 | + .load = load_module, |
michael@202 | 635 | + .unload = unload_module, |
michael@202 | 636 | + .reload = reload, |
michael@202 | 637 | + ); |
michael@202 | 638 | Index: codecs/g722/g722_decode.c |
michael@202 | 639 | diff -Nau codecs/g722/g722_decode.c.orig codecs/g722/g722_decode.c |
michael@202 | 640 | --- codecs/g722/g722_decode.c.orig 1970-01-01 01:00:00.000000000 +0100 |
michael@202 | 641 | +++ codecs/g722/g722_decode.c 2009-04-24 00:30:33.000000000 +0200 |
michael@202 | 642 | @@ -0,0 +1,398 @@ |
michael@202 | 643 | +/* |
michael@202 | 644 | + * SpanDSP - a series of DSP components for telephony |
michael@202 | 645 | + * |
michael@202 | 646 | + * g722_decode.c - The ITU G.722 codec, decode part. |
michael@202 | 647 | + * |
michael@202 | 648 | + * Written by Steve Underwood <steveu@coppice.org> |
michael@202 | 649 | + * |
michael@202 | 650 | + * Copyright (C) 2005 Steve Underwood |
michael@202 | 651 | + * |
michael@202 | 652 | + * Despite my general liking of the GPL, I place my own contributions |
michael@202 | 653 | + * to this code in the public domain for the benefit of all mankind - |
michael@202 | 654 | + * even the slimy ones who might try to proprietize my work and use it |
michael@202 | 655 | + * to my detriment. |
michael@202 | 656 | + * |
michael@202 | 657 | + * Based in part on a single channel G.722 codec which is: |
michael@202 | 658 | + * |
michael@202 | 659 | + * Copyright (c) CMU 1993 |
michael@202 | 660 | + * Computer Science, Speech Group |
michael@202 | 661 | + * Chengxiang Lu and Alex Hauptmann |
michael@202 | 662 | + * |
michael@202 | 663 | + * $Id: g722_decode.c 48661 2006-12-21 00:08:21Z mattf $ |
michael@202 | 664 | + */ |
michael@202 | 665 | + |
michael@202 | 666 | +/*! \file */ |
michael@202 | 667 | + |
michael@202 | 668 | +#ifdef HAVE_CONFIG_H |
michael@202 | 669 | +#include <config.h> |
michael@202 | 670 | +#endif |
michael@202 | 671 | + |
michael@202 | 672 | +#include <stdio.h> |
michael@202 | 673 | +#include <inttypes.h> |
michael@202 | 674 | +#include <memory.h> |
michael@202 | 675 | +#include <stdlib.h> |
michael@202 | 676 | +#if 0 |
michael@202 | 677 | +#include <tgmath.h> |
michael@202 | 678 | +#endif |
michael@202 | 679 | + |
michael@202 | 680 | +#include "g722.h" |
michael@202 | 681 | + |
michael@202 | 682 | +#if !defined(FALSE) |
michael@202 | 683 | +#define FALSE 0 |
michael@202 | 684 | +#endif |
michael@202 | 685 | +#if !defined(TRUE) |
michael@202 | 686 | +#define TRUE (!FALSE) |
michael@202 | 687 | +#endif |
michael@202 | 688 | + |
michael@202 | 689 | +static __inline__ int16_t saturate(int32_t amp) |
michael@202 | 690 | +{ |
michael@202 | 691 | + int16_t amp16; |
michael@202 | 692 | + |
michael@202 | 693 | + /* Hopefully this is optimised for the common case - not clipping */ |
michael@202 | 694 | + amp16 = (int16_t) amp; |
michael@202 | 695 | + if (amp == amp16) |
michael@202 | 696 | + return amp16; |
michael@202 | 697 | + if (amp > INT16_MAX) |
michael@202 | 698 | + return INT16_MAX; |
michael@202 | 699 | + return INT16_MIN; |
michael@202 | 700 | +} |
michael@202 | 701 | +/*- End of function --------------------------------------------------------*/ |
michael@202 | 702 | + |
michael@202 | 703 | +static void block4(g722_decode_state_t *s, int band, int d); |
michael@202 | 704 | + |
michael@202 | 705 | +static void block4(g722_decode_state_t *s, int band, int d) |
michael@202 | 706 | +{ |
michael@202 | 707 | + int wd1; |
michael@202 | 708 | + int wd2; |
michael@202 | 709 | + int wd3; |
michael@202 | 710 | + int i; |
michael@202 | 711 | + |
michael@202 | 712 | + /* Block 4, RECONS */ |
michael@202 | 713 | + s->band[band].d[0] = d; |
michael@202 | 714 | + s->band[band].r[0] = saturate(s->band[band].s + d); |
michael@202 | 715 | + |
michael@202 | 716 | + /* Block 4, PARREC */ |
michael@202 | 717 | + s->band[band].p[0] = saturate(s->band[band].sz + d); |
michael@202 | 718 | + |
michael@202 | 719 | + /* Block 4, UPPOL2 */ |
michael@202 | 720 | + for (i = 0; i < 3; i++) |
michael@202 | 721 | + s->band[band].sg[i] = s->band[band].p[i] >> 15; |
michael@202 | 722 | + wd1 = saturate(s->band[band].a[1] << 2); |
michael@202 | 723 | + |
michael@202 | 724 | + wd2 = (s->band[band].sg[0] == s->band[band].sg[1]) ? -wd1 : wd1; |
michael@202 | 725 | + if (wd2 > 32767) |
michael@202 | 726 | + wd2 = 32767; |
michael@202 | 727 | + wd3 = (s->band[band].sg[0] == s->band[band].sg[2]) ? 128 : -128; |
michael@202 | 728 | + wd3 += (wd2 >> 7); |
michael@202 | 729 | + wd3 += (s->band[band].a[2]*32512) >> 15; |
michael@202 | 730 | + if (wd3 > 12288) |
michael@202 | 731 | + wd3 = 12288; |
michael@202 | 732 | + else if (wd3 < -12288) |
michael@202 | 733 | + wd3 = -12288; |
michael@202 | 734 | + s->band[band].ap[2] = wd3; |
michael@202 | 735 | + |
michael@202 | 736 | + /* Block 4, UPPOL1 */ |
michael@202 | 737 | + s->band[band].sg[0] = s->band[band].p[0] >> 15; |
michael@202 | 738 | + s->band[band].sg[1] = s->band[band].p[1] >> 15; |
michael@202 | 739 | + wd1 = (s->band[band].sg[0] == s->band[band].sg[1]) ? 192 : -192; |
michael@202 | 740 | + wd2 = (s->band[band].a[1]*32640) >> 15; |
michael@202 | 741 | + |
michael@202 | 742 | + s->band[band].ap[1] = saturate(wd1 + wd2); |
michael@202 | 743 | + wd3 = saturate(15360 - s->band[band].ap[2]); |
michael@202 | 744 | + if (s->band[band].ap[1] > wd3) |
michael@202 | 745 | + s->band[band].ap[1] = wd3; |
michael@202 | 746 | + else if (s->band[band].ap[1] < -wd3) |
michael@202 | 747 | + s->band[band].ap[1] = -wd3; |
michael@202 | 748 | + |
michael@202 | 749 | + /* Block 4, UPZERO */ |
michael@202 | 750 | + wd1 = (d == 0) ? 0 : 128; |
michael@202 | 751 | + s->band[band].sg[0] = d >> 15; |
michael@202 | 752 | + for (i = 1; i < 7; i++) |
michael@202 | 753 | + { |
michael@202 | 754 | + s->band[band].sg[i] = s->band[band].d[i] >> 15; |
michael@202 | 755 | + wd2 = (s->band[band].sg[i] == s->band[band].sg[0]) ? wd1 : -wd1; |
michael@202 | 756 | + wd3 = (s->band[band].b[i]*32640) >> 15; |
michael@202 | 757 | + s->band[band].bp[i] = saturate(wd2 + wd3); |
michael@202 | 758 | + } |
michael@202 | 759 | + |
michael@202 | 760 | + /* Block 4, DELAYA */ |
michael@202 | 761 | + for (i = 6; i > 0; i--) |
michael@202 | 762 | + { |
michael@202 | 763 | + s->band[band].d[i] = s->band[band].d[i - 1]; |
michael@202 | 764 | + s->band[band].b[i] = s->band[band].bp[i]; |
michael@202 | 765 | + } |
michael@202 | 766 | + |
michael@202 | 767 | + for (i = 2; i > 0; i--) |
michael@202 | 768 | + { |
michael@202 | 769 | + s->band[band].r[i] = s->band[band].r[i - 1]; |
michael@202 | 770 | + s->band[band].p[i] = s->band[band].p[i - 1]; |
michael@202 | 771 | + s->band[band].a[i] = s->band[band].ap[i]; |
michael@202 | 772 | + } |
michael@202 | 773 | + |
michael@202 | 774 | + /* Block 4, FILTEP */ |
michael@202 | 775 | + wd1 = saturate(s->band[band].r[1] + s->band[band].r[1]); |
michael@202 | 776 | + wd1 = (s->band[band].a[1]*wd1) >> 15; |
michael@202 | 777 | + wd2 = saturate(s->band[band].r[2] + s->band[band].r[2]); |
michael@202 | 778 | + wd2 = (s->band[band].a[2]*wd2) >> 15; |
michael@202 | 779 | + s->band[band].sp = saturate(wd1 + wd2); |
michael@202 | 780 | + |
michael@202 | 781 | + /* Block 4, FILTEZ */ |
michael@202 | 782 | + s->band[band].sz = 0; |
michael@202 | 783 | + for (i = 6; i > 0; i--) |
michael@202 | 784 | + { |
michael@202 | 785 | + wd1 = saturate(s->band[band].d[i] + s->band[band].d[i]); |
michael@202 | 786 | + s->band[band].sz += (s->band[band].b[i]*wd1) >> 15; |
michael@202 | 787 | + } |
michael@202 | 788 | + s->band[band].sz = saturate(s->band[band].sz); |
michael@202 | 789 | + |
michael@202 | 790 | + /* Block 4, PREDIC */ |
michael@202 | 791 | + s->band[band].s = saturate(s->band[band].sp + s->band[band].sz); |
michael@202 | 792 | +} |
michael@202 | 793 | +/*- End of function --------------------------------------------------------*/ |
michael@202 | 794 | + |
michael@202 | 795 | +g722_decode_state_t *g722_decode_init(g722_decode_state_t *s, int rate, int options) |
michael@202 | 796 | +{ |
michael@202 | 797 | + if (s == NULL) |
michael@202 | 798 | + { |
michael@202 | 799 | + if ((s = (g722_decode_state_t *) malloc(sizeof(*s))) == NULL) |
michael@202 | 800 | + return NULL; |
michael@202 | 801 | + } |
michael@202 | 802 | + memset(s, 0, sizeof(*s)); |
michael@202 | 803 | + if (rate == 48000) |
michael@202 | 804 | + s->bits_per_sample = 6; |
michael@202 | 805 | + else if (rate == 56000) |
michael@202 | 806 | + s->bits_per_sample = 7; |
michael@202 | 807 | + else |
michael@202 | 808 | + s->bits_per_sample = 8; |
michael@202 | 809 | + if ((options & G722_SAMPLE_RATE_8000)) |
michael@202 | 810 | + s->eight_k = TRUE; |
michael@202 | 811 | + if ((options & G722_PACKED) && s->bits_per_sample != 8) |
michael@202 | 812 | + s->packed = TRUE; |
michael@202 | 813 | + else |
michael@202 | 814 | + s->packed = FALSE; |
michael@202 | 815 | + s->band[0].det = 32; |
michael@202 | 816 | + s->band[1].det = 8; |
michael@202 | 817 | + return s; |
michael@202 | 818 | +} |
michael@202 | 819 | +/*- End of function --------------------------------------------------------*/ |
michael@202 | 820 | + |
michael@202 | 821 | +int g722_decode_release(g722_decode_state_t *s) |
michael@202 | 822 | +{ |
michael@202 | 823 | + free(s); |
michael@202 | 824 | + return 0; |
michael@202 | 825 | +} |
michael@202 | 826 | +/*- End of function --------------------------------------------------------*/ |
michael@202 | 827 | + |
michael@202 | 828 | +int g722_decode(g722_decode_state_t *s, int16_t amp[], const uint8_t g722_data[], int len) |
michael@202 | 829 | +{ |
michael@202 | 830 | + static const int wl[8] = {-60, -30, 58, 172, 334, 538, 1198, 3042 }; |
michael@202 | 831 | + static const int rl42[16] = {0, 7, 6, 5, 4, 3, 2, 1, 7, 6, 5, 4, 3, 2, 1, 0 }; |
michael@202 | 832 | + static const int ilb[32] = |
michael@202 | 833 | + { |
michael@202 | 834 | + 2048, 2093, 2139, 2186, 2233, 2282, 2332, |
michael@202 | 835 | + 2383, 2435, 2489, 2543, 2599, 2656, 2714, |
michael@202 | 836 | + 2774, 2834, 2896, 2960, 3025, 3091, 3158, |
michael@202 | 837 | + 3228, 3298, 3371, 3444, 3520, 3597, 3676, |
michael@202 | 838 | + 3756, 3838, 3922, 4008 |
michael@202 | 839 | + }; |
michael@202 | 840 | + static const int wh[3] = {0, -214, 798}; |
michael@202 | 841 | + static const int rh2[4] = {2, 1, 2, 1}; |
michael@202 | 842 | + static const int qm2[4] = {-7408, -1616, 7408, 1616}; |
michael@202 | 843 | + static const int qm4[16] = |
michael@202 | 844 | + { |
michael@202 | 845 | + 0, -20456, -12896, -8968, |
michael@202 | 846 | + -6288, -4240, -2584, -1200, |
michael@202 | 847 | + 20456, 12896, 8968, 6288, |
michael@202 | 848 | + 4240, 2584, 1200, 0 |
michael@202 | 849 | + }; |
michael@202 | 850 | + static const int qm5[32] = |
michael@202 | 851 | + { |
michael@202 | 852 | + -280, -280, -23352, -17560, |
michael@202 | 853 | + -14120, -11664, -9752, -8184, |
michael@202 | 854 | + -6864, -5712, -4696, -3784, |
michael@202 | 855 | + -2960, -2208, -1520, -880, |
michael@202 | 856 | + 23352, 17560, 14120, 11664, |
michael@202 | 857 | + 9752, 8184, 6864, 5712, |
michael@202 | 858 | + 4696, 3784, 2960, 2208, |
michael@202 | 859 | + 1520, 880, 280, -280 |
michael@202 | 860 | + }; |
michael@202 | 861 | + static const int qm6[64] = |
michael@202 | 862 | + { |
michael@202 | 863 | + -136, -136, -136, -136, |
michael@202 | 864 | + -24808, -21904, -19008, -16704, |
michael@202 | 865 | + -14984, -13512, -12280, -11192, |
michael@202 | 866 | + -10232, -9360, -8576, -7856, |
michael@202 | 867 | + -7192, -6576, -6000, -5456, |
michael@202 | 868 | + -4944, -4464, -4008, -3576, |
michael@202 | 869 | + -3168, -2776, -2400, -2032, |
michael@202 | 870 | + -1688, -1360, -1040, -728, |
michael@202 | 871 | + 24808, 21904, 19008, 16704, |
michael@202 | 872 | + 14984, 13512, 12280, 11192, |
michael@202 | 873 | + 10232, 9360, 8576, 7856, |
michael@202 | 874 | + 7192, 6576, 6000, 5456, |
michael@202 | 875 | + 4944, 4464, 4008, 3576, |
michael@202 | 876 | + 3168, 2776, 2400, 2032, |
michael@202 | 877 | + 1688, 1360, 1040, 728, |
michael@202 | 878 | + 432, 136, -432, -136 |
michael@202 | 879 | + }; |
michael@202 | 880 | + static const int qmf_coeffs[12] = |
michael@202 | 881 | + { |
michael@202 | 882 | + 3, -11, 12, 32, -210, 951, 3876, -805, 362, -156, 53, -11, |
michael@202 | 883 | + }; |
michael@202 | 884 | + |
michael@202 | 885 | + int dlowt; |
michael@202 | 886 | + int rlow; |
michael@202 | 887 | + int ihigh; |
michael@202 | 888 | + int dhigh; |
michael@202 | 889 | + int rhigh; |
michael@202 | 890 | + int xout1; |
michael@202 | 891 | + int xout2; |
michael@202 | 892 | + int wd1; |
michael@202 | 893 | + int wd2; |
michael@202 | 894 | + int wd3; |
michael@202 | 895 | + int code; |
michael@202 | 896 | + int outlen; |
michael@202 | 897 | + int i; |
michael@202 | 898 | + int j; |
michael@202 | 899 | + |
michael@202 | 900 | + outlen = 0; |
michael@202 | 901 | + rhigh = 0; |
michael@202 | 902 | + for (j = 0; j < len; ) |
michael@202 | 903 | + { |
michael@202 | 904 | + if (s->packed) |
michael@202 | 905 | + { |
michael@202 | 906 | + /* Unpack the code bits */ |
michael@202 | 907 | + if (s->in_bits < s->bits_per_sample) |
michael@202 | 908 | + { |
michael@202 | 909 | + s->in_buffer |= (g722_data[j++] << s->in_bits); |
michael@202 | 910 | + s->in_bits += 8; |
michael@202 | 911 | + } |
michael@202 | 912 | + code = s->in_buffer & ((1 << s->bits_per_sample) - 1); |
michael@202 | 913 | + s->in_buffer >>= s->bits_per_sample; |
michael@202 | 914 | + s->in_bits -= s->bits_per_sample; |
michael@202 | 915 | + } |
michael@202 | 916 | + else |
michael@202 | 917 | + { |
michael@202 | 918 | + code = g722_data[j++]; |
michael@202 | 919 | + } |
michael@202 | 920 | + |
michael@202 | 921 | + switch (s->bits_per_sample) |
michael@202 | 922 | + { |
michael@202 | 923 | + default: |
michael@202 | 924 | + case 8: |
michael@202 | 925 | + wd1 = code & 0x3F; |
michael@202 | 926 | + ihigh = (code >> 6) & 0x03; |
michael@202 | 927 | + wd2 = qm6[wd1]; |
michael@202 | 928 | + wd1 >>= 2; |
michael@202 | 929 | + break; |
michael@202 | 930 | + case 7: |
michael@202 | 931 | + wd1 = code & 0x1F; |
michael@202 | 932 | + ihigh = (code >> 5) & 0x03; |
michael@202 | 933 | + wd2 = qm5[wd1]; |
michael@202 | 934 | + wd1 >>= 1; |
michael@202 | 935 | + break; |
michael@202 | 936 | + case 6: |
michael@202 | 937 | + wd1 = code & 0x0F; |
michael@202 | 938 | + ihigh = (code >> 4) & 0x03; |
michael@202 | 939 | + wd2 = qm4[wd1]; |
michael@202 | 940 | + break; |
michael@202 | 941 | + } |
michael@202 | 942 | + /* Block 5L, LOW BAND INVQBL */ |
michael@202 | 943 | + wd2 = (s->band[0].det*wd2) >> 15; |
michael@202 | 944 | + /* Block 5L, RECONS */ |
michael@202 | 945 | + rlow = s->band[0].s + wd2; |
michael@202 | 946 | + /* Block 6L, LIMIT */ |
michael@202 | 947 | + if (rlow > 16383) |
michael@202 | 948 | + rlow = 16383; |
michael@202 | 949 | + else if (rlow < -16384) |
michael@202 | 950 | + rlow = -16384; |
michael@202 | 951 | + |
michael@202 | 952 | + /* Block 2L, INVQAL */ |
michael@202 | 953 | + wd2 = qm4[wd1]; |
michael@202 | 954 | + dlowt = (s->band[0].det*wd2) >> 15; |
michael@202 | 955 | + |
michael@202 | 956 | + /* Block 3L, LOGSCL */ |
michael@202 | 957 | + wd2 = rl42[wd1]; |
michael@202 | 958 | + wd1 = (s->band[0].nb*127) >> 7; |
michael@202 | 959 | + wd1 += wl[wd2]; |
michael@202 | 960 | + if (wd1 < 0) |
michael@202 | 961 | + wd1 = 0; |
michael@202 | 962 | + else if (wd1 > 18432) |
michael@202 | 963 | + wd1 = 18432; |
michael@202 | 964 | + s->band[0].nb = wd1; |
michael@202 | 965 | + |
michael@202 | 966 | + /* Block 3L, SCALEL */ |
michael@202 | 967 | + wd1 = (s->band[0].nb >> 6) & 31; |
michael@202 | 968 | + wd2 = 8 - (s->band[0].nb >> 11); |
michael@202 | 969 | + wd3 = (wd2 < 0) ? (ilb[wd1] << -wd2) : (ilb[wd1] >> wd2); |
michael@202 | 970 | + s->band[0].det = wd3 << 2; |
michael@202 | 971 | + |
michael@202 | 972 | + block4(s, 0, dlowt); |
michael@202 | 973 | + |
michael@202 | 974 | + if (!s->eight_k) |
michael@202 | 975 | + { |
michael@202 | 976 | + /* Block 2H, INVQAH */ |
michael@202 | 977 | + wd2 = qm2[ihigh]; |
michael@202 | 978 | + dhigh = (s->band[1].det*wd2) >> 15; |
michael@202 | 979 | + /* Block 5H, RECONS */ |
michael@202 | 980 | + rhigh = dhigh + s->band[1].s; |
michael@202 | 981 | + /* Block 6H, LIMIT */ |
michael@202 | 982 | + if (rhigh > 16383) |
michael@202 | 983 | + rhigh = 16383; |
michael@202 | 984 | + else if (rhigh < -16384) |
michael@202 | 985 | + rhigh = -16384; |
michael@202 | 986 | + |
michael@202 | 987 | + /* Block 2H, INVQAH */ |
michael@202 | 988 | + wd2 = rh2[ihigh]; |
michael@202 | 989 | + wd1 = (s->band[1].nb*127) >> 7; |
michael@202 | 990 | + wd1 += wh[wd2]; |
michael@202 | 991 | + if (wd1 < 0) |
michael@202 | 992 | + wd1 = 0; |
michael@202 | 993 | + else if (wd1 > 22528) |
michael@202 | 994 | + wd1 = 22528; |
michael@202 | 995 | + s->band[1].nb = wd1; |
michael@202 | 996 | + |
michael@202 | 997 | + /* Block 3H, SCALEH */ |
michael@202 | 998 | + wd1 = (s->band[1].nb >> 6) & 31; |
michael@202 | 999 | + wd2 = 10 - (s->band[1].nb >> 11); |
michael@202 | 1000 | + wd3 = (wd2 < 0) ? (ilb[wd1] << -wd2) : (ilb[wd1] >> wd2); |
michael@202 | 1001 | + s->band[1].det = wd3 << 2; |
michael@202 | 1002 | + |
michael@202 | 1003 | + block4(s, 1, dhigh); |
michael@202 | 1004 | + } |
michael@202 | 1005 | + |
michael@202 | 1006 | + if (s->itu_test_mode) |
michael@202 | 1007 | + { |
michael@202 | 1008 | + amp[outlen++] = (int16_t) (rlow << 1); |
michael@202 | 1009 | + amp[outlen++] = (int16_t) (rhigh << 1); |
michael@202 | 1010 | + } |
michael@202 | 1011 | + else |
michael@202 | 1012 | + { |
michael@202 | 1013 | + if (s->eight_k) |
michael@202 | 1014 | + { |
michael@202 | 1015 | + amp[outlen++] = (int16_t) rlow; |
michael@202 | 1016 | + } |
michael@202 | 1017 | + else |
michael@202 | 1018 | + { |
michael@202 | 1019 | + /* Apply the receive QMF */ |
michael@202 | 1020 | + for (i = 0; i < 22; i++) |
michael@202 | 1021 | + s->x[i] = s->x[i + 2]; |
michael@202 | 1022 | + s->x[22] = rlow + rhigh; |
michael@202 | 1023 | + s->x[23] = rlow - rhigh; |
michael@202 | 1024 | + |
michael@202 | 1025 | + xout1 = 0; |
michael@202 | 1026 | + xout2 = 0; |
michael@202 | 1027 | + for (i = 0; i < 12; i++) |
michael@202 | 1028 | + { |
michael@202 | 1029 | + xout2 += s->x[2*i]*qmf_coeffs[i]; |
michael@202 | 1030 | + xout1 += s->x[2*i + 1]*qmf_coeffs[11 - i]; |
michael@202 | 1031 | + } |
michael@202 | 1032 | + amp[outlen++] = (int16_t) (xout1 >> 12); |
michael@202 | 1033 | + amp[outlen++] = (int16_t) (xout2 >> 12); |
michael@202 | 1034 | + } |
michael@202 | 1035 | + } |
michael@202 | 1036 | + } |
michael@202 | 1037 | + return outlen; |
michael@202 | 1038 | +} |
michael@202 | 1039 | +/*- End of function --------------------------------------------------------*/ |
michael@202 | 1040 | +/*- End of file ------------------------------------------------------------*/ |
michael@202 | 1041 | Index: codecs/g722/g722_encode.c |
michael@202 | 1042 | diff -Nau codecs/g722/g722_encode.c.orig codecs/g722/g722_encode.c |
michael@202 | 1043 | --- codecs/g722/g722_encode.c.orig 1970-01-01 01:00:00.000000000 +0100 |
michael@202 | 1044 | +++ codecs/g722/g722_encode.c 2009-04-24 00:30:33.000000000 +0200 |
michael@202 | 1045 | @@ -0,0 +1,400 @@ |
michael@202 | 1046 | +/* |
michael@202 | 1047 | + * SpanDSP - a series of DSP components for telephony |
michael@202 | 1048 | + * |
michael@202 | 1049 | + * g722_encode.c - The ITU G.722 codec, encode part. |
michael@202 | 1050 | + * |
michael@202 | 1051 | + * Written by Steve Underwood <steveu@coppice.org> |
michael@202 | 1052 | + * |
michael@202 | 1053 | + * Copyright (C) 2005 Steve Underwood |
michael@202 | 1054 | + * |
michael@202 | 1055 | + * All rights reserved. |
michael@202 | 1056 | + * |
michael@202 | 1057 | + * Despite my general liking of the GPL, I place my own contributions |
michael@202 | 1058 | + * to this code in the public domain for the benefit of all mankind - |
michael@202 | 1059 | + * even the slimy ones who might try to proprietize my work and use it |
michael@202 | 1060 | + * to my detriment. |
michael@202 | 1061 | + * |
michael@202 | 1062 | + * Based on a single channel 64kbps only G.722 codec which is: |
michael@202 | 1063 | + * |
michael@202 | 1064 | + ***** Copyright (c) CMU 1993 ***** |
michael@202 | 1065 | + * Computer Science, Speech Group |
michael@202 | 1066 | + * Chengxiang Lu and Alex Hauptmann |
michael@202 | 1067 | + * |
michael@202 | 1068 | + * $Id: g722_encode.c 48661 2006-12-21 00:08:21Z mattf $ |
michael@202 | 1069 | + */ |
michael@202 | 1070 | + |
michael@202 | 1071 | +/*! \file */ |
michael@202 | 1072 | + |
michael@202 | 1073 | +#ifdef HAVE_CONFIG_H |
michael@202 | 1074 | +#include <config.h> |
michael@202 | 1075 | +#endif |
michael@202 | 1076 | + |
michael@202 | 1077 | +#include <stdio.h> |
michael@202 | 1078 | +#include <inttypes.h> |
michael@202 | 1079 | +#include <memory.h> |
michael@202 | 1080 | +#include <stdlib.h> |
michael@202 | 1081 | +#if 0 |
michael@202 | 1082 | +#include <tgmath.h> |
michael@202 | 1083 | +#endif |
michael@202 | 1084 | + |
michael@202 | 1085 | +#include "g722.h" |
michael@202 | 1086 | + |
michael@202 | 1087 | +#if !defined(FALSE) |
michael@202 | 1088 | +#define FALSE 0 |
michael@202 | 1089 | +#endif |
michael@202 | 1090 | +#if !defined(TRUE) |
michael@202 | 1091 | +#define TRUE (!FALSE) |
michael@202 | 1092 | +#endif |
michael@202 | 1093 | + |
michael@202 | 1094 | +static __inline__ int16_t saturate(int32_t amp) |
michael@202 | 1095 | +{ |
michael@202 | 1096 | + int16_t amp16; |
michael@202 | 1097 | + |
michael@202 | 1098 | + /* Hopefully this is optimised for the common case - not clipping */ |
michael@202 | 1099 | + amp16 = (int16_t) amp; |
michael@202 | 1100 | + if (amp == amp16) |
michael@202 | 1101 | + return amp16; |
michael@202 | 1102 | + if (amp > INT16_MAX) |
michael@202 | 1103 | + return INT16_MAX; |
michael@202 | 1104 | + return INT16_MIN; |
michael@202 | 1105 | +} |
michael@202 | 1106 | +/*- End of function --------------------------------------------------------*/ |
michael@202 | 1107 | + |
michael@202 | 1108 | +static void block4(g722_encode_state_t *s, int band, int d) |
michael@202 | 1109 | +{ |
michael@202 | 1110 | + int wd1; |
michael@202 | 1111 | + int wd2; |
michael@202 | 1112 | + int wd3; |
michael@202 | 1113 | + int i; |
michael@202 | 1114 | + |
michael@202 | 1115 | + /* Block 4, RECONS */ |
michael@202 | 1116 | + s->band[band].d[0] = d; |
michael@202 | 1117 | + s->band[band].r[0] = saturate(s->band[band].s + d); |
michael@202 | 1118 | + |
michael@202 | 1119 | + /* Block 4, PARREC */ |
michael@202 | 1120 | + s->band[band].p[0] = saturate(s->band[band].sz + d); |
michael@202 | 1121 | + |
michael@202 | 1122 | + /* Block 4, UPPOL2 */ |
michael@202 | 1123 | + for (i = 0; i < 3; i++) |
michael@202 | 1124 | + s->band[band].sg[i] = s->band[band].p[i] >> 15; |
michael@202 | 1125 | + wd1 = saturate(s->band[band].a[1] << 2); |
michael@202 | 1126 | + |
michael@202 | 1127 | + wd2 = (s->band[band].sg[0] == s->band[band].sg[1]) ? -wd1 : wd1; |
michael@202 | 1128 | + if (wd2 > 32767) |
michael@202 | 1129 | + wd2 = 32767; |
michael@202 | 1130 | + wd3 = (wd2 >> 7) + ((s->band[band].sg[0] == s->band[band].sg[2]) ? 128 : -128); |
michael@202 | 1131 | + wd3 += (s->band[band].a[2]*32512) >> 15; |
michael@202 | 1132 | + if (wd3 > 12288) |
michael@202 | 1133 | + wd3 = 12288; |
michael@202 | 1134 | + else if (wd3 < -12288) |
michael@202 | 1135 | + wd3 = -12288; |
michael@202 | 1136 | + s->band[band].ap[2] = wd3; |
michael@202 | 1137 | + |
michael@202 | 1138 | + /* Block 4, UPPOL1 */ |
michael@202 | 1139 | + s->band[band].sg[0] = s->band[band].p[0] >> 15; |
michael@202 | 1140 | + s->band[band].sg[1] = s->band[band].p[1] >> 15; |
michael@202 | 1141 | + wd1 = (s->band[band].sg[0] == s->band[band].sg[1]) ? 192 : -192; |
michael@202 | 1142 | + wd2 = (s->band[band].a[1]*32640) >> 15; |
michael@202 | 1143 | + |
michael@202 | 1144 | + s->band[band].ap[1] = saturate(wd1 + wd2); |
michael@202 | 1145 | + wd3 = saturate(15360 - s->band[band].ap[2]); |
michael@202 | 1146 | + if (s->band[band].ap[1] > wd3) |
michael@202 | 1147 | + s->band[band].ap[1] = wd3; |
michael@202 | 1148 | + else if (s->band[band].ap[1] < -wd3) |
michael@202 | 1149 | + s->band[band].ap[1] = -wd3; |
michael@202 | 1150 | + |
michael@202 | 1151 | + /* Block 4, UPZERO */ |
michael@202 | 1152 | + wd1 = (d == 0) ? 0 : 128; |
michael@202 | 1153 | + s->band[band].sg[0] = d >> 15; |
michael@202 | 1154 | + for (i = 1; i < 7; i++) |
michael@202 | 1155 | + { |
michael@202 | 1156 | + s->band[band].sg[i] = s->band[band].d[i] >> 15; |
michael@202 | 1157 | + wd2 = (s->band[band].sg[i] == s->band[band].sg[0]) ? wd1 : -wd1; |
michael@202 | 1158 | + wd3 = (s->band[band].b[i]*32640) >> 15; |
michael@202 | 1159 | + s->band[band].bp[i] = saturate(wd2 + wd3); |
michael@202 | 1160 | + } |
michael@202 | 1161 | + |
michael@202 | 1162 | + /* Block 4, DELAYA */ |
michael@202 | 1163 | + for (i = 6; i > 0; i--) |
michael@202 | 1164 | + { |
michael@202 | 1165 | + s->band[band].d[i] = s->band[band].d[i - 1]; |
michael@202 | 1166 | + s->band[band].b[i] = s->band[band].bp[i]; |
michael@202 | 1167 | + } |
michael@202 | 1168 | + |
michael@202 | 1169 | + for (i = 2; i > 0; i--) |
michael@202 | 1170 | + { |
michael@202 | 1171 | + s->band[band].r[i] = s->band[band].r[i - 1]; |
michael@202 | 1172 | + s->band[band].p[i] = s->band[band].p[i - 1]; |
michael@202 | 1173 | + s->band[band].a[i] = s->band[band].ap[i]; |
michael@202 | 1174 | + } |
michael@202 | 1175 | + |
michael@202 | 1176 | + /* Block 4, FILTEP */ |
michael@202 | 1177 | + wd1 = saturate(s->band[band].r[1] + s->band[band].r[1]); |
michael@202 | 1178 | + wd1 = (s->band[band].a[1]*wd1) >> 15; |
michael@202 | 1179 | + wd2 = saturate(s->band[band].r[2] + s->band[band].r[2]); |
michael@202 | 1180 | + wd2 = (s->band[band].a[2]*wd2) >> 15; |
michael@202 | 1181 | + s->band[band].sp = saturate(wd1 + wd2); |
michael@202 | 1182 | + |
michael@202 | 1183 | + /* Block 4, FILTEZ */ |
michael@202 | 1184 | + s->band[band].sz = 0; |
michael@202 | 1185 | + for (i = 6; i > 0; i--) |
michael@202 | 1186 | + { |
michael@202 | 1187 | + wd1 = saturate(s->band[band].d[i] + s->band[band].d[i]); |
michael@202 | 1188 | + s->band[band].sz += (s->band[band].b[i]*wd1) >> 15; |
michael@202 | 1189 | + } |
michael@202 | 1190 | + s->band[band].sz = saturate(s->band[band].sz); |
michael@202 | 1191 | + |
michael@202 | 1192 | + /* Block 4, PREDIC */ |
michael@202 | 1193 | + s->band[band].s = saturate(s->band[band].sp + s->band[band].sz); |
michael@202 | 1194 | +} |
michael@202 | 1195 | +/*- End of function --------------------------------------------------------*/ |
michael@202 | 1196 | + |
michael@202 | 1197 | +g722_encode_state_t *g722_encode_init(g722_encode_state_t *s, int rate, int options) |
michael@202 | 1198 | +{ |
michael@202 | 1199 | + if (s == NULL) |
michael@202 | 1200 | + { |
michael@202 | 1201 | + if ((s = (g722_encode_state_t *) malloc(sizeof(*s))) == NULL) |
michael@202 | 1202 | + return NULL; |
michael@202 | 1203 | + } |
michael@202 | 1204 | + memset(s, 0, sizeof(*s)); |
michael@202 | 1205 | + if (rate == 48000) |
michael@202 | 1206 | + s->bits_per_sample = 6; |
michael@202 | 1207 | + else if (rate == 56000) |
michael@202 | 1208 | + s->bits_per_sample = 7; |
michael@202 | 1209 | + else |
michael@202 | 1210 | + s->bits_per_sample = 8; |
michael@202 | 1211 | + if ((options & G722_SAMPLE_RATE_8000)) |
michael@202 | 1212 | + s->eight_k = TRUE; |
michael@202 | 1213 | + if ((options & G722_PACKED) && s->bits_per_sample != 8) |
michael@202 | 1214 | + s->packed = TRUE; |
michael@202 | 1215 | + else |
michael@202 | 1216 | + s->packed = FALSE; |
michael@202 | 1217 | + s->band[0].det = 32; |
michael@202 | 1218 | + s->band[1].det = 8; |
michael@202 | 1219 | + return s; |
michael@202 | 1220 | +} |
michael@202 | 1221 | +/*- End of function --------------------------------------------------------*/ |
michael@202 | 1222 | + |
michael@202 | 1223 | +int g722_encode_release(g722_encode_state_t *s) |
michael@202 | 1224 | +{ |
michael@202 | 1225 | + free(s); |
michael@202 | 1226 | + return 0; |
michael@202 | 1227 | +} |
michael@202 | 1228 | +/*- End of function --------------------------------------------------------*/ |
michael@202 | 1229 | + |
michael@202 | 1230 | +int g722_encode(g722_encode_state_t *s, uint8_t g722_data[], const int16_t amp[], int len) |
michael@202 | 1231 | +{ |
michael@202 | 1232 | + static const int q6[32] = |
michael@202 | 1233 | + { |
michael@202 | 1234 | + 0, 35, 72, 110, 150, 190, 233, 276, |
michael@202 | 1235 | + 323, 370, 422, 473, 530, 587, 650, 714, |
michael@202 | 1236 | + 786, 858, 940, 1023, 1121, 1219, 1339, 1458, |
michael@202 | 1237 | + 1612, 1765, 1980, 2195, 2557, 2919, 0, 0 |
michael@202 | 1238 | + }; |
michael@202 | 1239 | + static const int iln[32] = |
michael@202 | 1240 | + { |
michael@202 | 1241 | + 0, 63, 62, 31, 30, 29, 28, 27, |
michael@202 | 1242 | + 26, 25, 24, 23, 22, 21, 20, 19, |
michael@202 | 1243 | + 18, 17, 16, 15, 14, 13, 12, 11, |
michael@202 | 1244 | + 10, 9, 8, 7, 6, 5, 4, 0 |
michael@202 | 1245 | + }; |
michael@202 | 1246 | + static const int ilp[32] = |
michael@202 | 1247 | + { |
michael@202 | 1248 | + 0, 61, 60, 59, 58, 57, 56, 55, |
michael@202 | 1249 | + 54, 53, 52, 51, 50, 49, 48, 47, |
michael@202 | 1250 | + 46, 45, 44, 43, 42, 41, 40, 39, |
michael@202 | 1251 | + 38, 37, 36, 35, 34, 33, 32, 0 |
michael@202 | 1252 | + }; |
michael@202 | 1253 | + static const int wl[8] = |
michael@202 | 1254 | + { |
michael@202 | 1255 | + -60, -30, 58, 172, 334, 538, 1198, 3042 |
michael@202 | 1256 | + }; |
michael@202 | 1257 | + static const int rl42[16] = |
michael@202 | 1258 | + { |
michael@202 | 1259 | + 0, 7, 6, 5, 4, 3, 2, 1, 7, 6, 5, 4, 3, 2, 1, 0 |
michael@202 | 1260 | + }; |
michael@202 | 1261 | + static const int ilb[32] = |
michael@202 | 1262 | + { |
michael@202 | 1263 | + 2048, 2093, 2139, 2186, 2233, 2282, 2332, |
michael@202 | 1264 | + 2383, 2435, 2489, 2543, 2599, 2656, 2714, |
michael@202 | 1265 | + 2774, 2834, 2896, 2960, 3025, 3091, 3158, |
michael@202 | 1266 | + 3228, 3298, 3371, 3444, 3520, 3597, 3676, |
michael@202 | 1267 | + 3756, 3838, 3922, 4008 |
michael@202 | 1268 | + }; |
michael@202 | 1269 | + static const int qm4[16] = |
michael@202 | 1270 | + { |
michael@202 | 1271 | + 0, -20456, -12896, -8968, |
michael@202 | 1272 | + -6288, -4240, -2584, -1200, |
michael@202 | 1273 | + 20456, 12896, 8968, 6288, |
michael@202 | 1274 | + 4240, 2584, 1200, 0 |
michael@202 | 1275 | + }; |
michael@202 | 1276 | + static const int qm2[4] = |
michael@202 | 1277 | + { |
michael@202 | 1278 | + -7408, -1616, 7408, 1616 |
michael@202 | 1279 | + }; |
michael@202 | 1280 | + static const int qmf_coeffs[12] = |
michael@202 | 1281 | + { |
michael@202 | 1282 | + 3, -11, 12, 32, -210, 951, 3876, -805, 362, -156, 53, -11, |
michael@202 | 1283 | + }; |
michael@202 | 1284 | + static const int ihn[3] = {0, 1, 0}; |
michael@202 | 1285 | + static const int ihp[3] = {0, 3, 2}; |
michael@202 | 1286 | + static const int wh[3] = {0, -214, 798}; |
michael@202 | 1287 | + static const int rh2[4] = {2, 1, 2, 1}; |
michael@202 | 1288 | + |
michael@202 | 1289 | + int dlow; |
michael@202 | 1290 | + int dhigh; |
michael@202 | 1291 | + int el; |
michael@202 | 1292 | + int wd; |
michael@202 | 1293 | + int wd1; |
michael@202 | 1294 | + int ril; |
michael@202 | 1295 | + int wd2; |
michael@202 | 1296 | + int il4; |
michael@202 | 1297 | + int ih2; |
michael@202 | 1298 | + int wd3; |
michael@202 | 1299 | + int eh; |
michael@202 | 1300 | + int mih; |
michael@202 | 1301 | + int i; |
michael@202 | 1302 | + int j; |
michael@202 | 1303 | + /* Low and high band PCM from the QMF */ |
michael@202 | 1304 | + int xlow; |
michael@202 | 1305 | + int xhigh; |
michael@202 | 1306 | + int g722_bytes; |
michael@202 | 1307 | + /* Even and odd tap accumulators */ |
michael@202 | 1308 | + int sumeven; |
michael@202 | 1309 | + int sumodd; |
michael@202 | 1310 | + int ihigh; |
michael@202 | 1311 | + int ilow; |
michael@202 | 1312 | + int code; |
michael@202 | 1313 | + |
michael@202 | 1314 | + g722_bytes = 0; |
michael@202 | 1315 | + xhigh = 0; |
michael@202 | 1316 | + for (j = 0; j < len; ) |
michael@202 | 1317 | + { |
michael@202 | 1318 | + if (s->itu_test_mode) |
michael@202 | 1319 | + { |
michael@202 | 1320 | + xlow = |
michael@202 | 1321 | + xhigh = amp[j++] >> 1; |
michael@202 | 1322 | + } |
michael@202 | 1323 | + else |
michael@202 | 1324 | + { |
michael@202 | 1325 | + if (s->eight_k) |
michael@202 | 1326 | + { |
michael@202 | 1327 | + xlow = amp[j++]; |
michael@202 | 1328 | + } |
michael@202 | 1329 | + else |
michael@202 | 1330 | + { |
michael@202 | 1331 | + /* Apply the transmit QMF */ |
michael@202 | 1332 | + /* Shuffle the buffer down */ |
michael@202 | 1333 | + for (i = 0; i < 22; i++) |
michael@202 | 1334 | + s->x[i] = s->x[i + 2]; |
michael@202 | 1335 | + s->x[22] = amp[j++]; |
michael@202 | 1336 | + s->x[23] = amp[j++]; |
michael@202 | 1337 | + |
michael@202 | 1338 | + /* Discard every other QMF output */ |
michael@202 | 1339 | + sumeven = 0; |
michael@202 | 1340 | + sumodd = 0; |
michael@202 | 1341 | + for (i = 0; i < 12; i++) |
michael@202 | 1342 | + { |
michael@202 | 1343 | + sumodd += s->x[2*i]*qmf_coeffs[i]; |
michael@202 | 1344 | + sumeven += s->x[2*i + 1]*qmf_coeffs[11 - i]; |
michael@202 | 1345 | + } |
michael@202 | 1346 | + xlow = (sumeven + sumodd) >> 13; |
michael@202 | 1347 | + xhigh = (sumeven - sumodd) >> 13; |
michael@202 | 1348 | + } |
michael@202 | 1349 | + } |
michael@202 | 1350 | + /* Block 1L, SUBTRA */ |
michael@202 | 1351 | + el = saturate(xlow - s->band[0].s); |
michael@202 | 1352 | + |
michael@202 | 1353 | + /* Block 1L, QUANTL */ |
michael@202 | 1354 | + wd = (el >= 0) ? el : -(el + 1); |
michael@202 | 1355 | + |
michael@202 | 1356 | + for (i = 1; i < 30; i++) |
michael@202 | 1357 | + { |
michael@202 | 1358 | + wd1 = (q6[i]*s->band[0].det) >> 12; |
michael@202 | 1359 | + if (wd < wd1) |
michael@202 | 1360 | + break; |
michael@202 | 1361 | + } |
michael@202 | 1362 | + ilow = (el < 0) ? iln[i] : ilp[i]; |
michael@202 | 1363 | + |
michael@202 | 1364 | + /* Block 2L, INVQAL */ |
michael@202 | 1365 | + ril = ilow >> 2; |
michael@202 | 1366 | + wd2 = qm4[ril]; |
michael@202 | 1367 | + dlow = (s->band[0].det*wd2) >> 15; |
michael@202 | 1368 | + |
michael@202 | 1369 | + /* Block 3L, LOGSCL */ |
michael@202 | 1370 | + il4 = rl42[ril]; |
michael@202 | 1371 | + wd = (s->band[0].nb*127) >> 7; |
michael@202 | 1372 | + s->band[0].nb = wd + wl[il4]; |
michael@202 | 1373 | + if (s->band[0].nb < 0) |
michael@202 | 1374 | + s->band[0].nb = 0; |
michael@202 | 1375 | + else if (s->band[0].nb > 18432) |
michael@202 | 1376 | + s->band[0].nb = 18432; |
michael@202 | 1377 | + |
michael@202 | 1378 | + /* Block 3L, SCALEL */ |
michael@202 | 1379 | + wd1 = (s->band[0].nb >> 6) & 31; |
michael@202 | 1380 | + wd2 = 8 - (s->band[0].nb >> 11); |
michael@202 | 1381 | + wd3 = (wd2 < 0) ? (ilb[wd1] << -wd2) : (ilb[wd1] >> wd2); |
michael@202 | 1382 | + s->band[0].det = wd3 << 2; |
michael@202 | 1383 | + |
michael@202 | 1384 | + block4(s, 0, dlow); |
michael@202 | 1385 | + |
michael@202 | 1386 | + if (s->eight_k) |
michael@202 | 1387 | + { |
michael@202 | 1388 | + /* Just leave the high bits as zero */ |
michael@202 | 1389 | + code = (0xC0 | ilow) >> (8 - s->bits_per_sample); |
michael@202 | 1390 | + } |
michael@202 | 1391 | + else |
michael@202 | 1392 | + { |
michael@202 | 1393 | + /* Block 1H, SUBTRA */ |
michael@202 | 1394 | + eh = saturate(xhigh - s->band[1].s); |
michael@202 | 1395 | + |
michael@202 | 1396 | + /* Block 1H, QUANTH */ |
michael@202 | 1397 | + wd = (eh >= 0) ? eh : -(eh + 1); |
michael@202 | 1398 | + wd1 = (564*s->band[1].det) >> 12; |
michael@202 | 1399 | + mih = (wd >= wd1) ? 2 : 1; |
michael@202 | 1400 | + ihigh = (eh < 0) ? ihn[mih] : ihp[mih]; |
michael@202 | 1401 | + |
michael@202 | 1402 | + /* Block 2H, INVQAH */ |
michael@202 | 1403 | + wd2 = qm2[ihigh]; |
michael@202 | 1404 | + dhigh = (s->band[1].det*wd2) >> 15; |
michael@202 | 1405 | + |
michael@202 | 1406 | + /* Block 3H, LOGSCH */ |
michael@202 | 1407 | + ih2 = rh2[ihigh]; |
michael@202 | 1408 | + wd = (s->band[1].nb*127) >> 7; |
michael@202 | 1409 | + s->band[1].nb = wd + wh[ih2]; |
michael@202 | 1410 | + if (s->band[1].nb < 0) |
michael@202 | 1411 | + s->band[1].nb = 0; |
michael@202 | 1412 | + else if (s->band[1].nb > 22528) |
michael@202 | 1413 | + s->band[1].nb = 22528; |
michael@202 | 1414 | + |
michael@202 | 1415 | + /* Block 3H, SCALEH */ |
michael@202 | 1416 | + wd1 = (s->band[1].nb >> 6) & 31; |
michael@202 | 1417 | + wd2 = 10 - (s->band[1].nb >> 11); |
michael@202 | 1418 | + wd3 = (wd2 < 0) ? (ilb[wd1] << -wd2) : (ilb[wd1] >> wd2); |
michael@202 | 1419 | + s->band[1].det = wd3 << 2; |
michael@202 | 1420 | + |
michael@202 | 1421 | + block4(s, 1, dhigh); |
michael@202 | 1422 | + code = ((ihigh << 6) | ilow) >> (8 - s->bits_per_sample); |
michael@202 | 1423 | + } |
michael@202 | 1424 | + |
michael@202 | 1425 | + if (s->packed) |
michael@202 | 1426 | + { |
michael@202 | 1427 | + /* Pack the code bits */ |
michael@202 | 1428 | + s->out_buffer |= (code << s->out_bits); |
michael@202 | 1429 | + s->out_bits += s->bits_per_sample; |
michael@202 | 1430 | + if (s->out_bits >= 8) |
michael@202 | 1431 | + { |
michael@202 | 1432 | + g722_data[g722_bytes++] = (uint8_t) (s->out_buffer & 0xFF); |
michael@202 | 1433 | + s->out_bits -= 8; |
michael@202 | 1434 | + s->out_buffer >>= 8; |
michael@202 | 1435 | + } |
michael@202 | 1436 | + } |
michael@202 | 1437 | + else |
michael@202 | 1438 | + { |
michael@202 | 1439 | + g722_data[g722_bytes++] = (uint8_t) code; |
michael@202 | 1440 | + } |
michael@202 | 1441 | + } |
michael@202 | 1442 | + return g722_bytes; |
michael@202 | 1443 | +} |
michael@202 | 1444 | +/*- End of function --------------------------------------------------------*/ |
michael@202 | 1445 | +/*- End of file ------------------------------------------------------------*/ |
michael@202 | 1446 | Index: codecs/g722/g722.h |
michael@202 | 1447 | diff -Nau codecs/g722/g722.h.orig codecs/g722/g722.h |
michael@202 | 1448 | --- codecs/g722/g722.h.orig 1970-01-01 01:00:00.000000000 +0100 |
michael@202 | 1449 | +++ codecs/g722/g722.h 2009-04-24 00:30:33.000000000 +0200 |
michael@202 | 1450 | @@ -0,0 +1,148 @@ |
michael@202 | 1451 | +/* |
michael@202 | 1452 | + * SpanDSP - a series of DSP components for telephony |
michael@202 | 1453 | + * |
michael@202 | 1454 | + * g722.h - The ITU G.722 codec. |
michael@202 | 1455 | + * |
michael@202 | 1456 | + * Written by Steve Underwood <steveu@coppice.org> |
michael@202 | 1457 | + * |
michael@202 | 1458 | + * Copyright (C) 2005 Steve Underwood |
michael@202 | 1459 | + * |
michael@202 | 1460 | + * Despite my general liking of the GPL, I place my own contributions |
michael@202 | 1461 | + * to this code in the public domain for the benefit of all mankind - |
michael@202 | 1462 | + * even the slimy ones who might try to proprietize my work and use it |
michael@202 | 1463 | + * to my detriment. |
michael@202 | 1464 | + * |
michael@202 | 1465 | + * Based on a single channel G.722 codec which is: |
michael@202 | 1466 | + * |
michael@202 | 1467 | + ***** Copyright (c) CMU 1993 ***** |
michael@202 | 1468 | + * Computer Science, Speech Group |
michael@202 | 1469 | + * Chengxiang Lu and Alex Hauptmann |
michael@202 | 1470 | + * |
michael@202 | 1471 | + * $Id: g722.h 48959 2006-12-25 06:42:15Z rizzo $ |
michael@202 | 1472 | + */ |
michael@202 | 1473 | + |
michael@202 | 1474 | + |
michael@202 | 1475 | +/*! \file */ |
michael@202 | 1476 | + |
michael@202 | 1477 | +#if !defined(_G722_H_) |
michael@202 | 1478 | +#define _G722_H_ |
michael@202 | 1479 | + |
michael@202 | 1480 | +/*! \page g722_page G.722 encoding and decoding |
michael@202 | 1481 | +\section g722_page_sec_1 What does it do? |
michael@202 | 1482 | +The G.722 module is a bit exact implementation of the ITU G.722 specification for all three |
michael@202 | 1483 | +specified bit rates - 64000bps, 56000bps and 48000bps. It passes the ITU tests. |
michael@202 | 1484 | + |
michael@202 | 1485 | +To allow fast and flexible interworking with narrow band telephony, the encoder and decoder |
michael@202 | 1486 | +support an option for the linear audio to be an 8k samples/second stream. In this mode the |
michael@202 | 1487 | +codec is considerably faster, and still fully compatible with wideband terminals using G.722. |
michael@202 | 1488 | + |
michael@202 | 1489 | +\section g722_page_sec_2 How does it work? |
michael@202 | 1490 | +???. |
michael@202 | 1491 | +*/ |
michael@202 | 1492 | + |
michael@202 | 1493 | +enum |
michael@202 | 1494 | +{ |
michael@202 | 1495 | + G722_SAMPLE_RATE_8000 = 0x0001, |
michael@202 | 1496 | + G722_PACKED = 0x0002 |
michael@202 | 1497 | +}; |
michael@202 | 1498 | + |
michael@202 | 1499 | +#ifndef INT16_MAX |
michael@202 | 1500 | +#define INT16_MAX 32767 |
michael@202 | 1501 | +#endif |
michael@202 | 1502 | +#ifndef INT16_MIN |
michael@202 | 1503 | +#define INT16_MIN (-32768) |
michael@202 | 1504 | +#endif |
michael@202 | 1505 | + |
michael@202 | 1506 | +typedef struct |
michael@202 | 1507 | +{ |
michael@202 | 1508 | + /*! TRUE if the operating in the special ITU test mode, with the band split filters |
michael@202 | 1509 | + disabled. */ |
michael@202 | 1510 | + int itu_test_mode; |
michael@202 | 1511 | + /*! TRUE if the G.722 data is packed */ |
michael@202 | 1512 | + int packed; |
michael@202 | 1513 | + /*! TRUE if encode from 8k samples/second */ |
michael@202 | 1514 | + int eight_k; |
michael@202 | 1515 | + /*! 6 for 48000kbps, 7 for 56000kbps, or 8 for 64000kbps. */ |
michael@202 | 1516 | + int bits_per_sample; |
michael@202 | 1517 | + |
michael@202 | 1518 | + /*! Signal history for the QMF */ |
michael@202 | 1519 | + int x[24]; |
michael@202 | 1520 | + |
michael@202 | 1521 | + struct |
michael@202 | 1522 | + { |
michael@202 | 1523 | + int s; |
michael@202 | 1524 | + int sp; |
michael@202 | 1525 | + int sz; |
michael@202 | 1526 | + int r[3]; |
michael@202 | 1527 | + int a[3]; |
michael@202 | 1528 | + int ap[3]; |
michael@202 | 1529 | + int p[3]; |
michael@202 | 1530 | + int d[7]; |
michael@202 | 1531 | + int b[7]; |
michael@202 | 1532 | + int bp[7]; |
michael@202 | 1533 | + int sg[7]; |
michael@202 | 1534 | + int nb; |
michael@202 | 1535 | + int det; |
michael@202 | 1536 | + } band[2]; |
michael@202 | 1537 | + |
michael@202 | 1538 | + unsigned int in_buffer; |
michael@202 | 1539 | + int in_bits; |
michael@202 | 1540 | + unsigned int out_buffer; |
michael@202 | 1541 | + int out_bits; |
michael@202 | 1542 | +} g722_encode_state_t; |
michael@202 | 1543 | + |
michael@202 | 1544 | +typedef struct |
michael@202 | 1545 | +{ |
michael@202 | 1546 | + /*! TRUE if the operating in the special ITU test mode, with the band split filters |
michael@202 | 1547 | + disabled. */ |
michael@202 | 1548 | + int itu_test_mode; |
michael@202 | 1549 | + /*! TRUE if the G.722 data is packed */ |
michael@202 | 1550 | + int packed; |
michael@202 | 1551 | + /*! TRUE if decode to 8k samples/second */ |
michael@202 | 1552 | + int eight_k; |
michael@202 | 1553 | + /*! 6 for 48000kbps, 7 for 56000kbps, or 8 for 64000kbps. */ |
michael@202 | 1554 | + int bits_per_sample; |
michael@202 | 1555 | + |
michael@202 | 1556 | + /*! Signal history for the QMF */ |
michael@202 | 1557 | + int x[24]; |
michael@202 | 1558 | + |
michael@202 | 1559 | + struct |
michael@202 | 1560 | + { |
michael@202 | 1561 | + int s; |
michael@202 | 1562 | + int sp; |
michael@202 | 1563 | + int sz; |
michael@202 | 1564 | + int r[3]; |
michael@202 | 1565 | + int a[3]; |
michael@202 | 1566 | + int ap[3]; |
michael@202 | 1567 | + int p[3]; |
michael@202 | 1568 | + int d[7]; |
michael@202 | 1569 | + int b[7]; |
michael@202 | 1570 | + int bp[7]; |
michael@202 | 1571 | + int sg[7]; |
michael@202 | 1572 | + int nb; |
michael@202 | 1573 | + int det; |
michael@202 | 1574 | + } band[2]; |
michael@202 | 1575 | + |
michael@202 | 1576 | + unsigned int in_buffer; |
michael@202 | 1577 | + int in_bits; |
michael@202 | 1578 | + unsigned int out_buffer; |
michael@202 | 1579 | + int out_bits; |
michael@202 | 1580 | +} g722_decode_state_t; |
michael@202 | 1581 | + |
michael@202 | 1582 | +#ifdef __cplusplus |
michael@202 | 1583 | +extern "C" { |
michael@202 | 1584 | +#endif |
michael@202 | 1585 | + |
michael@202 | 1586 | +g722_encode_state_t *g722_encode_init(g722_encode_state_t *s, int rate, int options); |
michael@202 | 1587 | +int g722_encode_release(g722_encode_state_t *s); |
michael@202 | 1588 | +int g722_encode(g722_encode_state_t *s, uint8_t g722_data[], const int16_t amp[], int len); |
michael@202 | 1589 | + |
michael@202 | 1590 | +g722_decode_state_t *g722_decode_init(g722_decode_state_t *s, int rate, int options); |
michael@202 | 1591 | +int g722_decode_release(g722_decode_state_t *s); |
michael@202 | 1592 | +int g722_decode(g722_decode_state_t *s, int16_t amp[], const uint8_t g722_data[], int len); |
michael@202 | 1593 | + |
michael@202 | 1594 | +#ifdef __cplusplus |
michael@202 | 1595 | +} |
michael@202 | 1596 | +#endif |
michael@202 | 1597 | + |
michael@202 | 1598 | +#endif |
michael@202 | 1599 | Index: codecs/g722/Makefile |
michael@202 | 1600 | diff -Nau codecs/g722/Makefile.orig codecs/g722/Makefile |
michael@202 | 1601 | --- codecs/g722/Makefile.orig 1970-01-01 01:00:00.000000000 +0100 |
michael@202 | 1602 | +++ codecs/g722/Makefile 2009-04-24 00:30:33.000000000 +0200 |
michael@202 | 1603 | @@ -0,0 +1,18 @@ |
michael@202 | 1604 | +LIB=libg722.a |
michael@202 | 1605 | +CFLAGS+=-fPIC |
michael@202 | 1606 | + |
michael@202 | 1607 | +include $(ASTTOPDIR)/Makefile.rules |
michael@202 | 1608 | + |
michael@202 | 1609 | +OBJS=g722_encode.o g722_decode.o |
michael@202 | 1610 | + |
michael@202 | 1611 | +all: $(LIB) |
michael@202 | 1612 | + |
michael@202 | 1613 | +$(LIB): $(OBJS) |
michael@202 | 1614 | + $(ECHO_PREFIX) echo " [AR] $^ -> $@" |
michael@202 | 1615 | + $(CMD_PREFIX) $(AR) cr $@ $^ |
michael@202 | 1616 | + $(CMD_PREFIX) $(RANLIB) $@ |
michael@202 | 1617 | + |
michael@202 | 1618 | +clean: |
michael@202 | 1619 | + rm -f $(LIB) *.o |
michael@202 | 1620 | + rm -f .*.o.d |
michael@202 | 1621 | + rm -f *.s *.i |
michael@202 | 1622 | Index: codecs/g722_slin_ex.h |
michael@202 | 1623 | diff -Nau codecs/g722_slin_ex.h.orig codecs/g722_slin_ex.h |
michael@202 | 1624 | --- codecs/g722_slin_ex.h.orig 1970-01-01 01:00:00.000000000 +0100 |
michael@202 | 1625 | +++ codecs/g722_slin_ex.h 2009-04-24 00:30:33.000000000 +0200 |
michael@202 | 1626 | @@ -0,0 +1,25 @@ |
michael@202 | 1627 | +/*! \file |
michael@202 | 1628 | + * \brief g722_slin_ex.h -- |
michael@202 | 1629 | + * |
michael@202 | 1630 | + * 4-bit ADPCM data, 20 milliseconds worth at 8 kHz. |
michael@202 | 1631 | + * |
michael@202 | 1632 | + * Source: g723.example |
michael@202 | 1633 | + * |
michael@202 | 1634 | + * Copyright (C) 2001-2005, Digium Inc. |
michael@202 | 1635 | + * |
michael@202 | 1636 | + * Distributed under the terms of the GNU General Public License |
michael@202 | 1637 | + * |
michael@202 | 1638 | + */ |
michael@202 | 1639 | + |
michael@202 | 1640 | +static unsigned char g722_slin_ex[] = { |
michael@202 | 1641 | + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
michael@202 | 1642 | + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
michael@202 | 1643 | + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
michael@202 | 1644 | + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
michael@202 | 1645 | + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
michael@202 | 1646 | + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
michael@202 | 1647 | + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
michael@202 | 1648 | + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
michael@202 | 1649 | + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
michael@202 | 1650 | + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
michael@202 | 1651 | +}; |
michael@202 | 1652 | Index: codecs/Makefile |
michael@202 | 1653 | diff -Nau codecs/Makefile.orig codecs/Makefile |
michael@202 | 1654 | --- codecs/Makefile.orig 2008-03-26 17:42:35.000000000 +0100 |
michael@202 | 1655 | +++ codecs/Makefile 2009-04-24 00:30:33.000000000 +0200 |
michael@202 | 1656 | @@ -31,6 +31,7 @@ |
michael@202 | 1657 | |
michael@202 | 1658 | LIBILBC:=ilbc/libilbc.a |
michael@202 | 1659 | LIBLPC10:=lpc10/liblpc10.a |
michael@202 | 1660 | +LIBG722:=g722/libg722.a |
michael@202 | 1661 | |
michael@202 | 1662 | all: _all |
michael@202 | 1663 | |
michael@202 | 1664 | @@ -45,6 +46,7 @@ |
michael@202 | 1665 | $(MAKE) -C gsm clean |
michael@202 | 1666 | $(MAKE) -C lpc10 clean |
michael@202 | 1667 | $(MAKE) -C ilbc clean |
michael@202 | 1668 | + $(MAKE) -C g722 clean |
michael@202 | 1669 | |
michael@202 | 1670 | gsm/lib/libgsm.a: |
michael@202 | 1671 | @mkdir -p gsm/lib |
michael@202 | 1672 | @@ -59,3 +61,8 @@ |
michael@202 | 1673 | @$(MAKE) -C ilbc all ASTCFLAGS="$(filter-out -Wmissing-prototypes -Wmissing-declarations,$(ASTCFLAGS)) $(AST_NO_STRICT_OVERFLOW)" |
michael@202 | 1674 | |
michael@202 | 1675 | $(if $(filter codec_ilbc,$(EMBEDDED_MODS)),modules.link,codec_ilbc.so): $(LIBILBC) |
michael@202 | 1676 | + |
michael@202 | 1677 | +$(LIBG722): |
michael@202 | 1678 | + @$(MAKE) -C g722 all |
michael@202 | 1679 | + |
michael@202 | 1680 | +$(if $(filter codec_g722,$(EMBEDDED_MODS)),modules.link,codec_g722.so): $(LIBG722) |
michael@202 | 1681 | Index: codecs/slin_g722_ex.h |
michael@202 | 1682 | diff -Nau codecs/slin_g722_ex.h.orig codecs/slin_g722_ex.h |
michael@202 | 1683 | --- codecs/slin_g722_ex.h.orig 1970-01-01 01:00:00.000000000 +0100 |
michael@202 | 1684 | +++ codecs/slin_g722_ex.h 2009-04-24 00:30:33.000000000 +0200 |
michael@202 | 1685 | @@ -0,0 +1,25 @@ |
michael@202 | 1686 | +/*! \file |
michael@202 | 1687 | + * \brief slin_g722_ex.h -- |
michael@202 | 1688 | + * |
michael@202 | 1689 | + * Signed 16-bit audio data, 10 milliseconds worth at 8 kHz. |
michael@202 | 1690 | + * |
michael@202 | 1691 | + * Source: g723.example |
michael@202 | 1692 | + * |
michael@202 | 1693 | + * Copyright (C) 2001-2005, Digium Inc. |
michael@202 | 1694 | + * |
michael@202 | 1695 | + * Distributed under the terms of the GNU General Public License |
michael@202 | 1696 | + * |
michael@202 | 1697 | + */ |
michael@202 | 1698 | + |
michael@202 | 1699 | +static signed short slin_g722_ex[] = { |
michael@202 | 1700 | + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
michael@202 | 1701 | + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
michael@202 | 1702 | + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
michael@202 | 1703 | + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
michael@202 | 1704 | + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
michael@202 | 1705 | + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
michael@202 | 1706 | + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
michael@202 | 1707 | + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
michael@202 | 1708 | + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
michael@202 | 1709 | + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 |
michael@202 | 1710 | +}; |
michael@202 | 1711 | Index: configure |
michael@202 | 1712 | diff -Nau configure.orig configure |
michael@202 | 1713 | --- configure.orig 2009-02-18 21:06:45.000000000 +0100 |
michael@202 | 1714 | +++ configure 2009-04-24 00:30:33.000000000 +0200 |
michael@202 | 1715 | @@ -11143,6 +11143,61 @@ |
michael@202 | 1716 | |
michael@202 | 1717 | fi |
michael@202 | 1718 | |
michael@202 | 1719 | +{ echo "$as_me:$LINENO: checking for tm_gmtoff in struct tm" >&5 |
michael@202 | 1720 | +echo $ECHO_N "checking for tm_gmtoff in struct tm... $ECHO_C" >&6; } |
michael@202 | 1721 | +if test "${ac_cv_struct_tm_gmtoff+set}" = set; then |
michael@202 | 1722 | + echo $ECHO_N "(cached) $ECHO_C" >&6 |
michael@202 | 1723 | +else |
michael@202 | 1724 | + cat >conftest.$ac_ext <<_ACEOF |
michael@202 | 1725 | +/* confdefs.h. */ |
michael@202 | 1726 | +_ACEOF |
michael@202 | 1727 | +cat confdefs.h >>conftest.$ac_ext |
michael@202 | 1728 | +cat >>conftest.$ac_ext <<_ACEOF |
michael@202 | 1729 | +/* end confdefs.h. */ |
michael@202 | 1730 | +$ac_includes_default |
michael@202 | 1731 | +#include <sys/types.h> |
michael@202 | 1732 | +#include <$ac_cv_struct_tm> |
michael@202 | 1733 | +int main() { |
michael@202 | 1734 | +struct tm tm; tm.tm_gmtoff; |
michael@202 | 1735 | +; return 0; } |
michael@202 | 1736 | +_ACEOF |
michael@202 | 1737 | +rm -f conftest.$ac_objext |
michael@202 | 1738 | +if { (ac_try="$ac_compile" |
michael@202 | 1739 | +case "(($ac_try" in |
michael@202 | 1740 | + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; |
michael@202 | 1741 | + *) ac_try_echo=$ac_try;; |
michael@202 | 1742 | +esac |
michael@202 | 1743 | +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 |
michael@202 | 1744 | + (eval "$ac_compile") 2>conftest.er1 |
michael@202 | 1745 | + ac_status=$? |
michael@202 | 1746 | + grep -v '^ *+' conftest.er1 >conftest.err |
michael@202 | 1747 | + rm -f conftest.er1 |
michael@202 | 1748 | + cat conftest.err >&5 |
michael@202 | 1749 | + echo "$as_me:$LINENO: \$? = $ac_status" >&5 |
michael@202 | 1750 | + (exit $ac_status); } && { |
michael@202 | 1751 | + test -z "$ac_c_werror_flag" || |
michael@202 | 1752 | + test ! -s conftest.err |
michael@202 | 1753 | + } && test -s conftest.$ac_objext; then |
michael@202 | 1754 | + ac_cv_struct_tm_gmtoff=yes |
michael@202 | 1755 | +else |
michael@202 | 1756 | + echo "$as_me: failed program was:" >&5 |
michael@202 | 1757 | +sed 's/^/| /' conftest.$ac_ext >&5 |
michael@202 | 1758 | + |
michael@202 | 1759 | + ac_cv_struct_tm_gmtoff=no |
michael@202 | 1760 | +fi |
michael@202 | 1761 | + |
michael@202 | 1762 | +rm -f conftest* |
michael@202 | 1763 | +fi |
michael@202 | 1764 | +{ echo "$as_me:$LINENO: result: $ac_cv_struct_tm_gmtoff" >&5 |
michael@202 | 1765 | +echo "${ECHO_T}$ac_cv_struct_tm_gmtoff" >&6; } |
michael@202 | 1766 | +if test $ac_cv_struct_tm_gmtoff = yes; then |
michael@202 | 1767 | + |
michael@202 | 1768 | +cat >>confdefs.h <<\_ACEOF |
michael@202 | 1769 | +#define TM_GMTOFF 1 |
michael@202 | 1770 | +_ACEOF |
michael@202 | 1771 | + |
michael@202 | 1772 | +fi |
michael@202 | 1773 | + |
michael@202 | 1774 | { echo "$as_me:$LINENO: checking for working volatile" >&5 |
michael@202 | 1775 | echo $ECHO_N "checking for working volatile... $ECHO_C" >&6; } |
michael@202 | 1776 | if test "${ac_cv_c_volatile+set}" = set; then |
michael@202 | 1777 | Index: include/asterisk/config.h |
michael@202 | 1778 | diff -Nau include/asterisk/config.h.orig include/asterisk/config.h |
michael@202 | 1779 | --- include/asterisk/config.h.orig 2009-02-18 19:30:38.000000000 +0100 |
michael@202 | 1780 | +++ include/asterisk/config.h 2009-04-24 00:30:33.000000000 +0200 |
michael@202 | 1781 | @@ -33,6 +33,8 @@ |
michael@202 | 1782 | |
michael@202 | 1783 | struct ast_category; |
michael@202 | 1784 | |
michael@202 | 1785 | +#define CONFIG_STATUS_FILEUNCHANGED (void *)-1 |
michael@202 | 1786 | + |
michael@202 | 1787 | struct ast_variable { |
michael@202 | 1788 | char *name; |
michael@202 | 1789 | char *value; |
michael@202 | 1790 | Index: include/asterisk/frame.h |
michael@202 | 1791 | diff -Nau include/asterisk/frame.h.orig include/asterisk/frame.h |
michael@202 | 1792 | --- include/asterisk/frame.h.orig 2009-03-05 19:22:16.000000000 +0100 |
michael@202 | 1793 | +++ include/asterisk/frame.h 2009-04-24 00:30:33.000000000 +0200 |
michael@202 | 1794 | @@ -260,6 +260,8 @@ |
michael@202 | 1795 | #define AST_FORMAT_G726 (1 << 11) |
michael@202 | 1796 | /*! G.722 */ |
michael@202 | 1797 | #define AST_FORMAT_G722 (1 << 12) |
michael@202 | 1798 | +/*! Raw 16-bit Signed Linear (16000 Hz) PCM */ |
michael@202 | 1799 | +#define AST_FORMAT_SLINEAR16 (1 << 15) |
michael@202 | 1800 | /*! Unsupported audio bits */ |
michael@202 | 1801 | #define AST_FORMAT_AUDIO_UNDEFINED ((1 << 13) | (1 << 14) | (1 << 15)) |
michael@202 | 1802 | /*! Maximum audio format */ |
michael@202 | 1803 | Index: main/editline/np/vis.h |
michael@202 | 1804 | diff -Nau main/editline/np/vis.h.orig main/editline/np/vis.h |
michael@202 | 1805 | --- main/editline/np/vis.h.orig 2006-08-21 04:11:39.000000000 +0200 |
michael@202 | 1806 | +++ main/editline/np/vis.h 2009-04-24 00:30:33.000000000 +0200 |
michael@202 | 1807 | @@ -76,6 +76,22 @@ |
michael@202 | 1808 | |
michael@202 | 1809 | #include <sys/cdefs.h> |
michael@202 | 1810 | |
michael@202 | 1811 | +/* correct nonportable unsigned type usage */ |
michael@202 | 1812 | +#if !defined(__FreeBSD__) && !defined(__linux__) |
michael@202 | 1813 | +#ifndef u_int64_t |
michael@202 | 1814 | +#define u_int64_t unsigned long long |
michael@202 | 1815 | +#endif |
michael@202 | 1816 | +#ifndef u_int32_t |
michael@202 | 1817 | +#define u_int32_t unsigned int |
michael@202 | 1818 | +#endif |
michael@202 | 1819 | +#ifndef u_int16_t |
michael@202 | 1820 | +#define u_int16_t unsigned short |
michael@202 | 1821 | +#endif |
michael@202 | 1822 | +#ifndef u_int6_t |
michael@202 | 1823 | +#define u_int8_t unsigned char |
michael@202 | 1824 | +#endif |
michael@202 | 1825 | +#endif |
michael@202 | 1826 | + |
michael@202 | 1827 | __BEGIN_DECLS |
michael@202 | 1828 | char *vis __P((char *, int, int, int)); |
michael@202 | 1829 | char *svis __P((char *, int, int, int, const char *)); |
michael@202 | 1830 | Index: main/stdtime/localtime.c |
michael@202 | 1831 | diff -Nau main/stdtime/localtime.c.orig main/stdtime/localtime.c |
michael@202 | 1832 | --- main/stdtime/localtime.c.orig 2008-09-27 17:00:48.000000000 +0200 |
michael@202 | 1833 | +++ main/stdtime/localtime.c 2009-04-24 00:30:33.000000000 +0200 |
michael@202 | 1834 | @@ -1134,9 +1134,9 @@ |
michael@202 | 1835 | */ |
michael@202 | 1836 | result = timesub(&t, ttisp->tt_gmtoff, sp, tmp); |
michael@202 | 1837 | tmp->tm_isdst = ttisp->tt_isdst; |
michael@202 | 1838 | -#ifndef SOLARIS /* Solaris doesn't have this element */ |
michael@202 | 1839 | +#ifdef TM_GMTOFF |
michael@202 | 1840 | tmp->tm_gmtoff = ttisp->tt_gmtoff; |
michael@202 | 1841 | -#endif |
michael@202 | 1842 | +#endif /* defined TM_GMTOFF */ |
michael@202 | 1843 | #ifdef TM_ZONE |
michael@202 | 1844 | tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind]; |
michael@202 | 1845 | #endif /* defined TM_ZONE */ |
michael@202 | 1846 | Index: Makefile.moddir_rules |
michael@202 | 1847 | diff -Nau Makefile.moddir_rules.orig Makefile.moddir_rules |
michael@202 | 1848 | --- Makefile.moddir_rules.orig 2008-11-26 19:36:24.000000000 +0100 |
michael@202 | 1849 | +++ Makefile.moddir_rules 2009-04-24 00:30:33.000000000 +0200 |
michael@202 | 1850 | @@ -69,7 +69,9 @@ |
michael@202 | 1851 | rm -f modules.link |
michael@202 | 1852 | |
michael@202 | 1853 | install:: all |
michael@202 | 1854 | +ifneq ($(LOADABLE_MODS),) |
michael@202 | 1855 | for x in $(LOADABLE_MODS:%=%.so); do $(INSTALL) -m 755 $$x $(DESTDIR)$(MODULES_DIR) ; done |
michael@202 | 1856 | +endif |
michael@202 | 1857 | |
michael@202 | 1858 | uninstall:: |
michael@202 | 1859 | |
michael@202 | 1860 | Index: res/res_features.c |
michael@202 | 1861 | diff -Nau res/res_features.c.orig res/res_features.c |
michael@202 | 1862 | --- res/res_features.c.orig 2009-03-03 19:27:09.000000000 +0100 |
michael@202 | 1863 | +++ res/res_features.c 2009-04-24 00:30:33.000000000 +0200 |
michael@202 | 1864 | @@ -732,6 +732,10 @@ |
michael@202 | 1865 | snprintf(args, len, "%s|%s|m", S_OR(touch_format, "wav"), touch_filename); |
michael@202 | 1866 | } |
michael@202 | 1867 | |
michael@202 | 1868 | + for( x = 0; x < strlen(touch_filename); x++) { |
michael@202 | 1869 | + if (touch_filename[x] == '/') |
michael@202 | 1870 | + touch_filename[x] = '-'; |
michael@202 | 1871 | + } |
michael@202 | 1872 | for( x = 0; x < strlen(args); x++) { |
michael@202 | 1873 | if (args[x] == '/') |
michael@202 | 1874 | args[x] = '-'; |
michael@202 | 1875 | @@ -2774,6 +2778,293 @@ |
michael@202 | 1876 | } |
michael@202 | 1877 | } |
michael@202 | 1878 | |
michael@202 | 1879 | +static char mandescr_bridge[] = |
michael@202 | 1880 | +"Description: Bridge together two channels already in the PBX\n" |
michael@202 | 1881 | +"Variables: ( Headers marked with * are required )\n" |
michael@202 | 1882 | +" *Channel1: Channel to Bridge to Channel2\n" |
michael@202 | 1883 | +" *Channel2: Channel to Bridge to Channel1\n" |
michael@202 | 1884 | +" Tone: (Yes|No) Play courtesy tone to Channel 2\n" |
michael@202 | 1885 | +"\n"; |
michael@202 | 1886 | + |
michael@202 | 1887 | +/*! |
michael@202 | 1888 | + * \brief Actual bridge |
michael@202 | 1889 | + * \param chan |
michael@202 | 1890 | + * \param tmpchan |
michael@202 | 1891 | + * |
michael@202 | 1892 | + * Stop hold music, lock both channels, masq channels, |
michael@202 | 1893 | + * after bridge return channel to next priority. |
michael@202 | 1894 | +*/ |
michael@202 | 1895 | +static void do_bridge_masquerade(struct ast_channel *chan, struct ast_channel *tmpchan) |
michael@202 | 1896 | +{ |
michael@202 | 1897 | + ast_moh_stop(chan); |
michael@202 | 1898 | + ast_channel_lock(chan); |
michael@202 | 1899 | + ast_setstate(tmpchan, chan->_state); |
michael@202 | 1900 | + tmpchan->readformat = chan->readformat; |
michael@202 | 1901 | + tmpchan->writeformat = chan->writeformat; |
michael@202 | 1902 | + ast_channel_masquerade(tmpchan, chan); |
michael@202 | 1903 | + ast_channel_lock(tmpchan); |
michael@202 | 1904 | + ast_do_masquerade(tmpchan); |
michael@202 | 1905 | + /* when returning from bridge, the channel will continue at the next priority */ |
michael@202 | 1906 | + ast_explicit_goto(tmpchan, chan->context, chan->exten, chan->priority + 1); |
michael@202 | 1907 | + ast_channel_unlock(tmpchan); |
michael@202 | 1908 | + ast_channel_unlock(chan); |
michael@202 | 1909 | +} |
michael@202 | 1910 | + |
michael@202 | 1911 | +/*! |
michael@202 | 1912 | + * \brief Bridge channels together |
michael@202 | 1913 | + * \param s |
michael@202 | 1914 | + * \param m |
michael@202 | 1915 | + * |
michael@202 | 1916 | + * Make sure valid channels were specified, |
michael@202 | 1917 | + * send errors if any of the channels could not be found/locked, answer channels if needed, |
michael@202 | 1918 | + * create the placeholder channels and grab the other channels |
michael@202 | 1919 | + * make the channels compatible, send error if we fail doing so |
michael@202 | 1920 | + * setup the bridge thread object and start the bridge. |
michael@202 | 1921 | + * |
michael@202 | 1922 | + * \retval 0 on success or on incorrect use. |
michael@202 | 1923 | + * \retval 1 on failure to bridge channels. |
michael@202 | 1924 | +*/ |
michael@202 | 1925 | +static int action_bridge(struct mansession *s, const struct message *m) |
michael@202 | 1926 | +{ |
michael@202 | 1927 | + const char *channela = astman_get_header(m, "Channel1"); |
michael@202 | 1928 | + const char *channelb = astman_get_header(m, "Channel2"); |
michael@202 | 1929 | + const char *playtone = astman_get_header(m, "Tone"); |
michael@202 | 1930 | + struct ast_channel *chana = NULL, *chanb = NULL; |
michael@202 | 1931 | + struct ast_channel *tmpchana = NULL, *tmpchanb = NULL; |
michael@202 | 1932 | + struct ast_bridge_thread_obj *tobj = NULL; |
michael@202 | 1933 | + |
michael@202 | 1934 | + /* make sure valid channels were specified */ |
michael@202 | 1935 | + if (!ast_strlen_zero(channela) && !ast_strlen_zero(channelb)) { |
michael@202 | 1936 | + chana = ast_get_channel_by_name_prefix_locked(channela, strlen(channela)); |
michael@202 | 1937 | + chanb = ast_get_channel_by_name_prefix_locked(channelb, strlen(channelb)); |
michael@202 | 1938 | + if (chana) |
michael@202 | 1939 | + ast_channel_unlock(chana); |
michael@202 | 1940 | + if (chanb) |
michael@202 | 1941 | + ast_channel_unlock(chanb); |
michael@202 | 1942 | + |
michael@202 | 1943 | + /* send errors if any of the channels could not be found/locked */ |
michael@202 | 1944 | + if (!chana) { |
michael@202 | 1945 | + char buf[256]; |
michael@202 | 1946 | + snprintf(buf, sizeof(buf), "Channel1 does not exist: %s", channela); |
michael@202 | 1947 | + astman_send_error(s, m, buf); |
michael@202 | 1948 | + return 0; |
michael@202 | 1949 | + } |
michael@202 | 1950 | + if (!chanb) { |
michael@202 | 1951 | + char buf[256]; |
michael@202 | 1952 | + snprintf(buf, sizeof(buf), "Channel2 does not exist: %s", channelb); |
michael@202 | 1953 | + astman_send_error(s, m, buf); |
michael@202 | 1954 | + return 0; |
michael@202 | 1955 | + } |
michael@202 | 1956 | + } else { |
michael@202 | 1957 | + astman_send_error(s, m, "Missing channel parameter in request"); |
michael@202 | 1958 | + return 0; |
michael@202 | 1959 | + } |
michael@202 | 1960 | + |
michael@202 | 1961 | + /* Answer the channels if needed */ |
michael@202 | 1962 | + if (chana->_state != AST_STATE_UP) |
michael@202 | 1963 | + ast_answer(chana); |
michael@202 | 1964 | + if (chanb->_state != AST_STATE_UP) |
michael@202 | 1965 | + ast_answer(chanb); |
michael@202 | 1966 | + |
michael@202 | 1967 | + /* create the placeholder channels and grab the other channels */ |
michael@202 | 1968 | + if (!(tmpchana = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL, |
michael@202 | 1969 | + NULL, NULL, 0, "Bridge/%s", chana->name))) { |
michael@202 | 1970 | + astman_send_error(s, m, "Unable to create temporary channel!"); |
michael@202 | 1971 | + return 1; |
michael@202 | 1972 | + } |
michael@202 | 1973 | + |
michael@202 | 1974 | + if (!(tmpchanb = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL, |
michael@202 | 1975 | + NULL, NULL, 0, "Bridge/%s", chanb->name))) { |
michael@202 | 1976 | + astman_send_error(s, m, "Unable to create temporary channels!"); |
michael@202 | 1977 | + ast_channel_free(tmpchana); |
michael@202 | 1978 | + return 1; |
michael@202 | 1979 | + } |
michael@202 | 1980 | + |
michael@202 | 1981 | + do_bridge_masquerade(chana, tmpchana); |
michael@202 | 1982 | + do_bridge_masquerade(chanb, tmpchanb); |
michael@202 | 1983 | + |
michael@202 | 1984 | + /* make the channels compatible, send error if we fail doing so */ |
michael@202 | 1985 | + if (ast_channel_make_compatible(tmpchana, tmpchanb)) { |
michael@202 | 1986 | + ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for manager bridge\n", tmpchana->name, tmpchanb->name); |
michael@202 | 1987 | + astman_send_error(s, m, "Could not make channels compatible for manager bridge"); |
michael@202 | 1988 | + ast_hangup(tmpchana); |
michael@202 | 1989 | + ast_hangup(tmpchanb); |
michael@202 | 1990 | + return 1; |
michael@202 | 1991 | + } |
michael@202 | 1992 | + |
michael@202 | 1993 | + /* setup the bridge thread object and start the bridge */ |
michael@202 | 1994 | + if (!(tobj = ast_calloc(1, sizeof(*tobj)))) { |
michael@202 | 1995 | + ast_log(LOG_WARNING, "Unable to spawn a new bridge thread on %s and %s: %s\n", tmpchana->name, tmpchanb->name, strerror(errno)); |
michael@202 | 1996 | + astman_send_error(s, m, "Unable to spawn a new bridge thread"); |
michael@202 | 1997 | + ast_hangup(tmpchana); |
michael@202 | 1998 | + ast_hangup(tmpchanb); |
michael@202 | 1999 | + return 1; |
michael@202 | 2000 | + } |
michael@202 | 2001 | + |
michael@202 | 2002 | + tobj->chan = tmpchana; |
michael@202 | 2003 | + tobj->peer = tmpchanb; |
michael@202 | 2004 | + |
michael@202 | 2005 | + if (ast_true(playtone)) { |
michael@202 | 2006 | + if (!ast_strlen_zero(xfersound) && !ast_streamfile(tmpchanb, xfersound, tmpchanb->language)) { |
michael@202 | 2007 | + if (ast_waitstream(tmpchanb, "") < 0) |
michael@202 | 2008 | + ast_log(LOG_WARNING, "Failed to play a courtesy tone on chan %s\n", tmpchanb->name); |
michael@202 | 2009 | + } |
michael@202 | 2010 | + } |
michael@202 | 2011 | + |
michael@202 | 2012 | + ast_bridge_call_thread_launch(tobj); |
michael@202 | 2013 | + |
michael@202 | 2014 | + astman_send_ack(s, m, "Launched bridge thread with success"); |
michael@202 | 2015 | + |
michael@202 | 2016 | + return 0; |
michael@202 | 2017 | +} |
michael@202 | 2018 | + |
michael@202 | 2019 | +static char *app_bridge = "Bridge"; |
michael@202 | 2020 | +static char *bridge_synopsis = "Bridge two channels"; |
michael@202 | 2021 | +static char *bridge_descrip = |
michael@202 | 2022 | +"Usage: Bridge(channel[,options])\n" |
michael@202 | 2023 | +" Allows the ability to bridge two channels via the dialplan.\n" |
michael@202 | 2024 | +"The current channel is bridged to the specified 'channel'.\n" |
michael@202 | 2025 | +" Options:\n" |
michael@202 | 2026 | +" p - Play a courtesy tone to 'channel'.\n" |
michael@202 | 2027 | +"This application sets the following channel variable upon completion:\n" |
michael@202 | 2028 | +" BRIDGERESULT The result of the bridge attempt as a text string, one of\n" |
michael@202 | 2029 | +" SUCCESS | FAILURE | LOOP | NONEXISTENT | INCOMPATIBLE\n"; |
michael@202 | 2030 | + |
michael@202 | 2031 | +enum { |
michael@202 | 2032 | + BRIDGE_OPT_PLAYTONE = (1 << 0), |
michael@202 | 2033 | +}; |
michael@202 | 2034 | + |
michael@202 | 2035 | +AST_APP_OPTIONS(bridge_exec_options, BEGIN_OPTIONS |
michael@202 | 2036 | + AST_APP_OPTION('p', BRIDGE_OPT_PLAYTONE) |
michael@202 | 2037 | +END_OPTIONS ); |
michael@202 | 2038 | + |
michael@202 | 2039 | +/*! |
michael@202 | 2040 | + * \brief Bridge channels |
michael@202 | 2041 | + * \param chan |
michael@202 | 2042 | + * \param data channel to bridge with. |
michael@202 | 2043 | + * |
michael@202 | 2044 | + * Split data, check we aren't bridging with ourself, check valid channel, |
michael@202 | 2045 | + * answer call if not already, check compatible channels, setup bridge config |
michael@202 | 2046 | + * now bridge call, if transfered party hangs up return to PBX extension. |
michael@202 | 2047 | +*/ |
michael@202 | 2048 | +static int bridge_exec(struct ast_channel *chan, void *data) |
michael@202 | 2049 | +{ |
michael@202 | 2050 | + struct ast_channel *current_dest_chan, *final_dest_chan; |
michael@202 | 2051 | + char *tmp_data = NULL; |
michael@202 | 2052 | + struct ast_flags opts = { 0, }; |
michael@202 | 2053 | + struct ast_bridge_config bconfig = { { 0, }, }; |
michael@202 | 2054 | + |
michael@202 | 2055 | + AST_DECLARE_APP_ARGS(args, |
michael@202 | 2056 | + AST_APP_ARG(dest_chan); |
michael@202 | 2057 | + AST_APP_ARG(options); |
michael@202 | 2058 | + ); |
michael@202 | 2059 | + |
michael@202 | 2060 | + if (ast_strlen_zero(data)) { |
michael@202 | 2061 | + ast_log(LOG_WARNING, "Bridge require at least 1 argument specifying the other end of the bridge\n"); |
michael@202 | 2062 | + return -1; |
michael@202 | 2063 | + } |
michael@202 | 2064 | + |
michael@202 | 2065 | + tmp_data = ast_strdupa(data); |
michael@202 | 2066 | + AST_STANDARD_APP_ARGS(args, tmp_data); |
michael@202 | 2067 | + if (!ast_strlen_zero(args.options)) |
michael@202 | 2068 | + ast_app_parse_options(bridge_exec_options, &opts, NULL, args.options); |
michael@202 | 2069 | + |
michael@202 | 2070 | + /* avoid bridge with ourselves */ |
michael@202 | 2071 | + if (!strncmp(chan->name, args.dest_chan, |
michael@202 | 2072 | + strlen(chan->name) < strlen(args.dest_chan) ? |
michael@202 | 2073 | + strlen(chan->name) : strlen(args.dest_chan))) { |
michael@202 | 2074 | + ast_log(LOG_WARNING, "Unable to bridge channel %s with itself\n", chan->name); |
michael@202 | 2075 | + manager_event(EVENT_FLAG_CALL, "BridgeExec", |
michael@202 | 2076 | + "Response: Failed\r\n" |
michael@202 | 2077 | + "Reason: Unable to bridge channel to itself\r\n" |
michael@202 | 2078 | + "Channel1: %s\r\n" |
michael@202 | 2079 | + "Channel2: %s\r\n", |
michael@202 | 2080 | + chan->name, args.dest_chan); |
michael@202 | 2081 | + pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "LOOP"); |
michael@202 | 2082 | + return 0; |
michael@202 | 2083 | + } |
michael@202 | 2084 | + |
michael@202 | 2085 | + /* make sure we have a valid end point */ |
michael@202 | 2086 | + if (!(current_dest_chan = ast_get_channel_by_name_prefix_locked(args.dest_chan, |
michael@202 | 2087 | + strlen(args.dest_chan)))) { |
michael@202 | 2088 | + ast_log(LOG_WARNING, "Bridge failed because channel %s does not exist or we " |
michael@202 | 2089 | + "cannot get its lock\n", args.dest_chan); |
michael@202 | 2090 | + manager_event(EVENT_FLAG_CALL, "BridgeExec", |
michael@202 | 2091 | + "Response: Failed\r\n" |
michael@202 | 2092 | + "Reason: Cannot grab end point\r\n" |
michael@202 | 2093 | + "Channel1: %s\r\n" |
michael@202 | 2094 | + "Channel2: %s\r\n", chan->name, args.dest_chan); |
michael@202 | 2095 | + pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "NONEXISTENT"); |
michael@202 | 2096 | + return 0; |
michael@202 | 2097 | + } |
michael@202 | 2098 | + ast_channel_unlock(current_dest_chan); |
michael@202 | 2099 | + |
michael@202 | 2100 | + /* answer the channel if needed */ |
michael@202 | 2101 | + if (current_dest_chan->_state != AST_STATE_UP) |
michael@202 | 2102 | + ast_answer(current_dest_chan); |
michael@202 | 2103 | + |
michael@202 | 2104 | + /* try to allocate a place holder where current_dest_chan will be placed */ |
michael@202 | 2105 | + if (!(final_dest_chan = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL, |
michael@202 | 2106 | + NULL, NULL, 0, "Bridge/%s", current_dest_chan->name))) { |
michael@202 | 2107 | + ast_log(LOG_WARNING, "Cannot create placeholder channel for chan %s\n", args.dest_chan); |
michael@202 | 2108 | + manager_event(EVENT_FLAG_CALL, "BridgeExec", |
michael@202 | 2109 | + "Response: Failed\r\n" |
michael@202 | 2110 | + "Reason: cannot create placeholder\r\n" |
michael@202 | 2111 | + "Channel1: %s\r\n" |
michael@202 | 2112 | + "Channel2: %s\r\n", chan->name, args.dest_chan); |
michael@202 | 2113 | + } |
michael@202 | 2114 | + do_bridge_masquerade(current_dest_chan, final_dest_chan); |
michael@202 | 2115 | + |
michael@202 | 2116 | + /* now current_dest_chan is a ZOMBIE and with softhangup set to 1 and final_dest_chan is our end point */ |
michael@202 | 2117 | + /* try to make compatible, send error if we fail */ |
michael@202 | 2118 | + if (ast_channel_make_compatible(chan, final_dest_chan) < 0) { |
michael@202 | 2119 | + ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, final_dest_chan->name); |
michael@202 | 2120 | + manager_event(EVENT_FLAG_CALL, "BridgeExec", |
michael@202 | 2121 | + "Response: Failed\r\n" |
michael@202 | 2122 | + "Reason: Could not make channels compatible for bridge\r\n" |
michael@202 | 2123 | + "Channel1: %s\r\n" |
michael@202 | 2124 | + "Channel2: %s\r\n", chan->name, final_dest_chan->name); |
michael@202 | 2125 | + ast_hangup(final_dest_chan); /* may be we should return this channel to the PBX? */ |
michael@202 | 2126 | + pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "INCOMPATIBLE"); |
michael@202 | 2127 | + return 0; |
michael@202 | 2128 | + } |
michael@202 | 2129 | + |
michael@202 | 2130 | + /* Report that the bridge will be successfull */ |
michael@202 | 2131 | + manager_event(EVENT_FLAG_CALL, "BridgeExec", |
michael@202 | 2132 | + "Response: Success\r\n" |
michael@202 | 2133 | + "Channel1: %s\r\n" |
michael@202 | 2134 | + "Channel2: %s\r\n", chan->name, final_dest_chan->name); |
michael@202 | 2135 | + |
michael@202 | 2136 | + /* we have 2 valid channels to bridge, now it is just a matter of setting up the bridge config and starting the bridge */ |
michael@202 | 2137 | + if (ast_test_flag(&opts, BRIDGE_OPT_PLAYTONE) && !ast_strlen_zero(xfersound)) { |
michael@202 | 2138 | + if (!ast_streamfile(final_dest_chan, xfersound, final_dest_chan->language)) { |
michael@202 | 2139 | + if (ast_waitstream(final_dest_chan, "") < 0) |
michael@202 | 2140 | + ast_log(LOG_WARNING, "Failed to play courtesy tone on %s\n", final_dest_chan->name); |
michael@202 | 2141 | + } |
michael@202 | 2142 | + } |
michael@202 | 2143 | + |
michael@202 | 2144 | + /* do the bridge */ |
michael@202 | 2145 | + ast_bridge_call(chan, final_dest_chan, &bconfig); |
michael@202 | 2146 | + |
michael@202 | 2147 | + /* the bridge has ended, set BRIDGERESULT to SUCCESS. If the other channel has not been hung up, return it to the PBX */ |
michael@202 | 2148 | + pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "SUCCESS"); |
michael@202 | 2149 | + if (!ast_check_hangup(final_dest_chan)) { |
michael@202 | 2150 | + ast_log(LOG_EVENT, "starting new PBX in %s,%s,%d for chan %s\n", |
michael@202 | 2151 | + final_dest_chan->context, final_dest_chan->exten, |
michael@202 | 2152 | + final_dest_chan->priority, final_dest_chan->name); |
michael@202 | 2153 | + |
michael@202 | 2154 | + if (ast_pbx_start(final_dest_chan) != AST_PBX_SUCCESS) { |
michael@202 | 2155 | + ast_log(LOG_WARNING, "FAILED continuing PBX on dest chan %s\n", final_dest_chan->name); |
michael@202 | 2156 | + ast_hangup(final_dest_chan); |
michael@202 | 2157 | + } else |
michael@202 | 2158 | + ast_log(LOG_EVENT, "SUCCESS continuing PBX on chan %s\n", final_dest_chan->name); |
michael@202 | 2159 | + } else { |
michael@202 | 2160 | + ast_log(LOG_EVENT, "hangup chan %s since the other endpoint has hung up\n", final_dest_chan->name); |
michael@202 | 2161 | + ast_hangup(final_dest_chan); |
michael@202 | 2162 | + } |
michael@202 | 2163 | + |
michael@202 | 2164 | + return 0; |
michael@202 | 2165 | +} |
michael@202 | 2166 | |
michael@202 | 2167 | static int load_config(void) |
michael@202 | 2168 | { |
michael@202 | 2169 | @@ -3034,6 +3325,8 @@ |
michael@202 | 2170 | { |
michael@202 | 2171 | int res; |
michael@202 | 2172 | |
michael@202 | 2173 | + ast_register_application(app_bridge, bridge_exec, bridge_synopsis, bridge_descrip); |
michael@202 | 2174 | + |
michael@202 | 2175 | memset(parking_ext, 0, sizeof(parking_ext)); |
michael@202 | 2176 | memset(parking_con, 0, sizeof(parking_con)); |
michael@202 | 2177 | |
michael@202 | 2178 | @@ -3048,6 +3341,7 @@ |
michael@202 | 2179 | ast_manager_register("ParkedCalls", 0, manager_parking_status, "List parked calls" ); |
michael@202 | 2180 | ast_manager_register2("Park", EVENT_FLAG_CALL, manager_park, |
michael@202 | 2181 | "Park a channel", mandescr_park); |
michael@202 | 2182 | + ast_manager_register2("Bridge", EVENT_FLAG_CALL, action_bridge, "Bridge two channels already in the PBX", mandescr_bridge); |
michael@202 | 2183 | } |
michael@202 | 2184 | |
michael@202 | 2185 | res |= ast_devstate_prov_add("Park", metermaidstate); |
michael@202 | 2186 | Index: apps/app_voicemail.c |
michael@202 | 2187 | diff -Nau apps/app_voicemail.c.orig apps/app_voicemail.c |
michael@202 | 2188 | --- apps/app_voicemail.c.orig 2009-04-25 02:38:20.343758775 +0200 |
michael@202 | 2189 | +++ apps/app_voicemail.c 2009-04-25 19:56:25.287569363 +0200 |
michael@202 | 2190 | @@ -115,6 +115,7 @@ |
michael@202 | 2191 | static char imapport[8]; |
michael@202 | 2192 | static char imapflags[128]; |
michael@202 | 2193 | static char imapfolder[64]; |
michael@202 | 2194 | +static int imapsubfold = 0; |
michael@202 | 2195 | static char authuser[32]; |
michael@202 | 2196 | static char authpassword[42]; |
michael@202 | 2197 | |
michael@202 | 2198 | @@ -4313,6 +4314,7 @@ |
michael@202 | 2199 | /* we must use mbox(x) folder names, and copy the message there */ |
michael@202 | 2200 | /* simple. huh? */ |
michael@202 | 2201 | char sequence[10]; |
michael@202 | 2202 | + char folder[256]; |
michael@202 | 2203 | /* get the real IMAP message number for this message */ |
michael@202 | 2204 | snprintf(sequence, sizeof(sequence), "%ld", vms->msgArray[msg]); |
michael@202 | 2205 | if (option_debug > 2) |
michael@202 | 2206 | @@ -4323,11 +4325,21 @@ |
michael@202 | 2207 | } else if (box == 0) { |
michael@202 | 2208 | mail_clearflag(vms->mailstream, sequence, "\\Seen"); |
michael@202 | 2209 | } |
michael@202 | 2210 | - if (!strcasecmp(mbox(0), vms->curbox) && (box == 0 || box == 1)) { |
michael@202 | 2211 | + if ((!strcasecmp(mbox(0), vms->curbox) || \ |
michael@202 | 2212 | + !strcasecmp(mbox(1), vms->curbox)) && \ |
michael@202 | 2213 | + (box == 0 || box == 1)) { /* Don't copy data, just change Seen flag */ |
michael@202 | 2214 | ast_mutex_unlock(&vms->lock); |
michael@202 | 2215 | return 0; |
michael@202 | 2216 | - } else { |
michael@202 | 2217 | - int res = !mail_copy(vms->mailstream,sequence,(char *) mbox(box)); |
michael@202 | 2218 | + } else if (box > 1) { /* Do copy data using INBOX or subfolder */ |
michael@202 | 2219 | + if (imapsubfold == 1) |
michael@202 | 2220 | + snprintf(folder, sizeof(folder), "%s%c%s", imapfolder, delimiter, mbox(box)); |
michael@202 | 2221 | + else |
michael@202 | 2222 | + strncpy(folder, mbox(box), sizeof(folder)); |
michael@202 | 2223 | + int res = !mail_copy(vms->mailstream,sequence,folder); |
michael@202 | 2224 | + ast_mutex_unlock(&vms->lock); |
michael@202 | 2225 | + return res; |
michael@202 | 2226 | + } else { /* Copy data to INBOX delegating new/old status to Seen flag */ |
michael@202 | 2227 | + int res = !mail_copy(vms->mailstream,sequence,imapfolder); |
michael@202 | 2228 | ast_mutex_unlock(&vms->lock); |
michael@202 | 2229 | return res; |
michael@202 | 2230 | } |
michael@202 | 2231 | @@ -7686,6 +7698,10 @@ |
michael@202 | 2232 | #ifndef IMAP_STORAGE |
michael@202 | 2233 | } else if (!cmd) { |
michael@202 | 2234 | vms.deleted[vms.curmsg] = 1; |
michael@202 | 2235 | +#else |
michael@202 | 2236 | + } else if (!cmd && (folder_int(vms.curbox) > 1 || box > 1)) { |
michael@202 | 2237 | + vms.deleted[vms.curmsg] = 1; /* Enforce deletion after */ |
michael@202 | 2238 | + deleted = 1; /* successful copy op */ |
michael@202 | 2239 | #endif |
michael@202 | 2240 | } else { |
michael@202 | 2241 | vms.deleted[vms.curmsg] = 0; |
michael@202 | 2242 | @@ -8198,6 +8214,7 @@ |
michael@202 | 2243 | const char *imap_port; |
michael@202 | 2244 | const char *imap_flags; |
michael@202 | 2245 | const char *imap_folder; |
michael@202 | 2246 | + const char *imap_use_subfold; |
michael@202 | 2247 | const char *auth_user; |
michael@202 | 2248 | const char *auth_password; |
michael@202 | 2249 | const char *expunge_on_hangup; |
michael@202 | 2250 | @@ -8342,6 +8359,15 @@ |
michael@202 | 2251 | } else { |
michael@202 | 2252 | ast_copy_string(imapfolder,"INBOX", sizeof(imapfolder)); |
michael@202 | 2253 | } |
michael@202 | 2254 | + /* IMAP saved (sub)folder location policy */ |
michael@202 | 2255 | + if ((imap_use_subfold = ast_variable_retrieve(cfg, "general", "imapsubfold"))) { |
michael@202 | 2256 | + if (ast_false(imap_use_subfold)) |
michael@202 | 2257 | + imapsubfold = 0; |
michael@202 | 2258 | + else |
michael@202 | 2259 | + imapsubfold = 1; |
michael@202 | 2260 | + } else { |
michael@202 | 2261 | + imapsubfold = 0; |
michael@202 | 2262 | + } |
michael@202 | 2263 | |
michael@202 | 2264 | /* There is some very unorthodox casting done here. This is due |
michael@202 | 2265 | * to the way c-client handles the argument passed in. It expects a |