Compare commits
2
Commits
405483a00d
...
03c58c4572
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
03c58c4572 | ||
|
|
c8d9bad845 |
@@ -1132,13 +1132,15 @@ G722Codec::~G722Codec()
|
||||
|
||||
Codec::Info G722Codec::info()
|
||||
{
|
||||
// ToDo: double check the G722 calls - remember RFC has bug about samplerate
|
||||
// G.722 decodes to 16 kHz (640 bytes of PCM per 20 ms frame), but RFC 3551 keeps its RTP
|
||||
// clock at 8 kHz for historical reasons: the timestamp unit is 1/8000, not 1/samplerate.
|
||||
return {.mName = G722_MIME_NAME,
|
||||
.mSamplerate = 8000,
|
||||
.mSamplerate = 16000,
|
||||
.mChannels = 1,
|
||||
.mPcmLength = 640,
|
||||
.mFrameTime = 20,
|
||||
.mRtpLength = 160};
|
||||
.mRtpLength = 160,
|
||||
.mTimestampUnit = 1.0f / 8000};
|
||||
}
|
||||
|
||||
Codec::EncodeResult G722Codec::encode(std::span<const uint8_t> input, std::span<uint8_t> output)
|
||||
@@ -1186,7 +1188,8 @@ const char* G722Codec::G722Factory::name()
|
||||
|
||||
int G722Codec::G722Factory::samplerate()
|
||||
{
|
||||
// Although G722 uses 16000 as rate for timestamping RTP frames - in fact it is 8KHz codec. So return 8KHz here.
|
||||
// The rate SDP advertises (rtpmap G722/8000) is the RTP clock, 8 kHz by RFC 3551, although the
|
||||
// audio is 16 kHz; see G722Codec::info().
|
||||
return 8000;
|
||||
}
|
||||
|
||||
|
||||
@@ -526,7 +526,7 @@ Codec* AudioReceiver::add(const std::shared_ptr<jrtplib::RTPPacket>& p)
|
||||
time_length = lround(double(payloadLength) / codec->rtpLength() * codec->frameTime());
|
||||
|
||||
if (codec)
|
||||
samplerate = codec->samplerate();
|
||||
samplerate = codec->rtpClockRate(); // RTP timestamp units, not PCM rate (G.722)
|
||||
}
|
||||
|
||||
// Process jitter anyway - can we decode payload or not
|
||||
@@ -724,7 +724,7 @@ AudioReceiver::DecodeResult AudioReceiver::decodePacketTo(Audio::DataWindow& out
|
||||
if (mLastPacketTimestamp && mLastPacketTimeLength && mCodec)
|
||||
{
|
||||
int units = rtp.GetTimestamp() - *mLastPacketTimestamp;
|
||||
int milliseconds = units / (mCodec->samplerate() / 1000);
|
||||
int milliseconds = units / (mCodec->rtpClockRate() / 1000);
|
||||
if (milliseconds > mLastPacketTimeLength)
|
||||
{
|
||||
auto silenceLength = std::chrono::milliseconds(milliseconds - mLastPacketTimeLength);
|
||||
@@ -1157,11 +1157,16 @@ AudioReceiver::MediaInfo AudioReceiver::infoFor(jrtplib::RTPPacket& p)
|
||||
|
||||
if (codec->rtpLength() != 0)
|
||||
{
|
||||
int frameCount = static_cast<int>(p.GetPayloadLength() / codec->rtpLength());
|
||||
if (p.GetPayloadType() == 9 /*G729A silence*/ && p.GetPayloadLength() % codec->rtpLength())
|
||||
frameCount++;
|
||||
|
||||
packetTime = std::chrono::milliseconds(frameCount * codec->frameTime());
|
||||
// A G.729 (PT 18) SID frame is shorter than a voice frame but stands for one; other
|
||||
// codecs scale with the payload (G.722 at 10 ms ptime carries half a 160-byte frame).
|
||||
if (p.GetPayloadType() == 18 && p.GetPayloadLength() % codec->rtpLength())
|
||||
{
|
||||
int frameCount = static_cast<int>(p.GetPayloadLength() / codec->rtpLength()) + 1;
|
||||
packetTime = std::chrono::milliseconds(frameCount * codec->frameTime());
|
||||
}
|
||||
else
|
||||
packetTime = std::chrono::milliseconds(
|
||||
lround(double(p.GetPayloadLength()) / codec->rtpLength() * codec->frameTime()));
|
||||
}
|
||||
else if (typeid(*codec) == typeid(OpusCodec))
|
||||
{
|
||||
|
||||
@@ -114,7 +114,7 @@ void AudioStream::setTransmittingCodec(Codec::Factory& factory, int payloadType)
|
||||
mTransmittingCodec = factory.create();
|
||||
mTransmittingPayloadType = payloadType;
|
||||
if (mRtpSession.IsActive())
|
||||
mRtpSession.SetTimestampUnit(1.0 / mTransmittingCodec->samplerate());
|
||||
mRtpSession.SetTimestampUnit(mTransmittingCodec->timestampUnit());
|
||||
}
|
||||
|
||||
PCodec AudioStream::transmittingCodec()
|
||||
@@ -241,7 +241,7 @@ void AudioStream::addData(const void* buffer, int bytes)
|
||||
ICELogMedia(<< "Sending RTP packet pt = " << mTransmittingPayloadType
|
||||
<< ", plength = " << (int)mEncodedAudio.size() << " to ");
|
||||
mRtpSession.SendPacketEx(mEncodedAudio.data(), mEncodedAudio.size(), mTransmittingPayloadType, false,
|
||||
packetTime * codec->samplerate() / 1000, 0, nullptr, 0);
|
||||
packetTime * codec->rtpClockRate() / 1000, 0, nullptr, 0);
|
||||
mEncodedAudio.clear();
|
||||
encodedTime = 0;
|
||||
}
|
||||
|
||||
@@ -66,6 +66,10 @@ public:
|
||||
int frameTime() { return info().mFrameTime; }
|
||||
std::string name() { return info().mName; }
|
||||
float timestampUnit() { return info().mTimestampUnit == 0.0f ? 1.0f / info().mSamplerate : info().mTimestampUnit; }
|
||||
// RTP clock rate in Hz, the unit of RTP timestamps. Equals samplerate() except for codecs
|
||||
// whose RTP clock differs from the decoded audio: G.722 decodes to 16 kHz but its RTP clock
|
||||
// is 8 kHz (RFC 3551). Use it for timestamp arithmetic and jitter, samplerate() for PCM.
|
||||
int rtpClockRate() { return static_cast<int>(1.0f / timestampUnit() + 0.5f); }
|
||||
|
||||
Audio::Format getAudioFormat() { return Audio::Format(this->info().mSamplerate, this->info().mChannels); }
|
||||
|
||||
|
||||
@@ -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})
|
||||
|
||||
|
||||
@@ -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 `<stdint.h>` and maps `__inline__` to `__inline` for MSVC.
|
||||
+153
-184
@@ -1,184 +1,153 @@
|
||||
/*
|
||||
* VoIPcodecs - a series of DSP components for telephony
|
||||
*
|
||||
* g722.h - The ITU G.722 codec.
|
||||
*
|
||||
* Written by Steve Underwood <steveu@coppice.org>
|
||||
*
|
||||
* 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 <steveu@coppice.org>
|
||||
*
|
||||
* 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 <stdint.h> /* 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
|
||||
|
||||
@@ -1,137 +0,0 @@
|
||||
/*
|
||||
* VoIPcodecs - a series of DSP components for telephony
|
||||
*
|
||||
* bitstream.c - Bitstream composition and decomposition routines.
|
||||
*
|
||||
* Written by Steve Underwood <steveu@coppice.org>
|
||||
*
|
||||
* 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 <config.h>
|
||||
#endif
|
||||
|
||||
#include "inttypes.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#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 ------------------------------------------------------------*/
|
||||
@@ -1,89 +0,0 @@
|
||||
/*
|
||||
* VoIPcodecs - a series of DSP components for telephony
|
||||
*
|
||||
* bitstream.h - Bitstream composition and decomposition routines.
|
||||
*
|
||||
* Written by Steve Underwood <steveu@coppice.org>
|
||||
*
|
||||
* 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 ------------------------------------------------------------*/
|
||||
@@ -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 <steveu@coppice.org>
|
||||
*
|
||||
* 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 ------------------------------------------------------------*/
|
||||
+402
-403
@@ -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 <steveu@coppice.org>
|
||||
*
|
||||
* 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 <config.h>
|
||||
#endif
|
||||
|
||||
#include "g722_inttypes.h"
|
||||
#include <memory.h>
|
||||
#include <stdlib.h>
|
||||
#if defined(HAVE_TGMATH_H)
|
||||
#include <tgmath.h>
|
||||
#endif
|
||||
#include <math.h>
|
||||
|
||||
#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 <steveu@coppice.org>
|
||||
*
|
||||
* 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 <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <inttypes.h>
|
||||
#include <memory.h>
|
||||
#include <stdlib.h>
|
||||
#if 0
|
||||
#include <tgmath.h>
|
||||
#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 ------------------------------------------------------------*/
|
||||
|
||||
+400
-389
@@ -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 <steveu@coppice.org>
|
||||
*
|
||||
* 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 <config.h>
|
||||
#endif
|
||||
|
||||
#include "g722_inttypes.h"
|
||||
#include <memory.h>
|
||||
#include <stdlib.h>
|
||||
#if defined(HAVE_TGMATH_H)
|
||||
#include <tgmath.h>
|
||||
#endif
|
||||
#include <math.h>
|
||||
|
||||
#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 <steveu@coppice.org>
|
||||
*
|
||||
* 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 <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <inttypes.h>
|
||||
#include <memory.h>
|
||||
#include <stdlib.h>
|
||||
#if 0
|
||||
#include <tgmath.h>
|
||||
#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 ------------------------------------------------------------*/
|
||||
|
||||
@@ -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 <steveu@coppice.org>
|
||||
*
|
||||
* 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 <windows.h>
|
||||
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 <stdint.h>
|
||||
#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_
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
/*
|
||||
* VoIPcodecs - a series of DSP components for telephony
|
||||
*
|
||||
* telephony.h - some very basic telephony definitions
|
||||
*
|
||||
* Written by Steve Underwood <steveu@coppice.org>
|
||||
*
|
||||
* 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 <assert.h>
|
||||
#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 ------------------------------------------------------------*/
|
||||
@@ -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 <codec/opalplugin.h>
|
||||
|
||||
#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)
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
Reference in New Issue
Block a user