Repo created

This commit is contained in:
Fr4nz D13trich 2025-11-22 14:04:28 +01:00
parent 81b91f4139
commit f8c34fa5ee
22732 changed files with 4815320 additions and 2 deletions

View file

@ -0,0 +1,25 @@
/*
* Copyright(c)1995,97 Mark Olesen <olesen@me.QueensU.CA>
* Queen's Univ at Kingston (Canada)
*
* Permission to use, copy, modify, and distribute this software for
* any purpose without fee is hereby granted, provided that this
* entire notice is included in all copies of any software which is
* or includes a copy or modification of this software and in all
* copies of the supporting documentation for such software.
*
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR QUEEN'S
* UNIVERSITY AT KINGSTON MAKES ANY REPRESENTATION OR WARRANTY OF ANY
* KIND CONCERNING THE MERCHANTABILITY OF THIS SOFTWARE OR ITS
* FITNESS FOR ANY PARTICULAR PURPOSE.
*
* All of which is to say that you can do what you like with this
* source code provided you don't try to sell it as your own and you
* include an unaltered copy of this message (including the
* copyright).
*
* It is also implicitly understood that bug fixes and improvements
* should make their way back to the general Internet community so
* that everyone benefits.
*/

View file

@ -0,0 +1,13 @@
Name: fft
Short Name: fft
URL:
Version: 0
Date: 2018-07-26
License: Custom license
License File: LICENSE
Security Critical: yes
Shipped: yes
Description:
Multivariate complex Fourier transform, computed in place
using mixed-radix Fast Fourier Transform algorithm.

View file

@ -0,0 +1,942 @@
/*
* Copyright(c)1995,97 Mark Olesen <olesen@me.QueensU.CA>
* Queen's Univ at Kingston (Canada)
*
* Permission to use, copy, modify, and distribute this software for
* any purpose without fee is hereby granted, provided that this
* entire notice is included in all copies of any software which is
* or includes a copy or modification of this software and in all
* copies of the supporting documentation for such software.
*
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR QUEEN'S
* UNIVERSITY AT KINGSTON MAKES ANY REPRESENTATION OR WARRANTY OF ANY
* KIND CONCERNING THE MERCHANTABILITY OF THIS SOFTWARE OR ITS
* FITNESS FOR ANY PARTICULAR PURPOSE.
*
* All of which is to say that you can do what you like with this
* source code provided you don't try to sell it as your own and you
* include an unaltered copy of this message (including the
* copyright).
*
* It is also implicitly understood that bug fixes and improvements
* should make their way back to the general Internet community so
* that everyone benefits.
*
* Changes:
* Trivial type modifications by the WebRTC authors.
*/
/*
* File:
* WebRtcIsac_Fftn.c
*
* Public:
* WebRtcIsac_Fftn / fftnf ();
*
* Private:
* WebRtcIsac_Fftradix / fftradixf ();
*
* Descript:
* multivariate complex Fourier transform, computed in place
* using mixed-radix Fast Fourier Transform algorithm.
*
* Fortran code by:
* RC Singleton, Stanford Research Institute, Sept. 1968
*
* translated by f2c (version 19950721).
*
* int WebRtcIsac_Fftn (int ndim, const int dims[], REAL Re[], REAL Im[],
* int iSign, double scaling);
*
* NDIM = the total number dimensions
* DIMS = a vector of array sizes
* if NDIM is zero then DIMS must be zero-terminated
*
* RE and IM hold the real and imaginary components of the data, and return
* the resulting real and imaginary Fourier coefficients. Multidimensional
* data *must* be allocated contiguously. There is no limit on the number
* of dimensions.
*
* ISIGN = the sign of the complex exponential (ie, forward or inverse FFT)
* the magnitude of ISIGN (normally 1) is used to determine the
* correct indexing increment (see below).
*
* SCALING = normalizing constant by which the final result is *divided*
* if SCALING == -1, normalize by total dimension of the transform
* if SCALING < -1, normalize by the square-root of the total dimension
*
* example:
* tri-variate transform with Re[n1][n2][n3], Im[n1][n2][n3]
*
* int dims[3] = {n1,n2,n3}
* WebRtcIsac_Fftn (3, dims, Re, Im, 1, scaling);
*
*-----------------------------------------------------------------------*
* int WebRtcIsac_Fftradix (REAL Re[], REAL Im[], size_t nTotal, size_t nPass,
* size_t nSpan, int iSign, size_t max_factors,
* size_t max_perm);
*
* RE, IM - see above documentation
*
* Although there is no limit on the number of dimensions, WebRtcIsac_Fftradix() must
* be called once for each dimension, but the calls may be in any order.
*
* NTOTAL = the total number of complex data values
* NPASS = the dimension of the current variable
* NSPAN/NPASS = the spacing of consecutive data values while indexing the
* current variable
* ISIGN - see above documentation
*
* example:
* tri-variate transform with Re[n1][n2][n3], Im[n1][n2][n3]
*
* WebRtcIsac_Fftradix (Re, Im, n1*n2*n3, n1, n1, 1, maxf, maxp);
* WebRtcIsac_Fftradix (Re, Im, n1*n2*n3, n2, n1*n2, 1, maxf, maxp);
* WebRtcIsac_Fftradix (Re, Im, n1*n2*n3, n3, n1*n2*n3, 1, maxf, maxp);
*
* single-variate transform,
* NTOTAL = N = NSPAN = (number of complex data values),
*
* WebRtcIsac_Fftradix (Re, Im, n, n, n, 1, maxf, maxp);
*
* The data can also be stored in a single array with alternating real and
* imaginary parts, the magnitude of ISIGN is changed to 2 to give correct
* indexing increment, and data [0] and data [1] used to pass the initial
* addresses for the sequences of real and imaginary values,
*
* example:
* REAL data [2*NTOTAL];
* WebRtcIsac_Fftradix ( &data[0], &data[1], NTOTAL, nPass, nSpan, 2, maxf, maxp);
*
* for temporary allocation:
*
* MAX_FACTORS >= the maximum prime factor of NPASS
* MAX_PERM >= the number of prime factors of NPASS. In addition,
* if the square-free portion K of NPASS has two or more prime
* factors, then MAX_PERM >= (K-1)
*
* storage in FACTOR for a maximum of 15 prime factors of NPASS. if NPASS
* has more than one square-free factor, the product of the square-free
* factors must be <= 210 array storage for maximum prime factor of 23 the
* following two constants should agree with the array dimensions.
*
*----------------------------------------------------------------------*/
#include <stdlib.h>
#include <math.h>
#include "modules/third_party/fft/fft.h"
/* double precision routine */
static int
WebRtcIsac_Fftradix (double Re[], double Im[],
size_t nTotal, size_t nPass, size_t nSpan, int isign,
int max_factors, unsigned int max_perm,
FFTstr *fftstate);
#ifndef M_PI
# define M_PI 3.14159265358979323846264338327950288
#endif
#ifndef SIN60
# define SIN60 0.86602540378443865 /* sin(60 deg) */
# define COS72 0.30901699437494742 /* cos(72 deg) */
# define SIN72 0.95105651629515357 /* sin(72 deg) */
#endif
# define REAL double
# define FFTN WebRtcIsac_Fftn
# define FFTNS "fftn"
# define FFTRADIX WebRtcIsac_Fftradix
# define FFTRADIXS "fftradix"
int WebRtcIsac_Fftns(unsigned int ndim, const int dims[],
double Re[],
double Im[],
int iSign,
double scaling,
FFTstr *fftstate)
{
size_t nSpan, nPass, nTotal;
unsigned int i;
int ret, max_factors, max_perm;
/*
* tally the number of elements in the data array
* and determine the number of dimensions
*/
nTotal = 1;
if (ndim && dims [0])
{
for (i = 0; i < ndim; i++)
{
if (dims [i] <= 0)
{
return -1;
}
nTotal *= dims [i];
}
}
else
{
ndim = 0;
for (i = 0; dims [i]; i++)
{
if (dims [i] <= 0)
{
return -1;
}
nTotal *= dims [i];
ndim++;
}
}
/* determine maximum number of factors and permuations */
#if 1
/*
* follow John Beale's example, just use the largest dimension and don't
* worry about excess allocation. May be someone else will do it?
*/
max_factors = max_perm = 1;
for (i = 0; i < ndim; i++)
{
nSpan = dims [i];
if ((int)nSpan > max_factors)
{
max_factors = (int)nSpan;
}
if ((int)nSpan > max_perm)
{
max_perm = (int)nSpan;
}
}
#else
/* use the constants used in the original Fortran code */
max_factors = 23;
max_perm = 209;
#endif
/* loop over the dimensions: */
nPass = 1;
for (i = 0; i < ndim; i++)
{
nSpan = dims [i];
nPass *= nSpan;
ret = FFTRADIX (Re, Im, nTotal, nSpan, nPass, iSign,
max_factors, max_perm, fftstate);
/* exit, clean-up already done */
if (ret)
return ret;
}
/* Divide through by the normalizing constant: */
if (scaling && scaling != 1.0)
{
if (iSign < 0) iSign = -iSign;
if (scaling < 0.0)
{
scaling = (double)nTotal;
if (scaling < -1.0)
scaling = sqrt (scaling);
}
scaling = 1.0 / scaling; /* multiply is often faster */
for (i = 0; i < nTotal; i += iSign)
{
Re [i] *= scaling;
Im [i] *= scaling;
}
}
return 0;
}
/*
* singleton's mixed radix routine
*
* could move allocation out to WebRtcIsac_Fftn(), but leave it here so that it's
* possible to make this a standalone function
*/
static int FFTRADIX (REAL Re[],
REAL Im[],
size_t nTotal,
size_t nPass,
size_t nSpan,
int iSign,
int max_factors,
unsigned int max_perm,
FFTstr *fftstate)
{
int ii, mfactor, kspan, ispan, inc;
int j, jc, jf, jj, k, k1, k2, k3, k4, kk, kt, nn, ns, nt;
REAL radf;
REAL c1, c2, c3, cd, aa, aj, ak, ajm, ajp, akm, akp;
REAL s1, s2, s3, sd, bb, bj, bk, bjm, bjp, bkm, bkp;
REAL *Rtmp = NULL; /* temp space for real part*/
REAL *Itmp = NULL; /* temp space for imaginary part */
REAL *Cos = NULL; /* Cosine values */
REAL *Sin = NULL; /* Sine values */
REAL s60 = SIN60; /* sin(60 deg) */
REAL c72 = COS72; /* cos(72 deg) */
REAL s72 = SIN72; /* sin(72 deg) */
REAL pi2 = M_PI; /* use PI first, 2 PI later */
fftstate->SpaceAlloced = 0;
fftstate->MaxPermAlloced = 0;
// initialize to avoid warnings
k3 = c2 = c3 = s2 = s3 = 0.0;
if (nPass < 2)
return 0;
/* allocate storage */
if (fftstate->SpaceAlloced < max_factors * sizeof (REAL))
{
#ifdef SUN_BROKEN_REALLOC
if (!fftstate->SpaceAlloced) /* first time */
{
fftstate->SpaceAlloced = max_factors * sizeof (REAL);
}
else
{
#endif
fftstate->SpaceAlloced = max_factors * sizeof (REAL);
#ifdef SUN_BROKEN_REALLOC
}
#endif
}
else
{
/* allow full use of alloc'd space */
max_factors = fftstate->SpaceAlloced / sizeof (REAL);
}
if (fftstate->MaxPermAlloced < max_perm)
{
#ifdef SUN_BROKEN_REALLOC
if (!fftstate->MaxPermAlloced) /* first time */
else
#endif
fftstate->MaxPermAlloced = max_perm;
}
else
{
/* allow full use of alloc'd space */
max_perm = fftstate->MaxPermAlloced;
}
/* assign pointers */
Rtmp = (REAL *) fftstate->Tmp0;
Itmp = (REAL *) fftstate->Tmp1;
Cos = (REAL *) fftstate->Tmp2;
Sin = (REAL *) fftstate->Tmp3;
/*
* Function Body
*/
inc = iSign;
if (iSign < 0) {
s72 = -s72;
s60 = -s60;
pi2 = -pi2;
inc = -inc; /* absolute value */
}
/* adjust for strange increments */
nt = inc * (int)nTotal;
ns = inc * (int)nSpan;
kspan = ns;
nn = nt - inc;
jc = ns / (int)nPass;
radf = pi2 * (double) jc;
pi2 *= 2.0; /* use 2 PI from here on */
ii = 0;
jf = 0;
/* determine the factors of n */
mfactor = 0;
k = (int)nPass;
while (k % 16 == 0) {
mfactor++;
fftstate->factor [mfactor - 1] = 4;
k /= 16;
}
j = 3;
jj = 9;
do {
while (k % jj == 0) {
mfactor++;
fftstate->factor [mfactor - 1] = j;
k /= jj;
}
j += 2;
jj = j * j;
} while (jj <= k);
if (k <= 4) {
kt = mfactor;
fftstate->factor [mfactor] = k;
if (k != 1)
mfactor++;
} else {
if (k - (k / 4 << 2) == 0) {
mfactor++;
fftstate->factor [mfactor - 1] = 2;
k /= 4;
}
kt = mfactor;
j = 2;
do {
if (k % j == 0) {
mfactor++;
fftstate->factor [mfactor - 1] = j;
k /= j;
}
j = ((j + 1) / 2 << 1) + 1;
} while (j <= k);
}
if (kt) {
j = kt;
do {
mfactor++;
fftstate->factor [mfactor - 1] = fftstate->factor [j - 1];
j--;
} while (j);
}
/* test that mfactors is in range */
if (mfactor > FFT_NFACTOR)
{
return -1;
}
/* compute fourier transform */
for (;;) {
sd = radf / (double) kspan;
cd = sin(sd);
cd = 2.0 * cd * cd;
sd = sin(sd + sd);
kk = 0;
ii++;
switch (fftstate->factor [ii - 1]) {
case 2:
/* transform for factor of 2 (including rotation factor) */
kspan /= 2;
k1 = kspan + 2;
do {
do {
k2 = kk + kspan;
ak = Re [k2];
bk = Im [k2];
Re [k2] = Re [kk] - ak;
Im [k2] = Im [kk] - bk;
Re [kk] += ak;
Im [kk] += bk;
kk = k2 + kspan;
} while (kk < nn);
kk -= nn;
} while (kk < jc);
if (kk >= kspan)
goto Permute_Results_Label; /* exit infinite loop */
do {
c1 = 1.0 - cd;
s1 = sd;
do {
do {
do {
k2 = kk + kspan;
ak = Re [kk] - Re [k2];
bk = Im [kk] - Im [k2];
Re [kk] += Re [k2];
Im [kk] += Im [k2];
Re [k2] = c1 * ak - s1 * bk;
Im [k2] = s1 * ak + c1 * bk;
kk = k2 + kspan;
} while (kk < (nt-1));
k2 = kk - nt;
c1 = -c1;
kk = k1 - k2;
} while (kk > k2);
ak = c1 - (cd * c1 + sd * s1);
s1 = sd * c1 - cd * s1 + s1;
c1 = 2.0 - (ak * ak + s1 * s1);
s1 *= c1;
c1 *= ak;
kk += jc;
} while (kk < k2);
k1 += inc + inc;
kk = (k1 - kspan + 1) / 2 + jc - 1;
} while (kk < (jc + jc));
break;
case 4: /* transform for factor of 4 */
ispan = kspan;
kspan /= 4;
do {
c1 = 1.0;
s1 = 0.0;
do {
do {
k1 = kk + kspan;
k2 = k1 + kspan;
k3 = k2 + kspan;
akp = Re [kk] + Re [k2];
akm = Re [kk] - Re [k2];
ajp = Re [k1] + Re [k3];
ajm = Re [k1] - Re [k3];
bkp = Im [kk] + Im [k2];
bkm = Im [kk] - Im [k2];
bjp = Im [k1] + Im [k3];
bjm = Im [k1] - Im [k3];
Re [kk] = akp + ajp;
Im [kk] = bkp + bjp;
ajp = akp - ajp;
bjp = bkp - bjp;
if (iSign < 0) {
akp = akm + bjm;
bkp = bkm - ajm;
akm -= bjm;
bkm += ajm;
} else {
akp = akm - bjm;
bkp = bkm + ajm;
akm += bjm;
bkm -= ajm;
}
/* avoid useless multiplies */
if (s1 == 0.0) {
Re [k1] = akp;
Re [k2] = ajp;
Re [k3] = akm;
Im [k1] = bkp;
Im [k2] = bjp;
Im [k3] = bkm;
} else {
Re [k1] = akp * c1 - bkp * s1;
Re [k2] = ajp * c2 - bjp * s2;
Re [k3] = akm * c3 - bkm * s3;
Im [k1] = akp * s1 + bkp * c1;
Im [k2] = ajp * s2 + bjp * c2;
Im [k3] = akm * s3 + bkm * c3;
}
kk = k3 + kspan;
} while (kk < nt);
c2 = c1 - (cd * c1 + sd * s1);
s1 = sd * c1 - cd * s1 + s1;
c1 = 2.0 - (c2 * c2 + s1 * s1);
s1 *= c1;
c1 *= c2;
/* values of c2, c3, s2, s3 that will get used next time */
c2 = c1 * c1 - s1 * s1;
s2 = 2.0 * c1 * s1;
c3 = c2 * c1 - s2 * s1;
s3 = c2 * s1 + s2 * c1;
kk = kk - nt + jc;
} while (kk < kspan);
kk = kk - kspan + inc;
} while (kk < jc);
if (kspan == jc)
goto Permute_Results_Label; /* exit infinite loop */
break;
default:
/* transform for odd factors */
#ifdef FFT_RADIX4
return -1;
break;
#else /* FFT_RADIX4 */
k = fftstate->factor [ii - 1];
ispan = kspan;
kspan /= k;
switch (k) {
case 3: /* transform for factor of 3 (optional code) */
do {
do {
k1 = kk + kspan;
k2 = k1 + kspan;
ak = Re [kk];
bk = Im [kk];
aj = Re [k1] + Re [k2];
bj = Im [k1] + Im [k2];
Re [kk] = ak + aj;
Im [kk] = bk + bj;
ak -= 0.5 * aj;
bk -= 0.5 * bj;
aj = (Re [k1] - Re [k2]) * s60;
bj = (Im [k1] - Im [k2]) * s60;
Re [k1] = ak - bj;
Re [k2] = ak + bj;
Im [k1] = bk + aj;
Im [k2] = bk - aj;
kk = k2 + kspan;
} while (kk < (nn - 1));
kk -= nn;
} while (kk < kspan);
break;
case 5: /* transform for factor of 5 (optional code) */
c2 = c72 * c72 - s72 * s72;
s2 = 2.0 * c72 * s72;
do {
do {
k1 = kk + kspan;
k2 = k1 + kspan;
k3 = k2 + kspan;
k4 = k3 + kspan;
akp = Re [k1] + Re [k4];
akm = Re [k1] - Re [k4];
bkp = Im [k1] + Im [k4];
bkm = Im [k1] - Im [k4];
ajp = Re [k2] + Re [k3];
ajm = Re [k2] - Re [k3];
bjp = Im [k2] + Im [k3];
bjm = Im [k2] - Im [k3];
aa = Re [kk];
bb = Im [kk];
Re [kk] = aa + akp + ajp;
Im [kk] = bb + bkp + bjp;
ak = akp * c72 + ajp * c2 + aa;
bk = bkp * c72 + bjp * c2 + bb;
aj = akm * s72 + ajm * s2;
bj = bkm * s72 + bjm * s2;
Re [k1] = ak - bj;
Re [k4] = ak + bj;
Im [k1] = bk + aj;
Im [k4] = bk - aj;
ak = akp * c2 + ajp * c72 + aa;
bk = bkp * c2 + bjp * c72 + bb;
aj = akm * s2 - ajm * s72;
bj = bkm * s2 - bjm * s72;
Re [k2] = ak - bj;
Re [k3] = ak + bj;
Im [k2] = bk + aj;
Im [k3] = bk - aj;
kk = k4 + kspan;
} while (kk < (nn-1));
kk -= nn;
} while (kk < kspan);
break;
default:
if (k != jf) {
jf = k;
s1 = pi2 / (double) k;
c1 = cos(s1);
s1 = sin(s1);
if (jf > max_factors){
return -1;
}
Cos [jf - 1] = 1.0;
Sin [jf - 1] = 0.0;
j = 1;
do {
Cos [j - 1] = Cos [k - 1] * c1 + Sin [k - 1] * s1;
Sin [j - 1] = Cos [k - 1] * s1 - Sin [k - 1] * c1;
k--;
Cos [k - 1] = Cos [j - 1];
Sin [k - 1] = -Sin [j - 1];
j++;
} while (j < k);
}
do {
do {
k1 = kk;
k2 = kk + ispan;
ak = aa = Re [kk];
bk = bb = Im [kk];
j = 1;
k1 += kspan;
do {
k2 -= kspan;
j++;
Rtmp [j - 1] = Re [k1] + Re [k2];
ak += Rtmp [j - 1];
Itmp [j - 1] = Im [k1] + Im [k2];
bk += Itmp [j - 1];
j++;
Rtmp [j - 1] = Re [k1] - Re [k2];
Itmp [j - 1] = Im [k1] - Im [k2];
k1 += kspan;
} while (k1 < k2);
Re [kk] = ak;
Im [kk] = bk;
k1 = kk;
k2 = kk + ispan;
j = 1;
do {
k1 += kspan;
k2 -= kspan;
jj = j;
ak = aa;
bk = bb;
aj = 0.0;
bj = 0.0;
k = 1;
do {
k++;
ak += Rtmp [k - 1] * Cos [jj - 1];
bk += Itmp [k - 1] * Cos [jj - 1];
k++;
aj += Rtmp [k - 1] * Sin [jj - 1];
bj += Itmp [k - 1] * Sin [jj - 1];
jj += j;
if (jj > jf) {
jj -= jf;
}
} while (k < jf);
k = jf - j;
Re [k1] = ak - bj;
Im [k1] = bk + aj;
Re [k2] = ak + bj;
Im [k2] = bk - aj;
j++;
} while (j < k);
kk += ispan;
} while (kk < nn);
kk -= nn;
} while (kk < kspan);
break;
}
/* multiply by rotation factor (except for factors of 2 and 4) */
if (ii == mfactor)
goto Permute_Results_Label; /* exit infinite loop */
kk = jc;
do {
c2 = 1.0 - cd;
s1 = sd;
do {
c1 = c2;
s2 = s1;
kk += kspan;
do {
do {
ak = Re [kk];
Re [kk] = c2 * ak - s2 * Im [kk];
Im [kk] = s2 * ak + c2 * Im [kk];
kk += ispan;
} while (kk < nt);
ak = s1 * s2;
s2 = s1 * c2 + c1 * s2;
c2 = c1 * c2 - ak;
kk = kk - nt + kspan;
} while (kk < ispan);
c2 = c1 - (cd * c1 + sd * s1);
s1 += sd * c1 - cd * s1;
c1 = 2.0 - (c2 * c2 + s1 * s1);
s1 *= c1;
c2 *= c1;
kk = kk - ispan + jc;
} while (kk < kspan);
kk = kk - kspan + jc + inc;
} while (kk < (jc + jc));
break;
#endif /* FFT_RADIX4 */
}
}
/* permute the results to normal order---done in two stages */
/* permutation for square factors of n */
Permute_Results_Label:
fftstate->Perm [0] = ns;
if (kt) {
k = kt + kt + 1;
if (mfactor < k)
k--;
j = 1;
fftstate->Perm [k] = jc;
do {
fftstate->Perm [j] = fftstate->Perm [j - 1] / fftstate->factor [j - 1];
fftstate->Perm [k - 1] = fftstate->Perm [k] * fftstate->factor [j - 1];
j++;
k--;
} while (j < k);
k3 = fftstate->Perm [k];
kspan = fftstate->Perm [1];
kk = jc;
k2 = kspan;
j = 1;
if (nPass != nTotal) {
/* permutation for multivariate transform */
Permute_Multi_Label:
do {
do {
k = kk + jc;
do {
/* swap Re [kk] <> Re [k2], Im [kk] <> Im [k2] */
ak = Re [kk]; Re [kk] = Re [k2]; Re [k2] = ak;
bk = Im [kk]; Im [kk] = Im [k2]; Im [k2] = bk;
kk += inc;
k2 += inc;
} while (kk < (k-1));
kk += ns - jc;
k2 += ns - jc;
} while (kk < (nt-1));
k2 = k2 - nt + kspan;
kk = kk - nt + jc;
} while (k2 < (ns-1));
do {
do {
k2 -= fftstate->Perm [j - 1];
j++;
k2 = fftstate->Perm [j] + k2;
} while (k2 > fftstate->Perm [j - 1]);
j = 1;
do {
if (kk < (k2-1))
goto Permute_Multi_Label;
kk += jc;
k2 += kspan;
} while (k2 < (ns-1));
} while (kk < (ns-1));
} else {
/* permutation for single-variate transform (optional code) */
Permute_Single_Label:
do {
/* swap Re [kk] <> Re [k2], Im [kk] <> Im [k2] */
ak = Re [kk]; Re [kk] = Re [k2]; Re [k2] = ak;
bk = Im [kk]; Im [kk] = Im [k2]; Im [k2] = bk;
kk += inc;
k2 += kspan;
} while (k2 < (ns-1));
do {
do {
k2 -= fftstate->Perm [j - 1];
j++;
k2 = fftstate->Perm [j] + k2;
} while (k2 >= fftstate->Perm [j - 1]);
j = 1;
do {
if (kk < k2)
goto Permute_Single_Label;
kk += inc;
k2 += kspan;
} while (k2 < (ns-1));
} while (kk < (ns-1));
}
jc = k3;
}
if ((kt << 1) + 1 >= mfactor)
return 0;
ispan = fftstate->Perm [kt];
/* permutation for square-free factors of n */
j = mfactor - kt;
fftstate->factor [j] = 1;
do {
fftstate->factor [j - 1] *= fftstate->factor [j];
j--;
} while (j != kt);
kt++;
nn = fftstate->factor [kt - 1] - 1;
if (nn > (int) max_perm) {
return -1;
}
j = jj = 0;
for (;;) {
k = kt + 1;
k2 = fftstate->factor [kt - 1];
kk = fftstate->factor [k - 1];
j++;
if (j > nn)
break; /* exit infinite loop */
jj += kk;
while (jj >= k2) {
jj -= k2;
k2 = kk;
k++;
kk = fftstate->factor [k - 1];
jj += kk;
}
fftstate->Perm [j - 1] = jj;
}
/* determine the permutation cycles of length greater than 1 */
j = 0;
for (;;) {
do {
j++;
kk = fftstate->Perm [j - 1];
} while (kk < 0);
if (kk != j) {
do {
k = kk;
kk = fftstate->Perm [k - 1];
fftstate->Perm [k - 1] = -kk;
} while (kk != j);
k3 = kk;
} else {
fftstate->Perm [j - 1] = -j;
if (j == nn)
break; /* exit infinite loop */
}
}
max_factors *= inc;
/* reorder a and b, following the permutation cycles */
for (;;) {
j = k3 + 1;
nt -= ispan;
ii = nt - inc + 1;
if (nt < 0)
break; /* exit infinite loop */
do {
do {
j--;
} while (fftstate->Perm [j - 1] < 0);
jj = jc;
do {
kspan = jj;
if (jj > max_factors) {
kspan = max_factors;
}
jj -= kspan;
k = fftstate->Perm [j - 1];
kk = jc * k + ii + jj;
k1 = kk + kspan - 1;
k2 = 0;
do {
k2++;
Rtmp [k2 - 1] = Re [k1];
Itmp [k2 - 1] = Im [k1];
k1 -= inc;
} while (k1 != (kk-1));
do {
k1 = kk + kspan - 1;
k2 = k1 - jc * (k + fftstate->Perm [k - 1]);
k = -fftstate->Perm [k - 1];
do {
Re [k1] = Re [k2];
Im [k1] = Im [k2];
k1 -= inc;
k2 -= inc;
} while (k1 != (kk-1));
kk = k2 + 1;
} while (k != j);
k1 = kk + kspan - 1;
k2 = 0;
do {
k2++;
Re [k1] = Rtmp [k2 - 1];
Im [k1] = Itmp [k2 - 1];
k1 -= inc;
} while (k1 != (kk-1));
} while (jj);
} while (j != 1);
}
return 0; /* exit point here */
}
/* ---------------------- end-of-file (c source) ---------------------- */

View file

@ -0,0 +1,58 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the ../../../LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/*--------------------------------*-C-*---------------------------------*
* File:
* fftn.h
* ---------------------------------------------------------------------*
* Re[]: real value array
* Im[]: imaginary value array
* nTotal: total number of complex values
* nPass: number of elements involved in this pass of transform
* nSpan: nspan/nPass = number of bytes to increment pointer
* in Re[] and Im[]
* isign: exponent: +1 = forward -1 = reverse
* scaling: normalizing constant by which the final result is *divided*
* scaling == -1, normalize by total dimension of the transform
* scaling < -1, normalize by the square-root of the total dimension
*
* ----------------------------------------------------------------------
* See the comments in the code for correct usage!
*/
#ifndef MODULES_THIRD_PARTY_FFT_FFT_H_
#define MODULES_THIRD_PARTY_FFT_FFT_H_
#define FFT_MAXFFTSIZE 2048
#define FFT_NFACTOR 11
typedef struct {
unsigned int SpaceAlloced;
unsigned int MaxPermAlloced;
double Tmp0[FFT_MAXFFTSIZE];
double Tmp1[FFT_MAXFFTSIZE];
double Tmp2[FFT_MAXFFTSIZE];
double Tmp3[FFT_MAXFFTSIZE];
int Perm[FFT_MAXFFTSIZE];
int factor[FFT_NFACTOR];
} FFTstr;
/* double precision routine */
int WebRtcIsac_Fftns(unsigned int ndim,
const int dims[],
double Re[],
double Im[],
int isign,
double scaling,
FFTstr* fftstate);
#endif /* MODULES_THIRD_PARTY_FFT_FFT_H_ */

View file

@ -0,0 +1,14 @@
/*
* SpanDSP - a series of DSP components for telephony
*
* g711.h - In line A-law and u-law conversion routines
*
* Written by Steve Underwood <steveu@coppice.org>
*
* Copyright (C) 2001 Steve Underwood
*
* Despite my general liking of the GPL, I place 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.
*/

View file

@ -0,0 +1,12 @@
Name: In line A-law and u-law conversion routines
Short Name: g711
URL:
Version: 0
Date: 2018-06-25
License: Custom license
License File: LICENSE
Security Critical: yes
Shipped: yes
Description:
In line A-law and u-law conversion routines

View file

@ -0,0 +1,72 @@
/*
* SpanDSP - a series of DSP components for telephony
*
* g711.c - A-law and u-law transcoding routines
*
* Written by Steve Underwood <steveu@coppice.org>
*
* Copyright (C) 2006 Steve Underwood
*
* Despite my general liking of the GPL, I place 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.
*
* $Id: g711.c,v 1.1 2006/06/07 15:46:39 steveu Exp $
*
* Modifications for WebRtc, 2011/04/28, by tlegrand:
* -Removed unused include files
* -Changed to use WebRtc types
* -Added option to run encoder bitexact with ITU-T reference implementation
*/
#include "modules/third_party/g711/g711.h"
/* Copied from the CCITT G.711 specification */
static const uint8_t ulaw_to_alaw_table[256] = {
42, 43, 40, 41, 46, 47, 44, 45, 34, 35, 32, 33, 38, 39, 36,
37, 58, 59, 56, 57, 62, 63, 60, 61, 50, 51, 48, 49, 54, 55,
52, 53, 10, 11, 8, 9, 14, 15, 12, 13, 2, 3, 0, 1, 6,
7, 4, 26, 27, 24, 25, 30, 31, 28, 29, 18, 19, 16, 17, 22,
23, 20, 21, 106, 104, 105, 110, 111, 108, 109, 98, 99, 96, 97, 102,
103, 100, 101, 122, 120, 126, 127, 124, 125, 114, 115, 112, 113, 118, 119,
116, 117, 75, 73, 79, 77, 66, 67, 64, 65, 70, 71, 68, 69, 90,
91, 88, 89, 94, 95, 92, 93, 82, 82, 83, 83, 80, 80, 81, 81,
86, 86, 87, 87, 84, 84, 85, 85, 170, 171, 168, 169, 174, 175, 172,
173, 162, 163, 160, 161, 166, 167, 164, 165, 186, 187, 184, 185, 190, 191,
188, 189, 178, 179, 176, 177, 182, 183, 180, 181, 138, 139, 136, 137, 142,
143, 140, 141, 130, 131, 128, 129, 134, 135, 132, 154, 155, 152, 153, 158,
159, 156, 157, 146, 147, 144, 145, 150, 151, 148, 149, 234, 232, 233, 238,
239, 236, 237, 226, 227, 224, 225, 230, 231, 228, 229, 250, 248, 254, 255,
252, 253, 242, 243, 240, 241, 246, 247, 244, 245, 203, 201, 207, 205, 194,
195, 192, 193, 198, 199, 196, 197, 218, 219, 216, 217, 222, 223, 220, 221,
210, 210, 211, 211, 208, 208, 209, 209, 214, 214, 215, 215, 212, 212, 213,
213
};
/* These transcoding tables are copied from the CCITT G.711 specification. To
achieve optimal results, do not change them. */
static const uint8_t alaw_to_ulaw_table[256] = {
42, 43, 40, 41, 46, 47, 44, 45, 34, 35, 32, 33, 38, 39, 36,
37, 57, 58, 55, 56, 61, 62, 59, 60, 49, 50, 47, 48, 53, 54,
51, 52, 10, 11, 8, 9, 14, 15, 12, 13, 2, 3, 0, 1, 6,
7, 4, 5, 26, 27, 24, 25, 30, 31, 28, 29, 18, 19, 16, 17,
22, 23, 20, 21, 98, 99, 96, 97, 102, 103, 100, 101, 93, 93, 92,
92, 95, 95, 94, 94, 116, 118, 112, 114, 124, 126, 120, 122, 106, 107,
104, 105, 110, 111, 108, 109, 72, 73, 70, 71, 76, 77, 74, 75, 64,
65, 63, 63, 68, 69, 66, 67, 86, 87, 84, 85, 90, 91, 88, 89,
79, 79, 78, 78, 82, 83, 80, 81, 170, 171, 168, 169, 174, 175, 172,
173, 162, 163, 160, 161, 166, 167, 164, 165, 185, 186, 183, 184, 189, 190,
187, 188, 177, 178, 175, 176, 181, 182, 179, 180, 138, 139, 136, 137, 142,
143, 140, 141, 130, 131, 128, 129, 134, 135, 132, 133, 154, 155, 152, 153,
158, 159, 156, 157, 146, 147, 144, 145, 150, 151, 148, 149, 226, 227, 224,
225, 230, 231, 228, 229, 221, 221, 220, 220, 223, 223, 222, 222, 244, 246,
240, 242, 252, 254, 248, 250, 234, 235, 232, 233, 238, 239, 236, 237, 200,
201, 198, 199, 204, 205, 202, 203, 192, 193, 191, 191, 196, 197, 194, 195,
214, 215, 212, 213, 218, 219, 216, 217, 207, 207, 206, 206, 210, 211, 208,
209
};
uint8_t alaw_to_ulaw(uint8_t alaw) { return alaw_to_ulaw_table[alaw]; }
uint8_t ulaw_to_alaw(uint8_t ulaw) { return ulaw_to_alaw_table[ulaw]; }

View file

@ -0,0 +1,350 @@
/*
* SpanDSP - a series of DSP components for telephony
*
* g711.h - In line A-law and u-law conversion routines
*
* Written by Steve Underwood <steveu@coppice.org>
*
* Copyright (C) 2001 Steve Underwood
*
* Despite my general liking of the GPL, I place 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.
*
* $Id: g711.h,v 1.1 2006/06/07 15:46:39 steveu Exp $
*
* Modifications for WebRtc, 2011/04/28, by tlegrand:
* -Changed to use WebRtc types
* -Changed __inline__ to __inline
* -Two changes to make implementation bitexact with ITU-T reference
* implementation
*/
/*! \page g711_page A-law and mu-law handling
Lookup tables for A-law and u-law look attractive, until you consider the impact
on the CPU cache. If it causes a substantial area of your processor cache to get
hit too often, cache sloshing will severely slow things down. The main reason
these routines are slow in C, is the lack of direct access to the CPU's "find
the first 1" instruction. A little in-line assembler fixes that, and the
conversion routines can be faster than lookup tables, in most real world usage.
A "find the first 1" instruction is available on most modern CPUs, and is a
much underused feature.
If an assembly language method of bit searching is not available, these routines
revert to a method that can be a little slow, so the cache thrashing might not
seem so bad :(
Feel free to submit patches to add fast "find the first 1" support for your own
favourite processor.
Look up tables are used for transcoding between A-law and u-law, since it is
difficult to achieve the precise transcoding procedure laid down in the G.711
specification by other means.
*/
#ifndef MODULES_THIRD_PARTY_G711_G711_H_
#define MODULES_THIRD_PARTY_G711_G711_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#if defined(__i386__)
/*! \brief Find the bit position of the highest set bit in a word
\param bits The word to be searched
\return The bit number of the highest set bit, or -1 if the word is zero. */
static __inline__ int top_bit(unsigned int bits) {
int res;
__asm__ __volatile__(
" movl $-1,%%edx;\n"
" bsrl %%eax,%%edx;\n"
: "=d"(res)
: "a"(bits));
return res;
}
/*! \brief Find the bit position of the lowest set bit in a word
\param bits The word to be searched
\return The bit number of the lowest set bit, or -1 if the word is zero. */
static __inline__ int bottom_bit(unsigned int bits) {
int res;
__asm__ __volatile__(
" movl $-1,%%edx;\n"
" bsfl %%eax,%%edx;\n"
: "=d"(res)
: "a"(bits));
return res;
}
#elif defined(__x86_64__)
static __inline__ int top_bit(unsigned int bits) {
int res;
__asm__ __volatile__(
" movq $-1,%%rdx;\n"
" bsrq %%rax,%%rdx;\n"
: "=d"(res)
: "a"(bits));
return res;
}
static __inline__ int bottom_bit(unsigned int bits) {
int res;
__asm__ __volatile__(
" movq $-1,%%rdx;\n"
" bsfq %%rax,%%rdx;\n"
: "=d"(res)
: "a"(bits));
return res;
}
#else
static __inline int top_bit(unsigned int bits) {
int i;
if (bits == 0) {
return -1;
}
i = 0;
if (bits & 0xFFFF0000) {
bits &= 0xFFFF0000;
i += 16;
}
if (bits & 0xFF00FF00) {
bits &= 0xFF00FF00;
i += 8;
}
if (bits & 0xF0F0F0F0) {
bits &= 0xF0F0F0F0;
i += 4;
}
if (bits & 0xCCCCCCCC) {
bits &= 0xCCCCCCCC;
i += 2;
}
if (bits & 0xAAAAAAAA) {
bits &= 0xAAAAAAAA;
i += 1;
}
return i;
}
static __inline int bottom_bit(unsigned int bits) {
int i;
if (bits == 0) {
return -1;
}
i = 32;
if (bits & 0x0000FFFF) {
bits &= 0x0000FFFF;
i -= 16;
}
if (bits & 0x00FF00FF) {
bits &= 0x00FF00FF;
i -= 8;
}
if (bits & 0x0F0F0F0F) {
bits &= 0x0F0F0F0F;
i -= 4;
}
if (bits & 0x33333333) {
bits &= 0x33333333;
i -= 2;
}
if (bits & 0x55555555) {
bits &= 0x55555555;
i -= 1;
}
return i;
}
#endif
/* N.B. It is tempting to use look-up tables for A-law and u-law conversion.
* However, you should consider the cache footprint.
*
* A 64K byte table for linear to x-law and a 512 byte table for x-law to
* linear sound like peanuts these days, and shouldn't an array lookup be
* real fast? No! When the cache sloshes as badly as this one will, a tight
* calculation may be better. The messiest part is normally finding the
* segment, but a little inline assembly can fix that on an i386, x86_64
* and many other modern processors.
*/
/*
* Mu-law is basically as follows:
*
* Biased Linear Input Code Compressed Code
* ------------------------ ---------------
* 00000001wxyza 000wxyz
* 0000001wxyzab 001wxyz
* 000001wxyzabc 010wxyz
* 00001wxyzabcd 011wxyz
* 0001wxyzabcde 100wxyz
* 001wxyzabcdef 101wxyz
* 01wxyzabcdefg 110wxyz
* 1wxyzabcdefgh 111wxyz
*
* Each biased linear code has a leading 1 which identifies the segment
* number. The value of the segment number is equal to 7 minus the number
* of leading 0's. The quantization interval is directly available as the
* four bits wxyz. * The trailing bits (a - h) are ignored.
*
* Ordinarily the complement of the resulting code word is used for
* transmission, and so the code word is complemented before it is returned.
*
* For further information see John C. Bellamy's Digital Telephony, 1982,
* John Wiley & Sons, pps 98-111 and 472-476.
*/
// #define ULAW_ZEROTRAP /* turn on the trap as per the MIL-STD
//*/
#define ULAW_BIAS 0x84 /* Bias for linear code. */
/*! \brief Encode a linear sample to u-law
\param linear The sample to encode.
\return The u-law value.
*/
static __inline uint8_t linear_to_ulaw(int linear) {
uint8_t u_val;
int mask;
int seg;
/* Get the sign and the magnitude of the value. */
if (linear < 0) {
/* WebRtc, tlegrand: -1 added to get bitexact to reference implementation */
linear = ULAW_BIAS - linear - 1;
mask = 0x7F;
} else {
linear = ULAW_BIAS + linear;
mask = 0xFF;
}
seg = top_bit(linear | 0xFF) - 7;
/*
* Combine the sign, segment, quantization bits,
* and complement the code word.
*/
if (seg >= 8)
u_val = (uint8_t)(0x7F ^ mask);
else
u_val = (uint8_t)(((seg << 4) | ((linear >> (seg + 3)) & 0xF)) ^ mask);
#ifdef ULAW_ZEROTRAP
/* Optional ITU trap */
if (u_val == 0)
u_val = 0x02;
#endif
return u_val;
}
/*! \brief Decode an u-law sample to a linear value.
\param ulaw The u-law sample to decode.
\return The linear value.
*/
static __inline int16_t ulaw_to_linear(uint8_t ulaw) {
int t;
/* Complement to obtain normal u-law value. */
ulaw = ~ulaw;
/*
* Extract and bias the quantization bits. Then
* shift up by the segment number and subtract out the bias.
*/
t = (((ulaw & 0x0F) << 3) + ULAW_BIAS) << (((int)ulaw & 0x70) >> 4);
return (int16_t)((ulaw & 0x80) ? (ULAW_BIAS - t) : (t - ULAW_BIAS));
}
/*
* A-law is basically as follows:
*
* Linear Input Code Compressed Code
* ----------------- ---------------
* 0000000wxyza 000wxyz
* 0000001wxyza 001wxyz
* 000001wxyzab 010wxyz
* 00001wxyzabc 011wxyz
* 0001wxyzabcd 100wxyz
* 001wxyzabcde 101wxyz
* 01wxyzabcdef 110wxyz
* 1wxyzabcdefg 111wxyz
*
* For further information see John C. Bellamy's Digital Telephony, 1982,
* John Wiley & Sons, pps 98-111 and 472-476.
*/
#define ALAW_AMI_MASK 0x55
/*! \brief Encode a linear sample to A-law
\param linear The sample to encode.
\return The A-law value.
*/
static __inline uint8_t linear_to_alaw(int linear) {
int mask;
int seg;
if (linear >= 0) {
/* Sign (bit 7) bit = 1 */
mask = ALAW_AMI_MASK | 0x80;
} else {
/* Sign (bit 7) bit = 0 */
mask = ALAW_AMI_MASK;
/* WebRtc, tlegrand: Changed from -8 to -1 to get bitexact to reference
* implementation */
linear = -linear - 1;
}
/* Convert the scaled magnitude to segment number. */
seg = top_bit(linear | 0xFF) - 7;
if (seg >= 8) {
if (linear >= 0) {
/* Out of range. Return maximum value. */
return (uint8_t)(0x7F ^ mask);
}
/* We must be just a tiny step below zero */
return (uint8_t)(0x00 ^ mask);
}
/* Combine the sign, segment, and quantization bits. */
return (uint8_t)(((seg << 4) | ((linear >> ((seg) ? (seg + 3) : 4)) & 0x0F)) ^
mask);
}
/*! \brief Decode an A-law sample to a linear value.
\param alaw The A-law sample to decode.
\return The linear value.
*/
static __inline int16_t alaw_to_linear(uint8_t alaw) {
int i;
int seg;
alaw ^= ALAW_AMI_MASK;
i = ((alaw & 0x0F) << 4);
seg = (((int)alaw & 0x70) >> 4);
if (seg)
i = (i + 0x108) << (seg - 1);
else
i += 8;
return (int16_t)((alaw & 0x80) ? i : -i);
}
/*! \brief Transcode from A-law to u-law, using the procedure defined in G.711.
\param alaw The A-law sample to transcode.
\return The best matching u-law value.
*/
uint8_t alaw_to_ulaw(uint8_t alaw);
/*! \brief Transcode from u-law to A-law, using the procedure defined in G.711.
\param alaw The u-law sample to transcode.
\return The best matching A-law value.
*/
uint8_t ulaw_to_alaw(uint8_t ulaw);
#ifdef __cplusplus
}
#endif
#endif /* MODULES_THIRD_PARTY_G711_G711_H_ */

View file

@ -0,0 +1,20 @@
/*
* 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
*/

View file

@ -0,0 +1,12 @@
Name: The ITU G.722 codec, encode and decode part.
Short Name: g722
URL:
Version: 0
Date: 2018-06-25
License: Custom license
License File: LICENSE
Security Critical: yes
Shipped: yes
Description:
The ITU G.722 codec, encode and decode part.

View file

@ -0,0 +1,399 @@
/*
* 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: g722_decode.c,v 1.15 2006/07/07 16:37:49 steveu Exp $
*
* Modifications for WebRtc, 2011/04/28, by tlegrand:
* -Removed usage of inttypes.h and tgmath.h
* -Changed to use WebRtc types
* -Changed __inline__ to __inline
* -Added saturation check on output
*/
/*! \file */
#include <memory.h>
#include <stdio.h>
#include <stdlib.h>
#include "modules/third_party/g722/g722_enc_dec.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 > WEBRTC_INT16_MAX)
return WEBRTC_INT16_MAX;
return WEBRTC_INT16_MIN;
}
/*- End of function --------------------------------------------------------*/
static void block4(G722DecoderState *s, int band, int d);
static void block4(G722DecoderState *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] * 4);
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 --------------------------------------------------------*/
G722DecoderState* WebRtc_g722_decode_init(G722DecoderState* s,
int rate,
int options) {
s = s ? s : malloc(sizeof(*s));
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 WebRtc_g722_decode_release(G722DecoderState *s)
{
free(s);
return 0;
}
/*- End of function --------------------------------------------------------*/
size_t WebRtc_g722_decode(G722DecoderState *s, int16_t amp[],
const uint8_t g722_data[], size_t 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;
size_t outlen;
int i;
size_t 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 << 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];
}
/* We shift by 12 to allow for the QMF filters (DC gain = 4096), less 1
to allow for the 15 bit input to the G.722 algorithm. */
/* WebRtc, tlegrand: added saturation */
amp[outlen++] = saturate(xout1 >> 11);
amp[outlen++] = saturate(xout2 >> 11);
}
}
}
return outlen;
}
/*- End of function --------------------------------------------------------*/
/*- End of file ------------------------------------------------------------*/

View file

@ -0,0 +1,154 @@
/*
* 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: g722.h,v 1.10 2006/06/16 12:45:53 steveu Exp $
*
* Modifications for WebRtc, 2011/04/28, by tlegrand:
* -Changed to use WebRtc types
* -Added new defines for minimum and maximum values of short int
*/
/*! \file */
#ifndef MODULES_THIRD_PARTY_G722_G722_H_
#define MODULES_THIRD_PARTY_G722_G722_H_
#include <stddef.h>
#include <stdint.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?
???.
*/
#define WEBRTC_INT16_MAX 32767
#define WEBRTC_INT16_MIN -32768
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;
} G722EncoderState;
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;
} G722DecoderState;
#ifdef __cplusplus
extern "C" {
#endif
G722EncoderState* WebRtc_g722_encode_init(G722EncoderState* s,
int rate,
int options);
int WebRtc_g722_encode_release(G722EncoderState* s);
size_t WebRtc_g722_encode(G722EncoderState* s,
uint8_t g722_data[],
const int16_t amp[],
size_t len);
G722DecoderState* WebRtc_g722_decode_init(G722DecoderState* s,
int rate,
int options);
int WebRtc_g722_decode_release(G722DecoderState* s);
size_t WebRtc_g722_decode(G722DecoderState* s,
int16_t amp[],
const uint8_t g722_data[],
size_t len);
#ifdef __cplusplus
}
#endif
#endif /* MODULES_THIRD_PARTY_G722_G722_H_ */

View file

@ -0,0 +1,429 @@
/*
* 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: g722_encode.c,v 1.14 2006/07/07 16:37:49 steveu Exp $
*
* Modifications for WebRtc, 2011/04/28, by tlegrand:
* -Removed usage of inttypes.h and tgmath.h
* -Changed to use WebRtc types
* -Added option to run encoder bitexact with ITU-T reference implementation
*/
/*! \file */
#include <memory.h>
#include <stdio.h>
#include <stdlib.h>
#include "modules/third_party/g722/g722_enc_dec.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 > WEBRTC_INT16_MAX)
return WEBRTC_INT16_MAX;
return WEBRTC_INT16_MIN;
}
/*- End of function --------------------------------------------------------*/
static void block4(G722EncoderState *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 --------------------------------------------------------*/
G722EncoderState* WebRtc_g722_encode_init(G722EncoderState* s,
int rate,
int options) {
if (s == NULL)
{
if ((s = (G722EncoderState *) 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 WebRtc_g722_encode_release(G722EncoderState *s)
{
free(s);
return 0;
}
/*- End of function --------------------------------------------------------*/
/* WebRtc, tlegrand:
* Only define the following if bit-exactness with reference implementation
* is needed. Will only have any effect if input signal is saturated.
*/
//#define RUN_LIKE_REFERENCE_G722
#ifdef RUN_LIKE_REFERENCE_G722
int16_t limitValues (int16_t rl)
{
int16_t yl;
yl = (rl > 16383) ? 16383 : ((rl < -16384) ? -16384 : rl);
return (yl);
}
#endif
size_t WebRtc_g722_encode(G722EncoderState *s, uint8_t g722_data[],
const int16_t amp[], size_t 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;
size_t j;
/* Low and high band PCM from the QMF */
int xlow;
int xhigh;
size_t 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)
{
/* We shift by 1 to allow for the 15 bit input to the G.722 algorithm. */
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];
}
/* We shift by 12 to allow for the QMF filters (DC gain = 4096), plus 1
to allow for us summing two filters, plus 1 to allow for the 15 bit
input to the G.722 algorithm. */
xlow = (sumeven + sumodd) >> 14;
xhigh = (sumeven - sumodd) >> 14;
#ifdef RUN_LIKE_REFERENCE_G722
/* The following lines are only used to verify bit-exactness
* with reference implementation of G.722. Higher precision
* is achieved without limiting the values.
*/
xlow = limitValues(xlow);
xhigh = limitValues(xhigh);
#endif
}
}
/* 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 ------------------------------------------------------------*/

View file

@ -0,0 +1,91 @@
/*
* $Id: pa_memorybarrier.h 1240 2007-07-17 13:05:07Z bjornroche $
* Portable Audio I/O Library
* Memory barrier utilities
*
* Author: Bjorn Roche, XO Audio, LLC
*
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.portaudio.com
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
/*
* $Id: pa_ringbuffer.c 1421 2009-11-18 16:09:05Z bjornroche $
* Portable Audio I/O Library
* Ring Buffer utility.
*
* Author: Phil Burk, http://www.softsynth.com
* modified for SMP safety on Mac OS X by Bjorn Roche
* modified for SMP safety on Linux by Leland Lucius
* also, allowed for const where possible
* modified for multiple-byte-sized data elements by Sven Fischer
*
* Note that this is safe only for a single-thread reader and a
* single-thread writer.
*
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.portaudio.com
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/

View file

@ -0,0 +1,15 @@
Name: Portaudio library for mac
Short Name: portaudio
URL: https://github.com/PortAudio/portaudio/tree/master/src/common
Version: 9d8563100d841300f1689b186d131347ad43a0f6
Date: 2022-04-12
License: Custom license
License File: LICENSE
Security Critical: yes
Shipped: yes
Description:
Part of portaudio library to operate with memory barriers and ring buffer.
Local changes:
- Minor formatting to make 'git cl format' happy.

View file

@ -0,0 +1,144 @@
/*
* $Id: pa_memorybarrier.h 1240 2007-07-17 13:05:07Z bjornroche $
* Portable Audio I/O Library
* Memory barrier utilities
*
* Author: Bjorn Roche, XO Audio, LLC
*
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.portaudio.com
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
/**
@file pa_memorybarrier.h
@ingroup common_src
*/
/****************
* Some memory barrier primitives based on the system.
* right now only OS X, FreeBSD, and Linux are supported. In addition to
*providing memory barriers, these functions should ensure that data cached in
*registers is written out to cache where it can be snooped by other CPUs. (ie,
*the volatile keyword should not be required)
*
* the primitives that must be defined are:
*
* PaUtil_FullMemoryBarrier()
* PaUtil_ReadMemoryBarrier()
* PaUtil_WriteMemoryBarrier()
*
****************/
#ifndef MODULES_THIRD_PARTY_PORTAUDIO_PA_MEMORYBARRIER_H_
#define MODULES_THIRD_PARTY_PORTAUDIO_PA_MEMORYBARRIER_H_
#if defined(__APPLE__)
/* Support for the atomic library was added in C11.
*/
#if (__STDC_VERSION__ < 201112L) || defined(__STDC_NO_ATOMICS__)
#include <libkern/OSAtomic.h>
/* Here are the memory barrier functions. Mac OS X only provides
full memory barriers, so the three types of barriers are the same,
however, these barriers are superior to compiler-based ones.
These were deprecated in MacOS 10.12. */
#define PaUtil_FullMemoryBarrier() OSMemoryBarrier()
#define PaUtil_ReadMemoryBarrier() OSMemoryBarrier()
#define PaUtil_WriteMemoryBarrier() OSMemoryBarrier()
#else
#include <stdatomic.h>
#define PaUtil_FullMemoryBarrier() atomic_thread_fence(memory_order_seq_cst)
#define PaUtil_ReadMemoryBarrier() atomic_thread_fence(memory_order_acquire)
#define PaUtil_WriteMemoryBarrier() atomic_thread_fence(memory_order_release)
#endif
#elif defined(__GNUC__)
/* GCC >= 4.1 has built-in intrinsics. We'll use those */
#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)
#define PaUtil_FullMemoryBarrier() __sync_synchronize()
#define PaUtil_ReadMemoryBarrier() __sync_synchronize()
#define PaUtil_WriteMemoryBarrier() __sync_synchronize()
/* as a fallback, GCC understands volatile asm and "memory" to mean it
* should not reorder memory read/writes */
/* Note that it is not clear that any compiler actually defines __PPC__,
* it can probably removed safely. */
#elif defined(__ppc__) || defined(__powerpc__) || defined(__PPC__)
#define PaUtil_FullMemoryBarrier() asm volatile("sync" ::: "memory")
#define PaUtil_ReadMemoryBarrier() asm volatile("sync" ::: "memory")
#define PaUtil_WriteMemoryBarrier() asm volatile("sync" ::: "memory")
#elif defined(__i386__) || defined(__i486__) || defined(__i586__) || \
defined(__i686__) || defined(__x86_64__)
#define PaUtil_FullMemoryBarrier() asm volatile("mfence" ::: "memory")
#define PaUtil_ReadMemoryBarrier() asm volatile("lfence" ::: "memory")
#define PaUtil_WriteMemoryBarrier() asm volatile("sfence" ::: "memory")
#else
#ifdef ALLOW_SMP_DANGERS
#warning Memory barriers not defined on this system or system unknown
#warning For SMP safety, you should fix this.
#define PaUtil_FullMemoryBarrier()
#define PaUtil_ReadMemoryBarrier()
#define PaUtil_WriteMemoryBarrier()
#else
# error Memory barriers are not defined on this system. You can still compile by defining ALLOW_SMP_DANGERS, but SMP safety will not be guaranteed.
#endif
#endif
#elif (_MSC_VER >= 1400) && !defined(_WIN32_WCE)
#include <intrin.h>
#pragma intrinsic(_ReadWriteBarrier)
#pragma intrinsic(_ReadBarrier)
#pragma intrinsic(_WriteBarrier)
/* note that MSVC intrinsics _ReadWriteBarrier(), _ReadBarrier(),
* _WriteBarrier() are just compiler barriers *not* memory barriers */
#define PaUtil_FullMemoryBarrier() _ReadWriteBarrier()
#define PaUtil_ReadMemoryBarrier() _ReadBarrier()
#define PaUtil_WriteMemoryBarrier() _WriteBarrier()
#elif defined(_WIN32_WCE)
#define PaUtil_FullMemoryBarrier()
#define PaUtil_ReadMemoryBarrier()
#define PaUtil_WriteMemoryBarrier()
#elif defined(_MSC_VER) || defined(__BORLANDC__)
#define PaUtil_FullMemoryBarrier() _asm { lock add [esp], 0}
#define PaUtil_ReadMemoryBarrier() _asm { lock add [esp], 0}
#define PaUtil_WriteMemoryBarrier() _asm { lock add [esp], 0}
#else
#ifdef ALLOW_SMP_DANGERS
#warning Memory barriers not defined on this system or system unknown
#warning For SMP safety, you should fix this.
#define PaUtil_FullMemoryBarrier()
#define PaUtil_ReadMemoryBarrier()
#define PaUtil_WriteMemoryBarrier()
#else
# error Memory barriers are not defined on this system. You can still compile by defining ALLOW_SMP_DANGERS, but SMP safety will not be guaranteed.
#endif
#endif
#endif /* MODULES_THIRD_PARTY_PORTAUDIO_PA_MEMORYBARRIER_H_ */

View file

@ -0,0 +1,237 @@
/*
* $Id$
* Portable Audio I/O Library
* Ring Buffer utility.
*
* Author: Phil Burk, http://www.softsynth.com
* modified for SMP safety on Mac OS X by Bjorn Roche
* modified for SMP safety on Linux by Leland Lucius
* also, allowed for const where possible
* modified for multiple-byte-sized data elements by Sven Fischer
*
* Note that this is safe only for a single-thread reader and a
* single-thread writer.
*
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.portaudio.com
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
/**
@file
@ingroup common_src
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "pa_ringbuffer.h"
#include <string.h>
#include "pa_memorybarrier.h"
/***************************************************************************
* Initialize FIFO.
* elementCount must be power of 2, returns -1 if not.
*/
ring_buffer_size_t PaUtil_InitializeRingBuffer( PaUtilRingBuffer *rbuf, ring_buffer_size_t elementSizeBytes, ring_buffer_size_t elementCount, void *dataPtr )
{
if( ((elementCount-1) & elementCount) != 0) return -1; /* Not Power of two. */
rbuf->bufferSize = elementCount;
rbuf->buffer = (char *)dataPtr;
PaUtil_FlushRingBuffer( rbuf );
rbuf->bigMask = (elementCount*2)-1;
rbuf->smallMask = (elementCount)-1;
rbuf->elementSizeBytes = elementSizeBytes;
return 0;
}
/***************************************************************************
** Return number of elements available for reading. */
ring_buffer_size_t PaUtil_GetRingBufferReadAvailable( const PaUtilRingBuffer *rbuf )
{
return ( (rbuf->writeIndex - rbuf->readIndex) & rbuf->bigMask );
}
/***************************************************************************
** Return number of elements available for writing. */
ring_buffer_size_t PaUtil_GetRingBufferWriteAvailable( const PaUtilRingBuffer *rbuf )
{
return ( rbuf->bufferSize - PaUtil_GetRingBufferReadAvailable(rbuf));
}
/***************************************************************************
** Clear buffer. Should only be called when buffer is NOT being read or written. */
void PaUtil_FlushRingBuffer( PaUtilRingBuffer *rbuf )
{
rbuf->writeIndex = rbuf->readIndex = 0;
}
/***************************************************************************
** Get address of region(s) to which we can write data.
** If the region is contiguous, size2 will be zero.
** If non-contiguous, size2 will be the size of second region.
** Returns room available to be written or elementCount, whichever is smaller.
*/
ring_buffer_size_t PaUtil_GetRingBufferWriteRegions( PaUtilRingBuffer *rbuf, ring_buffer_size_t elementCount,
void **dataPtr1, ring_buffer_size_t *sizePtr1,
void **dataPtr2, ring_buffer_size_t *sizePtr2 )
{
ring_buffer_size_t index;
ring_buffer_size_t available = PaUtil_GetRingBufferWriteAvailable( rbuf );
if( elementCount > available ) elementCount = available;
/* Check to see if write is not contiguous. */
index = rbuf->writeIndex & rbuf->smallMask;
if( (index + elementCount) > rbuf->bufferSize )
{
/* Write data in two blocks that wrap the buffer. */
ring_buffer_size_t firstHalf = rbuf->bufferSize - index;
*dataPtr1 = &rbuf->buffer[index*rbuf->elementSizeBytes];
*sizePtr1 = firstHalf;
*dataPtr2 = &rbuf->buffer[0];
*sizePtr2 = elementCount - firstHalf;
}
else
{
*dataPtr1 = &rbuf->buffer[index*rbuf->elementSizeBytes];
*sizePtr1 = elementCount;
*dataPtr2 = NULL;
*sizePtr2 = 0;
}
if( available )
PaUtil_FullMemoryBarrier(); /* (write-after-read) => full barrier */
return elementCount;
}
/***************************************************************************
*/
ring_buffer_size_t PaUtil_AdvanceRingBufferWriteIndex( PaUtilRingBuffer *rbuf, ring_buffer_size_t elementCount )
{
/* ensure that previous writes are seen before we update the write index
(write after write)
*/
PaUtil_WriteMemoryBarrier();
return rbuf->writeIndex = (rbuf->writeIndex + elementCount) & rbuf->bigMask;
}
/***************************************************************************
** Get address of region(s) from which we can read data.
** If the region is contiguous, size2 will be zero.
** If non-contiguous, size2 will be the size of second region.
** Returns room available to be read or elementCount, whichever is smaller.
*/
ring_buffer_size_t PaUtil_GetRingBufferReadRegions( PaUtilRingBuffer *rbuf, ring_buffer_size_t elementCount,
void **dataPtr1, ring_buffer_size_t *sizePtr1,
void **dataPtr2, ring_buffer_size_t *sizePtr2 )
{
ring_buffer_size_t index;
ring_buffer_size_t available = PaUtil_GetRingBufferReadAvailable( rbuf ); /* doesn't use memory barrier */
if( elementCount > available ) elementCount = available;
/* Check to see if read is not contiguous. */
index = rbuf->readIndex & rbuf->smallMask;
if( (index + elementCount) > rbuf->bufferSize )
{
/* Write data in two blocks that wrap the buffer. */
ring_buffer_size_t firstHalf = rbuf->bufferSize - index;
*dataPtr1 = &rbuf->buffer[index*rbuf->elementSizeBytes];
*sizePtr1 = firstHalf;
*dataPtr2 = &rbuf->buffer[0];
*sizePtr2 = elementCount - firstHalf;
}
else
{
*dataPtr1 = &rbuf->buffer[index*rbuf->elementSizeBytes];
*sizePtr1 = elementCount;
*dataPtr2 = NULL;
*sizePtr2 = 0;
}
if( available )
PaUtil_ReadMemoryBarrier(); /* (read-after-read) => read barrier */
return elementCount;
}
/***************************************************************************
*/
ring_buffer_size_t PaUtil_AdvanceRingBufferReadIndex( PaUtilRingBuffer *rbuf, ring_buffer_size_t elementCount )
{
/* ensure that previous reads (copies out of the ring buffer) are always completed before updating (writing) the read index.
(write-after-read) => full barrier
*/
PaUtil_FullMemoryBarrier();
return rbuf->readIndex = (rbuf->readIndex + elementCount) & rbuf->bigMask;
}
/***************************************************************************
** Return elements written. */
ring_buffer_size_t PaUtil_WriteRingBuffer( PaUtilRingBuffer *rbuf, const void *data, ring_buffer_size_t elementCount )
{
ring_buffer_size_t size1, size2, numWritten;
void *data1, *data2;
numWritten = PaUtil_GetRingBufferWriteRegions( rbuf, elementCount, &data1, &size1, &data2, &size2 );
if( size2 > 0 )
{
memcpy( data1, data, size1*rbuf->elementSizeBytes );
data = ((char *)data) + size1*rbuf->elementSizeBytes;
memcpy( data2, data, size2*rbuf->elementSizeBytes );
}
else
{
memcpy( data1, data, size1*rbuf->elementSizeBytes );
}
PaUtil_AdvanceRingBufferWriteIndex( rbuf, numWritten );
return numWritten;
}
/***************************************************************************
** Return elements read. */
ring_buffer_size_t PaUtil_ReadRingBuffer( PaUtilRingBuffer *rbuf, void *data, ring_buffer_size_t elementCount )
{
ring_buffer_size_t size1, size2, numRead;
void *data1, *data2;
numRead = PaUtil_GetRingBufferReadRegions( rbuf, elementCount, &data1, &size1, &data2, &size2 );
if( size2 > 0 )
{
memcpy( data, data1, size1*rbuf->elementSizeBytes );
data = ((char *)data) + size1*rbuf->elementSizeBytes;
memcpy( data, data2, size2*rbuf->elementSizeBytes );
}
else
{
memcpy( data, data1, size1*rbuf->elementSizeBytes );
}
PaUtil_AdvanceRingBufferReadIndex( rbuf, numRead );
return numRead;
}

View file

@ -0,0 +1,263 @@
#ifndef MODULES_THIRD_PARTY_PORTAUDIO_PA_RINGBUFFER_H_
#define MODULES_THIRD_PARTY_PORTAUDIO_PA_RINGBUFFER_H_
/*
* $Id$
* Portable Audio I/O Library
* Ring Buffer utility.
*
* Author: Phil Burk, http://www.softsynth.com
* modified for SMP safety on OS X by Bjorn Roche.
* also allowed for const where possible.
* modified for multiple-byte-sized data elements by Sven Fischer
*
* Note that this is safe only for a single-thread reader
* and a single-thread writer.
*
* This program is distributed with the PortAudio Portable Audio Library.
* For more information see: http://www.portaudio.com
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
/** @file
@ingroup common_src
@brief Single-reader single-writer lock-free ring buffer
PaUtilRingBuffer is a ring buffer used to transport samples between
different execution contexts (threads, OS callbacks, interrupt handlers)
without requiring the use of any locks. This only works when there is
a single reader and a single writer (ie. one thread or callback writes
to the ring buffer, another thread or callback reads from it).
The PaUtilRingBuffer structure manages a ring buffer containing N
elements, where N must be a power of two. An element may be any size
(specified in bytes).
The memory area used to store the buffer elements must be allocated by
the client prior to calling PaUtil_InitializeRingBuffer() and must outlive
the use of the ring buffer.
@note The ring buffer functions are not normally exposed in the PortAudio
libraries. If you want to call them then you will need to add pa_ringbuffer.c
to your application source code.
*/
#if defined(__APPLE__)
#include <sys/types.h>
typedef int32_t ring_buffer_size_t;
#elif defined(__GNUC__)
typedef long ring_buffer_size_t;
#elif (_MSC_VER >= 1400)
typedef long ring_buffer_size_t;
#elif defined(_MSC_VER) || defined(__BORLANDC__)
typedef long ring_buffer_size_t;
#else
typedef long ring_buffer_size_t;
#endif
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
typedef struct PaUtilRingBuffer {
ring_buffer_size_t bufferSize; /**< Number of elements in FIFO. Power of 2.
Set by PaUtil_InitRingBuffer. */
volatile ring_buffer_size_t
writeIndex; /**< Index of next writable element. Set by
PaUtil_AdvanceRingBufferWriteIndex. */
volatile ring_buffer_size_t
readIndex; /**< Index of next readable element. Set by
PaUtil_AdvanceRingBufferReadIndex. */
ring_buffer_size_t bigMask; /**< Used for wrapping indices with extra bit to
distinguish full/empty. */
ring_buffer_size_t smallMask; /**< Used for fitting indices to buffer. */
ring_buffer_size_t elementSizeBytes; /**< Number of bytes per element. */
char* buffer; /**< Pointer to the buffer containing the actual data. */
} PaUtilRingBuffer;
/** Initialize Ring Buffer to empty state ready to have elements written to it.
@param rbuf The ring buffer.
@param elementSizeBytes The size of a single data element in bytes.
@param elementCount The number of elements in the buffer (must be a power of
2).
@param dataPtr A pointer to a previously allocated area where the data
will be maintained. It must be elementCount*elementSizeBytes long.
@return -1 if elementCount is not a power of 2, otherwise 0.
*/
ring_buffer_size_t PaUtil_InitializeRingBuffer(
PaUtilRingBuffer* rbuf,
ring_buffer_size_t elementSizeBytes,
ring_buffer_size_t elementCount,
void* dataPtr);
/** Reset buffer to empty. Should only be called when buffer is NOT being read
or written.
@param rbuf The ring buffer.
*/
void PaUtil_FlushRingBuffer(PaUtilRingBuffer* rbuf);
/** Retrieve the number of elements available in the ring buffer for writing.
@param rbuf The ring buffer.
@return The number of elements available for writing.
*/
ring_buffer_size_t PaUtil_GetRingBufferWriteAvailable(
const PaUtilRingBuffer* rbuf);
/** Retrieve the number of elements available in the ring buffer for reading.
@param rbuf The ring buffer.
@return The number of elements available for reading.
*/
ring_buffer_size_t PaUtil_GetRingBufferReadAvailable(
const PaUtilRingBuffer* rbuf);
/** Write data to the ring buffer.
@param rbuf The ring buffer.
@param data The address of new data to write to the buffer.
@param elementCount The number of elements to be written.
@return The number of elements written.
*/
ring_buffer_size_t PaUtil_WriteRingBuffer(PaUtilRingBuffer* rbuf,
const void* data,
ring_buffer_size_t elementCount);
/** Read data from the ring buffer.
@param rbuf The ring buffer.
@param data The address where the data should be stored.
@param elementCount The number of elements to be read.
@return The number of elements read.
*/
ring_buffer_size_t PaUtil_ReadRingBuffer(PaUtilRingBuffer* rbuf,
void* data,
ring_buffer_size_t elementCount);
/** Get address of region(s) to which we can write data.
@param rbuf The ring buffer.
@param elementCount The number of elements desired.
@param dataPtr1 The address where the first (or only) region pointer will be
stored.
@param sizePtr1 The address where the first (or only) region length will be
stored.
@param dataPtr2 The address where the second region pointer will be stored if
the first region is too small to satisfy elementCount.
@param sizePtr2 The address where the second region length will be stored if
the first region is too small to satisfy elementCount.
@return The room available to be written or elementCount, whichever is smaller.
*/
ring_buffer_size_t PaUtil_GetRingBufferWriteRegions(
PaUtilRingBuffer* rbuf,
ring_buffer_size_t elementCount,
void** dataPtr1,
ring_buffer_size_t* sizePtr1,
void** dataPtr2,
ring_buffer_size_t* sizePtr2);
/** Advance the write index to the next location to be written.
@param rbuf The ring buffer.
@param elementCount The number of elements to advance.
@return The new position.
*/
ring_buffer_size_t PaUtil_AdvanceRingBufferWriteIndex(
PaUtilRingBuffer* rbuf,
ring_buffer_size_t elementCount);
/** Get address of region(s) from which we can read data.
@param rbuf The ring buffer.
@param elementCount The number of elements desired.
@param dataPtr1 The address where the first (or only) region pointer will be
stored.
@param sizePtr1 The address where the first (or only) region length will be
stored.
@param dataPtr2 The address where the second region pointer will be stored if
the first region is too small to satisfy elementCount.
@param sizePtr2 The address where the second region length will be stored if
the first region is too small to satisfy elementCount.
@return The number of elements available for reading.
*/
ring_buffer_size_t PaUtil_GetRingBufferReadRegions(
PaUtilRingBuffer* rbuf,
ring_buffer_size_t elementCount,
void** dataPtr1,
ring_buffer_size_t* sizePtr1,
void** dataPtr2,
ring_buffer_size_t* sizePtr2);
/** Advance the read index to the next location to be read.
@param rbuf The ring buffer.
@param elementCount The number of elements to advance.
@return The new position.
*/
ring_buffer_size_t PaUtil_AdvanceRingBufferReadIndex(
PaUtilRingBuffer* rbuf,
ring_buffer_size_t elementCount);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* MODULES_THIRD_PARTY_PORTAUDIO_PA_RINGBUFFER_H_ */