diff --git a/src/libs/g722/CMakeLists.txt b/src/libs/g722/CMakeLists.txt index 006d16b9..f07a174f 100644 --- a/src/libs/g722/CMakeLists.txt +++ b/src/libs/g722/CMakeLists.txt @@ -1,16 +1,13 @@ project (g722_codec) -# Rely on C++ 11 -set (CMAKE_CXX_STANDARD 20) -set (CMAKE_CXX_STANDARD_REQUIRED ON) - set(CMAKE_POSITION_INDEPENDENT_CODE ON) +# G.722 from Asterisk (codecs/g722): Steve Underwood's spandsp code, which he +# placed in the public domain, on top of the CMU 1993 codec, whose use "for +# any research or commercial purpose, is completely unrestricted". See README.md. set (G722_SOURCES - g722_bitstream.c g722_decode.c g722_encode.c ) add_library(g722_codec ${G722_SOURCES}) - diff --git a/src/libs/g722/README.md b/src/libs/g722/README.md new file mode 100644 index 00000000..206e8f87 --- /dev/null +++ b/src/libs/g722/README.md @@ -0,0 +1,35 @@ +# G.722 codec + +Source: Asterisk, `codecs/g722/` (`g722.h`, `g722_encode.c`, `g722_decode.c`), +https://github.com/asterisk/asterisk, taken 2026-09-21. + +## Licence + +No copyleft. The code has two layers: + +- **Steve Underwood, 2005** (spandsp): "Despite my general liking of the GPL, I + place my own contributions to this code in the public domain for the benefit + of all mankind - even the slimy ones who might try to proprietize my work and + use it to my detriment." (in each file's header) +- **Carnegie Mellon University, 1993** (Chengxiang Lu and Alex Hauptmann, Speech + Group): "The Carnegie Mellon ADPCM program is Copyright (c) 1993 by Carnegie + Mellon University. Use of this program, for any research or commercial + purpose, is completely unrestricted. If you make use of or redistribute this + material, we would appreciate acknowlegement of its origin." (the terms as + reproduced in sippy's libg722, https://github.com/sippy/libg722, LICENSE) + +This replaces an older copy of the same spandsp code that was offered only +under GPL-2 or LGPL-2.1. + +## Behaviour + +Asterisk's version maps 16-bit PCM to the codec's range: the encoder halves its +input and the decoder doubles its output. Streams from Asterisk and ffmpeg +therefore decode at their original level. The older copy did neither, so it +decoded those streams 6 dB too quiet and clipped encoder input above -6 dBFS. + +Local changes: +- the decoder saturates its output (`saturate()`) instead of casting. Asterisk's + cast wraps loud samples around int16: 259 samples in 11 s of speech peaking + at -0.2 dBFS came out as large values of the opposite sign; +- `g722.h` includes `` and maps `__inline__` to `__inline` for MSVC. diff --git a/src/libs/g722/g722.h b/src/libs/g722/g722.h index 23bd782a..fdee80e6 100644 --- a/src/libs/g722/g722.h +++ b/src/libs/g722/g722.h @@ -1,184 +1,153 @@ -/* - * VoIPcodecs - a series of DSP components for telephony - * - * g722.h - The ITU G.722 codec. - * - * Written by Steve Underwood - * - * Copyright (C) 2005 Steve Underwood - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2, or - * the Lesser GNU General Public License version 2.1, as published by - * the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Based on a single channel G.722 codec which is: - * - ***** Copyright (c) CMU 1993 ***** - * Computer Science, Speech Group - * Chengxiang Lu and Alex Hauptmann - * - * $Id: g722.h,v 1.17 2008/02/09 15:32:26 steveu Exp $ - */ - - -/*! \file */ - -#if !defined(_SPANDSP_G722_H_) -#define _SPANDSP_G722_H_ - -#include "inttypes.h" - - -/*! \page g722_page G.722 encoding and decoding -\section g722_page_sec_1 What does it do? -The G.722 module is a bit exact implementation of the ITU G.722 specification for all three -specified bit rates - 64000bps, 56000bps and 48000bps. It passes the ITU tests. - -To allow fast and flexible interworking with narrow band telephony, the encoder and decoder -support an option for the linear audio to be an 8k samples/second stream. In this mode the -codec is considerably faster, and still fully compatible with wideband terminals using G.722. - -\section g722_page_sec_2 How does it work? -???. -*/ - -enum -{ - G722_SAMPLE_RATE_8000 = 0x0001, - G722_PACKED = 0x0002 -}; - -typedef struct -{ - /*! TRUE if the operating in the special ITU test mode, with the band split filters - disabled. */ - int itu_test_mode; - /*! TRUE if the G.722 data is packed */ - int packed; - /*! TRUE if encode from 8k samples/second */ - int eight_k; - /*! 6 for 48000kbps, 7 for 56000kbps, or 8 for 64000kbps. */ - int bits_per_sample; - - /*! Signal history for the QMF */ - int x[24]; - - struct - { - int s; - int sp; - int sz; - int r[3]; - int a[3]; - int ap[3]; - int p[3]; - int d[7]; - int b[7]; - int bp[7]; - int sg[7]; - int nb; - int det; - } band[2]; - - unsigned int in_buffer; - int in_bits; - unsigned int out_buffer; - int out_bits; -} g722_encode_state_t; - -typedef struct -{ - /*! TRUE if the operating in the special ITU test mode, with the band split filters - disabled. */ - int itu_test_mode; - /*! TRUE if the G.722 data is packed */ - int packed; - /*! TRUE if decode to 8k samples/second */ - int eight_k; - /*! 6 for 48000kbps, 7 for 56000kbps, or 8 for 64000kbps. */ - int bits_per_sample; - - /*! Signal history for the QMF */ - int x[24]; - - struct - { - int s; - int sp; - int sz; - int r[3]; - int a[3]; - int ap[3]; - int p[3]; - int d[7]; - int b[7]; - int bp[7]; - int sg[7]; - int nb; - int det; - } band[2]; - - unsigned int in_buffer; - int in_bits; - unsigned int out_buffer; - int out_bits; -} g722_decode_state_t; - -#if defined(__cplusplus) -extern "C" -{ -#endif - -/*! Initialise an G.722 encode context. - \param s The G.722 encode context. - \param rate The required bit rate for the G.722 data. - The valid rates are 64000, 56000 and 48000. - \param options - \return A pointer to the G.722 encode context, or NULL for error. */ -g722_encode_state_t *g722_encode_init(g722_encode_state_t *s, int rate, int options); - -int g722_encode_release(g722_encode_state_t *s); - -/*! Encode a buffer of linear PCM data to G.722 - \param s The G.722 context. - \param g722_data The G.722 data produced. - \param amp The audio sample buffer. - \param len The number of samples in the buffer. - \return The number of bytes of G.722 data produced. */ -int g722_encode(g722_encode_state_t *s, uint8_t g722_data[], const int16_t amp[], int len); - -/*! Initialise an G.722 decode context. - \param s The G.722 decode context. - \param rate The bit rate of the G.722 data. - The valid rates are 64000, 56000 and 48000. - \param options - \return A pointer to the G.722 decode context, or NULL for error. */ -g722_decode_state_t *g722_decode_init(g722_decode_state_t *s, int rate, int options); - -int g722_decode_release(g722_decode_state_t *s); - -/*! Decode a buffer of G.722 data to linear PCM. - \param s The G.722 context. - \param amp The audio sample buffer. - \param g722_data - \param len - \return The number of samples returned. */ -int g722_decode(g722_decode_state_t *s, int16_t amp[], const uint8_t g722_data[], int len); - -#if defined(__cplusplus) -} -#endif - -#endif +/* + * SpanDSP - a series of DSP components for telephony + * + * g722.h - The ITU G.722 codec. + * + * Written by Steve Underwood + * + * Copyright (C) 2005 Steve Underwood + * + * Despite my general liking of the GPL, I place my own contributions + * to this code in the public domain for the benefit of all mankind - + * even the slimy ones who might try to proprietize my work and use it + * to my detriment. + * + * Based on a single channel G.722 codec which is: + * + ***** Copyright (c) CMU 1993 ***** + * Computer Science, Speech Group + * Chengxiang Lu and Alex Hauptmann + * + * $Id$ + */ + + +/*! \file */ + +#if !defined(_G722_H_) +#define _G722_H_ + +#include /* rtphone: the header uses int16_t/uint8_t itself */ +#if defined(_MSC_VER) && !defined(__inline__) +#define __inline__ __inline /* rtphone: MSVC has no __inline__ (the .c files use it) */ +#endif + +/*! \page g722_page G.722 encoding and decoding +\section g722_page_sec_1 What does it do? +The G.722 module is a bit exact implementation of the ITU G.722 specification for all three +specified bit rates - 64000bps, 56000bps and 48000bps. It passes the ITU tests. + +To allow fast and flexible interworking with narrow band telephony, the encoder and decoder +support an option for the linear audio to be an 8k samples/second stream. In this mode the +codec is considerably faster, and still fully compatible with wideband terminals using G.722. + +\section g722_page_sec_2 How does it work? +???. +*/ + +enum +{ + G722_SAMPLE_RATE_8000 = 0x0001, + G722_PACKED = 0x0002 +}; + +#ifndef INT16_MAX +#define INT16_MAX 32767 +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32768) +#endif + +typedef struct +{ + /*! TRUE if the operating in the special ITU test mode, with the band split filters + disabled. */ + int itu_test_mode; + /*! TRUE if the G.722 data is packed */ + int packed; + /*! TRUE if encode from 8k samples/second */ + int eight_k; + /*! 6 for 48000kbps, 7 for 56000kbps, or 8 for 64000kbps. */ + int bits_per_sample; + + /*! Signal history for the QMF */ + int x[24]; + + struct + { + int s; + int sp; + int sz; + int r[3]; + int a[3]; + int ap[3]; + int p[3]; + int d[7]; + int b[7]; + int bp[7]; + int sg[7]; + int nb; + int det; + } band[2]; + + unsigned int in_buffer; + int in_bits; + unsigned int out_buffer; + int out_bits; +} g722_encode_state_t; + +typedef struct +{ + /*! TRUE if the operating in the special ITU test mode, with the band split filters + disabled. */ + int itu_test_mode; + /*! TRUE if the G.722 data is packed */ + int packed; + /*! TRUE if decode to 8k samples/second */ + int eight_k; + /*! 6 for 48000kbps, 7 for 56000kbps, or 8 for 64000kbps. */ + int bits_per_sample; + + /*! Signal history for the QMF */ + int x[24]; + + struct + { + int s; + int sp; + int sz; + int r[3]; + int a[3]; + int ap[3]; + int p[3]; + int d[7]; + int b[7]; + int bp[7]; + int sg[7]; + int nb; + int det; + } band[2]; + + unsigned int in_buffer; + int in_bits; + unsigned int out_buffer; + int out_bits; +} g722_decode_state_t; + +#ifdef __cplusplus +extern "C" { +#endif + +g722_encode_state_t *g722_encode_init(g722_encode_state_t *s, int rate, int options); +int g722_encode_release(g722_encode_state_t *s); +int g722_encode(g722_encode_state_t *s, uint8_t g722_data[], const int16_t amp[], int len); + +g722_decode_state_t *g722_decode_init(g722_decode_state_t *s, int rate, int options); +int g722_decode_release(g722_decode_state_t *s); +int g722_decode(g722_decode_state_t *s, int16_t amp[], const uint8_t g722_data[], int len); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/libs/g722/g722_bitstream.c b/src/libs/g722/g722_bitstream.c deleted file mode 100644 index 19a33935..00000000 --- a/src/libs/g722/g722_bitstream.c +++ /dev/null @@ -1,137 +0,0 @@ -/* - * VoIPcodecs - a series of DSP components for telephony - * - * bitstream.c - Bitstream composition and decomposition routines. - * - * Written by Steve Underwood - * - * Copyright (C) 2006 Steve Underwood - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the Lesser Lesser GNU General Public License version 2.1.1, as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * $Id: bitstream.c,v 1.8 2007/08/20 15:22:21 steveu Exp $ - */ - -/*! \file */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "inttypes.h" -#include -#include -#include - -#include "g722_telephony.h" -#include "g722_bitstream.h" - -void bitstream_put(bitstream_state_t *s, uint8_t **c, unsigned int value, int bits) -{ - value &= ((1 << bits) - 1); - if (s->residue + bits <= 32) - { - s->bitstream |= (value << s->residue); - s->residue += bits; - } - while (s->residue >= 8) - { - s->residue -= 8; - *(*c)++ = (uint8_t) (s->bitstream & 0xFF); - s->bitstream >>= 8; - } -} -/*- End of function --------------------------------------------------------*/ - -void bitstream_put2(bitstream_state_t *s, uint8_t **c, unsigned int value, int bits) -{ - value &= ((1 << bits) - 1); - if (s->residue + bits <= 32) - { - s->bitstream = (s->bitstream << bits) | value; - s->residue += bits; - } - while (s->residue >= 8) - { - s->residue -= 8; - *(*c)++ = (uint8_t) ((s->bitstream >> s->residue) & 0xFF); - } -} -/*- End of function --------------------------------------------------------*/ - -unsigned int bitstream_get(bitstream_state_t *s, const uint8_t **c, int bits) -{ - unsigned int x; - - while (s->residue < (unsigned int) bits) - { - x = (unsigned int) *(*c)++; - s->bitstream |= (x << s->residue); - s->residue += 8; - } - s->residue -= bits; - x = s->bitstream & ((1 << bits) - 1); - s->bitstream >>= bits; - return x; -} -/*- End of function --------------------------------------------------------*/ - -unsigned int bitstream_get2(bitstream_state_t *s, const uint8_t **c, int bits) -{ - unsigned int x; - - while (s->residue < (unsigned int) bits) - { - x = (unsigned int) *(*c)++; - s->bitstream = (s->bitstream << 8) | x; - s->residue += 8; - } - s->residue -= bits; - x = (s->bitstream >> s->residue) & ((1 << bits) - 1); - return x; -} -/*- End of function --------------------------------------------------------*/ - -void bitstream_flush(bitstream_state_t *s, uint8_t **c) -{ - if (s->residue > 0) - { - *(*c)++ = (uint8_t) ((s->bitstream << (8 - s->residue)) & 0xFF); - s->residue = 0; - } -} -/*- End of function --------------------------------------------------------*/ - -void bitstream_flush2(bitstream_state_t *s, uint8_t **c) -{ - if (s->residue > 0) - { - *(*c)++ = (uint8_t) ((s->bitstream << (8 - s->residue)) & 0xFF); - s->residue = 0; - } -} -/*- End of function --------------------------------------------------------*/ - -bitstream_state_t *bitstream_init(bitstream_state_t *s) -{ - if (s == NULL) - return NULL; - s->bitstream = 0; - s->residue = 0; - return s; -} -/*- End of function --------------------------------------------------------*/ -/*- End of file ------------------------------------------------------------*/ diff --git a/src/libs/g722/g722_bitstream.h b/src/libs/g722/g722_bitstream.h deleted file mode 100644 index cb535990..00000000 --- a/src/libs/g722/g722_bitstream.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * VoIPcodecs - a series of DSP components for telephony - * - * bitstream.h - Bitstream composition and decomposition routines. - * - * Written by Steve Underwood - * - * Copyright (C) 2006 Steve Underwood - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the Lesser GNU General Public License version 2.1, as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * $Id: bitstream.h,v 1.8 2007/12/13 11:31:32 steveu Exp $ - */ - -/*! \file */ - -#if !defined(_SPANDSP_BITSTREAM_H_) -#define _SPANDSP_BITSTREAM_H_ - -/*! \page bitstream_page Bitstream composition and decomposition -\section bitstream_page_sec_1 What does it do? - -\section bitstream_page_sec_2 How does it work? -*/ - -/*! Bitstream handler state */ -typedef struct -{ - /*! The bit stream. */ - unsigned int bitstream; - /*! The residual bits in bitstream. */ - unsigned int residue; -} bitstream_state_t; - - -#if defined(__cplusplus) -extern "C" -{ -#endif - -/*! \brief Put a chunk of bits into the output buffer. - \param s A pointer to the bitstream context. - \param c A pointer to the bitstream output buffer. - \param value The value to be pushed into the output buffer. - \param bits The number of bits of value to be pushed. 1 to 25 bit is valid. */ -void bitstream_put(bitstream_state_t *s, uint8_t **c, unsigned int value, int bits); - -void bitstream_put2(bitstream_state_t *s, uint8_t **c, unsigned int value, int bits); - -/*! \brief Get a chunk of bits from the input buffer. - \param s A pointer to the bitstream context. - \param c A pointer to the bitstream input buffer. - \param bits The number of bits of value to be grabbed. 1 to 25 bit is valid. - \return The value retrieved from the input buffer. */ -unsigned int bitstream_get(bitstream_state_t *s, const uint8_t **c, int bits); - -unsigned int bitstream_get2(bitstream_state_t *s, const uint8_t **c, int bits); - -/*! \brief Flush any residual bit to the output buffer. - \param s A pointer to the bitstream context. - \param c A pointer to the bitstream output buffer. */ -void bitstream_flush(bitstream_state_t *s, uint8_t **c); - -void bitstream_flush2(bitstream_state_t *s, uint8_t **c); - -/*! \brief Initialise a bitstream context. - \param s A pointer to the bitstream context. - \return A pointer to the bitstream context. */ -bitstream_state_t *bitstream_init(bitstream_state_t *s); - -#if defined(__cplusplus) -} -#endif - -#endif -/*- End of file ------------------------------------------------------------*/ diff --git a/src/libs/g722/g722_dc_restore.h b/src/libs/g722/g722_dc_restore.h deleted file mode 100644 index f166d320..00000000 --- a/src/libs/g722/g722_dc_restore.h +++ /dev/null @@ -1,157 +0,0 @@ -/* - * VoIPcodecs - a series of DSP components for telephony - * - * dc_restore.h - General telephony routines to restore the zero D.C. - * level to audio which has a D.C. bias. - * - * Written by Steve Underwood - * - * Copyright (C) 2001 Steve Underwood - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2, as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * $Id: dc_restore.h,v 1.18 2007/04/08 08:16:17 steveu Exp $ - */ - -/*! \file */ - -#if !defined(_SPANDSP_DC_RESTORE_H_) -#define _SPANDSP_DC_RESTORE_H_ - -/*! \page dc_restore_page Removing DC bias from a signal - -\section dc_restore_page_sec_1 What does it do? - -Telecoms signals often contain considerable DC, but DC upsets a lot of signal -processing functions. Placing a zero DC restorer at the front of the processing -chain can often simplify the downstream processing. - -\section dc_restore_page_sec_2 How does it work? - -The DC restorer uses a leaky integrator to provide a long-ish term estimate of -the DC bias in the signal. A 32 bit estimate is used for the 16 bit audio, so -the noise introduced by the estimation can be keep in the lower bits, and the 16 -bit DC value, which is subtracted from the signal, is fairly clean. The -following code fragment shows the algorithm used. dc_bias is a 32 bit integer, -while the sample and the resulting clean_sample are 16 bit integers. - - dc_bias += ((((int32_t) sample << 15) - dc_bias) >> 14); - clean_sample = sample - (dc_bias >> 15); -*/ - -/*! - Zero DC restoration descriptor. This defines the working state for a single - instance of DC content filter. -*/ -typedef struct -{ - int32_t state; -} dc_restore_state_t; - -#if defined(__cplusplus) -extern "C" -{ -#endif - -static __inline__ void dc_restore_init(dc_restore_state_t *dc) -{ - dc->state = 0; -} -/*- End of function --------------------------------------------------------*/ - -static __inline__ int16_t dc_restore(dc_restore_state_t *dc, int16_t sample) -{ - dc->state += ((((int32_t) sample << 15) - dc->state) >> 14); - return (int16_t) (sample - (dc->state >> 15)); -} -/*- End of function --------------------------------------------------------*/ - -static __inline__ int16_t dc_restore_estimate(dc_restore_state_t *dc) -{ - return (int16_t) (dc->state >> 15); -} -/*- End of function --------------------------------------------------------*/ - -static __inline__ int16_t saturate(int32_t amp) -{ - int16_t amp16; - - /* Hopefully this is optimised for the common case - not clipping */ - amp16 = (int16_t) amp; - if (amp == amp16) - return amp16; - if (amp > INT16_MAX) - return INT16_MAX; - return INT16_MIN; -} -/*- End of function --------------------------------------------------------*/ - -/*#ifdef _MSC_VER -__inline float rintf (float flt) -{ - _asm - { fld flt - frndint - } -} - -__inline double rint(double dbl) -{ - __asm - { - fld dbl - frndint - } -} - -__inline long lrintf (float flt) -{ - long retval; - _asm - { fld flt - fistp retval - } - return retval; -} -#endif -*/ - -static __inline__ int16_t fsaturatef(float famp) -{ - if (famp > 32767.0) - return INT16_MAX; - if (famp < -32768.0) - return INT16_MIN; - return (int16_t) rintf(famp); -} -/*- End of function --------------------------------------------------------*/ - -static __inline__ int16_t fsaturate(double damp) -{ - if (damp > 32767.0) - return INT16_MAX; - if (damp < -32768.0) - return INT16_MIN; - return (int16_t) rint(damp); -} -/*- End of function --------------------------------------------------------*/ - -#if defined(__cplusplus) -} -#endif - -#endif -/*- End of file ------------------------------------------------------------*/ diff --git a/src/libs/g722/g722_decode.c b/src/libs/g722/g722_decode.c index 3f6d9968..fd0b2ac0 100644 --- a/src/libs/g722/g722_decode.c +++ b/src/libs/g722/g722_decode.c @@ -1,403 +1,402 @@ -/* - * VoIPcodecs - a series of DSP components for telephony - * - * g722_decode.c - The ITU G.722 codec, decode part. - * - * Written by Steve Underwood - * - * Copyright (C) 2005 Steve Underwood - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2, or - * the Lesser GNU General Public License version 2.1, as published by - * the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Based in part on a single channel G.722 codec which is: - * - * Copyright (c) CMU 1993 - * Computer Science, Speech Group - * Chengxiang Lu and Alex Hauptmann - * - * $Id: g722_decode.c,v 1.20 2008/02/09 15:32:56 steveu Exp $ - */ - -/*! \file */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "g722_inttypes.h" -#include -#include -#if defined(HAVE_TGMATH_H) -#include -#endif -#include - -#include "g722_telephony.h" -#include "g722_dc_restore.h" -#include "g722.h" - -static void block4(g722_decode_state_t *s, int band, int d); - -static void block4(g722_decode_state_t *s, int band, int d) -{ - int wd1; - int wd2; - int wd3; - int i; - - /* Block 4, RECONS */ - s->band[band].d[0] = d; - s->band[band].r[0] = saturate(s->band[band].s + d); - - /* Block 4, PARREC */ - s->band[band].p[0] = saturate(s->band[band].sz + d); - - /* Block 4, UPPOL2 */ - for (i = 0; i < 3; i++) - s->band[band].sg[i] = s->band[band].p[i] >> 15; - wd1 = saturate(s->band[band].a[1] << 2); - - wd2 = (s->band[band].sg[0] == s->band[band].sg[1]) ? -wd1 : wd1; - if (wd2 > 32767) - wd2 = 32767; - wd3 = (s->band[band].sg[0] == s->band[band].sg[2]) ? 128 : -128; - wd3 += (wd2 >> 7); - wd3 += (s->band[band].a[2]*32512) >> 15; - if (wd3 > 12288) - wd3 = 12288; - else if (wd3 < -12288) - wd3 = -12288; - s->band[band].ap[2] = wd3; - - /* Block 4, UPPOL1 */ - s->band[band].sg[0] = s->band[band].p[0] >> 15; - s->band[band].sg[1] = s->band[band].p[1] >> 15; - wd1 = (s->band[band].sg[0] == s->band[band].sg[1]) ? 192 : -192; - wd2 = (s->band[band].a[1]*32640) >> 15; - - s->band[band].ap[1] = saturate(wd1 + wd2); - wd3 = saturate(15360 - s->band[band].ap[2]); - if (s->band[band].ap[1] > wd3) - s->band[band].ap[1] = wd3; - else if (s->band[band].ap[1] < -wd3) - s->band[band].ap[1] = -wd3; - - /* Block 4, UPZERO */ - wd1 = (d == 0) ? 0 : 128; - s->band[band].sg[0] = d >> 15; - for (i = 1; i < 7; i++) - { - s->band[band].sg[i] = s->band[band].d[i] >> 15; - wd2 = (s->band[band].sg[i] == s->band[band].sg[0]) ? wd1 : -wd1; - wd3 = (s->band[band].b[i]*32640) >> 15; - s->band[band].bp[i] = saturate(wd2 + wd3); - } - - /* Block 4, DELAYA */ - for (i = 6; i > 0; i--) - { - s->band[band].d[i] = s->band[band].d[i - 1]; - s->band[band].b[i] = s->band[band].bp[i]; - } - - for (i = 2; i > 0; i--) - { - s->band[band].r[i] = s->band[band].r[i - 1]; - s->band[band].p[i] = s->band[band].p[i - 1]; - s->band[band].a[i] = s->band[band].ap[i]; - } - - /* Block 4, FILTEP */ - wd1 = saturate(s->band[band].r[1] + s->band[band].r[1]); - wd1 = (s->band[band].a[1]*wd1) >> 15; - wd2 = saturate(s->band[band].r[2] + s->band[band].r[2]); - wd2 = (s->band[band].a[2]*wd2) >> 15; - s->band[band].sp = saturate(wd1 + wd2); - - /* Block 4, FILTEZ */ - s->band[band].sz = 0; - for (i = 6; i > 0; i--) - { - wd1 = saturate(s->band[band].d[i] + s->band[band].d[i]); - s->band[band].sz += (s->band[band].b[i]*wd1) >> 15; - } - s->band[band].sz = saturate(s->band[band].sz); - - /* Block 4, PREDIC */ - s->band[band].s = saturate(s->band[band].sp + s->band[band].sz); -} -/*- End of function --------------------------------------------------------*/ - -g722_decode_state_t *g722_decode_init(g722_decode_state_t *s, int rate, int options) -{ - if (s == NULL) - { - if ((s = (g722_decode_state_t *) malloc(sizeof(*s))) == NULL) - return NULL; - } - memset(s, 0, sizeof(*s)); - if (rate == 48000) - s->bits_per_sample = 6; - else if (rate == 56000) - s->bits_per_sample = 7; - else - s->bits_per_sample = 8; - if ((options & G722_SAMPLE_RATE_8000)) - s->eight_k = TRUE; - if ((options & G722_PACKED) && s->bits_per_sample != 8) - s->packed = TRUE; - else - s->packed = FALSE; - s->band[0].det = 32; - s->band[1].det = 8; - return s; -} -/*- End of function --------------------------------------------------------*/ - -int g722_decode_release(g722_decode_state_t *s) -{ - free(s); - return 0; -} -/*- End of function --------------------------------------------------------*/ - -int g722_decode(g722_decode_state_t *s, int16_t amp[], const uint8_t g722_data[], int len) -{ - static const int wl[8] = - { - -60, -30, 58, 172, 334, 538, 1198, 3042 - }; - static const int rl42[16] = - { - 0, 7, 6, 5, 4, 3, 2, 1, 7, 6, 5, 4, 3, 2, 1, 0 - }; - static const int ilb[32] = - { - 2048, 2093, 2139, 2186, 2233, 2282, 2332, - 2383, 2435, 2489, 2543, 2599, 2656, 2714, - 2774, 2834, 2896, 2960, 3025, 3091, 3158, - 3228, 3298, 3371, 3444, 3520, 3597, 3676, - 3756, 3838, 3922, 4008 - }; - static const int wh[3] = - { - 0, -214, 798 - }; - static const int rh2[4] = - { - 2, 1, 2, 1 - }; - static const int qm2[4] = - { - -7408, -1616, 7408, 1616 - }; - static const int qm4[16] = - { - 0, -20456, -12896, -8968, - -6288, -4240, -2584, -1200, - 20456, 12896, 8968, 6288, - 4240, 2584, 1200, 0 - }; - static const int qm5[32] = - { - -280, -280, -23352, -17560, - -14120, -11664, -9752, -8184, - -6864, -5712, -4696, -3784, - -2960, -2208, -1520, -880, - 23352, 17560, 14120, 11664, - 9752, 8184, 6864, 5712, - 4696, 3784, 2960, 2208, - 1520, 880, 280, -280 - }; - static const int qm6[64] = - { - -136, -136, -136, -136, - -24808, -21904, -19008, -16704, - -14984, -13512, -12280, -11192, - -10232, -9360, -8576, -7856, - -7192, -6576, -6000, -5456, - -4944, -4464, -4008, -3576, - -3168, -2776, -2400, -2032, - -1688, -1360, -1040, -728, - 24808, 21904, 19008, 16704, - 14984, 13512, 12280, 11192, - 10232, 9360, 8576, 7856, - 7192, 6576, 6000, 5456, - 4944, 4464, 4008, 3576, - 3168, 2776, 2400, 2032, - 1688, 1360, 1040, 728, - 432, 136, -432, -136 - }; - static const int qmf_coeffs[12] = - { - 3, -11, 12, 32, -210, 951, 3876, -805, 362, -156, 53, -11, - }; - int dlowt; - int rlow; - int ihigh; - int dhigh; - int rhigh; - int xout1; - int xout2; - int wd1; - int wd2; - int wd3; - int code; - int outlen; - int i; - int j; - - outlen = 0; - rhigh = 0; - for (j = 0; j < len; ) - { - if (s->packed) - { - /* Unpack the code bits */ - if (s->in_bits < s->bits_per_sample) - { - s->in_buffer |= (g722_data[j++] << s->in_bits); - s->in_bits += 8; - } - code = s->in_buffer & ((1 << s->bits_per_sample) - 1); - s->in_buffer >>= s->bits_per_sample; - s->in_bits -= s->bits_per_sample; - } - else - { - code = g722_data[j++]; - } - - switch (s->bits_per_sample) - { - default: - case 8: - wd1 = code & 0x3F; - ihigh = (code >> 6) & 0x03; - wd2 = qm6[wd1]; - wd1 >>= 2; - break; - case 7: - wd1 = code & 0x1F; - ihigh = (code >> 5) & 0x03; - wd2 = qm5[wd1]; - wd1 >>= 1; - break; - case 6: - wd1 = code & 0x0F; - ihigh = (code >> 4) & 0x03; - wd2 = qm4[wd1]; - break; - } - /* Block 5L, LOW BAND INVQBL */ - wd2 = (s->band[0].det*wd2) >> 15; - /* Block 5L, RECONS */ - rlow = s->band[0].s + wd2; - /* Block 6L, LIMIT */ - if (rlow > 16383) - rlow = 16383; - else if (rlow < -16384) - rlow = -16384; - - /* Block 2L, INVQAL */ - wd2 = qm4[wd1]; - dlowt = (s->band[0].det*wd2) >> 15; - - /* Block 3L, LOGSCL */ - wd2 = rl42[wd1]; - wd1 = (s->band[0].nb*127) >> 7; - wd1 += wl[wd2]; - if (wd1 < 0) - wd1 = 0; - else if (wd1 > 18432) - wd1 = 18432; - s->band[0].nb = wd1; - - /* Block 3L, SCALEL */ - wd1 = (s->band[0].nb >> 6) & 31; - wd2 = 8 - (s->band[0].nb >> 11); - wd3 = (wd2 < 0) ? (ilb[wd1] << -wd2) : (ilb[wd1] >> wd2); - s->band[0].det = wd3 << 2; - - block4(s, 0, dlowt); - - if (!s->eight_k) - { - /* Block 2H, INVQAH */ - wd2 = qm2[ihigh]; - dhigh = (s->band[1].det*wd2) >> 15; - /* Block 5H, RECONS */ - rhigh = dhigh + s->band[1].s; - /* Block 6H, LIMIT */ - if (rhigh > 16383) - rhigh = 16383; - else if (rhigh < -16384) - rhigh = -16384; - - /* Block 2H, INVQAH */ - wd2 = rh2[ihigh]; - wd1 = (s->band[1].nb*127) >> 7; - wd1 += wh[wd2]; - if (wd1 < 0) - wd1 = 0; - else if (wd1 > 22528) - wd1 = 22528; - s->band[1].nb = wd1; - - /* Block 3H, SCALEH */ - wd1 = (s->band[1].nb >> 6) & 31; - wd2 = 10 - (s->band[1].nb >> 11); - wd3 = (wd2 < 0) ? (ilb[wd1] << -wd2) : (ilb[wd1] >> wd2); - s->band[1].det = wd3 << 2; - - block4(s, 1, dhigh); - } - - if (s->itu_test_mode) - { - amp[outlen++] = (int16_t) (rlow << 1); - amp[outlen++] = (int16_t) (rhigh << 1); - } - else - { - if (s->eight_k) - { - amp[outlen++] = (int16_t) rlow; - } - else - { - /* Apply the receive QMF */ - memcpy(s->x, &s->x[2], 22*sizeof(s->x[0])); - s->x[22] = rlow + rhigh; - s->x[23] = rlow - rhigh; - - xout1 = 0; - xout2 = 0; - for (i = 0; i < 12; i++) - { - xout2 += s->x[2*i]*qmf_coeffs[i]; - xout1 += s->x[2*i + 1]*qmf_coeffs[11 - i]; - } - amp[outlen++] = (int16_t) (xout1 >> 12); - amp[outlen++] = (int16_t) (xout2 >> 12); - } - } - } - return outlen; -} -/*- End of function --------------------------------------------------------*/ -/*- End of file ------------------------------------------------------------*/ +/* + * SpanDSP - a series of DSP components for telephony + * + * g722_decode.c - The ITU G.722 codec, decode part. + * + * Written by Steve Underwood + * + * Copyright (C) 2005 Steve Underwood + * + * Despite my general liking of the GPL, I place my own contributions + * to this code in the public domain for the benefit of all mankind - + * even the slimy ones who might try to proprietize my work and use it + * to my detriment. + * + * Based in part on a single channel G.722 codec which is: + * + * Copyright (c) CMU 1993 + * Computer Science, Speech Group + * Chengxiang Lu and Alex Hauptmann + * + * $Id$ + * + * rtphone: taken from Asterisk (codecs/g722). The only change is that the + * decoder saturates its output instead of letting a corrupt stream wrap + * around int16 (Asterisk casts (rlow << 1) and (xout >> 11) directly). + */ + +/*! \file */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#if 0 +#include +#endif + +#include "g722.h" + +#if !defined(FALSE) +#define FALSE 0 +#endif +#if !defined(TRUE) +#define TRUE (!FALSE) +#endif + +static __inline__ int16_t saturate(int32_t amp) +{ + int16_t amp16; + + /* Hopefully this is optimised for the common case - not clipping */ + amp16 = (int16_t) amp; + if (amp == amp16) + return amp16; + if (amp > INT16_MAX) + return INT16_MAX; + return INT16_MIN; +} +/*- End of function --------------------------------------------------------*/ + +static void block4(g722_decode_state_t *s, int band, int d); + +static void block4(g722_decode_state_t *s, int band, int d) +{ + int wd1; + int wd2; + int wd3; + int i; + + /* Block 4, RECONS */ + s->band[band].d[0] = d; + s->band[band].r[0] = saturate(s->band[band].s + d); + + /* Block 4, PARREC */ + s->band[band].p[0] = saturate(s->band[band].sz + d); + + /* Block 4, UPPOL2 */ + for (i = 0; i < 3; i++) + s->band[band].sg[i] = s->band[band].p[i] >> 15; + wd1 = saturate(s->band[band].a[1] << 2); + + wd2 = (s->band[band].sg[0] == s->band[band].sg[1]) ? -wd1 : wd1; + if (wd2 > 32767) + wd2 = 32767; + wd3 = (s->band[band].sg[0] == s->band[band].sg[2]) ? 128 : -128; + wd3 += (wd2 >> 7); + wd3 += (s->band[band].a[2]*32512) >> 15; + if (wd3 > 12288) + wd3 = 12288; + else if (wd3 < -12288) + wd3 = -12288; + s->band[band].ap[2] = wd3; + + /* Block 4, UPPOL1 */ + s->band[band].sg[0] = s->band[band].p[0] >> 15; + s->band[band].sg[1] = s->band[band].p[1] >> 15; + wd1 = (s->band[band].sg[0] == s->band[band].sg[1]) ? 192 : -192; + wd2 = (s->band[band].a[1]*32640) >> 15; + + s->band[band].ap[1] = saturate(wd1 + wd2); + wd3 = saturate(15360 - s->band[band].ap[2]); + if (s->band[band].ap[1] > wd3) + s->band[band].ap[1] = wd3; + else if (s->band[band].ap[1] < -wd3) + s->band[band].ap[1] = -wd3; + + /* Block 4, UPZERO */ + wd1 = (d == 0) ? 0 : 128; + s->band[band].sg[0] = d >> 15; + for (i = 1; i < 7; i++) + { + s->band[band].sg[i] = s->band[band].d[i] >> 15; + wd2 = (s->band[band].sg[i] == s->band[band].sg[0]) ? wd1 : -wd1; + wd3 = (s->band[band].b[i]*32640) >> 15; + s->band[band].bp[i] = saturate(wd2 + wd3); + } + + /* Block 4, DELAYA */ + for (i = 6; i > 0; i--) + { + s->band[band].d[i] = s->band[band].d[i - 1]; + s->band[band].b[i] = s->band[band].bp[i]; + } + + for (i = 2; i > 0; i--) + { + s->band[band].r[i] = s->band[band].r[i - 1]; + s->band[band].p[i] = s->band[band].p[i - 1]; + s->band[band].a[i] = s->band[band].ap[i]; + } + + /* Block 4, FILTEP */ + wd1 = saturate(s->band[band].r[1] + s->band[band].r[1]); + wd1 = (s->band[band].a[1]*wd1) >> 15; + wd2 = saturate(s->band[band].r[2] + s->band[band].r[2]); + wd2 = (s->band[band].a[2]*wd2) >> 15; + s->band[band].sp = saturate(wd1 + wd2); + + /* Block 4, FILTEZ */ + s->band[band].sz = 0; + for (i = 6; i > 0; i--) + { + wd1 = saturate(s->band[band].d[i] + s->band[band].d[i]); + s->band[band].sz += (s->band[band].b[i]*wd1) >> 15; + } + s->band[band].sz = saturate(s->band[band].sz); + + /* Block 4, PREDIC */ + s->band[band].s = saturate(s->band[band].sp + s->band[band].sz); +} +/*- End of function --------------------------------------------------------*/ + +g722_decode_state_t *g722_decode_init(g722_decode_state_t *s, int rate, int options) +{ + if (s == NULL) + { + if ((s = (g722_decode_state_t *) malloc(sizeof(*s))) == NULL) + return NULL; + } + memset(s, 0, sizeof(*s)); + if (rate == 48000) + s->bits_per_sample = 6; + else if (rate == 56000) + s->bits_per_sample = 7; + else + s->bits_per_sample = 8; + if ((options & G722_SAMPLE_RATE_8000)) + s->eight_k = TRUE; + if ((options & G722_PACKED) && s->bits_per_sample != 8) + s->packed = TRUE; + else + s->packed = FALSE; + s->band[0].det = 32; + s->band[1].det = 8; + return s; +} +/*- End of function --------------------------------------------------------*/ + +int g722_decode_release(g722_decode_state_t *s) +{ + free(s); + return 0; +} +/*- End of function --------------------------------------------------------*/ + +int g722_decode(g722_decode_state_t *s, int16_t amp[], const uint8_t g722_data[], int len) +{ + static const int wl[8] = {-60, -30, 58, 172, 334, 538, 1198, 3042 }; + static const int rl42[16] = {0, 7, 6, 5, 4, 3, 2, 1, 7, 6, 5, 4, 3, 2, 1, 0 }; + static const int ilb[32] = + { + 2048, 2093, 2139, 2186, 2233, 2282, 2332, + 2383, 2435, 2489, 2543, 2599, 2656, 2714, + 2774, 2834, 2896, 2960, 3025, 3091, 3158, + 3228, 3298, 3371, 3444, 3520, 3597, 3676, + 3756, 3838, 3922, 4008 + }; + static const int wh[3] = {0, -214, 798}; + static const int rh2[4] = {2, 1, 2, 1}; + static const int qm2[4] = {-7408, -1616, 7408, 1616}; + static const int qm4[16] = + { + 0, -20456, -12896, -8968, + -6288, -4240, -2584, -1200, + 20456, 12896, 8968, 6288, + 4240, 2584, 1200, 0 + }; + static const int qm5[32] = + { + -280, -280, -23352, -17560, + -14120, -11664, -9752, -8184, + -6864, -5712, -4696, -3784, + -2960, -2208, -1520, -880, + 23352, 17560, 14120, 11664, + 9752, 8184, 6864, 5712, + 4696, 3784, 2960, 2208, + 1520, 880, 280, -280 + }; + static const int qm6[64] = + { + -136, -136, -136, -136, + -24808, -21904, -19008, -16704, + -14984, -13512, -12280, -11192, + -10232, -9360, -8576, -7856, + -7192, -6576, -6000, -5456, + -4944, -4464, -4008, -3576, + -3168, -2776, -2400, -2032, + -1688, -1360, -1040, -728, + 24808, 21904, 19008, 16704, + 14984, 13512, 12280, 11192, + 10232, 9360, 8576, 7856, + 7192, 6576, 6000, 5456, + 4944, 4464, 4008, 3576, + 3168, 2776, 2400, 2032, + 1688, 1360, 1040, 728, + 432, 136, -432, -136 + }; + static const int qmf_coeffs[12] = + { + 3, -11, 12, 32, -210, 951, 3876, -805, 362, -156, 53, -11, + }; + + int dlowt; + int rlow; + int ihigh; + int dhigh; + int rhigh; + int xout1; + int xout2; + int wd1; + int wd2; + int wd3; + int code; + int outlen; + int i; + int j; + + outlen = 0; + rhigh = 0; + for (j = 0; j < len; ) + { + if (s->packed) + { + /* Unpack the code bits */ + if (s->in_bits < s->bits_per_sample) + { + s->in_buffer |= (g722_data[j++] << s->in_bits); + s->in_bits += 8; + } + code = s->in_buffer & ((1 << s->bits_per_sample) - 1); + s->in_buffer >>= s->bits_per_sample; + s->in_bits -= s->bits_per_sample; + } + else + { + code = g722_data[j++]; + } + + switch (s->bits_per_sample) + { + default: + case 8: + wd1 = code & 0x3F; + ihigh = (code >> 6) & 0x03; + wd2 = qm6[wd1]; + wd1 >>= 2; + break; + case 7: + wd1 = code & 0x1F; + ihigh = (code >> 5) & 0x03; + wd2 = qm5[wd1]; + wd1 >>= 1; + break; + case 6: + wd1 = code & 0x0F; + ihigh = (code >> 4) & 0x03; + wd2 = qm4[wd1]; + break; + } + /* Block 5L, LOW BAND INVQBL */ + wd2 = (s->band[0].det*wd2) >> 15; + /* Block 5L, RECONS */ + rlow = s->band[0].s + wd2; + /* Block 6L, LIMIT */ + if (rlow > 16383) + rlow = 16383; + else if (rlow < -16384) + rlow = -16384; + + /* Block 2L, INVQAL */ + wd2 = qm4[wd1]; + dlowt = (s->band[0].det*wd2) >> 15; + + /* Block 3L, LOGSCL */ + wd2 = rl42[wd1]; + wd1 = (s->band[0].nb*127) >> 7; + wd1 += wl[wd2]; + if (wd1 < 0) + wd1 = 0; + else if (wd1 > 18432) + wd1 = 18432; + s->band[0].nb = wd1; + + /* Block 3L, SCALEL */ + wd1 = (s->band[0].nb >> 6) & 31; + wd2 = 8 - (s->band[0].nb >> 11); + wd3 = (wd2 < 0) ? (ilb[wd1] << -wd2) : (ilb[wd1] >> wd2); + s->band[0].det = wd3 << 2; + + block4(s, 0, dlowt); + + if (!s->eight_k) + { + /* Block 2H, INVQAH */ + wd2 = qm2[ihigh]; + dhigh = (s->band[1].det*wd2) >> 15; + /* Block 5H, RECONS */ + rhigh = dhigh + s->band[1].s; + /* Block 6H, LIMIT */ + if (rhigh > 16383) + rhigh = 16383; + else if (rhigh < -16384) + rhigh = -16384; + + /* Block 2H, INVQAH */ + wd2 = rh2[ihigh]; + wd1 = (s->band[1].nb*127) >> 7; + wd1 += wh[wd2]; + if (wd1 < 0) + wd1 = 0; + else if (wd1 > 22528) + wd1 = 22528; + s->band[1].nb = wd1; + + /* Block 3H, SCALEH */ + wd1 = (s->band[1].nb >> 6) & 31; + wd2 = 10 - (s->band[1].nb >> 11); + wd3 = (wd2 < 0) ? (ilb[wd1] << -wd2) : (ilb[wd1] >> wd2); + s->band[1].det = wd3 << 2; + + block4(s, 1, dhigh); + } + + if (s->itu_test_mode) + { + amp[outlen++] = saturate(rlow << 1); + amp[outlen++] = (int16_t) (rhigh << 1); + } + else + { + if (s->eight_k) + { + amp[outlen++] = saturate(rlow << 1); + } + else + { + /* Apply the receive QMF */ + for (i = 0; i < 22; i++) + s->x[i] = s->x[i + 2]; + s->x[22] = rlow + rhigh; + s->x[23] = rlow - rhigh; + + xout1 = 0; + xout2 = 0; + for (i = 0; i < 12; i++) + { + xout2 += s->x[2*i]*qmf_coeffs[i]; + xout1 += s->x[2*i + 1]*qmf_coeffs[11 - i]; + } + amp[outlen++] = saturate(xout1 >> 11); + amp[outlen++] = saturate(xout2 >> 11); + } + } + } + return outlen; +} +/*- End of function --------------------------------------------------------*/ +/*- End of file ------------------------------------------------------------*/ diff --git a/src/libs/g722/g722_encode.c b/src/libs/g722/g722_encode.c index f3898192..cf53c74e 100644 --- a/src/libs/g722/g722_encode.c +++ b/src/libs/g722/g722_encode.c @@ -1,389 +1,400 @@ -/* - * VoIPcodecs - a series of DSP components for telephony - * - * g722_encode.c - The ITU G.722 codec, encode part. - * - * Written by Steve Underwood - * - * Copyright (C) 2005 Steve Underwood - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2, or - * the Lesser GNU General Public License version 2.1, as published by - * the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Based on a single channel 64kbps only G.722 codec which is: - * - ***** Copyright (c) CMU 1993 ***** - * Computer Science, Speech Group - * Chengxiang Lu and Alex Hauptmann - * - * $Id: g722_encode.c,v 1.18 2008/02/09 15:32:56 steveu Exp $ - */ - -/*! \file */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "g722_inttypes.h" -#include -#include -#if defined(HAVE_TGMATH_H) -#include -#endif -#include - -#include "g722_telephony.h" -#include "g722_dc_restore.h" -#include "g722.h" - -static void block4(g722_encode_state_t *s, int band, int d) -{ - int wd1; - int wd2; - int wd3; - int i; - - /* Block 4, RECONS */ - s->band[band].d[0] = d; - s->band[band].r[0] = saturate(s->band[band].s + d); - - /* Block 4, PARREC */ - s->band[band].p[0] = saturate(s->band[band].sz + d); - - /* Block 4, UPPOL2 */ - for (i = 0; i < 3; i++) - s->band[band].sg[i] = s->band[band].p[i] >> 15; - wd1 = saturate(s->band[band].a[1] << 2); - - wd2 = (s->band[band].sg[0] == s->band[band].sg[1]) ? -wd1 : wd1; - if (wd2 > 32767) - wd2 = 32767; - wd3 = (wd2 >> 7) + ((s->band[band].sg[0] == s->band[band].sg[2]) ? 128 : -128); - wd3 += (s->band[band].a[2]*32512) >> 15; - if (wd3 > 12288) - wd3 = 12288; - else if (wd3 < -12288) - wd3 = -12288; - s->band[band].ap[2] = wd3; - - /* Block 4, UPPOL1 */ - s->band[band].sg[0] = s->band[band].p[0] >> 15; - s->band[band].sg[1] = s->band[band].p[1] >> 15; - wd1 = (s->band[band].sg[0] == s->band[band].sg[1]) ? 192 : -192; - wd2 = (s->band[band].a[1]*32640) >> 15; - - s->band[band].ap[1] = saturate(wd1 + wd2); - wd3 = saturate(15360 - s->band[band].ap[2]); - if (s->band[band].ap[1] > wd3) - s->band[band].ap[1] = wd3; - else if (s->band[band].ap[1] < -wd3) - s->band[band].ap[1] = -wd3; - - /* Block 4, UPZERO */ - wd1 = (d == 0) ? 0 : 128; - s->band[band].sg[0] = d >> 15; - for (i = 1; i < 7; i++) - { - s->band[band].sg[i] = s->band[band].d[i] >> 15; - wd2 = (s->band[band].sg[i] == s->band[band].sg[0]) ? wd1 : -wd1; - wd3 = (s->band[band].b[i]*32640) >> 15; - s->band[band].bp[i] = saturate(wd2 + wd3); - } - - /* Block 4, DELAYA */ - for (i = 6; i > 0; i--) - { - s->band[band].d[i] = s->band[band].d[i - 1]; - s->band[band].b[i] = s->band[band].bp[i]; - } - - for (i = 2; i > 0; i--) - { - s->band[band].r[i] = s->band[band].r[i - 1]; - s->band[band].p[i] = s->band[band].p[i - 1]; - s->band[band].a[i] = s->band[band].ap[i]; - } - - /* Block 4, FILTEP */ - wd1 = saturate(s->band[band].r[1] + s->band[band].r[1]); - wd1 = (s->band[band].a[1]*wd1) >> 15; - wd2 = saturate(s->band[band].r[2] + s->band[band].r[2]); - wd2 = (s->band[band].a[2]*wd2) >> 15; - s->band[band].sp = saturate(wd1 + wd2); - - /* Block 4, FILTEZ */ - s->band[band].sz = 0; - for (i = 6; i > 0; i--) - { - wd1 = saturate(s->band[band].d[i] + s->band[band].d[i]); - s->band[band].sz += (s->band[band].b[i]*wd1) >> 15; - } - s->band[band].sz = saturate(s->band[band].sz); - - /* Block 4, PREDIC */ - s->band[band].s = saturate(s->band[band].sp + s->band[band].sz); -} -/*- End of function --------------------------------------------------------*/ - -g722_encode_state_t *g722_encode_init(g722_encode_state_t *s, int rate, int options) -{ - if (s == NULL) - { - if ((s = (g722_encode_state_t *) malloc(sizeof(*s))) == NULL) - return NULL; - } - memset(s, 0, sizeof(*s)); - if (rate == 48000) - s->bits_per_sample = 6; - else if (rate == 56000) - s->bits_per_sample = 7; - else - s->bits_per_sample = 8; - if ((options & G722_SAMPLE_RATE_8000)) - s->eight_k = TRUE; - if ((options & G722_PACKED) && s->bits_per_sample != 8) - s->packed = TRUE; - else - s->packed = FALSE; - s->band[0].det = 32; - s->band[1].det = 8; - return s; -} -/*- End of function --------------------------------------------------------*/ - -int g722_encode_release(g722_encode_state_t *s) -{ - free(s); - return 0; -} -/*- End of function --------------------------------------------------------*/ - -int g722_encode(g722_encode_state_t *s, uint8_t g722_data[], const int16_t amp[], int len) -{ - static const int q6[32] = - { - 0, 35, 72, 110, 150, 190, 233, 276, - 323, 370, 422, 473, 530, 587, 650, 714, - 786, 858, 940, 1023, 1121, 1219, 1339, 1458, - 1612, 1765, 1980, 2195, 2557, 2919, 0, 0 - }; - static const int iln[32] = - { - 0, 63, 62, 31, 30, 29, 28, 27, - 26, 25, 24, 23, 22, 21, 20, 19, - 18, 17, 16, 15, 14, 13, 12, 11, - 10, 9, 8, 7, 6, 5, 4, 0 - }; - static const int ilp[32] = - { - 0, 61, 60, 59, 58, 57, 56, 55, - 54, 53, 52, 51, 50, 49, 48, 47, - 46, 45, 44, 43, 42, 41, 40, 39, - 38, 37, 36, 35, 34, 33, 32, 0 - }; - static const int wl[8] = - { - -60, -30, 58, 172, 334, 538, 1198, 3042 - }; - static const int rl42[16] = - { - 0, 7, 6, 5, 4, 3, 2, 1, 7, 6, 5, 4, 3, 2, 1, 0 - }; - static const int ilb[32] = - { - 2048, 2093, 2139, 2186, 2233, 2282, 2332, - 2383, 2435, 2489, 2543, 2599, 2656, 2714, - 2774, 2834, 2896, 2960, 3025, 3091, 3158, - 3228, 3298, 3371, 3444, 3520, 3597, 3676, - 3756, 3838, 3922, 4008 - }; - static const int qm4[16] = - { - 0, -20456, -12896, -8968, - -6288, -4240, -2584, -1200, - 20456, 12896, 8968, 6288, - 4240, 2584, 1200, 0 - }; - static const int qm2[4] = - { - -7408, -1616, 7408, 1616 - }; - static const int qmf_coeffs[12] = - { - 3, -11, 12, 32, -210, 951, 3876, -805, 362, -156, 53, -11, - }; - static const int ihn[3] = {0, 1, 0}; - static const int ihp[3] = {0, 3, 2}; - static const int wh[3] = {0, -214, 798}; - static const int rh2[4] = {2, 1, 2, 1}; - - int dlow; - int dhigh; - int el; - int wd; - int wd1; - int ril; - int wd2; - int il4; - int ih2; - int wd3; - int eh; - int mih; - int i; - int j; - /* Low and high band PCM from the QMF */ - int xlow; - int xhigh; - int g722_bytes; - /* Even and odd tap accumulators */ - int sumeven; - int sumodd; - int ihigh; - int ilow; - int code; - - g722_bytes = 0; - xhigh = 0; - for (j = 0; j < len; ) - { - if (s->itu_test_mode) - { - xlow = - xhigh = amp[j++] >> 1; - } - else - { - if (s->eight_k) - { - xlow = amp[j++]; - } - else - { - /* Apply the transmit QMF */ - /* Shuffle the buffer down */ - memcpy(s->x, &s->x[2], 22*sizeof(s->x[0])); - s->x[22] = amp[j++]; - s->x[23] = amp[j++]; - - /* Discard every other QMF output */ - sumeven = 0; - sumodd = 0; - for (i = 0; i < 12; i++) - { - sumodd += s->x[2*i]*qmf_coeffs[i]; - sumeven += s->x[2*i + 1]*qmf_coeffs[11 - i]; - } - xlow = (sumeven + sumodd) >> 13; - xhigh = (sumeven - sumodd) >> 13; - } - } - /* Block 1L, SUBTRA */ - el = saturate(xlow - s->band[0].s); - - /* Block 1L, QUANTL */ - wd = (el >= 0) ? el : -(el + 1); - - for (i = 1; i < 30; i++) - { - wd1 = (q6[i]*s->band[0].det) >> 12; - if (wd < wd1) - break; - } - ilow = (el < 0) ? iln[i] : ilp[i]; - - /* Block 2L, INVQAL */ - ril = ilow >> 2; - wd2 = qm4[ril]; - dlow = (s->band[0].det*wd2) >> 15; - - /* Block 3L, LOGSCL */ - il4 = rl42[ril]; - wd = (s->band[0].nb*127) >> 7; - s->band[0].nb = wd + wl[il4]; - if (s->band[0].nb < 0) - s->band[0].nb = 0; - else if (s->band[0].nb > 18432) - s->band[0].nb = 18432; - - /* Block 3L, SCALEL */ - wd1 = (s->band[0].nb >> 6) & 31; - wd2 = 8 - (s->band[0].nb >> 11); - wd3 = (wd2 < 0) ? (ilb[wd1] << -wd2) : (ilb[wd1] >> wd2); - s->band[0].det = wd3 << 2; - - block4(s, 0, dlow); - - if (s->eight_k) - { - /* Just leave the high bits as zero */ - code = (0xC0 | ilow) >> (8 - s->bits_per_sample); - } - else - { - /* Block 1H, SUBTRA */ - eh = saturate(xhigh - s->band[1].s); - - /* Block 1H, QUANTH */ - wd = (eh >= 0) ? eh : -(eh + 1); - wd1 = (564*s->band[1].det) >> 12; - mih = (wd >= wd1) ? 2 : 1; - ihigh = (eh < 0) ? ihn[mih] : ihp[mih]; - - /* Block 2H, INVQAH */ - wd2 = qm2[ihigh]; - dhigh = (s->band[1].det*wd2) >> 15; - - /* Block 3H, LOGSCH */ - ih2 = rh2[ihigh]; - wd = (s->band[1].nb*127) >> 7; - s->band[1].nb = wd + wh[ih2]; - if (s->band[1].nb < 0) - s->band[1].nb = 0; - else if (s->band[1].nb > 22528) - s->band[1].nb = 22528; - - /* Block 3H, SCALEH */ - wd1 = (s->band[1].nb >> 6) & 31; - wd2 = 10 - (s->band[1].nb >> 11); - wd3 = (wd2 < 0) ? (ilb[wd1] << -wd2) : (ilb[wd1] >> wd2); - s->band[1].det = wd3 << 2; - - block4(s, 1, dhigh); - code = ((ihigh << 6) | ilow) >> (8 - s->bits_per_sample); - } - - if (s->packed) - { - /* Pack the code bits */ - s->out_buffer |= (code << s->out_bits); - s->out_bits += s->bits_per_sample; - if (s->out_bits >= 8) - { - g722_data[g722_bytes++] = (uint8_t) (s->out_buffer & 0xFF); - s->out_bits -= 8; - s->out_buffer >>= 8; - } - } - else - { - g722_data[g722_bytes++] = (uint8_t) code; - } - } - return g722_bytes; -} -/*- End of function --------------------------------------------------------*/ -/*- End of file ------------------------------------------------------------*/ +/* + * SpanDSP - a series of DSP components for telephony + * + * g722_encode.c - The ITU G.722 codec, encode part. + * + * Written by Steve Underwood + * + * Copyright (C) 2005 Steve Underwood + * + * All rights reserved. + * + * Despite my general liking of the GPL, I place my own contributions + * to this code in the public domain for the benefit of all mankind - + * even the slimy ones who might try to proprietize my work and use it + * to my detriment. + * + * Based on a single channel 64kbps only G.722 codec which is: + * + ***** Copyright (c) CMU 1993 ***** + * Computer Science, Speech Group + * Chengxiang Lu and Alex Hauptmann + * + * $Id$ + */ + +/*! \file */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#if 0 +#include +#endif + +#include "g722.h" + +#if !defined(FALSE) +#define FALSE 0 +#endif +#if !defined(TRUE) +#define TRUE (!FALSE) +#endif + +static __inline__ int16_t saturate(int32_t amp) +{ + int16_t amp16; + + /* Hopefully this is optimised for the common case - not clipping */ + amp16 = (int16_t) amp; + if (amp == amp16) + return amp16; + if (amp > INT16_MAX) + return INT16_MAX; + return INT16_MIN; +} +/*- End of function --------------------------------------------------------*/ + +static void block4(g722_encode_state_t *s, int band, int d) +{ + int wd1; + int wd2; + int wd3; + int i; + + /* Block 4, RECONS */ + s->band[band].d[0] = d; + s->band[band].r[0] = saturate(s->band[band].s + d); + + /* Block 4, PARREC */ + s->band[band].p[0] = saturate(s->band[band].sz + d); + + /* Block 4, UPPOL2 */ + for (i = 0; i < 3; i++) + s->band[band].sg[i] = s->band[band].p[i] >> 15; + wd1 = saturate(s->band[band].a[1] << 2); + + wd2 = (s->band[band].sg[0] == s->band[band].sg[1]) ? -wd1 : wd1; + if (wd2 > 32767) + wd2 = 32767; + wd3 = (wd2 >> 7) + ((s->band[band].sg[0] == s->band[band].sg[2]) ? 128 : -128); + wd3 += (s->band[band].a[2]*32512) >> 15; + if (wd3 > 12288) + wd3 = 12288; + else if (wd3 < -12288) + wd3 = -12288; + s->band[band].ap[2] = wd3; + + /* Block 4, UPPOL1 */ + s->band[band].sg[0] = s->band[band].p[0] >> 15; + s->band[band].sg[1] = s->band[band].p[1] >> 15; + wd1 = (s->band[band].sg[0] == s->band[band].sg[1]) ? 192 : -192; + wd2 = (s->band[band].a[1]*32640) >> 15; + + s->band[band].ap[1] = saturate(wd1 + wd2); + wd3 = saturate(15360 - s->band[band].ap[2]); + if (s->band[band].ap[1] > wd3) + s->band[band].ap[1] = wd3; + else if (s->band[band].ap[1] < -wd3) + s->band[band].ap[1] = -wd3; + + /* Block 4, UPZERO */ + wd1 = (d == 0) ? 0 : 128; + s->band[band].sg[0] = d >> 15; + for (i = 1; i < 7; i++) + { + s->band[band].sg[i] = s->band[band].d[i] >> 15; + wd2 = (s->band[band].sg[i] == s->band[band].sg[0]) ? wd1 : -wd1; + wd3 = (s->band[band].b[i]*32640) >> 15; + s->band[band].bp[i] = saturate(wd2 + wd3); + } + + /* Block 4, DELAYA */ + for (i = 6; i > 0; i--) + { + s->band[band].d[i] = s->band[band].d[i - 1]; + s->band[band].b[i] = s->band[band].bp[i]; + } + + for (i = 2; i > 0; i--) + { + s->band[band].r[i] = s->band[band].r[i - 1]; + s->band[band].p[i] = s->band[band].p[i - 1]; + s->band[band].a[i] = s->band[band].ap[i]; + } + + /* Block 4, FILTEP */ + wd1 = saturate(s->band[band].r[1] + s->band[band].r[1]); + wd1 = (s->band[band].a[1]*wd1) >> 15; + wd2 = saturate(s->band[band].r[2] + s->band[band].r[2]); + wd2 = (s->band[band].a[2]*wd2) >> 15; + s->band[band].sp = saturate(wd1 + wd2); + + /* Block 4, FILTEZ */ + s->band[band].sz = 0; + for (i = 6; i > 0; i--) + { + wd1 = saturate(s->band[band].d[i] + s->band[band].d[i]); + s->band[band].sz += (s->band[band].b[i]*wd1) >> 15; + } + s->band[band].sz = saturate(s->band[band].sz); + + /* Block 4, PREDIC */ + s->band[band].s = saturate(s->band[band].sp + s->band[band].sz); +} +/*- End of function --------------------------------------------------------*/ + +g722_encode_state_t *g722_encode_init(g722_encode_state_t *s, int rate, int options) +{ + if (s == NULL) + { + if ((s = (g722_encode_state_t *) malloc(sizeof(*s))) == NULL) + return NULL; + } + memset(s, 0, sizeof(*s)); + if (rate == 48000) + s->bits_per_sample = 6; + else if (rate == 56000) + s->bits_per_sample = 7; + else + s->bits_per_sample = 8; + if ((options & G722_SAMPLE_RATE_8000)) + s->eight_k = TRUE; + if ((options & G722_PACKED) && s->bits_per_sample != 8) + s->packed = TRUE; + else + s->packed = FALSE; + s->band[0].det = 32; + s->band[1].det = 8; + return s; +} +/*- End of function --------------------------------------------------------*/ + +int g722_encode_release(g722_encode_state_t *s) +{ + free(s); + return 0; +} +/*- End of function --------------------------------------------------------*/ + +int g722_encode(g722_encode_state_t *s, uint8_t g722_data[], const int16_t amp[], int len) +{ + static const int q6[32] = + { + 0, 35, 72, 110, 150, 190, 233, 276, + 323, 370, 422, 473, 530, 587, 650, 714, + 786, 858, 940, 1023, 1121, 1219, 1339, 1458, + 1612, 1765, 1980, 2195, 2557, 2919, 0, 0 + }; + static const int iln[32] = + { + 0, 63, 62, 31, 30, 29, 28, 27, + 26, 25, 24, 23, 22, 21, 20, 19, + 18, 17, 16, 15, 14, 13, 12, 11, + 10, 9, 8, 7, 6, 5, 4, 0 + }; + static const int ilp[32] = + { + 0, 61, 60, 59, 58, 57, 56, 55, + 54, 53, 52, 51, 50, 49, 48, 47, + 46, 45, 44, 43, 42, 41, 40, 39, + 38, 37, 36, 35, 34, 33, 32, 0 + }; + static const int wl[8] = + { + -60, -30, 58, 172, 334, 538, 1198, 3042 + }; + static const int rl42[16] = + { + 0, 7, 6, 5, 4, 3, 2, 1, 7, 6, 5, 4, 3, 2, 1, 0 + }; + static const int ilb[32] = + { + 2048, 2093, 2139, 2186, 2233, 2282, 2332, + 2383, 2435, 2489, 2543, 2599, 2656, 2714, + 2774, 2834, 2896, 2960, 3025, 3091, 3158, + 3228, 3298, 3371, 3444, 3520, 3597, 3676, + 3756, 3838, 3922, 4008 + }; + static const int qm4[16] = + { + 0, -20456, -12896, -8968, + -6288, -4240, -2584, -1200, + 20456, 12896, 8968, 6288, + 4240, 2584, 1200, 0 + }; + static const int qm2[4] = + { + -7408, -1616, 7408, 1616 + }; + static const int qmf_coeffs[12] = + { + 3, -11, 12, 32, -210, 951, 3876, -805, 362, -156, 53, -11, + }; + static const int ihn[3] = {0, 1, 0}; + static const int ihp[3] = {0, 3, 2}; + static const int wh[3] = {0, -214, 798}; + static const int rh2[4] = {2, 1, 2, 1}; + + int dlow; + int dhigh; + int el; + int wd; + int wd1; + int ril; + int wd2; + int il4; + int ih2; + int wd3; + int eh; + int mih; + int i; + int j; + /* Low and high band PCM from the QMF */ + int xlow; + int xhigh; + int g722_bytes; + /* Even and odd tap accumulators */ + int sumeven; + int sumodd; + int ihigh; + int ilow; + int code; + + g722_bytes = 0; + xhigh = 0; + for (j = 0; j < len; ) + { + if (s->itu_test_mode) + { + xlow = + xhigh = amp[j++] >> 1; + } + else + { + if (s->eight_k) + { + xlow = amp[j++] >> 1; + } + else + { + /* Apply the transmit QMF */ + /* Shuffle the buffer down */ + for (i = 0; i < 22; i++) + s->x[i] = s->x[i + 2]; + s->x[22] = amp[j++]; + s->x[23] = amp[j++]; + + /* Discard every other QMF output */ + sumeven = 0; + sumodd = 0; + for (i = 0; i < 12; i++) + { + sumodd += s->x[2*i]*qmf_coeffs[i]; + sumeven += s->x[2*i + 1]*qmf_coeffs[11 - i]; + } + xlow = (sumeven + sumodd) >> 14; + xhigh = (sumeven - sumodd) >> 14; + } + } + /* Block 1L, SUBTRA */ + el = saturate(xlow - s->band[0].s); + + /* Block 1L, QUANTL */ + wd = (el >= 0) ? el : -(el + 1); + + for (i = 1; i < 30; i++) + { + wd1 = (q6[i]*s->band[0].det) >> 12; + if (wd < wd1) + break; + } + ilow = (el < 0) ? iln[i] : ilp[i]; + + /* Block 2L, INVQAL */ + ril = ilow >> 2; + wd2 = qm4[ril]; + dlow = (s->band[0].det*wd2) >> 15; + + /* Block 3L, LOGSCL */ + il4 = rl42[ril]; + wd = (s->band[0].nb*127) >> 7; + s->band[0].nb = wd + wl[il4]; + if (s->band[0].nb < 0) + s->band[0].nb = 0; + else if (s->band[0].nb > 18432) + s->band[0].nb = 18432; + + /* Block 3L, SCALEL */ + wd1 = (s->band[0].nb >> 6) & 31; + wd2 = 8 - (s->band[0].nb >> 11); + wd3 = (wd2 < 0) ? (ilb[wd1] << -wd2) : (ilb[wd1] >> wd2); + s->band[0].det = wd3 << 2; + + block4(s, 0, dlow); + + if (s->eight_k) + { + /* Just leave the high bits as zero */ + code = (0xC0 | ilow) >> (8 - s->bits_per_sample); + } + else + { + /* Block 1H, SUBTRA */ + eh = saturate(xhigh - s->band[1].s); + + /* Block 1H, QUANTH */ + wd = (eh >= 0) ? eh : -(eh + 1); + wd1 = (564*s->band[1].det) >> 12; + mih = (wd >= wd1) ? 2 : 1; + ihigh = (eh < 0) ? ihn[mih] : ihp[mih]; + + /* Block 2H, INVQAH */ + wd2 = qm2[ihigh]; + dhigh = (s->band[1].det*wd2) >> 15; + + /* Block 3H, LOGSCH */ + ih2 = rh2[ihigh]; + wd = (s->band[1].nb*127) >> 7; + s->band[1].nb = wd + wh[ih2]; + if (s->band[1].nb < 0) + s->band[1].nb = 0; + else if (s->band[1].nb > 22528) + s->band[1].nb = 22528; + + /* Block 3H, SCALEH */ + wd1 = (s->band[1].nb >> 6) & 31; + wd2 = 10 - (s->band[1].nb >> 11); + wd3 = (wd2 < 0) ? (ilb[wd1] << -wd2) : (ilb[wd1] >> wd2); + s->band[1].det = wd3 << 2; + + block4(s, 1, dhigh); + code = ((ihigh << 6) | ilow) >> (8 - s->bits_per_sample); + } + + if (s->packed) + { + /* Pack the code bits */ + s->out_buffer |= (code << s->out_bits); + s->out_bits += s->bits_per_sample; + if (s->out_bits >= 8) + { + g722_data[g722_bytes++] = (uint8_t) (s->out_buffer & 0xFF); + s->out_bits -= 8; + s->out_buffer >>= 8; + } + } + else + { + g722_data[g722_bytes++] = (uint8_t) code; + } + } + return g722_bytes; +} +/*- End of function --------------------------------------------------------*/ +/*- End of file ------------------------------------------------------------*/ diff --git a/src/libs/g722/g722_inttypes.h b/src/libs/g722/g722_inttypes.h deleted file mode 100644 index 28856ee7..00000000 --- a/src/libs/g722/g722_inttypes.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - * SpanDSP - a series of DSP components for telephony - * - * inttypes.h - a fudge for MSVC, which lacks this header - * - * Written by Steve Underwood - * - * Copyright (C) 2006 Michael Jerris - * - * - * This file is released in the public domain. - * - */ - -#if !defined(_INTTYPES_H_) -#define _INTTYPES_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef _MSC_VER - #if (_MSC_VER >= 1400) // VC8+ - #ifndef _CRT_SECURE_NO_DEPRECATE - #define _CRT_SECURE_NO_DEPRECATE - #endif - #ifndef _CRT_NONSTDC_NO_DEPRECATE - #define _CRT_NONSTDC_NO_DEPRECATE - #endif - #endif // VC8+ - - #include - typedef unsigned __int8 uint8_t; - typedef unsigned __int16 uint16_t; - typedef unsigned __int32 uint32_t; - typedef unsigned __int64 uint64_t; - typedef __int8 int8_t; - typedef __int16 int16_t; - typedef __int32 int32_t; - typedef __int64 int64_t; - #define inline __inline - #define __inline__ __inline - #define INT16_MAX 0x7fff - #define INT16_MIN (-INT16_MAX - 1) - #define _MMX_H_ - - /* disable the following warnings - * C4100: The formal parameter is not referenced in the body of the function. The unreferenced parameter is ignored. - * C4200: Non standard extension C zero sized array - * C4706: assignment within conditional expression - * C4244: conversion from 'type1' to 'type2', possible loss of data - * C4295: array is too small to include a terminating null character - * C4125: decimal digit terminates octal escape sequence - */ - #pragma warning(disable:4100 4200 4706 4295 4125) - - //#pragma comment(lib, "ws2_32.lib") - - #define strncasecmp _strnicmp - #define strcasecmp _stricmp - #define snprintf _snprintf - - #if !defined(INFINITY) - #define INFINITY 0x7fffffff - #endif -#else - #include -#endif - -#define PACKAGE "voipcodecs" -#define VERSION "0.0.1andabit" - -#ifndef INT32_MAX - #define INT32_MAX (2147483647) -#endif -#ifndef INT32_MIN - #define INT32_MIN (-2147483647 - 1) -#endif - -#define PRId8 "d" -#define PRId16 "d" -#ifndef PRId32 -# define PRId32 "ld" -#endif - -#ifndef PRId64 -# define PRId64 "lld" -#endif - -#define PRIu8 "u" -#define PRIu16 "u" -#ifndef PRIu32 -# define PRIu32 "lu" -#endif -#ifndef PRIu64 -# define PRIu64 "llu" -#endif -#ifdef __cplusplus -} -#endif - -#endif // _INTTYPES_H_ - diff --git a/src/libs/g722/g722_telephony.h b/src/libs/g722/g722_telephony.h deleted file mode 100644 index 53c92fd2..00000000 --- a/src/libs/g722/g722_telephony.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * VoIPcodecs - a series of DSP components for telephony - * - * telephony.h - some very basic telephony definitions - * - * Written by Steve Underwood - * - * Copyright (C) 2003 Steve Underwood - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the Lesser GNU General Public License version 2.1, as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * $Id: telephony.h,v 1.10 2007/04/05 19:20:50 steveu Exp $ - */ - -#if !defined(_SPANDSP_TELEPHONY_H_) -#define _SPANDSP_TELEPHONY_H_ - -#define SAMPLE_RATE 8000 - -/* This is based on A-law, but u-law is only 0.03dB different */ -#define DBM0_MAX_POWER (3.14f + 3.02f) -#define DBM0_MAX_SINE_POWER (3.14f) -/* This is based on the ITU definition of dbOv in G.100.1 */ -#define DBOV_MAX_POWER (0.0f) -#define DBOV_MAX_SINE_POWER (-3.02f) - -/*! \brief A handler for pure receive. The buffer cannot be altered. */ -typedef int (span_rx_handler_t)(void *s, const int16_t amp[], int len); - -/*! \brief A handler for receive, where the buffer can be altered. */ -typedef int (span_mod_handler_t)(void *s, int16_t amp[], int len); - -/*! \brief A handler for transmit, where the buffer will be filled. */ -typedef int (span_tx_handler_t)(void *s, int16_t amp[], int max_len); - -#define ms_to_samples(t) (((t)*SAMPLE_RATE)/1000) - -#if !defined(FALSE) -#define FALSE 0 -#endif -#if !defined(TRUE) -#define TRUE (!FALSE) -#endif - -#include -#if (_MSC_VER >= 1400) // VC8+ -#define vc_assert(expr) assert(expr);__analysis_assume( expr ) -#else -#define vc_assert(expr) assert(expr) -#endif - -#if defined(__cplusplus) -/* C++ doesn't seem to have sane rounding functions/macros yet */ -#ifndef _MSC_VER -#define lrint(x) ((long int) (x)) -#define lrintf(x) ((long int) (x)) -#endif -#endif - -#endif -/*- End of file ------------------------------------------------------------*/ diff --git a/src/libs/g722/g722codec.c b/src/libs/g722/g722codec.c deleted file mode 100644 index 6ec50dd5..00000000 --- a/src/libs/g722/g722codec.c +++ /dev/null @@ -1,300 +0,0 @@ -/* - * G.722 Plugin codec for OpenH323/OPAL - * - * Copyright (C) 2008 by Hermon Labs, All Rights Reserved - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - * the License for the specific language governing rights and limitations - * under the License. - * - * The Original Code is Open Phone Abstraction Library. - * - * The Initial Developer of the Original Code is Eugene Mednikov - * - * Contributor(s): ______________________________________. - * - * $Revision: 23265 $ - * $Author: rjongbloed $ - * $Date: 2009-08-25 04:25:58 +0300 (вт, 25 серп 2009) $ - */ - -#ifndef PLUGIN_CODEC_DLL_EXPORTS -#include "plugin-config.h" -#endif - -#include - -#include "VoIPCodecs/inttypes.h" -#include "VoIPCodecs/g722.h" - - -#define INCLUDE_SDP_16000_VERSION 0 - -/* Due to a spec error, clock rate is 8kHz even though this is 16kHz codec, - see RFC3551/4.5.2. So some of these values have to be lied about so that - the OPAL system gets it right. - */ -#define CLOCK_RATE 8000 // Clock rate is not samples/second in this case! -#define BITS_PER_SECOND 64000 // raw bits per second -#define FRAME_TIME 1000 // Microseconds in a millisecond -#define SAMPLES_PER_FRAME 16 // Samples in a millisecond -#define BYTES_PER_FRAME 8 // Bytes in a millisecond -#define MAX_FRAMES_PER_PACKET 90 // 90 milliseconds, which means RTP packets smaller than 1500 bytes typical LAN maximum -#define PREF_FRAMES_PER_PACKET 20 // 20 milliseconds - -static const char L16Desc[] = "PCM-16-16kHz"; // Cannot use "L16" as usual, force 16kHz PCM -static const char g722[] = "G.722-64k"; -static const char sdpG722[] = "G722"; - -#if INCLUDE_SDP_16000_VERSION -static const char g722_16[] = "G.722-16kHz"; -#endif - -#define PAYLOAD_CODE 9 - - -///////////////////////////////////////////////////////////////////////////// - -static void * create_encoder(const struct PluginCodec_Definition * codec) -{ - return g722_encode_init(NULL, BITS_PER_SECOND, 0); -} - -static void destroy_encoder(const struct PluginCodec_Definition * codec, void * context) -{ - g722_encode_release(context); -} - -static int encode(const struct PluginCodec_Definition * codec, - void * context, - const void * from, - unsigned * fromLen, - void * to, - unsigned * toLen, - unsigned int * flag) -{ - g722_encode_state_t * state = context; - - if (*toLen < *fromLen / 4) - return 0; // Destination buffer not big enough - - *toLen = g722_encode(state, to, from, *fromLen / 2); - return 1; -} - - -///////////////////////////////////////////////////////////////////////////// - -static void * create_decoder(const struct PluginCodec_Definition * codec) -{ - return g722_decode_init(NULL, BITS_PER_SECOND, 0); -} - -static void destroy_decoder(const struct PluginCodec_Definition * codec, void * context) -{ - g722_decode_release(context); -} - - -static int decode(const struct PluginCodec_Definition * codec, - void * _context, - const void * from, - unsigned * fromLen, - void * to, - unsigned * toLen, - unsigned int * flag) -{ - g722_decode_state_t * state = _context; - - if (*toLen < *fromLen * 4) - return 0; // Destination buffer not big enough - - *toLen = g722_decode(state, to, from, *fromLen) * 2; - return 1; -} - - -///////////////////////////////////////////////////////////////////////////// - -static struct PluginCodec_information licenseInfo = { - 1084181196, // timestamp = Mon 10 May 2004 09:26:36 AM UTC - - "Eugene Mednikov", // source code author - "1.0", // source code version - "em@hermonlabs.com", // source code email - "http://www.hermonlabs.com", // source code URL - "Copyright (C) 2008 by Hermon Labs, All Rights Reserved", // source code copyright - "MPL 1.0", // source code license - PluginCodec_License_MPL, // source code license - - "ITU G.722", // codec description - "Steve Underwood", // codec author - NULL, // codec version - "steveu@coppice.org", // codec email - NULL, // codec URL - NULL, // codec copyright information - NULL, // codec license - PluginCodec_License_LGPL // codec license code -}; - -///////////////////////////////////////////////////////////////////////////// - -static struct PluginCodec_Definition g722CodecDefn[] = -{ -#if INCLUDE_SDP_16000_VERSION - // Include a version for SIP/SDP that indicates the more logical, though - // incorrect by RFC3551/4.5.2, 16000Hz version of G.722. We use dynamic - // payload types to avoid conflict with the compliant 8000Hz version. - { - // encoder - PLUGIN_CODEC_VERSION_WIDEBAND, // codec API version - &licenseInfo, // license information - - PluginCodec_MediaTypeAudio | // audio codec - PluginCodec_InputTypeRaw | // raw input data - PluginCodec_OutputTypeRaw | // raw output data - PluginCodec_RTPTypeDynamic, // specified RTP type - - g722_16, // text decription - L16Desc, // source format - g722_16, // destination format - - 0, // user data - - 16000, // samples per second - BITS_PER_SECOND, // raw bits per second - FRAME_TIME, // microseconds per frame - SAMPLES_PER_FRAME, // samples per frame - BYTES_PER_FRAME, // bytes per frame - PREF_FRAMES_PER_PACKET, // recommended number of frames per packet - MAX_FRAMES_PER_PACKET, // maximum number of frames per packe - PAYLOAD_CODE, // IANA RTP payload code - sdpG722, // RTP payload name - - create_encoder, // create codec function - destroy_encoder, // destroy codec - encode, // encode/decode - NULL, // codec controls - - 0, // h323CapabilityType - NULL // h323CapabilityData - }, - - { - // decoder - PLUGIN_CODEC_VERSION_WIDEBAND, // codec API version - &licenseInfo, // license information - - PluginCodec_MediaTypeAudio | // audio codec - PluginCodec_InputTypeRaw | // raw input data - PluginCodec_OutputTypeRaw | // raw output data - PluginCodec_RTPTypeDynamic, // specified RTP type - - g722_16, // text decription - g722_16, // source format - L16Desc, // destination format - - 0, // user data - - 16000, // samples per second - BITS_PER_SECOND, // raw bits per second - FRAME_TIME, // microseconds per frame - SAMPLES_PER_FRAME, // samples per frame - BYTES_PER_FRAME, // bytes per frame - PREF_FRAMES_PER_PACKET, // recommended number of frames per packet - MAX_FRAMES_PER_PACKET, // maximum number of frames per packe - PAYLOAD_CODE, // IANA RTP payload code - sdpG722, // RTP payload name - - create_decoder, // create codec function - destroy_decoder, // destroy codec - decode, // encode/decode - NULL, // codec controls - - 0, // h323CapabilityType - NULL // h323CapabilityData - }, -#endif - - // Standards compliant version - { - // encoder - PLUGIN_CODEC_VERSION_WIDEBAND, // codec API version - &licenseInfo, // license information - - PluginCodec_MediaTypeAudio | // audio codec - PluginCodec_InputTypeRaw | // raw input data - PluginCodec_OutputTypeRaw | // raw output data - PluginCodec_RTPTypeExplicit, // specified RTP type - - g722, // text decription - L16Desc, // source format - g722, // destination format - - 0, // user data - - CLOCK_RATE, // samples per second - BITS_PER_SECOND, // raw bits per second - FRAME_TIME, // microseconds per frame - SAMPLES_PER_FRAME, // samples per frame - BYTES_PER_FRAME, // bytes per frame - PREF_FRAMES_PER_PACKET, // recommended number of frames per packet - MAX_FRAMES_PER_PACKET, // maximum number of frames per packe - PAYLOAD_CODE, // IANA RTP payload code - sdpG722, // RTP payload name - - create_encoder, // create codec function - destroy_encoder, // destroy codec - encode, // encode/decode - NULL, // codec controls - - PluginCodec_H323AudioCodec_g722_64k, // h323CapabilityType - NULL // h323CapabilityData - }, - - { - // decoder - PLUGIN_CODEC_VERSION_WIDEBAND, // codec API version - &licenseInfo, // license information - - PluginCodec_MediaTypeAudio | // audio codec - PluginCodec_InputTypeRaw | // raw input data - PluginCodec_OutputTypeRaw | // raw output data - PluginCodec_RTPTypeExplicit, // specified RTP type - - g722, // text decription - g722, // source format - L16Desc, // destination format - - 0, // user data - - CLOCK_RATE, // samples per second - BITS_PER_SECOND, // raw bits per second - FRAME_TIME, // microseconds per frame - SAMPLES_PER_FRAME, // samples per frame - BYTES_PER_FRAME, // bytes per frame - PREF_FRAMES_PER_PACKET, // recommended number of frames per packet - MAX_FRAMES_PER_PACKET, // maximum number of frames per packe - PAYLOAD_CODE, // IANA RTP payload code - sdpG722, // RTP payload name - - create_decoder, // create codec function - destroy_decoder, // destroy codec - decode, // encode/decode - NULL, // codec controls - - PluginCodec_H323AudioCodec_g722_64k, // h323CapabilityType - NULL // h323CapabilityData - } -}; - - -PLUGIN_CODEC_IMPLEMENT_ALL(G722, g722CodecDefn, PLUGIN_CODEC_VERSION_WIDEBAND) - -/////////////////////////////////////////////////////////////////////////////