prm2bits_ld8k -converts encoder parameter vector into vector of serial bits
- *bits2prm_ld8k - converts serial received bits to encoder parameter vector
+ *bits2prm_ld8k - converts serial received bits to encoder parameter vector
*
* The transmitted parameters for 8000 bits/sec are:
*
@@ -45,164 +47,105 @@
*
* @author Lubomir Marinov (translation of ITU-T C source code to Java)
*/
-namespace SIPSorcery.Media.G729Codec
+namespace SIPSorcery.Media.G729Codec;
+
+internal static class Bits
{
- internal class Bits
- {
- /* ITU-T G.729 Software Package Release 2 (November 2006) */
- /*
- ITU-T G.729 Annex C - Reference C code for floating point
- implementation of G.729
- Version 1.01 of 15.September.98
+ /* ITU-T G.729 Software Package Release 2 (November 2006) */
+ /*
+ITU-T G.729 Annex C - Reference C code for floating point
+ implementation of G.729
+ Version 1.01 of 15.September.98
*/
- /*
+ /*
----------------------------------------------------------------------
- COPYRIGHT NOTICE
+ COPYRIGHT NOTICE
----------------------------------------------------------------------
- ITU-T G.729 Annex C ANSI C source code
- Copyright (C) 1998, AT&T, France Telecom, NTT, University of
- Sherbrooke. All rights reserved.
+ITU-T G.729 Annex C ANSI C source code
+Copyright (C) 1998, AT&T, France Telecom, NTT, University of
+Sherbrooke. All rights reserved.
----------------------------------------------------------------------
*/
- /*
- File : BITS.C
- Used for the floating point version of both
- G.729 main body and G.729A
+ /*
+File : BITS.C
+Used for the floating point version of both
+G.729 main body and G.729A
*/
- /**
- * Converts encoder parameter vector into vector of serial bits.
- *
- * @param prm input : encoded parameters
- * @param bits output: serial bits
- */
+ ///
+ /// Converts encoder parameter vector into vector of serial bits using spans.
+ ///
+ /// Input: encoded parameters as ReadOnlySpan
+ /// Output: serial bits as Span
+ public static void prm2bits_ld8k(
+ ReadOnlySpan prm,
+ Span bits
+ )
+ {
+ var j = 0;
+ bits[j++] = Ld8k.SYNC_WORD; // At receiver this bit indicates BFI
+ bits[j++] = Ld8k.SIZE_WORD; // Number of bits in this frame
- public static void prm2bits_ld8k(
- int[] prm,
- short[] bits
- )
+ for (var i = 0; i < Ld8k.PRM_SIZE; i++)
{
- var PRM_SIZE = Ld8k.PRM_SIZE;
- var SIZE_WORD = Ld8k.SIZE_WORD;
- var SYNC_WORD = Ld8k.SYNC_WORD;
- var bitsno = TabLd8k.bitsno;
-
- int j = 0, i;
- bits[j] = SYNC_WORD; /* At receiver this bit indicates BFI */
- j++;
- bits[j] = SIZE_WORD; /* Number of bits in this frame */
- j++;
-
- for (i = 0; i < PRM_SIZE; i++)
- {
- int2bin(prm[i], bitsno[i], bits, j);
- j += bitsno[i];
- }
+ int2bin(prm[i], TabLd8k.bitsno[i], bits, j);
+ j += TabLd8k.bitsno[i];
}
- /**
- * Convert integer to binary and write the bits bitstream array.
- *
- * @param value input : decimal value
- * @param no_of_bits input : number of bits to use
- * @param bitstream output: bitstream
- * @param bitstream_offset input: bitstream offset
- */
- private static void int2bin(
+ static void int2bin(
int value,
int no_of_bits,
- short[] bitstream,
+ Span bitstream,
int bitstream_offset
)
{
- var BIT_0 = Ld8k.BIT_0;
- var BIT_1 = Ld8k.BIT_1;
-
- int pt_bitstream;
- int i, bit;
-
- pt_bitstream = bitstream_offset + no_of_bits;
-
- for (i = 0; i < no_of_bits; i++)
+ var pt_bitstream = bitstream_offset + no_of_bits;
+ for (var i = 0; i < no_of_bits; i++)
{
- bit = value & 0x0001; /* get lsb */
- if (bit == 0)
- bitstream[--pt_bitstream] = BIT_0;
- else
- bitstream[--pt_bitstream] = BIT_1;
+ var bit = value & 0x0001; // get lsb
+ bitstream[--pt_bitstream] = bit == 0 ? Ld8k.BIT_0 : Ld8k.BIT_1;
value >>= 1;
}
}
+ }
- /**
- * Converts serial received bits to encoder parameter vector.
- *
- * @param bits input : serial bits
- * @param prm output: decoded parameters
- */
- private static void bits2prm_ld8k(short[] bits, int[] prm)
- {
- bits2prm_ld8k(bits, 0, prm, 0);
- }
-
- /**
- * Converts serial received bits to encoder parameter vector.
- *
- * @param bits input : serial bits
- * @param bits_offset input : serial bits offset
- * @param prm output: decoded parameters
- * @param prm_offset input: decoded parameters offset
- */
- public static void bits2prm_ld8k(
- short[] bits,
- int bits_offset,
- int[] prm,
- int prm_offset
- )
+ ///
+ /// Span-based version: Converts serial received bits to encoder parameter vector.
+ ///
+ /// Input: serial bits as ReadOnlySpan
+ /// Input: serial bits offset
+ /// Output: decoded parameters
+ /// Input: decoded parameters offset
+ public static void bits2prm_ld8k(
+ ReadOnlySpan bits,
+ int bits_offset,
+ Span prm,
+ int prm_offset
+ )
+ {
+ for (var i = 0; i < Ld8k.PRM_SIZE; i++)
{
- var PRM_SIZE = Ld8k.PRM_SIZE;
- var bitsno = TabLd8k.bitsno;
-
- int i;
- for (i = 0; i < PRM_SIZE; i++)
- {
- prm[i + prm_offset] = bin2int(bitsno[i], bits, bits_offset);
- bits_offset += bitsno[i];
- }
+ var bitCount = TabLd8k.bitsno[i];
+ prm[i + prm_offset] = bin2int(bits.Slice(bits_offset, bitCount));
+ bits_offset += bitCount;
}
- /**
- * Read specified bits from bit array and convert to integer value.
- *
- * @param no_of_bits input : number of bits to read
- * @param bitstream input : array containing bits
- * @param bitstream_offset input : array offset
- * @return decimal value of bit pattern
- */
- private static int bin2int(
- int no_of_bits,
- short[] bitstream,
- int bitstream_offset
- )
+ static int bin2int(ReadOnlySpan bitstream)
{
- var BIT_1 = Ld8k.BIT_1;
-
- int value, i;
- int bit;
-
- value = 0;
- for (i = 0; i < no_of_bits; i++)
+ var value = 0;
+ for (var i = 0; i < bitstream.Length; i++)
{
value <<= 1;
- bit = bitstream[bitstream_offset++];
- if (bit == BIT_1) value += 1;
+ if (bitstream[i] == Ld8k.BIT_1)
+ {
+ value |= 1;
+ }
}
-
return value;
}
}
-}
\ No newline at end of file
+}
diff --git a/src/SIPSorcery/app/Media/Codecs/G729Codec/CodLd8k.cs b/src/SIPSorcery/app/Media/Codecs/G729Codec/CodLd8k.cs
index f6be7031e..346bebc8b 100644
--- a/src/SIPSorcery/app/Media/Codecs/G729Codec/CodLd8k.cs
+++ b/src/SIPSorcery/app/Media/Codecs/G729Codec/CodLd8k.cs
@@ -19,6 +19,9 @@
* SIPRO Lab Telecom.
*/
+
+using System.Diagnostics;
+
/**
* Functions coder_ld8k and init_coder_ld8k
* Coder constant parameters (defined in "ld8k.h")
@@ -37,510 +40,541 @@
*
* @author Lubomir Marinov (translation of ITU-T C source code to Java)
*/
-namespace SIPSorcery.Media.G729Codec
-{
- internal class CodLd8k : Ld8k
- {
+namespace SIPSorcery.Media.G729Codec;
- private readonly AcelpCo acelpCo = new AcelpCo();
+internal sealed class CodLd8k : Ld8k
+{
+ private readonly AcelpCo acelpCo = new AcelpCo();
- /* Zero vector */
+ /* Zero vector */
- private readonly float[] ai_zero = new float[L_SUBFR + MP1];
+ private readonly float[] ai_zero = new float[L_SUBFR + MP1];
- private float[] error;
+ private float[]? error;
- private int error_offset;
+ private int error_offset;
- private float[] exc;
+ private float[]? exc;
- private int exc_offset;
+ private int exc_offset;
- /* Lsp (Line spectral pairs) */
- private readonly float[ /* M */] lsp_old =
- {
- 0.9595f,
- 0.8413f,
- 0.6549f,
- 0.4154f,
- 0.1423f,
- -0.1423f,
- -0.4154f,
- -0.6549f,
- -0.8413f,
- -0.9595f
- };
+ /* Lsp (Line spectral pairs) */
+ private readonly float[ /* M */] lsp_old =
+ {
+ 0.9595f,
+ 0.8413f,
+ 0.6549f,
+ 0.4154f,
+ 0.1423f,
+ -0.1423f,
+ -0.4154f,
+ -0.6549f,
+ -0.8413f,
+ -0.9595f
+ };
- private readonly float[] lsp_old_q = new float[M];
+ private readonly float[] lsp_old_q = new float[M];
- private readonly float[] mem_err = new float[M + L_SUBFR];
+ private readonly float[] mem_err = new float[M + L_SUBFR];
- /* Filter's memory */
+ /* Filter's memory */
- private readonly float[] mem_syn = new float[M];
+ private readonly float[] mem_syn = new float[M];
- private readonly float[] mem_w = new float[M];
+ private readonly float[] mem_w = new float[M];
- private readonly float[] mem_w0 = new float[M];
+ private readonly float[] mem_w0 = new float[M];
- public float[] new_speech;
+ public float[]? new_speech;
- public int new_speech_offset;
+ public int new_speech_offset;
- /* Excitation vector */
+ /* Excitation vector */
- private readonly float[] old_exc = new float[L_FRAME + PIT_MAX + L_INTERPOL];
+ private readonly float[] old_exc = new float[L_FRAME + PIT_MAX + L_INTERPOL];
- /* ITU-T G.729 Software Package Release 2 (November 2006) */
- /*
- ITU-T G.729 Annex C - Reference C code for floating point
- implementation of G.729
- Version 1.01 of 15.September.98
+ /* ITU-T G.729 Software Package Release 2 (November 2006) */
+ /*
+ITU-T G.729 Annex C - Reference C code for floating point
+ implementation of G.729
+ Version 1.01 of 15.September.98
*/
- /*
+ /*
----------------------------------------------------------------------
- COPYRIGHT NOTICE
+ COPYRIGHT NOTICE
----------------------------------------------------------------------
- ITU-T G.729 Annex C ANSI C source code
- Copyright (C) 1998, AT&T, France Telecom, NTT, University of
- Sherbrooke. All rights reserved.
+ITU-T G.729 Annex C ANSI C source code
+Copyright (C) 1998, AT&T, France Telecom, NTT, University of
+Sherbrooke. All rights reserved.
----------------------------------------------------------------------
*/
- /*
- File : COD_LD8K.C
- Used for the floating point version of G.729 main body
- (not for G.729A)
+ /*
+File : COD_LD8K.C
+Used for the floating point version of G.729 main body
+(not for G.729A)
*/
- /*--------------------------------------------------------*
- * Static memory allocation. *
- *--------------------------------------------------------*/
+ /*--------------------------------------------------------*
+* Static memory allocation. *
+*--------------------------------------------------------*/
- /* Speech vector */
- private readonly float[] old_speech = new float[L_TOTAL];
+ /* Speech vector */
+ private readonly float[] old_speech = new float[L_TOTAL];
- /* Weighted speech vector */
+ /* Weighted speech vector */
- private readonly float[] old_wsp = new float[L_FRAME + PIT_MAX];
+ private readonly float[] old_wsp = new float[L_FRAME + PIT_MAX];
- private float[] p_window;
+ private float[]? p_window;
- private int p_window_offset;
+ private int p_window_offset;
- private readonly Pwf pwf = new Pwf();
+ private readonly Pwf pwf = new Pwf();
- private readonly QuaGain quaGain = new QuaGain();
+ private readonly QuaGain quaGain = new QuaGain();
- private readonly QuaLsp quaLsp = new QuaLsp();
+ private readonly QuaLsp quaLsp = new QuaLsp();
- private float sharp;
+ private float sharp;
- private float[] speech;
+ private float[]? speech;
- private int speech_offset;
+ private int speech_offset;
- private readonly Taming taming = new Taming();
+ private readonly Taming taming = new Taming();
- private float[] wsp;
+ private float[]? wsp;
- private int wsp_offset;
+ private int wsp_offset;
- private float[] zero;
+ private float[]? zero;
- private int zero_offset;
+ private int zero_offset;
- /**
- * Initialization of variables for the encoder.
- * Initialize pointers to speech vector.
- *
- * | <------------ LPC analysis window (L_WINDOW) ----------->
- * | | <-- present frame (L_FRAME) -->
- * old_speech | <-- new speech (L_FRAME) -->
- * p_wind | |
- * speech |
- * new_speech
- * ]]>
- */
+ /**
+* Initialization of variables for the encoder.
+* Initialize pointers to speech vector.
+*
+* | <------------ LPC analysis window (L_WINDOW) ----------->
+* | | <-- present frame (L_FRAME) -->
+* old_speech | <-- new speech (L_FRAME) -->
+* p_wind | |
+* speech |
+* new_speech
+* ]]>
+*/
- public void init_coder_ld8k()
- {
+ public void init_coder_ld8k()
+ {
- new_speech = old_speech;
- new_speech_offset = L_TOTAL - L_FRAME; /* New speech */
- speech = new_speech; /* Present frame */
- speech_offset = new_speech_offset - L_NEXT;
- p_window = old_speech;
- p_window_offset = L_TOTAL - L_WINDOW; /* For LPC window */
-
- /* Initialize static pointers */
-
- wsp = old_wsp;
- wsp_offset = PIT_MAX;
- exc = old_exc;
- exc_offset = PIT_MAX + L_INTERPOL;
- zero = ai_zero;
- zero_offset = MP1;
- error = mem_err;
- error_offset = M;
-
- /* Static vectors to zero */
- Util.set_zero(old_speech, L_TOTAL);
- Util.set_zero(old_exc, PIT_MAX + L_INTERPOL);
- Util.set_zero(old_wsp, PIT_MAX);
- Util.set_zero(mem_syn, M);
- Util.set_zero(mem_w, M);
- Util.set_zero(mem_w0, M);
- Util.set_zero(mem_err, M);
- Util.set_zero(zero, zero_offset, L_SUBFR);
- sharp = SHARPMIN;
-
- /* Initialize lsp_old_q[] */
- Util.copy(lsp_old, lsp_old_q, M);
-
- quaLsp.lsp_encw_reset();
- taming.init_exc_err();
- }
+ new_speech = old_speech;
+ new_speech_offset = L_TOTAL - L_FRAME; /* New speech */
+ speech = new_speech; /* Present frame */
+ speech_offset = new_speech_offset - L_NEXT;
+ p_window = old_speech;
+ p_window_offset = L_TOTAL - L_WINDOW; /* For LPC window */
+
+ /* Initialize static pointers */
+
+ wsp = old_wsp;
+ wsp_offset = PIT_MAX;
+ exc = old_exc;
+ exc_offset = PIT_MAX + L_INTERPOL;
+ zero = ai_zero;
+ zero_offset = MP1;
+ error = mem_err;
+ error_offset = M;
+
+ /* Static vectors to zero */
+ Util.set_zero(old_speech, L_TOTAL);
+ Util.set_zero(old_exc, PIT_MAX + L_INTERPOL);
+ Util.set_zero(old_wsp, PIT_MAX);
+ Util.set_zero(mem_syn, M);
+ Util.set_zero(mem_w, M);
+ Util.set_zero(mem_w0, M);
+ Util.set_zero(mem_err, M);
+ Util.set_zero(zero, zero_offset, L_SUBFR);
+ sharp = SHARPMIN;
+
+ /* Initialize lsp_old_q[] */
+ Util.copy(lsp_old, lsp_old_q, M);
+
+ quaLsp.lsp_encw_reset();
+ taming.init_exc_err();
+ }
- /**
- * Encoder routine ( speech data should be in new_speech ).
- *
- * @param ana output: analysis parameters
- */
+ /**
+* Encoder routine ( speech data should be in new_speech ).
+*
+* @param ana output: analysis parameters
+*/
- public void coder_ld8k(
- int[] ana
- )
+ public void coder_ld8k(
+ int[] ana
+ )
+ {
+ /* LPC coefficients */
+ var r = new float[MP1]; /* Autocorrelations low and hi */
+ var A_t = new float[MP1 * 2]; /* A(z) unquantized for the 2 subframes */
+ var Aq_t = new float[MP1 * 2]; /* A(z) quantized for the 2 subframes */
+ var Ap1 = new float[MP1]; /* A(z) with spectral expansion */
+ var Ap2 = new float[MP1]; /* A(z) with spectral expansion */
+ float[] A, Aq; /* Pointer on A_t and Aq_t */
+ int A_offset, Aq_offset;
+
+ /* LSP coefficients */
+ float[] lsp_new = new float[M], lsp_new_q = new float[M]; /* LSPs at 2th subframe */
+ var lsf_int = new float[M]; /* Interpolated LSF 1st subframe. */
+ var lsf_new = new float[M];
+
+ /* Variable added for adaptive gamma1 and gamma2 of the PWF */
+
+ var rc = new float[M]; /* Reflection coefficients */
+ var gamma1 = new float[2]; /* Gamma1 for 1st and 2nd subframes */
+ var gamma2 = new float[2]; /* Gamma2 for 1st and 2nd subframes */
+
+ /* Other vectors */
+ var synth = new float[L_FRAME]; /* Buffer for synthesis speech */
+ var h1 = new float[L_SUBFR]; /* Impulse response h1[] */
+ var xn = new float[L_SUBFR]; /* Target vector for pitch search */
+ var xn2 = new float[L_SUBFR]; /* Target vector for codebook search */
+ var code = new float[L_SUBFR]; /* Fixed codebook excitation */
+ var y1 = new float[L_SUBFR]; /* Filtered adaptive excitation */
+ var y2 = new float[L_SUBFR]; /* Filtered fixed codebook excitation */
+ var g_coeff = new float[5]; /* Correlations between xn, y1, & y2:
+ , , , ,*/
+
+ /* Scalars */
+
+ int i, j, i_gamma, i_subfr;
+ var iRef = new IntReference();
+ int T_op, t0;
+ IntReference t0_min = new IntReference(), t0_max = new IntReference(), t0_frac = new IntReference();
+ int index, taming;
+ float gain_pit, gain_code = 0.0f;
+ FloatReference _gain_pit = new FloatReference(), _gain_code = new FloatReference();
+
+ var ana_offset = 0;
+
+ /*------------------------------------------------------------------------*
+* - Perform LPC analysis: *
+* * autocorrelation + lag windowing *
+* * Levinson-durbin algorithm to find a[] *
+* * convert a[] to lsp[] *
+* * quantize and code the LSPs *
+* * find the interpolated LSPs and convert to a[] for the 2 *
+* subframes (both quantized and unquantized) *
+*------------------------------------------------------------------------*/
+
+ /* LP analysis */
+
+ Debug.Assert(p_window is { });
+
+ Lpc.autocorr(p_window, p_window_offset, M, r); /* Autocorrelations */
+ Lpc.lag_window(M, r); /* Lag windowing */
+ Lpc.levinson(r, A_t, MP1, rc); /* Levinson Durbin */
+ Lpc.az_lsp(A_t, MP1, lsp_new, lsp_old); /* From A(z) to lsp */
+
+ /* LSP quantization */
+
+ quaLsp.qua_lsp(lsp_new, lsp_new_q, ana);
+ ana_offset += 2; /* Advance analysis parameters pointer */
+
+ /*--------------------------------------------------------------------*
+* Find interpolated LPC parameters in all subframes (both quantized *
+* and unquantized). *
+* The interpolated parameters are in array A_t[] of size (M+1)*4 *
+* and the quantized interpolated parameters are in array Aq_t[] *
+*--------------------------------------------------------------------*/
+
+ Lpcfunc.int_lpc(lsp_old, lsp_new, lsf_int, lsf_new, A_t);
+ Lpcfunc.int_qlpc(lsp_old_q, lsp_new_q, Aq_t);
+
+ /* update the LSPs for the next frame */
+
+ for (i = 0; i < M; i++)
{
- /* LPC coefficients */
- var r = new float[MP1]; /* Autocorrelations low and hi */
- var A_t = new float[MP1 * 2]; /* A(z) unquantized for the 2 subframes */
- var Aq_t = new float[MP1 * 2]; /* A(z) quantized for the 2 subframes */
- var Ap1 = new float[MP1]; /* A(z) with spectral expansion */
- var Ap2 = new float[MP1]; /* A(z) with spectral expansion */
- float[] A, Aq; /* Pointer on A_t and Aq_t */
- int A_offset, Aq_offset;
-
- /* LSP coefficients */
- float[] lsp_new = new float[M], lsp_new_q = new float[M]; /* LSPs at 2th subframe */
- var lsf_int = new float[M]; /* Interpolated LSF 1st subframe. */
- var lsf_new = new float[M];
-
- /* Variable added for adaptive gamma1 and gamma2 of the PWF */
-
- var rc = new float[M]; /* Reflection coefficients */
- var gamma1 = new float[2]; /* Gamma1 for 1st and 2nd subframes */
- var gamma2 = new float[2]; /* Gamma2 for 1st and 2nd subframes */
-
- /* Other vectors */
- var synth = new float[L_FRAME]; /* Buffer for synthesis speech */
- var h1 = new float[L_SUBFR]; /* Impulse response h1[] */
- var xn = new float[L_SUBFR]; /* Target vector for pitch search */
- var xn2 = new float[L_SUBFR]; /* Target vector for codebook search */
- var code = new float[L_SUBFR]; /* Fixed codebook excitation */
- var y1 = new float[L_SUBFR]; /* Filtered adaptive excitation */
- var y2 = new float[L_SUBFR]; /* Filtered fixed codebook excitation */
- var g_coeff = new float[5]; /* Correlations between xn, y1, & y2:
- , , , ,*/
-
- /* Scalars */
-
- int i, j, i_gamma, i_subfr;
- var iRef = new IntReference();
- int T_op, t0;
- IntReference t0_min = new IntReference(), t0_max = new IntReference(), t0_frac = new IntReference();
- int index, taming;
- float gain_pit, gain_code = 0.0f;
- FloatReference _gain_pit = new FloatReference(), _gain_code = new FloatReference();
-
- var ana_offset = 0;
-
- /*------------------------------------------------------------------------*
- * - Perform LPC analysis: *
- * * autocorrelation + lag windowing *
- * * Levinson-durbin algorithm to find a[] *
- * * convert a[] to lsp[] *
- * * quantize and code the LSPs *
- * * find the interpolated LSPs and convert to a[] for the 2 *
- * subframes (both quantized and unquantized) *
- *------------------------------------------------------------------------*/
-
- /* LP analysis */
-
- Lpc.autocorr(p_window, p_window_offset, M, r); /* Autocorrelations */
- Lpc.lag_window(M, r); /* Lag windowing */
- Lpc.levinson(r, A_t, MP1, rc); /* Levinson Durbin */
- Lpc.az_lsp(A_t, MP1, lsp_new, lsp_old); /* From A(z) to lsp */
+ lsp_old[i] = lsp_new[i];
+ lsp_old_q[i] = lsp_new_q[i];
+ }
- /* LSP quantization */
+ /*----------------------------------------------------------------------*
+* - Find the weighting factors *
+*----------------------------------------------------------------------*/
- quaLsp.qua_lsp(lsp_new, lsp_new_q, ana);
- ana_offset += 2; /* Advance analysis parameters pointer */
+ pwf.perc_var(gamma1, gamma2, lsf_int, lsf_new, rc);
- /*--------------------------------------------------------------------*
- * Find interpolated LPC parameters in all subframes (both quantized *
- * and unquantized). *
- * The interpolated parameters are in array A_t[] of size (M+1)*4 *
- * and the quantized interpolated parameters are in array Aq_t[] *
- *--------------------------------------------------------------------*/
+ /*----------------------------------------------------------------------*
+* - Find the weighted input speech w_sp[] for the whole speech frame *
+* - Find the open-loop pitch delay for the whole speech frame *
+* - Set the range for searching closed-loop pitch in 1st subframe *
+*----------------------------------------------------------------------*/
- Lpcfunc.int_lpc(lsp_old, lsp_new, lsf_int, lsf_new, A_t);
- Lpcfunc.int_qlpc(lsp_old_q, lsp_new_q, Aq_t);
+ Debug.Assert(speech is { });
+ Debug.Assert(wsp is { });
- /* update the LSPs for the next frame */
+ Lpcfunc.weight_az(A_t, 0, gamma1[0], M, Ap1);
+ Lpcfunc.weight_az(A_t, 0, gamma2[0], M, Ap2);
+ Filter.residu(Ap1, 0, speech, speech_offset, wsp, wsp_offset, L_SUBFR);
+ Filter.syn_filt(Ap2, 0, wsp, wsp_offset, wsp, wsp_offset, L_SUBFR, mem_w, 0, 1);
- for (i = 0; i < M; i++)
- {
- lsp_old[i] = lsp_new[i];
- lsp_old_q[i] = lsp_new_q[i];
- }
+ Lpcfunc.weight_az(A_t, MP1, gamma1[1], M, Ap1);
+ Lpcfunc.weight_az(A_t, MP1, gamma2[1], M, Ap2);
+ Filter.residu(Ap1, 0, speech, speech_offset + L_SUBFR, wsp, wsp_offset + L_SUBFR, L_SUBFR);
+ Filter.syn_filt(Ap2, 0, wsp, wsp_offset + L_SUBFR, wsp, wsp_offset + L_SUBFR, L_SUBFR, mem_w, 0, 1);
- /*----------------------------------------------------------------------*
- * - Find the weighting factors *
- *----------------------------------------------------------------------*/
+ /* Find open loop pitch lag for whole speech frame */
- pwf.perc_var(gamma1, gamma2, lsf_int, lsf_new, rc);
+ T_op = Pitch.pitch_ol(wsp, wsp_offset, PIT_MIN, PIT_MAX, L_FRAME);
- /*----------------------------------------------------------------------*
- * - Find the weighted input speech w_sp[] for the whole speech frame *
- * - Find the open-loop pitch delay for the whole speech frame *
- * - Set the range for searching closed-loop pitch in 1st subframe *
- *----------------------------------------------------------------------*/
+ /* range for closed loop pitch search in 1st subframe */
- Lpcfunc.weight_az(A_t, 0, gamma1[0], M, Ap1);
- Lpcfunc.weight_az(A_t, 0, gamma2[0], M, Ap2);
- Filter.residu(Ap1, 0, speech, speech_offset, wsp, wsp_offset, L_SUBFR);
- Filter.syn_filt(Ap2, 0, wsp, wsp_offset, wsp, wsp_offset, L_SUBFR, mem_w, 0, 1);
+ t0_min.value = T_op - 3;
+ if (t0_min.value < PIT_MIN)
+ {
+ t0_min.value = PIT_MIN;
+ }
- Lpcfunc.weight_az(A_t, MP1, gamma1[1], M, Ap1);
- Lpcfunc.weight_az(A_t, MP1, gamma2[1], M, Ap2);
- Filter.residu(Ap1, 0, speech, speech_offset + L_SUBFR, wsp, wsp_offset + L_SUBFR, L_SUBFR);
- Filter.syn_filt(Ap2, 0, wsp, wsp_offset + L_SUBFR, wsp, wsp_offset + L_SUBFR, L_SUBFR, mem_w, 0, 1);
+ t0_max.value = t0_min.value + 6;
+ if (t0_max.value > PIT_MAX)
+ {
+ t0_max.value = PIT_MAX;
+ t0_min.value = t0_max.value - 6;
+ }
- /* Find open loop pitch lag for whole speech frame */
+ /*------------------------------------------------------------------------*
+* Loop for every subframe in the analysis frame *
+*------------------------------------------------------------------------*
+* To find the pitch and innovation parameters. The subframe size is *
+* L_SUBFR and the loop is repeated L_FRAME/L_SUBFR times. *
+* - find the weighted LPC coefficients *
+* - find the LPC residual signal *
+* - compute the target signal for pitch search *
+* - compute impulse response of weighted synthesis filter (h1[]) *
+* - find the closed-loop pitch parameters *
+* - encode the pitch delay *
+* - update the impulse response h1[] by including fixed-gain pitch *
+* - find target vector for codebook search *
+* - codebook search *
+* - encode codebook address *
+* - VQ of pitch and codebook gains *
+* - find synthesis speech *
+* - update states of weighting filter *
+*------------------------------------------------------------------------*/
+
+ A = A_t; /* pointer to interpolated LPC parameters */
+ A_offset = 0;
+ Aq = Aq_t; /* pointer to interpolated quantized LPC parameters */
+ Aq_offset = 0;
+
+ i_gamma = 0;
+
+ for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR)
+ {
+ /*---------------------------------------------------------------*
+* Find the weighted LPC coefficients for the weighting filter. *
+*---------------------------------------------------------------*/
- T_op = Pitch.pitch_ol(wsp, wsp_offset, PIT_MIN, PIT_MAX, L_FRAME);
+ Lpcfunc.weight_az(A, A_offset, gamma1[i_gamma], M, Ap1);
+ Lpcfunc.weight_az(A, A_offset, gamma2[i_gamma], M, Ap2);
+ i_gamma++;
- /* range for closed loop pitch search in 1st subframe */
+ /*---------------------------------------------------------------*
+* Compute impulse response, h1[], of weighted synthesis filter *
+*---------------------------------------------------------------*/
- t0_min.value = T_op - 3;
- if (t0_min.value < PIT_MIN) t0_min.value = PIT_MIN;
- t0_max.value = t0_min.value + 6;
- if (t0_max.value > PIT_MAX)
+ for (i = 0; i <= M; i++)
{
- t0_max.value = PIT_MAX;
- t0_min.value = t0_max.value - 6;
+ ai_zero[i] = Ap1[i];
}
- /*------------------------------------------------------------------------*
- * Loop for every subframe in the analysis frame *
- *------------------------------------------------------------------------*
- * To find the pitch and innovation parameters. The subframe size is *
- * L_SUBFR and the loop is repeated L_FRAME/L_SUBFR times. *
- * - find the weighted LPC coefficients *
- * - find the LPC residual signal *
- * - compute the target signal for pitch search *
- * - compute impulse response of weighted synthesis filter (h1[]) *
- * - find the closed-loop pitch parameters *
- * - encode the pitch delay *
- * - update the impulse response h1[] by including fixed-gain pitch *
- * - find target vector for codebook search *
- * - codebook search *
- * - encode codebook address *
- * - VQ of pitch and codebook gains *
- * - find synthesis speech *
- * - update states of weighting filter *
- *------------------------------------------------------------------------*/
-
- A = A_t; /* pointer to interpolated LPC parameters */
- A_offset = 0;
- Aq = Aq_t; /* pointer to interpolated quantized LPC parameters */
- Aq_offset = 0;
-
- i_gamma = 0;
-
- for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR)
- {
- /*---------------------------------------------------------------*
- * Find the weighted LPC coefficients for the weighting filter. *
- *---------------------------------------------------------------*/
-
- Lpcfunc.weight_az(A, A_offset, gamma1[i_gamma], M, Ap1);
- Lpcfunc.weight_az(A, A_offset, gamma2[i_gamma], M, Ap2);
- i_gamma++;
-
- /*---------------------------------------------------------------*
- * Compute impulse response, h1[], of weighted synthesis filter *
- *---------------------------------------------------------------*/
-
- for (i = 0; i <= M; i++) ai_zero[i] = Ap1[i];
- Filter.syn_filt(Aq, Aq_offset, ai_zero, 0, h1, 0, L_SUBFR, zero, zero_offset, 0);
- Filter.syn_filt(Ap2, 0, h1, 0, h1, 0, L_SUBFR, zero, zero_offset, 0);
-
- /*------------------------------------------------------------------------*
- * *
- * Find the target vector for pitch search: *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *
- * *
- * |------| res[n] *
- * speech[n]---| A(z) |-------- *
- * |------| | |--------| error[n] |------| *
- * zero -- (-)--| 1/A(z) |-----------| W(z) |-- target *
- * exc |--------| |------| *
- * *
- * Instead of subtracting the zero-input response of filters from *
- * the weighted input speech, the above configuration is used to *
- * compute the target vector. This configuration gives better performance *
- * with fixed-point implementation. The memory of 1/A(z) is updated by *
- * filtering (res[n]-exc[n]) through 1/A(z), or simply by subtracting *
- * the synthesis speech from the input speech: *
- * error[n] = speech[n] - syn[n]. *
- * The memory of W(z) is updated by filtering error[n] through W(z), *
- * or more simply by subtracting the filtered adaptive and fixed *
- * codebook excitations from the target: *
- * target[n] - gain_pit*y1[n] - gain_code*y2[n] *
- * as these signals are already available. *
- * *
- *------------------------------------------------------------------------*/
-
- Filter.residu(
- Aq,
- Aq_offset,
- speech,
- speech_offset + i_subfr,
- exc,
- exc_offset + i_subfr,
- L_SUBFR); /* LPC residual */
-
- Filter.syn_filt(Aq, Aq_offset, exc, exc_offset + i_subfr, error, error_offset, L_SUBFR, mem_err, 0, 0);
-
- Filter.residu(Ap1, 0, error, error_offset, xn, 0, L_SUBFR);
-
- Filter.syn_filt(Ap2, 0, xn, 0, xn, 0, L_SUBFR, mem_w0, 0, 0); /* target signal xn[]*/
-
- /*----------------------------------------------------------------------*
- * Closed-loop fractional pitch search *
- *----------------------------------------------------------------------*/
-
- t0 = Pitch.pitch_fr3(
- exc,
- exc_offset + i_subfr,
- xn,
- h1,
- L_SUBFR,
- t0_min.value,
- t0_max.value,
- i_subfr,
- t0_frac);
-
- index = Pitch.enc_lag3(t0, t0_frac.value, t0_min, t0_max, PIT_MIN, PIT_MAX, i_subfr);
-
- ana[ana_offset] = index;
- ana_offset++;
- if (i_subfr == 0)
- {
- ana[ana_offset] = PParity.parity_pitch(index);
- ana_offset++;
- }
-
- /*-----------------------------------------------------------------*
- * - find unity gain pitch excitation (adaptive codebook entry) *
- * with fractional interpolation. *
- * - find filtered pitch exc. y1[]=exc[] convolve with h1[]) *
- * - compute pitch gain and limit between 0 and 1.2 *
- * - update target vector for codebook search *
- * - find LTP residual. *
- *-----------------------------------------------------------------*/
+ Debug.Assert(zero is { });
- PredLt3.pred_lt_3(exc, exc_offset + i_subfr, t0, t0_frac.value, L_SUBFR);
+ Filter.syn_filt(Aq, Aq_offset, ai_zero, 0, h1, 0, L_SUBFR, zero, zero_offset, 0);
+ Filter.syn_filt(Ap2, 0, h1, 0, h1, 0, L_SUBFR, zero, zero_offset, 0);
- Filter.convolve(exc, exc_offset + i_subfr, h1, y1, L_SUBFR);
-
- gain_pit = Pitch.g_pitch(xn, y1, g_coeff, L_SUBFR);
-
- /* clip pitch gain if taming is necessary */
- taming = this.taming.test_err(t0, t0_frac.value);
-
- if (taming == 1)
- if (gain_pit > GPCLIP)
- gain_pit = GPCLIP;
+ /*------------------------------------------------------------------------*
+* *
+* Find the target vector for pitch search: *
+* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *
+* *
+* |------| res[n] *
+* speech[n]---| A(z) |-------- *
+* |------| | |--------| error[n] |------| *
+* zero -- (-)--| 1/A(z) |-----------| W(z) |-- target *
+* exc |--------| |------| *
+* *
+* Instead of subtracting the zero-input response of filters from *
+* the weighted input speech, the above configuration is used to *
+* compute the target vector. This configuration gives better performance *
+* with fixed-point implementation. The memory of 1/A(z) is updated by *
+* filtering (res[n]-exc[n]) through 1/A(z), or simply by subtracting *
+* the synthesis speech from the input speech: *
+* error[n] = speech[n] - syn[n]. *
+* The memory of W(z) is updated by filtering error[n] through W(z), *
+* or more simply by subtracting the filtered adaptive and fixed *
+* codebook excitations from the target: *
+* target[n] - gain_pit*y1[n] - gain_code*y2[n] *
+* as these signals are already available. *
+* *
+*------------------------------------------------------------------------*/
+
+ Debug.Assert(exc is { });
+ Debug.Assert(error is { });
+
+ Filter.residu(
+ Aq,
+ Aq_offset,
+ speech,
+ speech_offset + i_subfr,
+ exc,
+ exc_offset + i_subfr,
+ L_SUBFR); /* LPC residual */
+
+ Filter.syn_filt(Aq, Aq_offset, exc, exc_offset + i_subfr, error, error_offset, L_SUBFR, mem_err, 0, 0);
+
+ Filter.residu(Ap1, 0, error, error_offset, xn, 0, L_SUBFR);
+
+ Filter.syn_filt(Ap2, 0, xn, 0, xn, 0, L_SUBFR, mem_w0, 0, 0); /* target signal xn[]*/
- for (i = 0; i < L_SUBFR; i++)
- xn2[i] = xn[i] - y1[i] * gain_pit;
+ /*----------------------------------------------------------------------*
+* Closed-loop fractional pitch search *
+*----------------------------------------------------------------------*/
+
+ t0 = Pitch.pitch_fr3(
+ exc,
+ exc_offset + i_subfr,
+ xn,
+ h1,
+ L_SUBFR,
+ t0_min.value,
+ t0_max.value,
+ i_subfr,
+ t0_frac);
+
+ index = Pitch.enc_lag3(t0, t0_frac.value, t0_min, t0_max, PIT_MIN, PIT_MAX, i_subfr);
+
+ ana[ana_offset] = index;
+ ana_offset++;
+ if (i_subfr == 0)
+ {
+ ana[ana_offset] = PParity.parity_pitch(index);
+ ana_offset++;
+ }
- /*-----------------------------------------------------*
- * - Innovative codebook search. *
- *-----------------------------------------------------*/
+ /*-----------------------------------------------------------------*
+* - find unity gain pitch excitation (adaptive codebook entry) *
+* with fractional interpolation. *
+* - find filtered pitch exc. y1[]=exc[] convolve with h1[]) *
+* - compute pitch gain and limit between 0 and 1.2 *
+* - update target vector for codebook search *
+* - find LTP residual. *
+*-----------------------------------------------------------------*/
- iRef.value = i;
- index = acelpCo.ACELP_codebook(xn2, h1, t0, sharp, i_subfr, code, y2, iRef);
- i = iRef.value;
- ana[ana_offset] = index; /* Positions index */
- ana_offset++;
- ana[ana_offset] = i; /* Signs index */
- ana_offset++;
+ PredLt3.pred_lt_3(exc, exc_offset + i_subfr, t0, t0_frac.value, L_SUBFR);
- /*-----------------------------------------------------*
- * - Quantization of gains. *
- *-----------------------------------------------------*/
- CorFunc.corr_xy2(xn, y1, y2, g_coeff);
+ Filter.convolve(exc, exc_offset + i_subfr, h1, y1, L_SUBFR);
- _gain_pit.value = gain_pit;
- _gain_code.value = gain_code;
- ana[ana_offset] = quaGain.qua_gain(code, g_coeff, L_SUBFR, _gain_pit, _gain_code, taming);
- gain_pit = _gain_pit.value;
- gain_code = _gain_code.value;
- ana_offset++;
+ gain_pit = Pitch.g_pitch(xn, y1, g_coeff, L_SUBFR);
- /*------------------------------------------------------------*
- * - Update pitch sharpening "sharp" with quantized gain_pit *
- *------------------------------------------------------------*/
+ /* clip pitch gain if taming is necessary */
+ taming = this.taming.test_err(t0, t0_frac.value);
- sharp = gain_pit;
- if (sharp > SHARPMAX) sharp = SHARPMAX;
- if (sharp < SHARPMIN) sharp = SHARPMIN;
- /*------------------------------------------------------*
- * - Find the total excitation *
- * - find synthesis speech corresponding to exc[] *
- * - update filters' memories for finding the target *
- * vector in the next subframe *
- * (update error[-m..-1] and mem_w0[]) *
- * update error function for taming process *
- *------------------------------------------------------*/
+ if (taming == 1)
+ {
+ if (gain_pit > GPCLIP)
+ {
+ gain_pit = GPCLIP;
+ }
+ }
- for (i = 0; i < L_SUBFR; i++)
- exc[exc_offset + i + i_subfr] = gain_pit * exc[exc_offset + i + i_subfr] + gain_code * code[i];
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ xn2[i] = xn[i] - y1[i] * gain_pit;
+ }
- this.taming.update_exc_err(gain_pit, t0);
+ /*-----------------------------------------------------*
+* - Innovative codebook search. *
+*-----------------------------------------------------*/
+
+ iRef.value = i;
+ index = acelpCo.ACELP_codebook(xn2, h1, t0, sharp, i_subfr, code, y2, iRef);
+ i = iRef.value;
+ ana[ana_offset] = index; /* Positions index */
+ ana_offset++;
+ ana[ana_offset] = i; /* Signs index */
+ ana_offset++;
+
+ /*-----------------------------------------------------*
+* - Quantization of gains. *
+*-----------------------------------------------------*/
+ CorFunc.corr_xy2(xn, y1, y2, g_coeff);
+
+ _gain_pit.value = gain_pit;
+ _gain_code.value = gain_code;
+ ana[ana_offset] = quaGain.qua_gain(code, g_coeff, L_SUBFR, _gain_pit, _gain_code, taming);
+ gain_pit = _gain_pit.value;
+ gain_code = _gain_code.value;
+ ana_offset++;
+
+ /*------------------------------------------------------------*
+* - Update pitch sharpening "sharp" with quantized gain_pit *
+*------------------------------------------------------------*/
+
+ sharp = gain_pit;
+ if (sharp > SHARPMAX)
+ {
+ sharp = SHARPMAX;
+ }
- Filter.syn_filt(Aq, Aq_offset, exc, exc_offset + i_subfr, synth, i_subfr, L_SUBFR, mem_syn, 0, 1);
+ if (sharp < SHARPMIN)
+ {
+ sharp = SHARPMIN;
+ }
+ /*------------------------------------------------------*
+* - Find the total excitation *
+* - find synthesis speech corresponding to exc[] *
+* - update filters' memories for finding the target *
+* vector in the next subframe *
+* (update error[-m..-1] and mem_w0[]) *
+* update error function for taming process *
+*------------------------------------------------------*/
+
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ exc[exc_offset + i + i_subfr] = gain_pit * exc[exc_offset + i + i_subfr] + gain_code * code[i];
+ }
- for (i = L_SUBFR - M, j = 0; i < L_SUBFR; i++, j++)
- {
- mem_err[j] = speech[speech_offset + i_subfr + i] - synth[i_subfr + i];
- mem_w0[j] = xn[i] - gain_pit * y1[i] - gain_code * y2[i];
- }
+ this.taming.update_exc_err(gain_pit, t0);
- A_offset += MP1; /* interpolated LPC parameters for next subframe */
- Aq_offset += MP1;
+ Filter.syn_filt(Aq, Aq_offset, exc, exc_offset + i_subfr, synth, i_subfr, L_SUBFR, mem_syn, 0, 1);
+ for (i = L_SUBFR - M, j = 0; i < L_SUBFR; i++, j++)
+ {
+ mem_err[j] = speech[speech_offset + i_subfr + i] - synth[i_subfr + i];
+ mem_w0[j] = xn[i] - gain_pit * y1[i] - gain_code * y2[i];
}
- /*--------------------------------------------------*
- * Update signal for next frame. *
- * -> shift to the left by L_FRAME: *
- * speech[], wsp[] and exc[] *
- *--------------------------------------------------*/
+ A_offset += MP1; /* interpolated LPC parameters for next subframe */
+ Aq_offset += MP1;
- Util.copy(old_speech, L_FRAME, old_speech, L_TOTAL - L_FRAME);
- Util.copy(old_wsp, L_FRAME, old_wsp, PIT_MAX);
- Util.copy(old_exc, L_FRAME, old_exc, PIT_MAX + L_INTERPOL);
}
+
+ /*--------------------------------------------------*
+* Update signal for next frame. *
+* -> shift to the left by L_FRAME: *
+* speech[], wsp[] and exc[] *
+*--------------------------------------------------*/
+
+ Util.copy(old_speech, L_FRAME, old_speech, L_TOTAL - L_FRAME);
+ Util.copy(old_wsp, L_FRAME, old_wsp, PIT_MAX);
+ Util.copy(old_exc, L_FRAME, old_exc, PIT_MAX + L_INTERPOL);
}
}
diff --git a/src/SIPSorcery/app/Media/Codecs/G729Codec/CorFunc.cs b/src/SIPSorcery/app/Media/Codecs/G729Codec/CorFunc.cs
index 2d5466af3..61319810b 100644
--- a/src/SIPSorcery/app/Media/Codecs/G729Codec/CorFunc.cs
+++ b/src/SIPSorcery/app/Media/Codecs/G729Codec/CorFunc.cs
@@ -24,95 +24,109 @@
*
* @author Lubomir Marinov (translation of ITU-T C source code to Java)
*/
-namespace SIPSorcery.Media.G729Codec
+namespace SIPSorcery.Media.G729Codec;
+
+internal static class CorFunc
{
- internal class CorFunc
- {
- /* ITU-T G.729 Software Package Release 2 (November 2006) */
- /*
- ITU-T G.729 Annex C - Reference C code for floating point
- implementation of G.729
- Version 1.01 of 15.September.98
+ /* ITU-T G.729 Software Package Release 2 (November 2006) */
+ /*
+ITU-T G.729 Annex C - Reference C code for floating point
+ implementation of G.729
+ Version 1.01 of 15.September.98
*/
- /*
+ /*
----------------------------------------------------------------------
- COPYRIGHT NOTICE
+ COPYRIGHT NOTICE
----------------------------------------------------------------------
- ITU-T G.729 Annex C ANSI C source code
- Copyright (C) 1998, AT&T, France Telecom, NTT, University of
- Sherbrooke. All rights reserved.
+ITU-T G.729 Annex C ANSI C source code
+Copyright (C) 1998, AT&T, France Telecom, NTT, University of
+Sherbrooke. All rights reserved.
----------------------------------------------------------------------
*/
- /*
- File : COR_FUNC.C
- Used for the floating point version of both
- G.729 main body and G.729A
+ /*
+File : COR_FUNC.C
+Used for the floating point version of both
+G.729 main body and G.729A
*/
- /**
- * Compute the correlation products needed for gain computation.
- *
- * @param xn input : target vector x[0:l_subfr]
- * @param y1 input : filtered adaptive codebook vector
- * @param y2 input : filtered 1st codebook innovation
- * @param g_coeff , -2 , and 2 ]]>
- */
+ /**
+* Compute the correlation products needed for gain computation.
+*
+* @param xn input : target vector x[0:l_subfr]
+* @param y1 input : filtered adaptive codebook vector
+* @param y2 input : filtered 1st codebook innovation
+* @param g_coeff , -2 , and 2 ]]>
+*/
- public static void corr_xy2(
- float[] xn,
- float[] y1,
- float[] y2,
- float[] g_coeff
- )
- {
- var L_SUBFR = Ld8k.L_SUBFR;
+ public static void corr_xy2(
+ float[] xn,
+ float[] y1,
+ float[] y2,
+ float[] g_coeff
+ )
+ {
+ var L_SUBFR = Ld8k.L_SUBFR;
- float y2y2, xny2, y1y2;
- int i;
+ float y2y2, xny2, y1y2;
+ int i;
- y2y2 = 0.01f;
- for (i = 0; i < L_SUBFR; i++) y2y2 += y2[i] * y2[i];
- g_coeff[2] = y2y2;
+ y2y2 = 0.01f;
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ y2y2 += y2[i] * y2[i];
+ }
- xny2 = 0.01f;
- for (i = 0; i < L_SUBFR; i++) xny2 += xn[i] * y2[i];
- g_coeff[3] = -2.0f * xny2;
+ g_coeff[2] = y2y2;
- y1y2 = 0.01f;
- for (i = 0; i < L_SUBFR; i++) y1y2 += y1[i] * y2[i];
- g_coeff[4] = 2.0f * y1y2;
+ xny2 = 0.01f;
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ xny2 += xn[i] * y2[i];
}
- /**
- * Compute correlations of input response h[] with the target vector X[].
- *
- * @param h (i) :Impulse response of filters
- * @param x (i) :Target vector
- * @param d (o) :Correlations between h[] and x[]
- */
+ g_coeff[3] = -2.0f * xny2;
- public static void cor_h_x(
- float[] h,
- float[] x,
- float[] d
- )
+ y1y2 = 0.01f;
+ for (i = 0; i < L_SUBFR; i++)
{
- var L_SUBFR = Ld8k.L_SUBFR;
+ y1y2 += y1[i] * y2[i];
+ }
+
+ g_coeff[4] = 2.0f * y1y2;
+ }
+
+ /**
+* Compute correlations of input response h[] with the target vector X[].
+*
+* @param h (i) :Impulse response of filters
+* @param x (i) :Target vector
+* @param d (o) :Correlations between h[] and x[]
+*/
+
+ public static void cor_h_x(
+ float[] h,
+ float[] x,
+ float[] d
+ )
+ {
+ var L_SUBFR = Ld8k.L_SUBFR;
- int i, j;
- float s;
+ int i, j;
+ float s;
- for (i = 0; i < L_SUBFR; i++)
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ s = 0.0f;
+ for (j = i; j < L_SUBFR; j++)
{
- s = 0.0f;
- for (j = i; j < L_SUBFR; j++)
- s += x[j] * h[j - i];
- d[i] = s;
+ s += x[j] * h[j - i];
}
+
+ d[i] = s;
}
}
}
diff --git a/src/SIPSorcery/app/Media/Codecs/G729Codec/DeAcelp.cs b/src/SIPSorcery/app/Media/Codecs/G729Codec/DeAcelp.cs
index 2cada2c88..eb824b0ea 100644
--- a/src/SIPSorcery/app/Media/Codecs/G729Codec/DeAcelp.cs
+++ b/src/SIPSorcery/app/Media/Codecs/G729Codec/DeAcelp.cs
@@ -22,90 +22,96 @@
/**
* @author Lubomir Marinov (translation of ITU-T C source code to Java)
*/
-namespace SIPSorcery.Media.G729Codec
+namespace SIPSorcery.Media.G729Codec;
+
+internal static class DeAcelp
{
- internal class DeAcelp
- {
- /* ITU-T G.729 Software Package Release 2 (November 2006) */
- /*
- ITU-T G.729 Annex C - Reference C code for floating point
- implementation of G.729
- Version 1.01 of 15.September.98
+ /* ITU-T G.729 Software Package Release 2 (November 2006) */
+ /*
+ITU-T G.729 Annex C - Reference C code for floating point
+ implementation of G.729
+ Version 1.01 of 15.September.98
*/
- /*
+ /*
----------------------------------------------------------------------
- COPYRIGHT NOTICE
+ COPYRIGHT NOTICE
----------------------------------------------------------------------
- ITU-T G.729 Annex C ANSI C source code
- Copyright (C) 1998, AT&T, France Telecom, NTT, University of
- Sherbrooke. All rights reserved.
+ITU-T G.729 Annex C ANSI C source code
+Copyright (C) 1998, AT&T, France Telecom, NTT, University of
+Sherbrooke. All rights reserved.
----------------------------------------------------------------------
*/
- /*
- File : DE_ACELP.C
- Used for the floating point version of both
- G.729 main body and G.729A
+ /*
+File : DE_ACELP.C
+Used for the floating point version of both
+G.729 main body and G.729A
*/
- /**
- * Algebraic codebook decoder.
- *
- * @param sign input : signs of 4 pulses
- * @param index input : positions of 4 pulses
- * @param cod output: innovative codevector
- */
+ /**
+* Algebraic codebook decoder.
+*
+* @param sign input : signs of 4 pulses
+* @param index input : positions of 4 pulses
+* @param cod output: innovative codevector
+*/
- public static void decod_ACELP(
- int sign,
- int index,
- float[] cod
- )
- {
- var L_SUBFR = Ld8k.L_SUBFR;
+ public static void decod_ACELP(
+ int sign,
+ int index,
+ float[] cod
+ )
+ {
+ var L_SUBFR = Ld8k.L_SUBFR;
- var pos = new int[4];
- int i, j;
+ var pos = new int[4];
+ int i, j;
- /* decode the positions of 4 pulses */
+ /* decode the positions of 4 pulses */
- i = index & 7;
- pos[0] = i * 5;
+ i = index & 7;
+ pos[0] = i * 5;
- index >>= 3;
- i = index & 7;
- pos[1] = i * 5 + 1;
+ index >>= 3;
+ i = index & 7;
+ pos[1] = i * 5 + 1;
- index >>= 3;
- i = index & 7;
- pos[2] = i * 5 + 2;
+ index >>= 3;
+ i = index & 7;
+ pos[2] = i * 5 + 2;
- index >>= 3;
- j = index & 1;
- index >>= 1;
- i = index & 7;
- pos[3] = i * 5 + 3 + j;
+ index >>= 3;
+ j = index & 1;
+ index >>= 1;
+ i = index & 7;
+ pos[3] = i * 5 + 3 + j;
- /* find the algebraic codeword */
+ /* find the algebraic codeword */
- for (i = 0; i < L_SUBFR; i++) cod[i] = 0;
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ cod[i] = 0;
+ }
- /* decode the signs of 4 pulses */
+ /* decode the signs of 4 pulses */
- for (j = 0; j < 4; j++)
- {
+ for (j = 0; j < 4; j++)
+ {
- i = sign & 1;
- sign >>= 1;
+ i = sign & 1;
+ sign >>= 1;
- if (i != 0)
- cod[pos[j]] = 1.0f;
- else
- cod[pos[j]] = -1.0f;
+ if (i != 0)
+ {
+ cod[pos[j]] = 1.0f;
+ }
+ else
+ {
+ cod[pos[j]] = -1.0f;
}
}
}
-}
\ No newline at end of file
+}
diff --git a/src/SIPSorcery/app/Media/Codecs/G729Codec/DecGain.cs b/src/SIPSorcery/app/Media/Codecs/G729Codec/DecGain.cs
index e8c9fe6da..4ecd21dec 100644
--- a/src/SIPSorcery/app/Media/Codecs/G729Codec/DecGain.cs
+++ b/src/SIPSorcery/app/Media/Codecs/G729Codec/DecGain.cs
@@ -22,114 +22,117 @@
/**
* @author Lubomir Marinov (translation of ITU-T C source code to Java)
*/
-namespace SIPSorcery.Media.G729Codec
+namespace SIPSorcery.Media.G729Codec;
+
+internal class DecGain
{
- internal class DecGain
- {
- /* ITU-T G.729 Software Package Release 2 (November 2006) */
- /*
- ITU-T G.729 Annex C - Reference C code for floating point
- implementation of G.729
- Version 1.01 of 15.September.98
+ /* ITU-T G.729 Software Package Release 2 (November 2006) */
+ /*
+ITU-T G.729 Annex C - Reference C code for floating point
+ implementation of G.729
+ Version 1.01 of 15.September.98
*/
- /*
+ /*
----------------------------------------------------------------------
- COPYRIGHT NOTICE
+ COPYRIGHT NOTICE
----------------------------------------------------------------------
- ITU-T G.729 Annex C ANSI C source code
- Copyright (C) 1998, AT&T, France Telecom, NTT, University of
- Sherbrooke. All rights reserved.
+ITU-T G.729 Annex C ANSI C source code
+Copyright (C) 1998, AT&T, France Telecom, NTT, University of
+Sherbrooke. All rights reserved.
----------------------------------------------------------------------
*/
- /*
- File : DEC_GAIN.C
- Used for the floating point version of both
- G.729 main body and G.729A
+ /*
+File : DEC_GAIN.C
+Used for the floating point version of both
+G.729 main body and G.729A
+*/
+ private readonly float[ /* 4 */] past_qua_en =
+ {
+ -14.0f,
+ -14.0f,
+ -14.0f,
+ -14.0f
+ };
+
+ /**
+* Decode the adaptive and fixed codebook gains.
+*
+* @param index input : quantizer index
+* @param code input : fixed code book vector
+* @param l_subfr input : subframe size
+* @param bfi input : bad frame indicator good = 0
+* @param gain_pit output: quantized acb gain
+* @param gain_code output: quantized fcb gain
*/
- private readonly float[ /* 4 */] past_qua_en =
- {
- -14.0f,
- -14.0f,
- -14.0f,
- -14.0f
- };
-
- /**
- * Decode the adaptive and fixed codebook gains.
- *
- * @param index input : quantizer index
- * @param code input : fixed code book vector
- * @param l_subfr input : subframe size
- * @param bfi input : bad frame indicator good = 0
- * @param gain_pit output: quantized acb gain
- * @param gain_code output: quantized fcb gain
- */
- public void dec_gain(
- int index,
- float[] code,
- int l_subfr,
- int bfi,
- FloatReference gain_pit,
- FloatReference gain_code
- )
- {
- var NCODE2 = Ld8k.NCODE2;
- var gbk1 = TabLd8k.gbk1;
- var gbk2 = TabLd8k.gbk2;
- var imap1 = TabLd8k.imap1;
- var imap2 = TabLd8k.imap2;
+ public void dec_gain(
+ int index,
+ float[] code,
+ int l_subfr,
+ int bfi,
+ FloatReference gain_pit,
+ FloatReference gain_code
+ )
+ {
+ var NCODE2 = Ld8k.NCODE2;
+ var gbk1 = TabLd8k.gbk1;
+ var gbk2 = TabLd8k.gbk2;
+ var imap1 = TabLd8k.imap1;
+ var imap2 = TabLd8k.imap2;
- int index1, index2;
- float gcode0, g_code;
+ int index1, index2;
+ float gcode0, g_code;
- /*----------------- Test erasure ---------------*/
- if (bfi != 0)
+ /*----------------- Test erasure ---------------*/
+ if (bfi != 0)
+ {
+ gain_pit.value *= 0.9f;
+ if (gain_pit.value > 0.9f)
{
- gain_pit.value *= 0.9f;
- if (gain_pit.value > 0.9f) gain_pit.value = 0.9f;
- gain_code.value *= 0.98f;
+ gain_pit.value = 0.9f;
+ }
- /*----------------------------------------------*
- * update table of past quantized energies *
- * (frame erasure) *
- *----------------------------------------------*/
- Gainpred.gain_update_erasure(past_qua_en);
+ gain_code.value *= 0.98f;
- return;
- }
+ /*----------------------------------------------*
+ * update table of past quantized energies *
+ * (frame erasure) *
+ *----------------------------------------------*/
+ Gainpred.gain_update_erasure(past_qua_en);
- /*-------------- Decode pitch gain ---------------*/
+ return;
+ }
- index1 = imap1[index / NCODE2];
- index2 = imap2[index % NCODE2];
- gain_pit.value = gbk1[index1][0] + gbk2[index2][0];
+ /*-------------- Decode pitch gain ---------------*/
- /*-------------- Decode codebook gain ---------------*/
+ index1 = imap1[index / NCODE2];
+ index2 = imap2[index % NCODE2];
+ gain_pit.value = gbk1[index1][0] + gbk2[index2][0];
- /*---------------------------------------------------*
- *- energy due to innovation -*
- *- predicted energy -*
- *- predicted codebook gain => gcode0[exp_gcode0] -*
- *---------------------------------------------------*/
+ /*-------------- Decode codebook gain ---------------*/
- gcode0 = Gainpred.gain_predict(past_qua_en, code, l_subfr);
+ /*---------------------------------------------------*
+*- energy due to innovation -*
+*- predicted energy -*
+*- predicted codebook gain => gcode0[exp_gcode0] -*
+*---------------------------------------------------*/
- /*-----------------------------------------------------------------*
- * *gain_code = (gbk1[indice1][1]+gbk2[indice2][1]) * gcode0; *
- *-----------------------------------------------------------------*/
+ gcode0 = Gainpred.gain_predict(past_qua_en, code, l_subfr);
- g_code = gbk1[index1][1] + gbk2[index2][1];
- gain_code.value = g_code * gcode0;
+ /*-----------------------------------------------------------------*
+* *gain_code = (gbk1[indice1][1]+gbk2[indice2][1]) * gcode0; *
+*-----------------------------------------------------------------*/
- /*----------------------------------------------*
- * update table of past quantized energies *
- *----------------------------------------------*/
+ g_code = gbk1[index1][1] + gbk2[index2][1];
+ gain_code.value = g_code * gcode0;
- Gainpred.gain_update(past_qua_en, g_code);
- }
+ /*----------------------------------------------*
+* update table of past quantized energies *
+*----------------------------------------------*/
+
+ Gainpred.gain_update(past_qua_en, g_code);
}
}
\ No newline at end of file
diff --git a/src/SIPSorcery/app/Media/Codecs/G729Codec/DecLag3.cs b/src/SIPSorcery/app/Media/Codecs/G729Codec/DecLag3.cs
index c4c8bf979..b147caaf8 100644
--- a/src/SIPSorcery/app/Media/Codecs/G729Codec/DecLag3.cs
+++ b/src/SIPSorcery/app/Media/Codecs/G729Codec/DecLag3.cs
@@ -22,96 +22,97 @@
/**
* @author Lubomir Marinov (translation of ITU-T C source code to Java)
*/
-namespace SIPSorcery.Media.G729Codec
+namespace SIPSorcery.Media.G729Codec;
+
+internal static class DecLag3
{
- internal class DecLag3
- {
- /* ITU-T G.729 Software Package Release 2 (November 2006) */
- /*
- ITU-T G.729 Annex C - Reference C code for floating point
- implementation of G.729
- Version 1.01 of 15.September.98
+ /* ITU-T G.729 Software Package Release 2 (November 2006) */
+ /*
+ITU-T G.729 Annex C - Reference C code for floating point
+ implementation of G.729
+ Version 1.01 of 15.September.98
*/
- /*
+ /*
----------------------------------------------------------------------
- COPYRIGHT NOTICE
+ COPYRIGHT NOTICE
----------------------------------------------------------------------
- ITU-T G.729 Annex C ANSI C source code
- Copyright (C) 1998, AT&T, France Telecom, NTT, University of
- Sherbrooke. All rights reserved.
+ITU-T G.729 Annex C ANSI C source code
+Copyright (C) 1998, AT&T, France Telecom, NTT, University of
+Sherbrooke. All rights reserved.
----------------------------------------------------------------------
*/
- /*
- File : DEC_LAG3.C
- Used for the floating point version of both
- G.729 main body and G.729A
+ /*
+File : DEC_LAG3.C
+Used for the floating point version of both
+G.729 main body and G.729A
*/
- /**
- * Decoding of fractional pitch lag with 1/3 resolution.
- * See the source for more details about the encoding procedure.
- *
- * @param index input : received pitch index
- * @param pit_min input : minimum pitch lag
- * @param pit_max input : maximum pitch lag
- * @param i_subfr input : subframe flag
- * @param T0 output: integer part of pitch lag
- * @param T0_frac output: fractional part of pitch lag
- */
+ /**
+* Decoding of fractional pitch lag with 1/3 resolution.
+* See the source for more details about the encoding procedure.
+*
+* @param index input : received pitch index
+* @param pit_min input : minimum pitch lag
+* @param pit_max input : maximum pitch lag
+* @param i_subfr input : subframe flag
+* @param T0 output: integer part of pitch lag
+* @param T0_frac output: fractional part of pitch lag
+*/
- public static void dec_lag3(
- int index,
- int pit_min,
- int pit_max,
- int i_subfr,
- IntReference T0,
- IntReference T0_frac
- )
- {
- int i;
- int _T0 = T0.value, _T0_frac = T0_frac.value;
- int T0_min, T0_max;
+ public static void dec_lag3(
+ int index,
+ int pit_min,
+ int pit_max,
+ int i_subfr,
+ IntReference T0,
+ IntReference T0_frac
+ )
+ {
+ int i;
+ int _T0 = T0.value, _T0_frac = T0_frac.value;
+ int T0_min, T0_max;
- if (i_subfr == 0) /* if 1st subframe */
+ if (i_subfr == 0) /* if 1st subframe */
+ {
+ if (index < 197)
{
- if (index < 197)
- {
- _T0 = (index + 2) / 3 + 19;
- _T0_frac = index - _T0 * 3 + 58;
- }
- else
- {
- _T0 = index - 112;
- _T0_frac = 0;
- }
+ _T0 = (index + 2) / 3 + 19;
+ _T0_frac = index - _T0 * 3 + 58;
}
-
- else /* second subframe */
+ else
{
- /* find T0_min and T0_max for 2nd subframe */
+ _T0 = index - 112;
+ _T0_frac = 0;
+ }
+ }
- T0_min = _T0 - 5;
- if (T0_min < pit_min)
- T0_min = pit_min;
+ else /* second subframe */
+ {
+ /* find T0_min and T0_max for 2nd subframe */
- T0_max = T0_min + 9;
- if (T0_max > pit_max)
- {
- T0_max = pit_max;
- T0_min = T0_max - 9;
- }
+ T0_min = _T0 - 5;
+ if (T0_min < pit_min)
+ {
+ T0_min = pit_min;
+ }
- i = (index + 2) / 3 - 1;
- _T0 = i + T0_min;
- _T0_frac = index - 2 - i * 3;
+ T0_max = T0_min + 9;
+ if (T0_max > pit_max)
+ {
+ T0_max = pit_max;
+ T0_min = T0_max - 9;
}
- T0.value = _T0;
- T0_frac.value = _T0_frac;
+ i = (index + 2) / 3 - 1;
+ _T0 = i + T0_min;
+ _T0_frac = index - 2 - i * 3;
}
+
+ T0.value = _T0;
+ T0_frac.value = _T0_frac;
}
-}
\ No newline at end of file
+}
diff --git a/src/SIPSorcery/app/Media/Codecs/G729Codec/DecLd8k.cs b/src/SIPSorcery/app/Media/Codecs/G729Codec/DecLd8k.cs
index 895b86792..f55bbe5f1 100644
--- a/src/SIPSorcery/app/Media/Codecs/G729Codec/DecLd8k.cs
+++ b/src/SIPSorcery/app/Media/Codecs/G729Codec/DecLd8k.cs
@@ -19,6 +19,9 @@
* SIPRO Lab Telecom.
*/
+
+using System.Diagnostics;
+
/**
* Functions init_decod_ld8k and decod_ld8k.
*
@@ -35,318 +38,343 @@
*
* @author Lubomir Marinov (translation of ITU-T C source code to Java)
*/
-namespace SIPSorcery.Media.G729Codec
+namespace SIPSorcery.Media.G729Codec;
+
+internal sealed class DecLd8k : Ld8k
{
- internal class DecLd8k : Ld8k
- {
- private readonly DecGain decGain = new DecGain();
+ private readonly DecGain decGain = new DecGain();
- /**
- * Excitation vector
- */
- private float[] exc;
+ /**
+* Excitation vector
+*/
+ private float[]? exc;
- /**
- * Excitation vector offset
- */
- private int exc_offset;
+ /**
+* Excitation vector offset
+*/
+ private int exc_offset;
- /**
- * fixed codebook gain
- */
- private readonly FloatReference gain_code = new FloatReference();
+ /**
+* fixed codebook gain
+*/
+ private readonly FloatReference gain_code = new FloatReference();
- /**
- * adaptive codebook gain
- */
- private readonly FloatReference gain_pitch = new FloatReference();
+ /**
+* adaptive codebook gain
+*/
+ private readonly FloatReference gain_pitch = new FloatReference();
- /**
- * Lsp (Line spectral pairs)
- */
- private readonly float[ /* M */] lsp_old =
- {
- 0.9595f,
- 0.8413f,
- 0.6549f,
- 0.4154f,
- 0.1423f,
- -0.1423f,
- -0.4154f,
- -0.6549f,
- -0.8413f,
- -0.9595f
- };
-
- private readonly Lspdec lspdec = new Lspdec();
-
- /**
- * Filter's memory
- */
- private readonly float[] mem_syn = new float[M];
+ /**
+* Lsp (Line spectral pairs)
+*/
+ private readonly float[ /* M */] lsp_old =
+ {
+ 0.9595f,
+ 0.8413f,
+ 0.6549f,
+ 0.4154f,
+ 0.1423f,
+ -0.1423f,
+ -0.4154f,
+ -0.6549f,
+ -0.8413f,
+ -0.9595f
+ };
+
+ private readonly Lspdec lspdec = new Lspdec();
+
+ /**
+* Filter's memory
+*/
+ private readonly float[] mem_syn = new float[M];
- /* ITU-T G.729 Software Package Release 2 (November 2006) */
- /*
- ITU-T G.729 Annex C - Reference C code for floating point
- implementation of G.729
- Version 1.01 of 15.September.98
+ /* ITU-T G.729 Software Package Release 2 (November 2006) */
+ /*
+ITU-T G.729 Annex C - Reference C code for floating point
+ implementation of G.729
+ Version 1.01 of 15.September.98
*/
- /*
+ /*
----------------------------------------------------------------------
- COPYRIGHT NOTICE
+ COPYRIGHT NOTICE
----------------------------------------------------------------------
- ITU-T G.729 Annex C ANSI C source code
- Copyright (C) 1998, AT&T, France Telecom, NTT, University of
- Sherbrooke. All rights reserved.
+ITU-T G.729 Annex C ANSI C source code
+Copyright (C) 1998, AT&T, France Telecom, NTT, University of
+Sherbrooke. All rights reserved.
----------------------------------------------------------------------
*/
- /*
- File : DEC_LD8K.C
- Used for the floating point version of G.729 main body
- (not for G.729A)
+ /*
+File : DEC_LD8K.C
+Used for the floating point version of G.729 main body
+(not for G.729A)
*/
- /*--------------------------------------------------------*
- * Static memory allocation. *
- *--------------------------------------------------------*/
+ /*--------------------------------------------------------*
+* Static memory allocation. *
+*--------------------------------------------------------*/
- /**
- * Excitation vector
- */
- private readonly float[] old_exc = new float[L_FRAME + PIT_MAX + L_INTERPOL];
+ /**
+* Excitation vector
+*/
+ private readonly float[] old_exc = new float[L_FRAME + PIT_MAX + L_INTERPOL];
- /**
+ /**
* integer delay of previous frame
*/
- private int old_t0;
+ private int old_t0;
- /**
- * pitch sharpening of previous fr
- */
- private float sharp;
+ /**
+* pitch sharpening of previous fr
+*/
+ private float sharp;
- /**
- * Initialization of variables for the decoder section.
- */
+ /**
+* Initialization of variables for the decoder section.
+*/
- public void init_decod_ld8k()
- {
- /* Initialize static pointer */
- exc = old_exc;
- exc_offset = PIT_MAX + L_INTERPOL;
+ public void init_decod_ld8k()
+ {
+ /* Initialize static pointer */
+ exc = old_exc;
+ exc_offset = PIT_MAX + L_INTERPOL;
- /* Static vectors to zero */
- Util.set_zero(old_exc, PIT_MAX + L_INTERPOL);
- Util.set_zero(mem_syn, M);
+ /* Static vectors to zero */
+ Util.set_zero(old_exc, PIT_MAX + L_INTERPOL);
+ Util.set_zero(mem_syn, M);
- sharp = SHARPMIN;
- old_t0 = 60;
- gain_code.value = 0.0f;
- gain_pitch.value = 0.0f;
+ sharp = SHARPMIN;
+ old_t0 = 60;
+ gain_code.value = 0.0f;
+ gain_pitch.value = 0.0f;
- lspdec.lsp_decw_reset();
- }
+ lspdec.lsp_decw_reset();
+ }
- /**
- * Decoder
- *
- * @param parm input : synthesis parameters (parm[0] = bfi)
- * @param voicing input : voicing decision from previous frame
- * @param synth output: synthesized speech
- * @param synth_offset input : synthesized speech offset
- * @param A_t output: two sets of A(z) coefficients length=2*MP1
- * @return output: integer delay of first subframe
- */
+ /**
+* Decoder
+*
+* @param parm input : synthesis parameters (parm[0] = bfi)
+* @param voicing input : voicing decision from previous frame
+* @param synth output: synthesized speech
+* @param synth_offset input : synthesized speech offset
+* @param A_t output: two sets of A(z) coefficients length=2*MP1
+* @return output: integer delay of first subframe
+*/
- public int decod_ld8k(
- int[] parm,
- int voicing,
- float[] synth,
- int synth_offset,
- float[] A_t
- )
- {
- var parm_offset = 0;
+ public int decod_ld8k(
+ int[] parm,
+ int voicing,
+ float[] synth,
+ int synth_offset,
+ float[] A_t
+ )
+ {
+ var parm_offset = 0;
- var t0_first = 0; /* output: integer delay of first subframe */
- float[] Az; /* Pointer to A_t (LPC coefficients) */
- int Az_offset;
- var lsp_new = new float[M]; /* LSPs */
- var code = new float[L_SUBFR]; /* algebraic codevector */
+ var t0_first = 0; /* output: integer delay of first subframe */
+ float[] Az; /* Pointer to A_t (LPC coefficients) */
+ int Az_offset;
+ var lsp_new = new float[M]; /* LSPs */
+ var code = new float[L_SUBFR]; /* algebraic codevector */
- /* Scalars */
- int i, i_subfr;
- IntReference t0 = new IntReference(), t0_frac = new IntReference();
- int index;
+ /* Scalars */
+ int i, i_subfr;
+ IntReference t0 = new IntReference(), t0_frac = new IntReference();
+ int index;
- int bfi;
- int bad_pitch;
+ int bfi;
+ int bad_pitch;
- /* Test bad frame indicator (bfi) */
+ /* Test bad frame indicator (bfi) */
- bfi = parm[parm_offset];
- parm_offset++;
+ bfi = parm[parm_offset];
+ parm_offset++;
- /* Decode the LSPs */
+ /* Decode the LSPs */
- lspdec.d_lsp(parm, parm_offset, lsp_new, bfi);
- parm_offset += 2; /* Advance synthesis parameters pointer */
+ lspdec.d_lsp(parm, parm_offset, lsp_new, bfi);
+ parm_offset += 2; /* Advance synthesis parameters pointer */
- /* Interpolation of LPC for the 2 subframes */
+ /* Interpolation of LPC for the 2 subframes */
- Lpcfunc.int_qlpc(lsp_old, lsp_new, A_t);
+ Lpcfunc.int_qlpc(lsp_old, lsp_new, A_t);
- /* update the LSFs for the next frame */
+ /* update the LSFs for the next frame */
- Util.copy(lsp_new, lsp_old, M);
+ Util.copy(lsp_new, lsp_old, M);
- /*------------------------------------------------------------------------*
- * Loop for every subframe in the analysis frame *
- *------------------------------------------------------------------------*
- * The subframe size is L_SUBFR and the loop is repeated L_FRAME/L_SUBFR *
- * times *
- * - decode the pitch delay *
- * - decode algebraic code *
- * - decode pitch and codebook gains *
- * - find the excitation and compute synthesis speech *
- *------------------------------------------------------------------------*/
+ /*------------------------------------------------------------------------*
+* Loop for every subframe in the analysis frame *
+*------------------------------------------------------------------------*
+* The subframe size is L_SUBFR and the loop is repeated L_FRAME/L_SUBFR *
+* times *
+* - decode the pitch delay *
+* - decode algebraic code *
+* - decode pitch and codebook gains *
+* - find the excitation and compute synthesis speech *
+*------------------------------------------------------------------------*/
- Az = A_t; /* pointer to interpolated LPC parameters */
- Az_offset = 0;
+ Az = A_t; /* pointer to interpolated LPC parameters */
+ Az_offset = 0;
- for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR)
- {
+ for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR)
+ {
- index = parm[parm_offset]; /* pitch index */
- parm_offset++;
+ index = parm[parm_offset]; /* pitch index */
+ parm_offset++;
- if (i_subfr == 0)
+ if (i_subfr == 0)
+ {
+ /* if first subframe */
+ i = parm[parm_offset]; /* get parity check result */
+ parm_offset++;
+ bad_pitch = bfi + i;
+ if (bad_pitch == 0)
{
- /* if first subframe */
- i = parm[parm_offset]; /* get parity check result */
- parm_offset++;
- bad_pitch = bfi + i;
- if (bad_pitch == 0)
- {
- DecLag3.dec_lag3(index, PIT_MIN, PIT_MAX, i_subfr, t0, t0_frac);
- old_t0 = t0.value;
- }
- else /* Bad frame, or parity error */
+ DecLag3.dec_lag3(index, PIT_MIN, PIT_MAX, i_subfr, t0, t0_frac);
+ old_t0 = t0.value;
+ }
+ else /* Bad frame, or parity error */
+ {
+ t0.value = old_t0;
+ t0_frac.value = 0;
+ old_t0++;
+ if (old_t0 > PIT_MAX)
{
- t0.value = old_t0;
- t0_frac.value = 0;
- old_t0++;
- if (old_t0 > PIT_MAX)
- old_t0 = PIT_MAX;
+ old_t0 = PIT_MAX;
}
+ }
- t0_first = t0.value; /* If first frame */
+ t0_first = t0.value; /* If first frame */
+ }
+ else /* second subframe */
+ {
+ if (bfi == 0)
+ {
+ DecLag3.dec_lag3(index, PIT_MIN, PIT_MAX, i_subfr, t0, t0_frac);
+ old_t0 = t0.value;
}
- else /* second subframe */
+ else
{
- if (bfi == 0)
+ t0.value = old_t0;
+ t0_frac.value = 0;
+ old_t0++;
+ if (old_t0 > PIT_MAX)
{
- DecLag3.dec_lag3(index, PIT_MIN, PIT_MAX, i_subfr, t0, t0_frac);
- old_t0 = t0.value;
- }
- else
- {
- t0.value = old_t0;
- t0_frac.value = 0;
- old_t0++;
- if (old_t0 > PIT_MAX)
- old_t0 = PIT_MAX;
+ old_t0 = PIT_MAX;
}
}
+ }
- /*-------------------------------------------------*
- * - Find the adaptive codebook vector. *
- *--------------------------------------------------*/
+ /*-------------------------------------------------*
+* - Find the adaptive codebook vector. *
+*--------------------------------------------------*/
- PredLt3.pred_lt_3(exc, exc_offset + i_subfr, t0.value, t0_frac.value, L_SUBFR);
+ Debug.Assert(exc is { });
- /*-------------------------------------------------------*
- * - Decode innovative codebook. *
- * - Add the fixed-gain pitch contribution to code[]. *
- *-------------------------------------------------------*/
+ PredLt3.pred_lt_3(exc, exc_offset + i_subfr, t0.value, t0_frac.value, L_SUBFR);
- if (bfi != 0)
- {
- /* Bad Frame Error Concealment */
- parm[parm_offset + 0] = Util.random_g729() & 0x1fff; /* 13 bits random*/
- parm[parm_offset + 1] = Util.random_g729() & 0x000f; /* 4 bits random */
- }
+ /*-------------------------------------------------------*
+* - Decode innovative codebook. *
+* - Add the fixed-gain pitch contribution to code[]. *
+*-------------------------------------------------------*/
- DeAcelp.decod_ACELP(parm[parm_offset + 1], parm[parm_offset + 0], code);
- parm_offset += 2;
- for (i = t0.value; i < L_SUBFR; i++) code[i] += sharp * code[i - t0.value];
+ if (bfi != 0)
+ {
+ /* Bad Frame Error Concealment */
+ parm[parm_offset + 0] = Util.random_g729() & 0x1fff; /* 13 bits random*/
+ parm[parm_offset + 1] = Util.random_g729() & 0x000f; /* 4 bits random */
+ }
- /*-------------------------------------------------*
- * - Decode pitch and codebook gains. *
- *-------------------------------------------------*/
+ DeAcelp.decod_ACELP(parm[parm_offset + 1], parm[parm_offset + 0], code);
+ parm_offset += 2;
+ for (i = t0.value; i < L_SUBFR; i++)
+ {
+ code[i] += sharp * code[i - t0.value];
+ }
- index = parm[parm_offset]; /* index of energy VQ */
- parm_offset++;
- decGain.dec_gain(index, code, L_SUBFR, bfi, gain_pitch, gain_code);
+ /*-------------------------------------------------*
+* - Decode pitch and codebook gains. *
+*-------------------------------------------------*/
- /*-------------------------------------------------------------*
- * - Update pitch sharpening "sharp" with quantized gain_pitch *
- *-------------------------------------------------------------*/
+ index = parm[parm_offset]; /* index of energy VQ */
+ parm_offset++;
+ decGain.dec_gain(index, code, L_SUBFR, bfi, gain_pitch, gain_code);
+
+ /*-------------------------------------------------------------*
+* - Update pitch sharpening "sharp" with quantized gain_pitch *
+*-------------------------------------------------------------*/
+
+ sharp = gain_pitch.value;
+ if (sharp > SHARPMAX)
+ {
+ sharp = SHARPMAX;
+ }
- sharp = gain_pitch.value;
- if (sharp > SHARPMAX) sharp = SHARPMAX;
- if (sharp < SHARPMIN) sharp = SHARPMIN;
+ if (sharp < SHARPMIN)
+ {
+ sharp = SHARPMIN;
+ }
- /*-------------------------------------------------------*
- * - Find the total excitation. *
- *-------------------------------------------------------*/
+ /*-------------------------------------------------------*
+* - Find the total excitation. *
+*-------------------------------------------------------*/
- if (bfi != 0)
+ if (bfi != 0)
+ {
+ if (voicing == 0)
{
- if (voicing == 0)
- for (i = 0; i < L_SUBFR; i++)
- exc[exc_offset + i + i_subfr] = gain_code.value * code[i];
- else
- for (i = 0; i < L_SUBFR; i++)
- exc[exc_offset + i + i_subfr] = gain_pitch.value * exc[exc_offset + i + i_subfr];
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ exc[exc_offset + i + i_subfr] = gain_code.value * code[i];
+ }
}
else
{
- /* No frame errors */
for (i = 0; i < L_SUBFR; i++)
- exc[exc_offset + i + i_subfr] =
- gain_pitch.value * exc[exc_offset + i + i_subfr] + gain_code.value * code[i];
+ {
+ exc[exc_offset + i + i_subfr] = gain_pitch.value * exc[exc_offset + i + i_subfr];
+ }
+ }
+ }
+ else
+ {
+ /* No frame errors */
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ exc[exc_offset + i + i_subfr] =
+ gain_pitch.value * exc[exc_offset + i + i_subfr] + gain_code.value * code[i];
}
-
- /*-------------------------------------------------------*
- * - Find synthesis speech corresponding to exc[]. *
- *-------------------------------------------------------*/
-
- Filter.syn_filt(
- Az,
- Az_offset,
- exc,
- exc_offset + i_subfr,
- synth,
- synth_offset + i_subfr,
- L_SUBFR,
- mem_syn,
- 0,
- 1);
-
- Az_offset += MP1; /* interpolated LPC parameters for next subframe */
}
- /*--------------------------------------------------*
- * Update signal for next frame. *
- * -> shift to the left by L_FRAME exc[] *
- *--------------------------------------------------*/
- Util.copy(old_exc, L_FRAME, old_exc, PIT_MAX + L_INTERPOL);
- return t0_first;
+ /*-------------------------------------------------------*
+ * - Find synthesis speech corresponding to exc[]. *
+ *-------------------------------------------------------*/
+
+ Filter.syn_filt(
+ Az,
+ Az_offset,
+ exc,
+ exc_offset + i_subfr,
+ synth,
+ synth_offset + i_subfr,
+ L_SUBFR,
+ mem_syn,
+ 0,
+ 1);
+
+ Az_offset += MP1; /* interpolated LPC parameters for next subframe */
}
+
+ /*--------------------------------------------------*
+* Update signal for next frame. *
+* -> shift to the left by L_FRAME exc[] *
+*--------------------------------------------------*/
+ Util.copy(old_exc, L_FRAME, old_exc, PIT_MAX + L_INTERPOL);
+ return t0_first;
}
-}
\ No newline at end of file
+}
diff --git a/src/SIPSorcery/app/Media/Codecs/G729Codec/Filter.cs b/src/SIPSorcery/app/Media/Codecs/G729Codec/Filter.cs
index 3b48d5045..5b8431072 100644
--- a/src/SIPSorcery/app/Media/Codecs/G729Codec/Filter.cs
+++ b/src/SIPSorcery/app/Media/Codecs/G729Codec/Filter.cs
@@ -24,159 +24,176 @@
*
* @author Lubomir Marinov (translation of ITU-T C source code to Java)
*/
-namespace SIPSorcery.Media.G729Codec
+namespace SIPSorcery.Media.G729Codec;
+
+internal static class Filter
{
- internal class Filter
- {
- /* ITU-T G.729 Software Package Release 2 (November 2006) */
- /*
- ITU-T G.729 Annex C - Reference C code for floating point
- implementation of G.729
- Version 1.01 of 15.September.98
+ /* ITU-T G.729 Software Package Release 2 (November 2006) */
+ /*
+ITU-T G.729 Annex C - Reference C code for floating point
+ implementation of G.729
+ Version 1.01 of 15.September.98
*/
- /*
+ /*
----------------------------------------------------------------------
- COPYRIGHT NOTICE
+ COPYRIGHT NOTICE
----------------------------------------------------------------------
- ITU-T G.729 Annex C ANSI C source code
- Copyright (C) 1998, AT&T, France Telecom, NTT, University of
- Sherbrooke. All rights reserved.
+ITU-T G.729 Annex C ANSI C source code
+Copyright (C) 1998, AT&T, France Telecom, NTT, University of
+Sherbrooke. All rights reserved.
----------------------------------------------------------------------
*/
- /*
- File : FILTER.C
- Used for the floating point version of both
- G.729 main body and G.729A
+ /*
+File : FILTER.C
+Used for the floating point version of both
+G.729 main body and G.729A
*/
- /**
- * Convolve vectors x and h and put result in y.
- *
- * @param x input : input vector x[0:l]
- * @param x_offset input : input vector offset
- * @param h input : impulse response or second input h[0:l]
- * @param y output: x convolved with h , y[0:l]
- * @param l input : dimension of all vectors
- */
+ /**
+* Convolve vectors x and h and put result in y.
+*
+* @param x input : input vector x[0:l]
+* @param x_offset input : input vector offset
+* @param h input : impulse response or second input h[0:l]
+* @param y output: x convolved with h , y[0:l]
+* @param l input : dimension of all vectors
+*/
- public static void convolve(
- float[] x,
- int x_offset,
- float[] h,
- float[] y,
- int l
- )
- {
- float temp;
- int i, n;
+ public static void convolve(
+ float[] x,
+ int x_offset,
+ float[] h,
+ float[] y,
+ int l
+ )
+ {
+ float temp;
+ int i, n;
- for (n = 0; n < l; n++)
+ for (n = 0; n < l; n++)
+ {
+ temp = 0.0f;
+ for (i = 0; i <= n; i++)
{
- temp = 0.0f;
- for (i = 0; i <= n; i++)
- temp += x[x_offset + i] * h[n - i];
- y[n] = temp;
+ temp += x[x_offset + i] * h[n - i];
}
+
+ y[n] = temp;
}
+ }
- /**
- * Filter with synthesis filter 1/A(z).
- *
- * @param a input : predictor coefficients a[0:m]
- * @param a_offset input : predictor coefficients a offset
- * @param x input : excitation signal
- * @param x_offset input : excitation signal offset
- * @param y output: filtered output signal
- * @param y_offset output: filtered output signal offset
- * @param l input : vector dimension
- * @param mem in/out: filter memory
- * @param mem_offset input : filter memory ofset
- * @param update input : 0 = no memory update, 1 = update
- */
+ /**
+* Filter with synthesis filter 1/A(z).
+*
+* @param a input : predictor coefficients a[0:m]
+* @param a_offset input : predictor coefficients a offset
+* @param x input : excitation signal
+* @param x_offset input : excitation signal offset
+* @param y output: filtered output signal
+* @param y_offset output: filtered output signal offset
+* @param l input : vector dimension
+* @param mem in/out: filter memory
+* @param mem_offset input : filter memory ofset
+* @param update input : 0 = no memory update, 1 = update
+*/
- public static void syn_filt(
- float[] a,
- int a_offset,
- float[] x,
- int x_offset,
- float[] y,
- int y_offset,
- int l,
- float[] mem,
- int mem_offset,
- int update
- )
+ public static void syn_filt(
+ float[] a,
+ int a_offset,
+ float[] x,
+ int x_offset,
+ float[] y,
+ int y_offset,
+ int l,
+ float[] mem,
+ int mem_offset,
+ int update
+ )
+ {
+ var L_SUBFR = Ld8k.L_SUBFR;
+ var M = Ld8k.M;
+
+ int i, j;
+
+ /* This is usually done by memory allocation (l+m) */
+ var yy_b = new float[L_SUBFR + M];
+ float s;
+ int yy, py, pa;
+ /* Copy mem[] to yy[] */
+ yy = 0; //index instead of pointer
+ for (i = 0; i < M; i++)
{
- var L_SUBFR = Ld8k.L_SUBFR;
- var M = Ld8k.M;
-
- int i, j;
-
- /* This is usually done by memory allocation (l+m) */
- var yy_b = new float[L_SUBFR + M];
- float s;
- int yy, py, pa;
- /* Copy mem[] to yy[] */
- yy = 0; //index instead of pointer
- for (i = 0; i < M; i++) yy_b[yy++] = mem[mem_offset++];
+ yy_b[yy++] = mem[mem_offset++];
+ }
- /* Filtering */
+ /* Filtering */
- for (i = 0; i < l; i++)
+ for (i = 0; i < l; i++)
+ {
+ py = yy;
+ pa = 0; //index instead of pointer
+ s = x[x_offset++];
+ for (j = 0; j < M; j++)
{
- py = yy;
- pa = 0; //index instead of pointer
- s = x[x_offset++];
- for (j = 0; j < M; j++) s -= a[a_offset + ++pa] * yy_b[--py];
- yy_b[yy++] = s;
- y[y_offset++] = s;
+ s -= a[a_offset + ++pa] * yy_b[--py];
}
- /* Update memory if required */
-
- if (update != 0)
- for (i = 0; i < M; i++)
- mem[--mem_offset] = yy_b[--yy];
+ yy_b[yy++] = s;
+ y[y_offset++] = s;
}
- /**
- * Filter input vector with all-zero filter A(Z).
- *
- * @param a input : prediction coefficients a[0:m+1], a[0]=1.
- * @param a_offset input : prediction coefficients a offset
- * @param x input : input signal x[0:l-1], x[-1:m] are needed
- * @param x_offset input : input signal x offset
- * @param y output: output signal y[0:l-1].
- * NOTE: x[] and y[] cannot point to same array
- * @param y_offset input : output signal y offset
- * @param l input : dimension of x and y
- */
+ /* Update memory if required */
- public static void residu(
- float[] a,
- int a_offset,
- float[] x,
- int x_offset,
- float[] y,
- int y_offset,
- int l
- )
+ if (update != 0)
{
- var M = Ld8k.M;
+ for (i = 0; i < M; i++)
+ {
+ mem[--mem_offset] = yy_b[--yy];
+ }
+ }
+ }
+
+ /**
+* Filter input vector with all-zero filter A(Z).
+*
+* @param a input : prediction coefficients a[0:m+1], a[0]=1.
+* @param a_offset input : prediction coefficients a offset
+* @param x input : input signal x[0:l-1], x[-1:m] are needed
+* @param x_offset input : input signal x offset
+* @param y output: output signal y[0:l-1].
+* NOTE: x[] and y[] cannot point to same array
+* @param y_offset input : output signal y offset
+* @param l input : dimension of x and y
+*/
- float s;
- int i, j;
+ public static void residu(
+ float[] a,
+ int a_offset,
+ float[] x,
+ int x_offset,
+ float[] y,
+ int y_offset,
+ int l
+ )
+ {
+ var M = Ld8k.M;
- for (i = 0; i < l; i++)
+ float s;
+ int i, j;
+
+ for (i = 0; i < l; i++)
+ {
+ s = x[x_offset + i];
+ for (j = 1; j <= M; j++)
{
- s = x[x_offset + i];
- for (j = 1; j <= M; j++) s += a[a_offset + j] * x[x_offset + i - j];
- y[y_offset + i] = s;
+ s += a[a_offset + j] * x[x_offset + i - j];
}
+
+ y[y_offset + i] = s;
}
}
-}
\ No newline at end of file
+}
diff --git a/src/SIPSorcery/app/Media/Codecs/G729Codec/FloatReference.cs b/src/SIPSorcery/app/Media/Codecs/G729Codec/FloatReference.cs
index 5ff8065aa..a346b13ad 100644
--- a/src/SIPSorcery/app/Media/Codecs/G729Codec/FloatReference.cs
+++ b/src/SIPSorcery/app/Media/Codecs/G729Codec/FloatReference.cs
@@ -17,10 +17,9 @@
/**
* @author Lubomir Marinov
*/
-namespace SIPSorcery.Media.G729Codec
+namespace SIPSorcery.Media.G729Codec;
+
+internal sealed class FloatReference
{
- internal class FloatReference
- {
- public float value;
- }
-}
\ No newline at end of file
+ public float value;
+}
diff --git a/src/SIPSorcery/app/Media/Codecs/G729Codec/Gainpred.cs b/src/SIPSorcery/app/Media/Codecs/G729Codec/Gainpred.cs
index 871c06252..e52a752d1 100644
--- a/src/SIPSorcery/app/Media/Codecs/G729Codec/Gainpred.cs
+++ b/src/SIPSorcery/app/Media/Codecs/G729Codec/Gainpred.cs
@@ -24,127 +24,144 @@
*/
using System;
-namespace SIPSorcery.Media.G729Codec
+namespace SIPSorcery.Media.G729Codec;
+
+internal static class Gainpred
{
- internal class Gainpred
- {
- /* ITU-T G.729 Software Package Release 2 (November 2006) */
- /*
- ITU-T G.729 Annex C - Reference C code for floating point
- implementation of G.729
- Version 1.01 of 15.September.98
+ /* ITU-T G.729 Software Package Release 2 (November 2006) */
+ /*
+ITU-T G.729 Annex C - Reference C code for floating point
+ implementation of G.729
+ Version 1.01 of 15.September.98
*/
- /*
+ /*
----------------------------------------------------------------------
- COPYRIGHT NOTICE
+ COPYRIGHT NOTICE
----------------------------------------------------------------------
- ITU-T G.729 Annex C ANSI C source code
- Copyright (C) 1998, AT&T, France Telecom, NTT, University of
- Sherbrooke. All rights reserved.
+ITU-T G.729 Annex C ANSI C source code
+Copyright (C) 1998, AT&T, France Telecom, NTT, University of
+Sherbrooke. All rights reserved.
----------------------------------------------------------------------
*/
- /*
- File : GAINPRED.C
- Used for the floating point version of both
- G.729 main body and G.729A
+ /*
+File : GAINPRED.C
+Used for the floating point version of both
+G.729 main body and G.729A
*/
- /**
- * MA prediction is performed on the innovation energy (in dB with mean
- * removed).
- *
- * @param past_qua_en (i) :Past quantized energies
- * @param code (i) :Innovative vector.
- * @param l_subfr (i) :Subframe length.
- * @return Predicted codebook gain
- */
+ /**
+* MA prediction is performed on the innovation energy (in dB with mean
+* removed).
+*
+* @param past_qua_en (i) :Past quantized energies
+* @param code (i) :Innovative vector.
+* @param l_subfr (i) :Subframe length.
+* @return Predicted codebook gain
+*/
+
+ public static float gain_predict(
+ float[] past_qua_en,
+ float[] code,
+ int l_subfr
+ )
+ {
+ var MEAN_ENER = Ld8k.MEAN_ENER;
+ var pred = TabLd8k.pred;
+
+ float ener_code, pred_code;
+ int i;
+ float gcode0; /* (o) :Predicted codebook gain */
- public static float gain_predict(
- float[] past_qua_en,
- float[] code,
- int l_subfr
- )
+ pred_code = MEAN_ENER;
+
+ /* innovation energy */
+ ener_code = 0.01f;
+ for (i = 0; i < l_subfr; i++)
{
- var MEAN_ENER = Ld8k.MEAN_ENER;
- var pred = TabLd8k.pred;
+ ener_code += code[i] * code[i];
+ }
- float ener_code, pred_code;
- int i;
- float gcode0; /* (o) :Predicted codebook gain */
+ ener_code = 10.0f * (float)Math.Log10(ener_code / l_subfr);
- pred_code = MEAN_ENER;
+ pred_code -= ener_code;
- /* innovation energy */
- ener_code = 0.01f;
- for (i = 0; i < l_subfr; i++)
- ener_code += code[i] * code[i];
- ener_code = 10.0f * (float)Math.Log10(ener_code / l_subfr);
+ /* predicted energy */
+ for (i = 0; i < 4; i++)
+ {
+ pred_code += pred[i] * past_qua_en[i];
+ }
- pred_code -= ener_code;
+ /* predicted codebook gain */
+ gcode0 = pred_code;
+ gcode0 = (float)Math.Pow(10.0, gcode0 / 20.0); /* predicted gain */
- /* predicted energy */
- for (i = 0; i < 4; i++) pred_code += pred[i] * past_qua_en[i];
+ return gcode0;
+ }
+
+ /**
+* Update table of past quantized energies.
+*
+* @param past_qua_en input/output :Past quantized energies
+* @param g_code input: gbk1[indice1][1]+gbk2[indice2][1]
+*/
- /* predicted codebook gain */
- gcode0 = pred_code;
- gcode0 = (float)Math.Pow(10.0, gcode0 / 20.0); /* predicted gain */
+ public static void gain_update(
+ float[] past_qua_en,
+ float g_code
+ )
+ {
+ int i;
- return gcode0;
+ /* update table of past quantized energies */
+ for (i = 3; i > 0; i--)
+ {
+ past_qua_en[i] = past_qua_en[i - 1];
}
- /**
- * Update table of past quantized energies.
- *
- * @param past_qua_en input/output :Past quantized energies
- * @param g_code input: gbk1[indice1][1]+gbk2[indice2][1]
- */
+ past_qua_en[0] = 20.0f * (float)Math.Log10(g_code);
+ }
- public static void gain_update(
- float[] past_qua_en,
- float g_code
- )
- {
- int i;
+ /**
+* Update table of past quantized energies (frame erasure).
+*
+*
+* @param past_qua_en input/output:Past quantized energies
+*/
- /* update table of past quantized energies */
- for (i = 3; i > 0; i--)
- past_qua_en[i] = past_qua_en[i - 1];
- past_qua_en[0] = 20.0f * (float)Math.Log10(g_code);
+ public static void gain_update_erasure(
+ float[] past_qua_en
+ )
+ {
+ int i;
+ float av_pred_en;
+
+ av_pred_en = 0.0f;
+ for (i = 0; i < 4; i++)
+ {
+ av_pred_en += past_qua_en[i];
}
- /**
- * Update table of past quantized energies (frame erasure).
- *
- *
- * @param past_qua_en input/output:Past quantized energies
- */
+ av_pred_en = av_pred_en * 0.25f - 4.0f;
+ if (av_pred_en < -14.0f)
+ {
+ av_pred_en = -14.0f;
+ }
- public static void gain_update_erasure(
- float[] past_qua_en
- )
+ for (i = 3; i > 0; i--)
{
- int i;
- float av_pred_en;
-
- av_pred_en = 0.0f;
- for (i = 0; i < 4; i++)
- av_pred_en += past_qua_en[i];
- av_pred_en = av_pred_en * 0.25f - 4.0f;
- if (av_pred_en < -14.0f) av_pred_en = -14.0f;
-
- for (i = 3; i > 0; i--)
- past_qua_en[i] = past_qua_en[i - 1];
- past_qua_en[0] = av_pred_en;
+ past_qua_en[i] = past_qua_en[i - 1];
}
+
+ past_qua_en[0] = av_pred_en;
}
}
diff --git a/src/SIPSorcery/app/Media/Codecs/G729Codec/IntReference.cs b/src/SIPSorcery/app/Media/Codecs/G729Codec/IntReference.cs
index 38b4517c3..15356fd8b 100644
--- a/src/SIPSorcery/app/Media/Codecs/G729Codec/IntReference.cs
+++ b/src/SIPSorcery/app/Media/Codecs/G729Codec/IntReference.cs
@@ -17,10 +17,9 @@
/**
* @author Lubomir Marinov
*/
-namespace SIPSorcery.Media.G729Codec
+namespace SIPSorcery.Media.G729Codec;
+
+internal sealed class IntReference
{
- internal class IntReference
- {
- public int value;
- }
-}
\ No newline at end of file
+ public int value;
+}
diff --git a/src/SIPSorcery/app/Media/Codecs/G729Codec/Ld8k.cs b/src/SIPSorcery/app/Media/Codecs/G729Codec/Ld8k.cs
index 34f6aa981..9c2ad8ffa 100644
--- a/src/SIPSorcery/app/Media/Codecs/G729Codec/Ld8k.cs
+++ b/src/SIPSorcery/app/Media/Codecs/G729Codec/Ld8k.cs
@@ -1,482 +1,480 @@
/*
- * Copyright @ 2015 Atlassian Pty Ltd
- *
- * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
+ * Copyright @ 2015 Atlassian Pty Ltd
+ *
+ * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
/*
- * WARNING: The use of G.729 may require a license fee and/or royalty fee in
- * some countries and is licensed by
- * SIPRO Lab Telecom.
- */
+ * WARNING: The use of G.729 may require a license fee and/or royalty fee in
+ * some countries and is licensed by
+ * SIPRO Lab Telecom.
+ */
/**
- * @author Lubomir Marinov (translation of ITU-T C source code to Java)
- */
-namespace SIPSorcery.Media.G729Codec
+ * @author Lubomir Marinov (translation of ITU-T C source code to Java)
+ */
+namespace SIPSorcery.Media.G729Codec;
+
+public class Ld8k
{
- public class Ld8k
- {
- /**
- * gain adjustment factor
- */
- public static float AGC_FAC = 0.9875f;
+ /**
+ * gain adjustment factor
+ */
+ public const float AGC_FAC = 0.9875f;
+
+ /**
+ * gain adjustment factor
+ */
+ public const float AGC_FAC1 = 1.0f - AGC_FAC;
+
+ public const float ALPHA = -6.0f;
+
+ public const float BETA = 1.0f;
- /**
- * gain adjustment factor
- */
- public static float AGC_FAC1 = 1.0f - AGC_FAC;
+ /**
+ * Definition of zero-bit in bit-stream.
+ */
+ public const short BIT_0 = 0x007f;
- public static float ALPHA = -6.0f;
+ /*---------------------------------------------------------------------------*
+ * Constants for bitstream packing *
+ *---------------------------------------------------------------------------*/
+ /**
+ * Definition of one-bit in bit-stream.
+ */
+ public const short BIT_1 = 0x0081;
- public static float BETA = 1.0f;
+ public const float CONST12 = 1.2f;
- /**
- * Definition of zero-bit in bit-stream.
- */
- public static short BIT_0 = 0x007f;
+ /*---------------------------------------------------------------------------*
+ * Constants for fixed codebook. *
+ *---------------------------------------------------------------------------*/
+ /**
+ * Size of correlation matrix
+ */
+ public const int DIM_RR = 616;
- /*---------------------------------------------------------------------------*
- * Constants for bitstream packing *
- *---------------------------------------------------------------------------*/
- /**
- * Definition of one-bit in bit-stream.
- */
- public static short BIT_1 = 0x0081;
+ /**
+ * resolution for fractionnal delay
+ */
+ public const int F_UP_PST = 8;
- public static float CONST12 = 1.2f;
+ public const int L_INTER4 = 4;
- /*---------------------------------------------------------------------------*
- * Constants for fixed codebook. *
- *---------------------------------------------------------------------------*/
- /**
- * Size of correlation matrix
- */
- public static int DIM_RR = 616;
+ public const int UP_SAMP = 3;
- /**
- * resolution for fractionnal delay
- */
- public static int F_UP_PST = 8;
+ public const int FIR_SIZE_ANA = UP_SAMP * L_INTER4 + 1;
- public static int L_INTER4 = 4;
+ public const int L_INTER10 = 10;
- public static int UP_SAMP = 3;
+ public const int FIR_SIZE_SYN = UP_SAMP * L_INTER10 + 1;
- public static int FIR_SIZE_ANA = UP_SAMP * L_INTER4 + 1;
+ /**
+ * Largest floating point number
+ */
+ public const float FLT_MAX_G729 = float.MaxValue;
- public static int L_INTER10 = 10;
-
- public static int FIR_SIZE_SYN = UP_SAMP * L_INTER10 + 1;
+ /**
+ * Largest floating point number
+ */
+ public const float FLT_MIN_G729 = -FLT_MAX_G729;
- /**
- * Largest floating point number
- */
- public static float FLT_MAX_G729 = float.MaxValue;
+ /**
+ * maximum adaptive codebook gain
+ */
+ public const float GAIN_PIT_MAX = 1.2f;
- /**
- * Largest floating point number
- */
- public static float FLT_MIN_G729 = -FLT_MAX_G729;
+ /**
+ * LT weighting factor
+ */
+ public const float GAMMA_G = 0.5f;
+
+ public const float GAMMA1_0 = 0.98f;
+
+ public const float GAMMA1_1 = 0.94f;
+
+ /*---------------------------------------------------------------------------
+ * Constants for postfilter.
+ *---------------------------------------------------------------------------
+ */
+ /* short term pst parameters : */
+ /**
+ * denominator weighting factor
+ */
+ public const float GAMMA1_PST = 0.7f;
+
+ public const float GAMMA2_0_H = 0.7f;
+
+ public const float GAMMA2_0_L = 0.4f;
+
+ public const float GAMMA2_1 = 0.6f;
+
+ /**
+ * numerator weighting factor
+ */
+ public const float GAMMA2_PST = 0.55f;
+
+ /**
+ * tilt weighting factor when k1 < 0
+ */
+ public const float GAMMA3_MINUS = 0.9f;
+
+ /**
+ * tilt weighting factor when k1 > 0
+ */
+ public const float GAMMA3_PLUS = 0.2f;
+
+ public const float GAP1 = 0.0012f;
- /**
- * maximum adaptive codebook gain
- */
- public static float GAIN_PIT_MAX = 1.2f;
-
- /**
- * LT weighting factor
- */
- public static float GAMMA_G = 0.5f;
-
- public static float GAMMA1_0 = 0.98f;
-
- public static float GAMMA1_1 = 0.94f;
-
- /*---------------------------------------------------------------------------
- * Constants for postfilter.
- *---------------------------------------------------------------------------
- */
- /* short term pst parameters : */
- /**
- * denominator weighting factor
- */
- public static float GAMMA1_PST = 0.7f;
-
- public static float GAMMA2_0_H = 0.7f;
-
- public static float GAMMA2_0_L = 0.4f;
-
- public static float GAMMA2_1 = 0.6f;
-
- /**
- * numerator weighting factor
- */
- public static float GAMMA2_PST = 0.55f;
-
- /**
- * tilt weighting factor when k1 < 0
- */
- public static float GAMMA3_MINUS = 0.9f;
-
- /**
- * tilt weighting factor when k1 > 0
- */
- public static float GAMMA3_PLUS = 0.2f;
-
- public static float GAP1 = 0.0012f;
-
- public static float GAP2 = 0.0006f;
-
- public static float GAP3 = 0.0392f;
-
- /**
- * Maximum pitch gain if taming is needed
- */
- public static float GP0999 = 0.9999f;
-
- /*--------------------------------------------------------------------------*
- * Constants for taming procedure. *
- *--------------------------------------------------------------------------*/
- /**
- * Maximum pitch gain if taming is needed
- */
- public static float GPCLIP = 0.95f;
+ public const float GAP2 = 0.0006f;
+
+ public const float GAP3 = 0.0392f;
+
+ /**
+ * Maximum pitch gain if taming is needed
+ */
+ public const float GP0999 = 0.9999f;
+
+ /*--------------------------------------------------------------------------*
+ * Constants for taming procedure. *
+ *--------------------------------------------------------------------------*/
+ /**
+ * Maximum pitch gain if taming is needed
+ */
+ public const float GPCLIP = 0.95f;
- /**
- * Maximum pitch gain if taming is needed
- */
- public static float GPCLIP2 = 0.94f;
-
- /**
- * Resolution of lsp search.
- */
- public static int GRID_POINTS = 60;
+ /**
+ * Maximum pitch gain if taming is needed
+ */
+ public const float GPCLIP2 = 0.94f;
+
+ /**
+ * Resolution of lsp search.
+ */
+ public const int GRID_POINTS = 60;
- public static float INV_COEF = -0.032623f;
+ public const float INV_COEF = -0.032623f;
- public static
- int L_SUBFR = 40;
+ public const int L_SUBFR = 40;
- public static float INV_L_SUBFR = 1.0f / L_SUBFR; /* =0.025 */
+ public const float INV_L_SUBFR = 1.0f / L_SUBFR; /* =0.025 */
- /**
- * LPC update frame size
- */
- public static int L_FRAME = 80;
- /**
- * Length for pitch interpolation
- */
-
- /**
- * upsampling ration for pitch search
- */
-
- /**
- * Length of filter for interpolation.
- */
- public static int L_INTERPOL = 10 + 1;
-
- public static float L_LIMIT = 0.005f;
-
- /**
- * Samples of next frame needed for LPC ana.
- */
- public static int L_NEXT = 40;
- /**
- * Sub-frame size
- */
-
- /* long term pst parameters : */
- /**
- * Sub-frame size + 1
- */
- public static int L_SUBFRP1 = L_SUBFR + 1;
-
- /**
- * Total size of speech buffer
- */
- public static int L_TOTAL = 240;
-
- /*---------------------------------------------------------------------------*
- * Constants for lpc analysis and lsp quantizer. *
- *---------------------------------------------------------------------------*/
- /**
- * LPC analysis window size.
- */
- public static int L_WINDOW = 240;
-
- public static int LH2_L = 16;
-
- public static int LH_UP_L = LH2_L / 2;
-
- public static int LH2_S = 4;
-
- public static int LH_UP_S = LH2_S / 2;
- /**
- * length of long interp. subfilters
- */
-
- public static int LH2_L_P1 = LH2_L + 1;
- /**
- * length of short interp. subfilters
- */
-
- /**
- * impulse response length
- */
- public static int LONG_H_ST = 20;
-
- /**
- * LPC order.
- */
- public static int M = 10;
-
- public static float M_LIMIT = 3.135f;
-
- /**
- * MA prediction order for LSP.
- */
- public static int MA_NP = 4;
-
- public static int MAX_TIME = 75;
-
- /*-------------------------------------------------------------------------
- * gain quantizer constants
- *-------------------------------------------------------------------------
- */
- /**
- * Average innovation energy
- */
- public static float MEAN_ENER = 36.0f;
-
- /* Array sizes */
- public static int PIT_MAX = 143;
-
- public static int MEM_RES2 = PIT_MAX + 1 + LH_UP_L;
-
- /**
- * LT gain minimum
- */
- public static float MIN_GPLT = 1.0f / (1.0f + GAMMA_G);
-
- /**
- * Number of modes for MA prediction.
- */
- public static int MODE = 2;
-
- /**
- * LPC order+1.
- */
- public static int MP1 = M + 1;
-
- /**
- * Size of vectors for cross-correlation between 2 pulses
- */
- public static int MSIZE = 64;
-
- /**
- * Number of positions for each pulse
- */
- public static int NB_POS = 8;
-
- /**
- * LPC order / 2.
- */
- public static int NC = M / 2;
-
- /**
- * Number of entries in first stage.
- */
- public static int NC0_B = 7;
-
- public static int NC0 = 1 << NC0_B;
- /**
- * Number of bits in first stage.
- */
-
- /**
- * Number of entries in second stage.
- */
- public static int NC1_B = 5;
-
- public static int NC1 = 1 << NC1_B;
- /**
- * Number of bits in second stage.
- */
-
- /**
- * Pre-selecting order for #1
- */
- public static int NCAN1 = 4;
-
- /**
- * Pre-selecting order for #2
- */
- public static int NCAN2 = 8;
-
- /**
- * Codebook 1 size
- */
- public static int NCODE1_B = 3;
-
- public static int NCODE1 = 1 << NCODE1_B;
- /**
- * Number of Codebook-bit
- */
-
- /**
- * Codebook 2 size
- */
- public static int NCODE2_B = 4;
-
- public static int NCODE2 = 1 << NCODE2_B;
- /**
- * Number of Codebook-bit
- */
-
- /* ITU-T G.729 Software Package Release 2 (November 2006) */
- /*
- ITU-T G.729 Annex C - Reference C code for floating point
- implementation of G.729
- Version 1.01 of 15.September.98
+ /**
+ * LPC update frame size
+ */
+ public const int L_FRAME = 80;
+ /**
+ * Length for pitch interpolation
+ */
+
+ /**
+ * upsampling ration for pitch search
+ */
+
+ /**
+ * Length of filter for interpolation.
+ */
+ public const int L_INTERPOL = 10 + 1;
+
+ public const float L_LIMIT = 0.005f;
+
+ /**
+ * Samples of next frame needed for LPC ana.
+ */
+ public const int L_NEXT = 40;
+ /**
+ * Sub-frame size
+ */
+
+ /* long term pst parameters : */
+ /**
+ * Sub-frame size + 1
+ */
+ public const int L_SUBFRP1 = L_SUBFR + 1;
+
+ /**
+ * Total size of speech buffer
+ */
+ public const int L_TOTAL = 240;
+
+ /*---------------------------------------------------------------------------*
+ * Constants for lpc analysis and lsp quantizer. *
+ *---------------------------------------------------------------------------*/
+ /**
+ * LPC analysis window size.
+ */
+ public const int L_WINDOW = 240;
+
+ public const int LH2_L = 16;
+
+ public const int LH_UP_L = LH2_L / 2;
+
+ public const int LH2_S = 4;
+
+ public const int LH_UP_S = LH2_S / 2;
+ /**
+ * length of long interp. subfilters
+ */
+
+ public const int LH2_L_P1 = LH2_L + 1;
+ /**
+ * length of short interp. subfilters
+ */
+
+ /**
+ * impulse response length
+ */
+ public const int LONG_H_ST = 20;
+
+ /**
+ * LPC order.
+ */
+ public const int M = 10;
+
+ public const float M_LIMIT = 3.135f;
+
+ /**
+ * MA prediction order for LSP.
+ */
+ public const int MA_NP = 4;
+
+ public const int MAX_TIME = 75;
+
+ /*-------------------------------------------------------------------------
+ * gain quantizer constants
+ *-------------------------------------------------------------------------
+ */
+ /**
+ * Average innovation energy
+ */
+ public const float MEAN_ENER = 36.0f;
+
+ /* Array sizes */
+ public const int PIT_MAX = 143;
+
+ public const int MEM_RES2 = PIT_MAX + 1 + LH_UP_L;
+
+ /**
+ * LT gain minimum
+ */
+ public const float MIN_GPLT = 1.0f / (1.0f + GAMMA_G);
+
+ /**
+ * Number of modes for MA prediction.
+ */
+ public const int MODE = 2;
+
+ /**
+ * LPC order+1.
+ */
+ public const int MP1 = M + 1;
+
+ /**
+ * Size of vectors for cross-correlation between 2 pulses
+ */
+ public const int MSIZE = 64;
+
+ /**
+ * Number of positions for each pulse
+ */
+ public const int NB_POS = 8;
+
+ /**
+ * LPC order / 2.
+ */
+ public const int NC = M / 2;
+
+ /**
+ * Number of entries in first stage.
+ */
+ public const int NC0_B = 7;
+
+ public const int NC0 = 1 << NC0_B;
+ /**
+ * Number of bits in first stage.
+ */
+
+ /**
+ * Number of entries in second stage.
+ */
+ public const int NC1_B = 5;
+
+ public const int NC1 = 1 << NC1_B;
+ /**
+ * Number of bits in second stage.
+ */
+
+ /**
+ * Pre-selecting order for #1
+ */
+ public const int NCAN1 = 4;
+
+ /**
+ * Pre-selecting order for #2
+ */
+ public const int NCAN2 = 8;
+
+ /**
+ * Codebook 1 size
+ */
+ public const int NCODE1_B = 3;
+
+ public const int NCODE1 = 1 << NCODE1_B;
+ /**
+ * Number of Codebook-bit
+ */
+
+ /**
+ * Codebook 2 size
+ */
+ public const int NCODE2_B = 4;
+
+ public const int NCODE2 = 1 << NCODE2_B;
+ /**
+ * Number of Codebook-bit
+ */
+
+ /* ITU-T G.729 Software Package Release 2 (November 2006) */
+ /*
+ITU-T G.729 Annex C - Reference C code for floating point
+ implementation of G.729
+ Version 1.01 of 15.September.98
*/
- /*
+ /*
----------------------------------------------------------------------
- COPYRIGHT NOTICE
+ COPYRIGHT NOTICE
----------------------------------------------------------------------
- ITU-T G.729 Annex C ANSI C source code
- Copyright (C) 1998, AT&T, France Telecom, NTT, University of
- Sherbrooke. All rights reserved.
+ITU-T G.729 Annex C ANSI C source code
+Copyright (C) 1998, AT&T, France Telecom, NTT, University of
+Sherbrooke. All rights reserved.
----------------------------------------------------------------------
*/
- /*
- File : LD8K.H
- Used for the floating point version of G.729 main body
- (not for G.729A)
+ /*
+File : LD8K.H
+Used for the floating point version of G.729 main body
+(not for G.729A)
*/
- /*---------------------------------------------------------------------------
- * ld8k.h - include file for all ITU-T 8 kb/s CELP coder routines
- *---------------------------------------------------------------------------
- */
-
- public static float PI = 3.14159265358979323846f;
-
- /**
- * pi*0.04
- */
- public static float PI04 = PI * 0.04f;
-
- /**
- * pi*0.92
- */
- public static float PI92 = PI * 0.92f;
- /**
- * Maximum pitch lag in samples
- */
-
- /*----------------------------------------------------------------------------
- * Constants for long-term predictor
- *----------------------------------------------------------------------------
- */
- /**
- * Minimum pitch lag in samples
- */
- public static int PIT_MIN = 20;
-
- /**
- * Number of parameters per 10 ms frame.
- */
- public static int PRM_SIZE = 11;
-
- /**
- * Bits per frame.
- */
- public static int SERIAL_SIZE = 82;
-
- /**
- * Maximum value of pitch sharpening
- */
- public static float SHARPMAX = 0.7945f;
-
- /**
- * minimum value of pitch sharpening
- */
- public static float SHARPMIN = 0.2f;
-
- public static int SIZ_RES2 = MEM_RES2 + L_SUBFR;
-
- public static int SIZ_TAB_HUP_L = (F_UP_PST - 1) * LH2_L;
-
- public static int SIZ_TAB_HUP_S = (F_UP_PST - 1) * LH2_S;
-
- public static int SIZ_Y_UP = (F_UP_PST - 1) * L_SUBFRP1;
-
- /**
- * Size of bitstream frame.
- */
- public static short SIZE_WORD = 80;
-
- /**
- * Step betweem position of the same pulse.
- */
- public static int STEP = 5;
-
- /**
- * Definition of frame erasure flag.
- */
- public static short SYNC_WORD = 0x6b21;
-
- /**
- * threshold LT pst switch off
- */
- public static float THRESCRIT = 0.5f;
-
- /**
- * Error threshold taming
- */
- public static float THRESH_ERR = 60000.0f;
-
- public static float THRESH_H1 = 0.65f;
-
- public static float THRESH_H2 = 0.43f;
-
- /*-------------------------------------------------------------------------
- * pwf constants
- *-------------------------------------------------------------------------
- */
-
- public static float THRESH_L1 = -1.74f;
-
- public static float THRESH_L2 = -1.52f;
-
- /*--------------------------------------------------------------------------*
- * Example values for threshold and approximated worst case complexity: *
- * *
- * threshold=0.40 maxtime= 75 extra=30 Mips = 6.0 *
- *--------------------------------------------------------------------------*/
- public static float THRESHFCB = 0.40f;
-
- /**
- * Threshold to favor smaller pitch lags
- */
- public static float THRESHPIT = 0.85f;
-
- /**
- * resolution of fractional delays
- */
- }
+ /*---------------------------------------------------------------------------
+ * ld8k.h - include file for all ITU-T 8 kb/s CELP coder routines
+ *---------------------------------------------------------------------------
+ */
+
+ public const float PI = 3.14159265358979323846f;
+
+ /**
+ * pi*0.04
+ */
+ public const float PI04 = PI * 0.04f;
+
+ /**
+ * pi*0.92
+ */
+ public const float PI92 = PI * 0.92f;
+ /**
+ * Maximum pitch lag in samples
+ */
+
+ /*----------------------------------------------------------------------------
+ * Constants for long-term predictor
+ *----------------------------------------------------------------------------
+ */
+ /**
+ * Minimum pitch lag in samples
+ */
+ public const int PIT_MIN = 20;
+
+ /**
+ * Number of parameters per 10 ms frame.
+ */
+ public const int PRM_SIZE = 11;
+
+ /**
+ * Bits per frame.
+ */
+ public const int SERIAL_SIZE = 82;
+
+ /**
+ * Maximum value of pitch sharpening
+ */
+ public const float SHARPMAX = 0.7945f;
+
+ /**
+ * minimum value of pitch sharpening
+ */
+ public const float SHARPMIN = 0.2f;
+
+ public const int SIZ_RES2 = MEM_RES2 + L_SUBFR;
+
+ public const int SIZ_TAB_HUP_L = (F_UP_PST - 1) * LH2_L;
+
+ public const int SIZ_TAB_HUP_S = (F_UP_PST - 1) * LH2_S;
+
+ public const int SIZ_Y_UP = (F_UP_PST - 1) * L_SUBFRP1;
+
+ /**
+ * Size of bitstream frame.
+ */
+ public const short SIZE_WORD = 80;
+
+ /**
+ * Step betweem position of the same pulse.
+ */
+ public const int STEP = 5;
+
+ /**
+ * Definition of frame erasure flag.
+ */
+ public const short SYNC_WORD = 0x6b21;
+
+ /**
+ * threshold LT pst switch off
+ */
+ public const float THRESCRIT = 0.5f;
+
+ /**
+ * Error threshold taming
+ */
+ public const float THRESH_ERR = 60000.0f;
+
+ public const float THRESH_H1 = 0.65f;
+
+ public const float THRESH_H2 = 0.43f;
+
+ /*-------------------------------------------------------------------------
+ * pwf constants
+ *-------------------------------------------------------------------------
+ */
+
+ public const float THRESH_L1 = -1.74f;
+
+ public const float THRESH_L2 = -1.52f;
+
+ /*--------------------------------------------------------------------------*
+ * Example values for threshold and approximated worst case complexity: *
+ * *
+ * threshold=0.40 maxtime= 75 extra=30 Mips = 6.0 *
+ *--------------------------------------------------------------------------*/
+ public const float THRESHFCB = 0.40f;
+
+ /**
+ * Threshold to favor smaller pitch lags
+ */
+ public const float THRESHPIT = 0.85f;
+
+ /**
+ * resolution of fractional delays
+ */
}
diff --git a/src/SIPSorcery/app/Media/Codecs/G729Codec/Lpc.cs b/src/SIPSorcery/app/Media/Codecs/G729Codec/Lpc.cs
index 5bc1f3e0d..f7f6c02d9 100644
--- a/src/SIPSorcery/app/Media/Codecs/G729Codec/Lpc.cs
+++ b/src/SIPSorcery/app/Media/Codecs/G729Codec/Lpc.cs
@@ -26,297 +26,315 @@
*
* @author Lubomir Marinov (translation of ITU-T C source code to Java)
*/
-namespace SIPSorcery.Media.G729Codec
+namespace SIPSorcery.Media.G729Codec;
+
+internal static class Lpc
{
- internal class Lpc
- {
- /* ITU-T G.729 Software Package Release 2 (November 2006) */
- /*
- ITU-T G.729 Annex C - Reference C code for floating point
- implementation of G.729
- Version 1.01 of 15.September.98
+ /* ITU-T G.729 Software Package Release 2 (November 2006) */
+ /*
+ITU-T G.729 Annex C - Reference C code for floating point
+ implementation of G.729
+ Version 1.01 of 15.September.98
*/
- /*
+ /*
----------------------------------------------------------------------
- COPYRIGHT NOTICE
+ COPYRIGHT NOTICE
----------------------------------------------------------------------
- ITU-T G.729 Annex C ANSI C source code
- Copyright (C) 1998, AT&T, France Telecom, NTT, University of
- Sherbrooke. All rights reserved.
+ITU-T G.729 Annex C ANSI C source code
+Copyright (C) 1998, AT&T, France Telecom, NTT, University of
+Sherbrooke. All rights reserved.
----------------------------------------------------------------------
*/
- /*
- File : LPC.C
- Used for the floating point version of G.729 main body
- (not for G.729A)
+ /*
+File : LPC.C
+Used for the floating point version of G.729 main body
+(not for G.729A)
*/
- /**
- * Compute the auto-correlations of windowed speech signal
- *
- * @param x (i) input signal x[0:L_WINDOW]
- * @param x_offset (i) input signal offset
- * @param m (i) LPC order
- * @param r (o) auto-correlation vector r[0:M]
- */
+ /**
+* Compute the auto-correlations of windowed speech signal
+*
+* @param x (i) input signal x[0:L_WINDOW]
+* @param x_offset (i) input signal offset
+* @param m (i) LPC order
+* @param r (o) auto-correlation vector r[0:M]
+*/
- public static void autocorr(
- float[] x,
- int x_offset,
- int m,
- float[] r
- )
- {
- var L_WINDOW = Ld8k.L_WINDOW;
- var hamwindow = TabLd8k.hamwindow;
+ public static void autocorr(
+ float[] x,
+ int x_offset,
+ int m,
+ float[] r
+ )
+ {
+ var L_WINDOW = Ld8k.L_WINDOW;
+ var hamwindow = TabLd8k.hamwindow;
- var y = new float[L_WINDOW];
- float sum;
- int i, j;
+ var y = new float[L_WINDOW];
+ float sum;
+ int i, j;
- for (i = 0; i < L_WINDOW; i++)
- y[i] = x[x_offset + i] * hamwindow[i];
+ for (i = 0; i < L_WINDOW; i++)
+ {
+ y[i] = x[x_offset + i] * hamwindow[i];
+ }
- for (i = 0; i <= m; i++)
+ for (i = 0; i <= m; i++)
+ {
+ sum = 0.0f;
+ for (j = 0; j < L_WINDOW - i; j++)
{
- sum = 0.0f;
- for (j = 0; j < L_WINDOW - i; j++)
- sum += y[j] * y[j + i];
- r[i] = sum;
+ sum += y[j] * y[j + i];
}
- if (r[0] < 1.0f) r[0] = 1.0f;
+ r[i] = sum;
}
- /**
- * Lag windowing of the autocorrelations
- *
- * @param m (i) LPC order
- * @param r (i/o) correlation
- */
-
- public static void lag_window(
- int m,
- float[] r
- )
+ if (r[0] < 1.0f)
{
- var lwindow = TabLd8k.lwindow;
+ r[0] = 1.0f;
+ }
+ }
- int i;
+ /**
+* Lag windowing of the autocorrelations
+*
+* @param m (i) LPC order
+* @param r (i/o) correlation
+*/
- for (i = 1; i <= m; i++)
- r[i] *= lwindow[i - 1];
- }
+ public static void lag_window(
+ int m,
+ float[] r
+ )
+ {
+ var lwindow = TabLd8k.lwindow;
- /**
- * Levinson-Durbin recursion to compute LPC parameters.
- *
- * @param r (i) auto correlation coefficients r[0:M]
- * @param a (o) lpc coefficients a[0] = 1
- * @param a_offset (i) lpc coefficients offset
- * @param rc (o) reflection coefficients rc[0:M-1]
- * @return prediction error (energy)
- */
+ int i;
- public static float levinson(
- float[] r,
- float[] a,
- int a_offset,
- float[] rc
- )
+ for (i = 1; i <= m; i++)
{
- var M = Ld8k.M;
+ r[i] *= lwindow[i - 1];
+ }
+ }
+
+ /**
+* Levinson-Durbin recursion to compute LPC parameters.
+*
+* @param r (i) auto correlation coefficients r[0:M]
+* @param a (o) lpc coefficients a[0] = 1
+* @param a_offset (i) lpc coefficients offset
+* @param rc (o) reflection coefficients rc[0:M-1]
+* @return prediction error (energy)
+*/
+
+ public static float levinson(
+ float[] r,
+ float[] a,
+ int a_offset,
+ float[] rc
+ )
+ {
+ var M = Ld8k.M;
- float s, at, err;
- int i, j, l;
+ float s, at, err;
+ int i, j, l;
- rc[0] = -r[1] / r[0];
- a[a_offset + 0] = 1.0f;
- a[a_offset + 1] = rc[0];
- err = r[0] + r[1] * rc[0];
- for (i = 2; i <= M; i++)
+ rc[0] = -r[1] / r[0];
+ a[a_offset + 0] = 1.0f;
+ a[a_offset + 1] = rc[0];
+ err = r[0] + r[1] * rc[0];
+ for (i = 2; i <= M; i++)
+ {
+ s = 0.0f;
+ for (j = 0; j < i; j++)
{
- s = 0.0f;
- for (j = 0; j < i; j++)
- s += r[i - j] * a[a_offset + j];
- rc[i - 1] = -s / err;
- for (j = 1; j <= i / 2; j++)
- {
- l = i - j;
- at = a[a_offset + j] + rc[i - 1] * a[a_offset + l];
- a[a_offset + l] += rc[i - 1] * a[a_offset + j];
- a[a_offset + j] = at;
- }
+ s += r[i - j] * a[a_offset + j];
+ }
- a[a_offset + i] = rc[i - 1];
- err += rc[i - 1] * s;
- if (err <= 0.0f)
- err = 0.001f;
+ rc[i - 1] = -s / err;
+ for (j = 1; j <= i / 2; j++)
+ {
+ l = i - j;
+ at = a[a_offset + j] + rc[i - 1] * a[a_offset + l];
+ a[a_offset + l] += rc[i - 1] * a[a_offset + j];
+ a[a_offset + j] = at;
}
- return err;
+ a[a_offset + i] = rc[i - 1];
+ err += rc[i - 1] * s;
+ if (err <= 0.0f)
+ {
+ err = 0.001f;
+ }
}
- /** *
- * Compute the LSPs from the LP coefficients a[] using Chebyshev
- * polynomials. The found LSPs are in the cosine domain with values
- * in the range from 1 down to -1.
- * The table grid[] contains the points (in the cosine domain) at
- * which the polynomials are evaluated. The table corresponds to
- * NO_POINTS frequencies uniformly spaced between 0 and pi.
- *
- * @param a (i) LP filter coefficients
- * @param a_offset (i) LP filter coefficients offset
- * @param lsp (o) Line spectral pairs (in the cosine domain)
- * @param old_lsp (i) LSP vector from past frame
- */
+ return err;
+ }
+
+ /** *
+* Compute the LSPs from the LP coefficients a[] using Chebyshev
+* polynomials. The found LSPs are in the cosine domain with values
+* in the range from 1 down to -1.
+* The table grid[] contains the points (in the cosine domain) at
+* which the polynomials are evaluated. The table corresponds to
+* NO_POINTS frequencies uniformly spaced between 0 and pi.
+*
+* @param a (i) LP filter coefficients
+* @param a_offset (i) LP filter coefficients offset
+* @param lsp (o) Line spectral pairs (in the cosine domain)
+* @param old_lsp (i) LSP vector from past frame
+*/
- public static void az_lsp(
- float[] a,
- int a_offset,
- float[] lsp,
- float[] old_lsp
- )
+ public static void az_lsp(
+ float[] a,
+ int a_offset,
+ float[] lsp,
+ float[] old_lsp
+ )
+ {
+ var GRID_POINTS = Ld8k.GRID_POINTS;
+ var M = Ld8k.M;
+ var NC = Ld8k.NC;
+ var grid = TabLd8k.grid;
+
+ int i, j, nf, ip;
+ float xlow, ylow, xhigh, yhigh, xmid, ymid, xint;
+ float[] coef;
+
+ float[] f1 = new float[NC + 1], f2 = new float[NC + 1];
+
+ /*-------------------------------------------------------------*
+* find the sum and diff polynomials F1(z) and F2(z) *
+* F1(z) = [A(z) + z^11 A(z^-1)]/(1+z^-1) *
+* F2(z) = [A(z) - z^11 A(z^-1)]/(1-z^-1) *
+*-------------------------------------------------------------*/
+
+ f1[0] = 1.0f;
+ f2[0] = 1.0f;
+ for (i = 1, j = a_offset + M; i <= NC; i++, j--)
{
- var GRID_POINTS = Ld8k.GRID_POINTS;
- var M = Ld8k.M;
- var NC = Ld8k.NC;
- var grid = TabLd8k.grid;
-
- int i, j, nf, ip;
- float xlow, ylow, xhigh, yhigh, xmid, ymid, xint;
- float[] coef;
-
- float[] f1 = new float[NC + 1], f2 = new float[NC + 1];
-
- /*-------------------------------------------------------------*
- * find the sum and diff polynomials F1(z) and F2(z) *
- * F1(z) = [A(z) + z^11 A(z^-1)]/(1+z^-1) *
- * F2(z) = [A(z) - z^11 A(z^-1)]/(1-z^-1) *
- *-------------------------------------------------------------*/
-
- f1[0] = 1.0f;
- f2[0] = 1.0f;
- for (i = 1, j = a_offset + M; i <= NC; i++, j--)
- {
- var ai = a[a_offset + i];
- var aj = a[j];
- f1[i] = ai + aj - f1[i - 1];
- f2[i] = ai - aj + f2[i - 1];
- }
+ var ai = a[a_offset + i];
+ var aj = a[j];
+ f1[i] = ai + aj - f1[i - 1];
+ f2[i] = ai - aj + f2[i - 1];
+ }
+
+ /*---------------------------------------------------------------------*
+* Find the LSPs (roots of F1(z) and F2(z) ) using the *
+* Chebyshev polynomial evaluation. *
+* The roots of F1(z) and F2(z) are alternatively searched. *
+* We start by finding the first root of F1(z) then we switch *
+* to F2(z) then back to F1(z) and so on until all roots are found. *
+* *
+* - Evaluate Chebyshev pol. at grid points and check for sign change.*
+* - If sign change track the root by subdividing the interval *
+* NO_ITER times and ckecking sign change. *
+*---------------------------------------------------------------------*/
- /*---------------------------------------------------------------------*
- * Find the LSPs (roots of F1(z) and F2(z) ) using the *
- * Chebyshev polynomial evaluation. *
- * The roots of F1(z) and F2(z) are alternatively searched. *
- * We start by finding the first root of F1(z) then we switch *
- * to F2(z) then back to F1(z) and so on until all roots are found. *
- * *
- * - Evaluate Chebyshev pol. at grid points and check for sign change.*
- * - If sign change track the root by subdividing the interval *
- * NO_ITER times and ckecking sign change. *
- *---------------------------------------------------------------------*/
+ nf = 0; /* number of found frequencies */
+ ip = 0; /* flag to first polynomial */
- nf = 0; /* number of found frequencies */
- ip = 0; /* flag to first polynomial */
+ coef = f1; /* start with F1(z) */
- coef = f1; /* start with F1(z) */
+ xlow = grid[0];
+ ylow = chebyshev(xlow, coef, NC);
- xlow = grid[0];
+ j = 0;
+ while (nf < M && j < GRID_POINTS)
+ {
+ j++;
+ xhigh = xlow;
+ yhigh = ylow;
+ xlow = grid[j];
ylow = chebyshev(xlow, coef, NC);
- j = 0;
- while (nf < M && j < GRID_POINTS)
+ if (ylow * yhigh <= 0.0f) /* if sign change new root exists */
{
- j++;
- xhigh = xlow;
- yhigh = ylow;
- xlow = grid[j];
- ylow = chebyshev(xlow, coef, NC);
+ j--;
- if (ylow * yhigh <= 0.0f) /* if sign change new root exists */
- {
- j--;
-
- /* divide the interval of sign change by 4 */
+ /* divide the interval of sign change by 4 */
- for (i = 0; i < 4; i++)
+ for (i = 0; i < 4; i++)
+ {
+ xmid = 0.5f * (xlow + xhigh);
+ ymid = chebyshev(xmid, coef, NC);
+ if (ylow * ymid <= 0.0f)
+ {
+ yhigh = ymid;
+ xhigh = xmid;
+ }
+ else
{
- xmid = 0.5f * (xlow + xhigh);
- ymid = chebyshev(xmid, coef, NC);
- if (ylow * ymid <= 0.0f)
- {
- yhigh = ymid;
- xhigh = xmid;
- }
- else
- {
- ylow = ymid;
- xlow = xmid;
- }
+ ylow = ymid;
+ xlow = xmid;
}
+ }
- /* linear interpolation for evaluating the root */
+ /* linear interpolation for evaluating the root */
- xint = xlow - ylow * (xhigh - xlow) / (yhigh - ylow);
+ xint = xlow - ylow * (xhigh - xlow) / (yhigh - ylow);
- lsp[nf] = xint; /* new root */
- nf++;
+ lsp[nf] = xint; /* new root */
+ nf++;
- ip = 1 - ip; /* flag to other polynomial */
- coef = ip != 0 ? f2 : f1; /* pointer to other polynomial */
+ ip = 1 - ip; /* flag to other polynomial */
+ coef = ip != 0 ? f2 : f1; /* pointer to other polynomial */
- xlow = xint;
- ylow = chebyshev(xlow, coef, NC);
- }
+ xlow = xint;
+ ylow = chebyshev(xlow, coef, NC);
}
+ }
- /* Check if M roots found */
- /* if not use the LSPs from previous frame */
+ /* Check if M roots found */
+ /* if not use the LSPs from previous frame */
- if (nf < M)
- for (i = 0; i < M; i++)
- lsp[i] = old_lsp[i];
+ if (nf < M)
+ {
+ for (i = 0; i < M; i++)
+ {
+ lsp[i] = old_lsp[i];
+ }
}
+ }
- /**
- * Evaluates the Chebyshev polynomial series.
- *
- * The polynomial order is
- * n = m/2 (m is the prediction order)
- * The polynomial is given by
- * C(x) = T_n(x) + f(1)T_n-1(x) + ... +f(n-1)T_1(x) + f(n)/2
- *
- * @param x (i) value of evaluation; x=cos(freq)
- * @param f (i) coefficients of sum or diff polynomial
- * @param n (i) order of polynomial
- * @return the value of the polynomial C(x)
- */
- private static float chebyshev(
- float x,
- float[] f,
- int n
- )
+ /**
+* Evaluates the Chebyshev polynomial series.
+*
+* The polynomial order is
+* n = m/2 (m is the prediction order)
+* The polynomial is given by
+* C(x) = T_n(x) + f(1)T_n-1(x) + ... +f(n-1)T_1(x) + f(n)/2
+*
+* @param x (i) value of evaluation; x=cos(freq)
+* @param f (i) coefficients of sum or diff polynomial
+* @param n (i) order of polynomial
+* @return the value of the polynomial C(x)
+*/
+ private static float chebyshev(
+ float x,
+ float[] f,
+ int n
+ )
+ {
+ float b1, b2, b0, x2;
+ int i; /* for the special case of 10th order */
+ /* filter (n=5) */
+ x2 = 2.0f * x; /* x2 = 2.0*x; */
+ b2 = 1.0f; /* f[0] */ /* */
+ b1 = x2 + f[1]; /* b1 = x2 + f[1]; */
+ for (i = 2; i < n; i++)
{
- float b1, b2, b0, x2;
- int i; /* for the special case of 10th order */
- /* filter (n=5) */
- x2 = 2.0f * x; /* x2 = 2.0*x; */
- b2 = 1.0f; /* f[0] */ /* */
- b1 = x2 + f[1]; /* b1 = x2 + f[1]; */
- for (i = 2; i < n; i++)
- {
- /* */
- b0 = x2 * b1 - b2 + f[i]; /* b0 = x2 * b1 - 1. + f[2]; */
- b2 = b1; /* b2 = x2 * b0 - b1 + f[3]; */
- b1 = b0; /* b1 = x2 * b2 - b0 + f[4]; */
- } /* */
+ /* */
+ b0 = x2 * b1 - b2 + f[i]; /* b0 = x2 * b1 - 1. + f[2]; */
+ b2 = b1; /* b2 = x2 * b0 - b1 + f[3]; */
+ b1 = b0; /* b1 = x2 * b2 - b0 + f[4]; */
+ } /* */
- return x * b1 - b2 + 0.5f * f[n]; /* return (x*b1 - b2 + 0.5*f[5]); */
- }
+ return x * b1 - b2 + 0.5f * f[n]; /* return (x*b1 - b2 + 0.5*f[5]); */
}
-}
\ No newline at end of file
+}
diff --git a/src/SIPSorcery/app/Media/Codecs/G729Codec/Lpcfunc.cs b/src/SIPSorcery/app/Media/Codecs/G729Codec/Lpcfunc.cs
index 8887b7f58..93ffabae1 100644
--- a/src/SIPSorcery/app/Media/Codecs/G729Codec/Lpcfunc.cs
+++ b/src/SIPSorcery/app/Media/Codecs/G729Codec/Lpcfunc.cs
@@ -24,226 +24,236 @@
*/
using System;
-namespace SIPSorcery.Media.G729Codec
+namespace SIPSorcery.Media.G729Codec;
+
+internal static class Lpcfunc
{
- internal class Lpcfunc
- {
- /* ITU-T G.729 Software Package Release 2 (November 2006) */
- /*
- ITU-T G.729 Annex C - Reference C code for floating point
- implementation of G.729
- Version 1.01 of 15.September.98
+ /* ITU-T G.729 Software Package Release 2 (November 2006) */
+ /*
+ITU-T G.729 Annex C - Reference C code for floating point
+ implementation of G.729
+ Version 1.01 of 15.September.98
*/
- /*
+ /*
----------------------------------------------------------------------
- COPYRIGHT NOTICE
+ COPYRIGHT NOTICE
----------------------------------------------------------------------
- ITU-T G.729 Annex C ANSI C source code
- Copyright (C) 1998, AT&T, France Telecom, NTT, University of
- Sherbrooke. All rights reserved.
+ITU-T G.729 Annex C ANSI C source code
+Copyright (C) 1998, AT&T, France Telecom, NTT, University of
+Sherbrooke. All rights reserved.
----------------------------------------------------------------------
*/
- /*
- File : LPCFUNC.C
- Used for the floating point version of G.729 main body
- (not for G.729A)
+ /*
+File : LPCFUNC.C
+Used for the floating point version of G.729 main body
+(not for G.729A)
*/
- /**
- * Convert LSPs to predictor coefficients a[]
- *
- * @param lsp input : lsp[0:M-1]
- * @param a output: predictor coeffs a[0:M], a[0] = 1.
- * @param a_offset input: predictor coeffs a offset.
- */
- private static void lsp_az(
- float[] lsp,
- float[] a,
- int a_offset
- )
- {
- var M = Ld8k.M;
- var NC = Ld8k.NC;
-
- float[] f1 = new float[NC + 1], f2 = new float[NC + 1];
- int i, j;
+ /**
+* Convert LSPs to predictor coefficients a[]
+*
+* @param lsp input : lsp[0:M-1]
+* @param a output: predictor coeffs a[0:M], a[0] = 1.
+* @param a_offset input: predictor coeffs a offset.
+*/
+ private static void lsp_az(
+ float[] lsp,
+ float[] a,
+ int a_offset
+ )
+ {
+ var M = Ld8k.M;
+ var NC = Ld8k.NC;
- get_lsp_pol(lsp, 0, f1);
- get_lsp_pol(lsp, 1, f2);
+ float[] f1 = new float[NC + 1], f2 = new float[NC + 1];
+ int i, j;
- for (i = NC; i > 0; i--)
- {
- f1[i] += f1[i - 1];
- f2[i] -= f2[i - 1];
- }
+ get_lsp_pol(lsp, 0, f1);
+ get_lsp_pol(lsp, 1, f2);
- a[a_offset + 0] = 1.0f;
- for (i = 1, j = M; i <= NC; i++, j--)
- {
- a[a_offset + i] = 0.5f * (f1[i] + f2[i]);
- a[a_offset + j] = 0.5f * (f1[i] - f2[i]);
- }
+ for (i = NC; i > 0; i--)
+ {
+ f1[i] += f1[i - 1];
+ f2[i] -= f2[i - 1];
}
- /**
- * Find the polynomial F1(z) or F2(z) from the LSFs
- *
- * @param lsp input : line spectral freq. (cosine domain)
- * @param lsp_offset input : line spectral freq offset
- * @param f output: the coefficients of F1 or F2
- */
- private static void get_lsp_pol(
- float[] lsp,
- int lsp_offset,
- float[] f
- )
+ a[a_offset + 0] = 1.0f;
+ for (i = 1, j = M; i <= NC; i++, j--)
{
- var NC = Ld8k.NC;
+ a[a_offset + i] = 0.5f * (f1[i] + f2[i]);
+ a[a_offset + j] = 0.5f * (f1[i] - f2[i]);
+ }
+ }
+
+ /**
+* Find the polynomial F1(z) or F2(z) from the LSFs
+*
+* @param lsp input : line spectral freq. (cosine domain)
+* @param lsp_offset input : line spectral freq offset
+* @param f output: the coefficients of F1 or F2
+*/
+ private static void get_lsp_pol(
+ float[] lsp,
+ int lsp_offset,
+ float[] f
+ )
+ {
+ var NC = Ld8k.NC;
- float b;
- int i, j;
+ float b;
+ int i, j;
- f[0] = 1.0f;
- b = -2.0f * lsp[lsp_offset + 0];
- f[1] = b;
- for (i = 2; i <= NC; i++)
+ f[0] = 1.0f;
+ b = -2.0f * lsp[lsp_offset + 0];
+ f[1] = b;
+ for (i = 2; i <= NC; i++)
+ {
+ b = -2.0f * lsp[lsp_offset + 2 * i - 2];
+ f[i] = b * f[i - 1] + 2.0f * f[i - 2];
+ for (j = i - 1; j > 1; j--)
{
- b = -2.0f * lsp[lsp_offset + 2 * i - 2];
- f[i] = b * f[i - 1] + 2.0f * f[i - 2];
- for (j = i - 1; j > 1; j--)
- f[j] += b * f[j - 1] + f[j - 2];
- f[1] += b;
+ f[j] += b * f[j - 1] + f[j - 2];
}
- }
- /**
- * Convert from lsf[0..M-1 to lsp[0..M-1]
- *
- * @param lsf input : lsf
- * @param lsp output: lsp
- * @param m input : length
- */
- private static void lsf_lsp(
- float[] lsf,
- float[] lsp,
- int m
- )
- {
- int i;
- for (i = 0; i < m; i++)
- lsp[i] = (float)Math.Cos(lsf[i]);
+ f[1] += b;
}
+ }
- /**
- * Convert from lsp[0..M-1 to lsf[0..M-1]
- *
- * @param lsp input : lsp coefficients
- * @param lsf output: lsf (normalized frequencies
- * @param m input: length
- */
- private static void lsp_lsf(
- float[] lsp,
- float[] lsf,
- int m
- )
+ /**
+* Convert from lsf[0..M-1 to lsp[0..M-1]
+*
+* @param lsf input : lsf
+* @param lsp output: lsp
+* @param m input : length
+*/
+ private static void lsf_lsp(
+ float[] lsf,
+ float[] lsp,
+ int m
+ )
+ {
+ int i;
+ for (i = 0; i < m; i++)
{
- int i;
-
- for (i = 0; i < m; i++)
- lsf[i] = (float)Math.Acos(lsp[i]);
+ lsp[i] = (float)Math.Cos(lsf[i]);
}
+ }
- /**
- * Weighting of LPC coefficients ap[i] = a[i] * (gamma ** i)
- *
- * @param a input : lpc coefficients a[0:m]
- * @param a_offset input : lpc coefficients offset
- * @param gamma input : weighting factor
- * @param m input : filter order
- * @param ap output: weighted coefficients ap[0:m]
- */
+ /**
+* Convert from lsp[0..M-1 to lsf[0..M-1]
+*
+* @param lsp input : lsp coefficients
+* @param lsf output: lsf (normalized frequencies
+* @param m input: length
+*/
+ private static void lsp_lsf(
+ float[] lsp,
+ float[] lsf,
+ int m
+ )
+ {
+ int i;
- public static void weight_az(
- float[] a,
- int a_offset,
- float gamma,
- int m,
- float[] ap
- )
+ for (i = 0; i < m; i++)
{
- float fac;
- int i;
-
- ap[0] = a[a_offset + 0];
- fac = gamma;
- for (i = 1; i < m; i++)
- {
- ap[i] = fac * a[a_offset + i];
- fac *= gamma;
- }
-
- ap[m] = fac * a[a_offset + m];
+ lsf[i] = (float)Math.Acos(lsp[i]);
}
+ }
- /**
- * Interpolated M LSP parameters and convert to M+1 LPC coeffs
- *
- * @param lsp_old input : LSPs for past frame (0:M-1)
- * @param lsp_new input : LSPs for present frame (0:M-1)
- * @param az output: filter parameters in 2 subfr (dim 2(m+1))
- */
+ /**
+* Weighting of LPC coefficients ap[i] = a[i] * (gamma ** i)
+*
+* @param a input : lpc coefficients a[0:m]
+* @param a_offset input : lpc coefficients offset
+* @param gamma input : weighting factor
+* @param m input : filter order
+* @param ap output: weighted coefficients ap[0:m]
+*/
+
+ public static void weight_az(
+ float[] a,
+ int a_offset,
+ float gamma,
+ int m,
+ float[] ap
+ )
+ {
+ float fac;
+ int i;
- public static void int_qlpc(
- float[] lsp_old,
- float[] lsp_new,
- float[] az
- )
+ ap[0] = a[a_offset + 0];
+ fac = gamma;
+ for (i = 1; i < m; i++)
{
- var M = Ld8k.M;
+ ap[i] = fac * a[a_offset + i];
+ fac *= gamma;
+ }
- int i;
- var lsp = new float[M];
+ ap[m] = fac * a[a_offset + m];
+ }
- for (i = 0; i < M; i++)
- lsp[i] = lsp_old[i] * 0.5f + lsp_new[i] * 0.5f;
+ /**
+* Interpolated M LSP parameters and convert to M+1 LPC coeffs
+*
+* @param lsp_old input : LSPs for past frame (0:M-1)
+* @param lsp_new input : LSPs for present frame (0:M-1)
+* @param az output: filter parameters in 2 subfr (dim 2(m+1))
+*/
- lsp_az(lsp, az, 0);
- lsp_az(lsp_new, az, M + 1);
- }
- /**
- * Interpolated M LSP parameters and convert to M+1 LPC coeffs
- *
- * @param lsp_old input : LSPs for past frame (0:M-1)
- * @param lsp_new input : LSPs for present frame (0:M-1)
- * @param lsf_int output: interpolated lsf coefficients
- * @param lsf_new input : LSFs for present frame (0:M-1)
- * @param az output: filter parameters in 2 subfr (dim 2(m+1))
- */
+ public static void int_qlpc(
+ float[] lsp_old,
+ float[] lsp_new,
+ float[] az
+ )
+ {
+ var M = Ld8k.M;
+
+ int i;
+ var lsp = new float[M];
- public static void int_lpc(
- float[] lsp_old,
- float[] lsp_new,
- float[] lsf_int,
- float[] lsf_new,
- float[] az
- )
+ for (i = 0; i < M; i++)
{
- var M = Ld8k.M;
+ lsp[i] = lsp_old[i] * 0.5f + lsp_new[i] * 0.5f;
+ }
- int i;
- var lsp = new float[M];
+ lsp_az(lsp, az, 0);
+ lsp_az(lsp_new, az, M + 1);
+ }
+ /**
+* Interpolated M LSP parameters and convert to M+1 LPC coeffs
+*
+* @param lsp_old input : LSPs for past frame (0:M-1)
+* @param lsp_new input : LSPs for present frame (0:M-1)
+* @param lsf_int output: interpolated lsf coefficients
+* @param lsf_new input : LSFs for present frame (0:M-1)
+* @param az output: filter parameters in 2 subfr (dim 2(m+1))
+*/
- for (i = 0; i < M; i++)
- lsp[i] = lsp_old[i] * 0.5f + lsp_new[i] * 0.5f;
+ public static void int_lpc(
+ float[] lsp_old,
+ float[] lsp_new,
+ float[] lsf_int,
+ float[] lsf_new,
+ float[] az
+ )
+ {
+ var M = Ld8k.M;
- lsp_az(lsp, az, 0);
+ int i;
+ var lsp = new float[M];
- lsp_lsf(lsp, lsf_int, M);
- lsp_lsf(lsp_new, lsf_new, M);
+ for (i = 0; i < M; i++)
+ {
+ lsp[i] = lsp_old[i] * 0.5f + lsp_new[i] * 0.5f;
}
+
+ lsp_az(lsp, az, 0);
+
+ lsp_lsf(lsp, lsf_int, M);
+ lsp_lsf(lsp_new, lsf_new, M);
}
-}
\ No newline at end of file
+}
diff --git a/src/SIPSorcery/app/Media/Codecs/G729Codec/Lspdec.cs b/src/SIPSorcery/app/Media/Codecs/G729Codec/Lspdec.cs
index 83e97276d..5b4badd3f 100644
--- a/src/SIPSorcery/app/Media/Codecs/G729Codec/Lspdec.cs
+++ b/src/SIPSorcery/app/Media/Codecs/G729Codec/Lspdec.cs
@@ -24,196 +24,204 @@
*/
using System;
-namespace SIPSorcery.Media.G729Codec
+namespace SIPSorcery.Media.G729Codec;
+
+internal sealed class Lspdec
{
- internal class Lspdec
- {
- /**
- * Previous LSP vector(init)
- */
- private static readonly float[ /* M */] FREQ_PREV_RESET =
- {
- 0.285599f,
- 0.571199f,
- 0.856798f,
- 1.142397f,
- 1.427997f,
- 1.713596f,
- 1.999195f,
- 2.284795f,
- 2.570394f,
- 2.855993f
- }; /* PI*(float)(j+1)/(float)(M+1) */
-
- /* ITU-T G.729 Software Package Release 2 (November 2006) */
- /*
- ITU-T G.729 Annex C - Reference C code for floating point
- implementation of G.729
- Version 1.01 of 15.September.98
+ /**
+* Previous LSP vector(init)
+*/
+ private static readonly float[ /* M */] FREQ_PREV_RESET =
+ {
+ 0.285599f,
+ 0.571199f,
+ 0.856798f,
+ 1.142397f,
+ 1.427997f,
+ 1.713596f,
+ 1.999195f,
+ 2.284795f,
+ 2.570394f,
+ 2.855993f
+ }; /* PI*(float)(j+1)/(float)(M+1) */
+
+ /* ITU-T G.729 Software Package Release 2 (November 2006) */
+ /*
+ITU-T G.729 Annex C - Reference C code for floating point
+ implementation of G.729
+ Version 1.01 of 15.September.98
*/
- /*
+ /*
----------------------------------------------------------------------
- COPYRIGHT NOTICE
+ COPYRIGHT NOTICE
----------------------------------------------------------------------
- ITU-T G.729 Annex C ANSI C source code
- Copyright (C) 1998, AT&T, France Telecom, NTT, University of
- Sherbrooke. All rights reserved.
+ITU-T G.729 Annex C ANSI C source code
+Copyright (C) 1998, AT&T, France Telecom, NTT, University of
+Sherbrooke. All rights reserved.
----------------------------------------------------------------------
*/
- /*
- File : LSPDEC.C
- Used for the floating point version of both
- G.729 main body and G.729A
+ /*
+File : LSPDEC.C
+Used for the floating point version of both
+G.729 main body and G.729A
*/
- private static readonly int M = Ld8k.M;
+ private static readonly int M = Ld8k.M;
- private static readonly int MA_NP = Ld8k.MA_NP;
+ private static readonly int MA_NP = Ld8k.MA_NP;
- /* static memory */
- /**
- * Previous LSP vector
- */
- private readonly float[][] freq_prev = new float[MA_NP][ /* M */];
+ /* static memory */
+ /**
+* Previous LSP vector
+*/
+ private readonly float[][] freq_prev = new float[MA_NP][ /* M */];
- /**
- * Previous LSP vector
- */
- private readonly float[] prev_lsp = new float[M];
+ /**
+* Previous LSP vector
+*/
+ private readonly float[] prev_lsp = new float[M];
- /* static memory for frame erase operation */
- /**
- * Previous MA prediction coef
- */
- private int prev_ma;
+ /* static memory for frame erase operation */
+ /**
+* Previous MA prediction coef
+*/
+ private int prev_ma;
- public Lspdec()
+ public Lspdec()
+ {
+ // need this to initialize freq_prev
+ for (var i = 0; i < freq_prev.Length; i++)
{
- // need this to initialize freq_prev
- for (var i = 0; i < freq_prev.Length; i++)
- freq_prev[i] = new float[M];
+ freq_prev[i] = new float[M];
}
+ }
- /**
- * Set the previous LSP vectors.
- */
+ /**
+* Set the previous LSP vectors.
+*/
+
+ public void lsp_decw_reset()
+ {
+ int i;
- public void lsp_decw_reset()
+ for (i = 0; i < MA_NP; i++)
{
- int i;
+ Util.copy(FREQ_PREV_RESET, freq_prev[i], M);
+ }
- for (i = 0; i < MA_NP; i++)
- Util.copy(FREQ_PREV_RESET, freq_prev[i], M);
+ prev_ma = 0;
- prev_ma = 0;
+ Util.copy(FREQ_PREV_RESET, prev_lsp, M);
+ }
- Util.copy(FREQ_PREV_RESET, prev_lsp, M);
+ private static int ZFRS(int i, int j)
+ {
+ var maskIt = i < 0;
+ i = i >> j;
+ if (maskIt)
+ {
+ i &= 0x7FFFFFFF;
}
- private static int ZFRS(int i, int j)
+ return i;
+ }
+
+ /**
+* LSP main quantization routine
+*
+* @param prm input : codes of the selected LSP
+* @param prm_offset input : codes offset
+* @param lsp_q output: Quantized LSP parameters
+* @param erase input : frame erase information
+*/
+ private void lsp_iqua_cs(
+ int[] prm,
+ int prm_offset,
+ float[] lsp_q,
+ int erase
+ )
+ {
+ var NC0 = Ld8k.NC0;
+ var NC0_B = Ld8k.NC0_B;
+ var NC1 = Ld8k.NC1;
+ var NC1_B = Ld8k.NC1_B;
+ var fg = TabLd8k.fg;
+ var fg_sum = TabLd8k.fg_sum;
+ var fg_sum_inv = TabLd8k.fg_sum_inv;
+ var lspcb1 = TabLd8k.lspcb1;
+ var lspcb2 = TabLd8k.lspcb2;
+
+ int mode_index;
+ int code0;
+ int code1;
+ int code2;
+ var buf = new float[M];
+
+ if (erase == 0) /* Not frame erasure */
{
- var maskIt = i < 0;
- i = i >> j;
- if (maskIt)
- i &= 0x7FFFFFFF;
- return i;
+ mode_index = ZFRS(prm[prm_offset + 0], NC0_B) & 1;
+ code0 = prm[prm_offset + 0] & (short)(NC0 - 1);
+ code1 = ZFRS(prm[prm_offset + 1], NC1_B) & (short)(NC1 - 1);
+ code2 = prm[prm_offset + 1] & (short)(NC1 - 1);
+
+ Lspgetq.lsp_get_quant(
+ lspcb1,
+ lspcb2,
+ code0,
+ code1,
+ code2,
+ fg[mode_index],
+ freq_prev,
+ lsp_q,
+ fg_sum[mode_index]);
+
+ Util.copy(lsp_q, prev_lsp, M);
+ prev_ma = mode_index;
}
-
- /**
- * LSP main quantization routine
- *
- * @param prm input : codes of the selected LSP
- * @param prm_offset input : codes offset
- * @param lsp_q output: Quantized LSP parameters
- * @param erase input : frame erase information
- */
- private void lsp_iqua_cs(
- int[] prm,
- int prm_offset,
- float[] lsp_q,
- int erase
- )
+ else /* Frame erased */
{
- var NC0 = Ld8k.NC0;
- var NC0_B = Ld8k.NC0_B;
- var NC1 = Ld8k.NC1;
- var NC1_B = Ld8k.NC1_B;
- var fg = TabLd8k.fg;
- var fg_sum = TabLd8k.fg_sum;
- var fg_sum_inv = TabLd8k.fg_sum_inv;
- var lspcb1 = TabLd8k.lspcb1;
- var lspcb2 = TabLd8k.lspcb2;
-
- int mode_index;
- int code0;
- int code1;
- int code2;
- var buf = new float[M];
-
- if (erase == 0) /* Not frame erasure */
- {
- mode_index = ZFRS(prm[prm_offset + 0], NC0_B) & 1;
- code0 = prm[prm_offset + 0] & (short)(NC0 - 1);
- code1 = ZFRS(prm[prm_offset + 1], NC1_B) & (short)(NC1 - 1);
- code2 = prm[prm_offset + 1] & (short)(NC1 - 1);
-
- Lspgetq.lsp_get_quant(
- lspcb1,
- lspcb2,
- code0,
- code1,
- code2,
- fg[mode_index],
- freq_prev,
- lsp_q,
- fg_sum[mode_index]);
-
- Util.copy(lsp_q, prev_lsp, M);
- prev_ma = mode_index;
- }
- else /* Frame erased */
- {
- Util.copy(prev_lsp, lsp_q, M);
-
- /* update freq_prev */
- Lspgetq.lsp_prev_extract(
- prev_lsp,
- buf,
- fg[prev_ma],
- freq_prev,
- fg_sum_inv[prev_ma]);
- Lspgetq.lsp_prev_update(buf, freq_prev);
- }
+ Util.copy(prev_lsp, lsp_q, M);
+
+ /* update freq_prev */
+ Lspgetq.lsp_prev_extract(
+ prev_lsp,
+ buf,
+ fg[prev_ma],
+ freq_prev,
+ fg_sum_inv[prev_ma]);
+ Lspgetq.lsp_prev_update(buf, freq_prev);
}
+ }
- /**
- * Decode lsp parameters
- *
- * @param index input : indexes
- * @param index_offset input : indexes offset
- * @param lsp_q output: decoded lsp
- * @param bfi input : frame erase information
- */
+ /**
+* Decode lsp parameters
+*
+* @param index input : indexes
+* @param index_offset input : indexes offset
+* @param lsp_q output: decoded lsp
+* @param bfi input : frame erase information
+*/
- public void d_lsp(
- int[] index,
- int index_offset,
- float[] lsp_q,
- int bfi
- )
- {
- int i;
+ public void d_lsp(
+ int[] index,
+ int index_offset,
+ float[] lsp_q,
+ int bfi
+ )
+ {
+ int i;
- lsp_iqua_cs(index, index_offset, lsp_q, bfi); /* decode quantized information */
+ lsp_iqua_cs(index, index_offset, lsp_q, bfi); /* decode quantized information */
- /* Convert LSFs to LSPs */
+ /* Convert LSFs to LSPs */
- for (i = 0; i < M; i++)
- lsp_q[i] = (float)Math.Cos(lsp_q[i]);
+ for (i = 0; i < M; i++)
+ {
+ lsp_q[i] = (float)Math.Cos(lsp_q[i]);
}
}
-}
\ No newline at end of file
+}
diff --git a/src/SIPSorcery/app/Media/Codecs/G729Codec/Lspgetq.cs b/src/SIPSorcery/app/Media/Codecs/G729Codec/Lspgetq.cs
index 4f71b45b1..16ba6f5a2 100644
--- a/src/SIPSorcery/app/Media/Codecs/G729Codec/Lspgetq.cs
+++ b/src/SIPSorcery/app/Media/Codecs/G729Codec/Lspgetq.cs
@@ -22,301 +22,320 @@
/**
* @author Lubomir Marinov (translation of ITU-T C source code to Java)
*/
-namespace SIPSorcery.Media.G729Codec
+namespace SIPSorcery.Media.G729Codec;
+
+internal static class Lspgetq
{
- internal class Lspgetq
- {
- /* ITU-T G.729 Software Package Release 2 (November 2006) */
- /*
- ITU-T G.729 Annex C - Reference C code for floating point
- implementation of G.729
- Version 1.01 of 15.September.98
+ /* ITU-T G.729 Software Package Release 2 (November 2006) */
+ /*
+ITU-T G.729 Annex C - Reference C code for floating point
+ implementation of G.729
+ Version 1.01 of 15.September.98
*/
- /*
+ /*
----------------------------------------------------------------------
- COPYRIGHT NOTICE
+ COPYRIGHT NOTICE
----------------------------------------------------------------------
- ITU-T G.729 Annex C ANSI C source code
- Copyright (C) 1998, AT&T, France Telecom, NTT, University of
- Sherbrooke. All rights reserved.
+ITU-T G.729 Annex C ANSI C source code
+Copyright (C) 1998, AT&T, France Telecom, NTT, University of
+Sherbrooke. All rights reserved.
----------------------------------------------------------------------
*/
- /*
- File : LSPGETQ.C
- Used for the floating point version of both
- G.729 main body and G.729A
+ /*
+File : LSPGETQ.C
+Used for the floating point version of both
+G.729 main body and G.729A
*/
- /**
- * Reconstruct quantized LSP parameter and check the stabilty
- *
- * @param lspcb1 input : first stage LSP codebook
- * @param lspcb2 input : Second stage LSP codebook
- * @param code0 input : selected code of first stage
- * @param code1 input : selected code of second stage
- * @param code2 input : selected code of second stage
- * @param fg input : MA prediction coef.
- * @param freq_prev input : previous LSP vector
- * @param lspq output: quantized LSP parameters
- * @param fg_sum input : present MA prediction coef.
- */
+ /**
+* Reconstruct quantized LSP parameter and check the stabilty
+*
+* @param lspcb1 input : first stage LSP codebook
+* @param lspcb2 input : Second stage LSP codebook
+* @param code0 input : selected code of first stage
+* @param code1 input : selected code of second stage
+* @param code2 input : selected code of second stage
+* @param fg input : MA prediction coef.
+* @param freq_prev input : previous LSP vector
+* @param lspq output: quantized LSP parameters
+* @param fg_sum input : present MA prediction coef.
+*/
- public static void lsp_get_quant(
- float[][ /* M */] lspcb1,
- float[][ /* M */] lspcb2,
- int code0,
- int code1,
- int code2,
- float[][ /* M */] fg,
- float[][ /* M */] freq_prev,
- float[] lspq,
- float[] fg_sum
- )
- {
- var GAP1 = Ld8k.GAP1;
- var GAP2 = Ld8k.GAP2;
- var M = Ld8k.M;
- var NC = Ld8k.NC;
+ public static void lsp_get_quant(
+ float[][ /* M */] lspcb1,
+ float[][ /* M */] lspcb2,
+ int code0,
+ int code1,
+ int code2,
+ float[][ /* M */] fg,
+ float[][ /* M */] freq_prev,
+ float[] lspq,
+ float[] fg_sum
+ )
+ {
+ var GAP1 = Ld8k.GAP1;
+ var GAP2 = Ld8k.GAP2;
+ var M = Ld8k.M;
+ var NC = Ld8k.NC;
- int j;
- var buf = new float[M];
+ int j;
+ var buf = new float[M];
+
+ for (j = 0; j < NC; j++)
+ {
+ buf[j] = lspcb1[code0][j] + lspcb2[code1][j];
+ }
- for (j = 0; j < NC; j++)
- buf[j] = lspcb1[code0][j] + lspcb2[code1][j];
- for (j = NC; j < M; j++)
- buf[j] = lspcb1[code0][j] + lspcb2[code2][j];
+ for (j = NC; j < M; j++)
+ {
+ buf[j] = lspcb1[code0][j] + lspcb2[code2][j];
+ }
- /* check */
- lsp_expand_1_2(buf, GAP1);
- lsp_expand_1_2(buf, GAP2);
+ /* check */
+ lsp_expand_1_2(buf, GAP1);
+ lsp_expand_1_2(buf, GAP2);
- /* reconstruct quantized LSP parameters */
- lsp_prev_compose(buf, lspq, fg, freq_prev, fg_sum);
+ /* reconstruct quantized LSP parameters */
+ lsp_prev_compose(buf, lspq, fg, freq_prev, fg_sum);
- lsp_prev_update(buf, freq_prev);
+ lsp_prev_update(buf, freq_prev);
- lsp_stability(lspq); /* check the stabilty */
- }
+ lsp_stability(lspq); /* check the stabilty */
+ }
- /**
- * Check for lower (0-4)
- *
- * @param buf in/out: lsp vectors
- * @param gap input : gap
- */
+ /**
+* Check for lower (0-4)
+*
+* @param buf in/out: lsp vectors
+* @param gap input : gap
+*/
- public static void lsp_expand_1(
- float[] buf, /* */
- float gap
- )
- {
- var NC = Ld8k.NC;
+ public static void lsp_expand_1(
+ float[] buf, /* */
+ float gap
+ )
+ {
+ var NC = Ld8k.NC;
- int j;
- float diff, tmp;
+ int j;
+ float diff, tmp;
- for (j = 1; j < NC; j++)
+ for (j = 1; j < NC; j++)
+ {
+ diff = buf[j - 1] - buf[j];
+ tmp = (diff + gap) * 0.5f;
+ if (tmp > 0)
{
- diff = buf[j - 1] - buf[j];
- tmp = (diff + gap) * 0.5f;
- if (tmp > 0)
- {
- buf[j - 1] -= tmp;
- buf[j] += tmp;
- }
+ buf[j - 1] -= tmp;
+ buf[j] += tmp;
}
}
+ }
- /**
- * Check for higher (5-9)
- *
- * @param buf in/out: lsp vectors
- * @param gap input : gap
- */
+ /**
+* Check for higher (5-9)
+*
+* @param buf in/out: lsp vectors
+* @param gap input : gap
+*/
- public static void lsp_expand_2(
- float[] buf,
- float gap
- )
- {
- var M = Ld8k.M;
- var NC = Ld8k.NC;
+ public static void lsp_expand_2(
+ float[] buf,
+ float gap
+ )
+ {
+ var M = Ld8k.M;
+ var NC = Ld8k.NC;
- int j;
- float diff, tmp;
+ int j;
+ float diff, tmp;
- for (j = NC; j < M; j++)
+ for (j = NC; j < M; j++)
+ {
+ diff = buf[j - 1] - buf[j];
+ tmp = (diff + gap) * 0.5f;
+ if (tmp > 0)
{
- diff = buf[j - 1] - buf[j];
- tmp = (diff + gap) * 0.5f;
- if (tmp > 0)
- {
- buf[j - 1] -= tmp;
- buf[j] += tmp;
- }
+ buf[j - 1] -= tmp;
+ buf[j] += tmp;
}
}
+ }
- /**
- *
- * @param buf in/out: LSP parameters
- * @param gap input: gap
- */
+ /**
+*
+* @param buf in/out: LSP parameters
+* @param gap input: gap
+*/
- public static void lsp_expand_1_2(
- float[] buf,
- float gap
- )
- {
- var M = Ld8k.M;
+ public static void lsp_expand_1_2(
+ float[] buf,
+ float gap
+ )
+ {
+ var M = Ld8k.M;
- int j;
- float diff, tmp;
+ int j;
+ float diff, tmp;
- for (j = 1; j < M; j++)
+ for (j = 1; j < M; j++)
+ {
+ diff = buf[j - 1] - buf[j];
+ tmp = (diff + gap) * 0.5f;
+ if (tmp > 0)
{
- diff = buf[j - 1] - buf[j];
- tmp = (diff + gap) * 0.5f;
- if (tmp > 0)
- {
- buf[j - 1] -= tmp;
- buf[j] += tmp;
- }
+ buf[j - 1] -= tmp;
+ buf[j] += tmp;
}
}
+ }
- /*
- Functions which use previous LSP parameter (freq_prev).
+ /*
+Functions which use previous LSP parameter (freq_prev).
*/
- /**
- * Compose LSP parameter from elementary LSP with previous LSP.
- *
- * @param lsp_ele (i) Q13 : LSP vectors
- * @param lsp (o) Q13 : quantized LSP parameters
- * @param fg (i) Q15 : MA prediction coef.
- * @param freq_prev (i) Q13 : previous LSP vector
- * @param fg_sum (i) Q15 : present MA prediction coef.
- */
- private static void lsp_prev_compose(
- float[] lsp_ele,
- float[] lsp,
- float[][ /* M */] fg,
- float[][ /* M */] freq_prev,
- float[] fg_sum
- )
- {
- var M = Ld8k.M;
- var MA_NP = Ld8k.MA_NP;
+ /**
+* Compose LSP parameter from elementary LSP with previous LSP.
+*
+* @param lsp_ele (i) Q13 : LSP vectors
+* @param lsp (o) Q13 : quantized LSP parameters
+* @param fg (i) Q15 : MA prediction coef.
+* @param freq_prev (i) Q13 : previous LSP vector
+* @param fg_sum (i) Q15 : present MA prediction coef.
+*/
+ private static void lsp_prev_compose(
+ float[] lsp_ele,
+ float[] lsp,
+ float[][ /* M */] fg,
+ float[][ /* M */] freq_prev,
+ float[] fg_sum
+ )
+ {
+ var M = Ld8k.M;
+ var MA_NP = Ld8k.MA_NP;
- int j, k;
+ int j, k;
- for (j = 0; j < M; j++)
+ for (j = 0; j < M; j++)
+ {
+ lsp[j] = lsp_ele[j] * fg_sum[j];
+ for (k = 0; k < MA_NP; k++)
{
- lsp[j] = lsp_ele[j] * fg_sum[j];
- for (k = 0; k < MA_NP; k++) lsp[j] += freq_prev[k][j] * fg[k][j];
+ lsp[j] += freq_prev[k][j] * fg[k][j];
}
}
+ }
- /**
- * Extract elementary LSP from composed LSP with previous LSP
- *
- * @param lsp (i) Q13 : unquantized LSP parameters
- * @param lsp_ele (o) Q13 : target vector
- * @param fg (i) Q15 : MA prediction coef.
- * @param freq_prev (i) Q13 : previous LSP vector
- * @param fg_sum_inv (i) Q12 : inverse previous LSP vector
- */
+ /**
+* Extract elementary LSP from composed LSP with previous LSP
+*
+* @param lsp (i) Q13 : unquantized LSP parameters
+* @param lsp_ele (o) Q13 : target vector
+* @param fg (i) Q15 : MA prediction coef.
+* @param freq_prev (i) Q13 : previous LSP vector
+* @param fg_sum_inv (i) Q12 : inverse previous LSP vector
+*/
- public static void lsp_prev_extract(
- float[ /* M */] lsp,
- float[ /* M */] lsp_ele,
- float[ /* MA_NP */][ /* M */] fg,
- float[ /* MA_NP */][ /* M */] freq_prev,
- float[ /* M */] fg_sum_inv
- )
- {
- var M = Ld8k.M;
- var MA_NP = Ld8k.MA_NP;
+ public static void lsp_prev_extract(
+ float[ /* M */] lsp,
+ float[ /* M */] lsp_ele,
+ float[ /* MA_NP */][ /* M */] fg,
+ float[ /* MA_NP */][ /* M */] freq_prev,
+ float[ /* M */] fg_sum_inv
+ )
+ {
+ var M = Ld8k.M;
+ var MA_NP = Ld8k.MA_NP;
- int j, k;
+ int j, k;
- /*----- compute target vectors for each MA coef.-----*/
- for (j = 0; j < M; j++)
+ /*----- compute target vectors for each MA coef.-----*/
+ for (j = 0; j < M; j++)
+ {
+ lsp_ele[j] = lsp[j];
+ for (k = 0; k < MA_NP; k++)
{
- lsp_ele[j] = lsp[j];
- for (k = 0; k < MA_NP; k++)
- lsp_ele[j] -= freq_prev[k][j] * fg[k][j];
- lsp_ele[j] *= fg_sum_inv[j];
+ lsp_ele[j] -= freq_prev[k][j] * fg[k][j];
}
- }
- /**
- * Update previous LSP parameter
- *
- * @param lsp_ele input : LSP vectors
- * @param freq_prev input/output: previous LSP vectors
- */
+ lsp_ele[j] *= fg_sum_inv[j];
+ }
+ }
- public static void lsp_prev_update(
- float[ /* M */] lsp_ele,
- float[ /* MA_NP */][ /* M */] freq_prev
- )
- {
- var M = Ld8k.M;
- var MA_NP = Ld8k.MA_NP;
+ /**
+* Update previous LSP parameter
+*
+* @param lsp_ele input : LSP vectors
+* @param freq_prev input/output: previous LSP vectors
+*/
- int k;
+ public static void lsp_prev_update(
+ float[ /* M */] lsp_ele,
+ float[ /* MA_NP */][ /* M */] freq_prev
+ )
+ {
+ var M = Ld8k.M;
+ var MA_NP = Ld8k.MA_NP;
- for (k = MA_NP - 1; k > 0; k--)
- Util.copy(freq_prev[k - 1], freq_prev[k], M);
+ int k;
- Util.copy(lsp_ele, freq_prev[0], M);
+ for (k = MA_NP - 1; k > 0; k--)
+ {
+ Util.copy(freq_prev[k - 1], freq_prev[k], M);
}
- /**
- * Check stability of lsp coefficients
- *
- * @param buf in/out: LSP parameters
- */
- private static void lsp_stability(
- float[] buf
- )
- {
- var GAP3 = Ld8k.GAP3;
- var L_LIMIT = Ld8k.L_LIMIT;
- var M = Ld8k.M;
- var M_LIMIT = Ld8k.M_LIMIT;
+ Util.copy(lsp_ele, freq_prev[0], M);
+ }
+
+ /**
+* Check stability of lsp coefficients
+*
+* @param buf in/out: LSP parameters
+*/
+ private static void lsp_stability(
+ float[] buf
+ )
+ {
+ var GAP3 = Ld8k.GAP3;
+ var L_LIMIT = Ld8k.L_LIMIT;
+ var M = Ld8k.M;
+ var M_LIMIT = Ld8k.M_LIMIT;
- int j;
- float diff, tmp;
+ int j;
+ float diff, tmp;
- for (j = 0; j < M - 1; j++)
+ for (j = 0; j < M - 1; j++)
+ {
+ diff = buf[j + 1] - buf[j];
+ if (diff < 0.0f)
{
- diff = buf[j + 1] - buf[j];
- if (diff < 0.0f)
- {
- tmp = buf[j + 1];
- buf[j + 1] = buf[j];
- buf[j] = tmp;
- }
+ tmp = buf[j + 1];
+ buf[j + 1] = buf[j];
+ buf[j] = tmp;
}
+ }
- if (buf[0] < L_LIMIT)
- buf[0] = L_LIMIT;
- for (j = 0; j < M - 1; j++)
+ if (buf[0] < L_LIMIT)
+ {
+ buf[0] = L_LIMIT;
+ }
+
+ for (j = 0; j < M - 1; j++)
+ {
+ diff = buf[j + 1] - buf[j];
+ if (diff < GAP3)
{
- diff = buf[j + 1] - buf[j];
- if (diff < GAP3)
- buf[j + 1] = buf[j] + GAP3;
+ buf[j + 1] = buf[j] + GAP3;
}
+ }
- if (buf[M - 1] > M_LIMIT)
- buf[M - 1] = M_LIMIT;
+ if (buf[M - 1] > M_LIMIT)
+ {
+ buf[M - 1] = M_LIMIT;
}
}
-}
\ No newline at end of file
+}
diff --git a/src/SIPSorcery/app/Media/Codecs/G729Codec/PParity.cs b/src/SIPSorcery/app/Media/Codecs/G729Codec/PParity.cs
index bd270143b..2d35951d0 100644
--- a/src/SIPSorcery/app/Media/Codecs/G729Codec/PParity.cs
+++ b/src/SIPSorcery/app/Media/Codecs/G729Codec/PParity.cs
@@ -22,89 +22,88 @@
/**
* @author Lubomir Marinov (translation of ITU-T C source code to Java)
*/
-namespace SIPSorcery.Media.G729Codec
+namespace SIPSorcery.Media.G729Codec;
+
+internal static class PParity
{
- internal class PParity
- {
- /* ITU-T G.729 Software Package Release 2 (November 2006) */
- /*
- ITU-T G.729 Annex C - Reference C code for floating point
- implementation of G.729
- Version 1.01 of 15.September.98
+ /* ITU-T G.729 Software Package Release 2 (November 2006) */
+ /*
+ITU-T G.729 Annex C - Reference C code for floating point
+ implementation of G.729
+ Version 1.01 of 15.September.98
*/
- /*
+ /*
----------------------------------------------------------------------
- COPYRIGHT NOTICE
+ COPYRIGHT NOTICE
----------------------------------------------------------------------
- ITU-T G.729 Annex C ANSI C source code
- Copyright (C) 1998, AT&T, France Telecom, NTT, University of
- Sherbrooke. All rights reserved.
+ITU-T G.729 Annex C ANSI C source code
+Copyright (C) 1998, AT&T, France Telecom, NTT, University of
+Sherbrooke. All rights reserved.
----------------------------------------------------------------------
*/
- /*
- File : P_PARITY.C
- Used for the floating point version of both
- G.729 main body and G.729A
+ /*
+File : P_PARITY.C
+Used for the floating point version of both
+G.729 main body and G.729A
*/
- /**
- * Compute parity bit for first 6 MSBs
- *
- * @param pitch_index input : index for which parity is computed
- * @return parity bit (XOR of 6 MSB bits)
- */
-
- public static int parity_pitch(
- int pitch_index
- )
- {
- int temp, sum, i, bit;
+ /**
+* Compute parity bit for first 6 MSBs
+*
+* @param pitch_index input : index for which parity is computed
+* @return parity bit (XOR of 6 MSB bits)
+*/
- temp = pitch_index >> 1;
+ public static int parity_pitch(
+ int pitch_index
+ )
+ {
+ int temp, sum, i, bit;
- sum = 1;
- for (i = 0; i <= 5; i++)
- {
- temp >>= 1;
- bit = temp & 1;
- sum = sum + bit;
- }
+ temp = pitch_index >> 1;
- sum = sum & 1;
- return sum;
+ sum = 1;
+ for (i = 0; i <= 5; i++)
+ {
+ temp >>= 1;
+ bit = temp & 1;
+ sum = sum + bit;
}
- /**
- * Check parity of index with transmitted parity
- *
- * @param pitch_index input : index of parameter
- * @param parity input : parity bit
- * @return 0 = no error, 1= error
- */
+ sum = sum & 1;
+ return sum;
+ }
- public static int check_parity_pitch(
- int pitch_index,
- int parity
- )
- {
- int temp, sum, i, bit;
- temp = pitch_index >> 1;
+ /**
+* Check parity of index with transmitted parity
+*
+* @param pitch_index input : index of parameter
+* @param parity input : parity bit
+* @return 0 = no error, 1= error
+*/
- sum = 1;
- for (i = 0; i <= 5; i++)
- {
- temp >>= 1;
- bit = temp & 1;
- sum = sum + bit;
- }
+ public static int check_parity_pitch(
+ int pitch_index,
+ int parity
+ )
+ {
+ int temp, sum, i, bit;
+ temp = pitch_index >> 1;
- sum += parity;
- sum = sum & 1;
- return sum;
+ sum = 1;
+ for (i = 0; i <= 5; i++)
+ {
+ temp >>= 1;
+ bit = temp & 1;
+ sum = sum + bit;
}
+
+ sum += parity;
+ sum = sum & 1;
+ return sum;
}
-}
\ No newline at end of file
+}
diff --git a/src/SIPSorcery/app/Media/Codecs/G729Codec/Pitch.cs b/src/SIPSorcery/app/Media/Codecs/G729Codec/Pitch.cs
index e077fa84d..258fd1cd5 100644
--- a/src/SIPSorcery/app/Media/Codecs/G729Codec/Pitch.cs
+++ b/src/SIPSorcery/app/Media/Codecs/G729Codec/Pitch.cs
@@ -26,507 +26,545 @@
*/
using System;
-namespace SIPSorcery.Media.G729Codec
+namespace SIPSorcery.Media.G729Codec;
+
+internal static class Pitch
{
- internal class Pitch
- {
- /* ITU-T G.729 Software Package Release 2 (November 2006) */
- /*
- ITU-T G.729 Annex C - Reference C code for floating point
- implementation of G.729
- Version 1.01 of 15.September.98
+ /* ITU-T G.729 Software Package Release 2 (November 2006) */
+ /*
+ITU-T G.729 Annex C - Reference C code for floating point
+ implementation of G.729
+ Version 1.01 of 15.September.98
*/
- /*
+ /*
----------------------------------------------------------------------
- COPYRIGHT NOTICE
+ COPYRIGHT NOTICE
----------------------------------------------------------------------
- ITU-T G.729 Annex C ANSI C source code
- Copyright (C) 1998, AT&T, France Telecom, NTT, University of
- Sherbrooke. All rights reserved.
+ITU-T G.729 Annex C ANSI C source code
+Copyright (C) 1998, AT&T, France Telecom, NTT, University of
+Sherbrooke. All rights reserved.
----------------------------------------------------------------------
*/
- /*
- File : PITCH.C
- Used for the floating point version of G.729 main body
- (not for G.729A)
+ /*
+File : PITCH.C
+Used for the floating point version of G.729 main body
+(not for G.729A)
*/
- /**
- * Compute the open loop pitch lag.
- *
- * @param signal input : signal to compute pitch
- * s[-PIT_MAX : l_frame-1]
- * @param signal_offset input : signal offset
- * @param pit_min input : minimum pitch lag
- * @param pit_max input : maximum pitch lag
- * @param l_frame input : error minimization window
- * @return open-loop pitch lag
- */
+ /**
+* Compute the open loop pitch lag.
+*
+* @param signal input : signal to compute pitch
+* s[-PIT_MAX : l_frame-1]
+* @param signal_offset input : signal offset
+* @param pit_min input : minimum pitch lag
+* @param pit_max input : maximum pitch lag
+* @param l_frame input : error minimization window
+* @return open-loop pitch lag
+*/
- public static int pitch_ol(
- float[] signal,
- int signal_offset,
- int pit_min,
- int pit_max,
- int l_frame
- )
+ public static int pitch_ol(
+ float[] signal,
+ int signal_offset,
+ int pit_min,
+ int pit_max,
+ int l_frame
+ )
+ {
+ var THRESHPIT = Ld8k.THRESHPIT;
+
+ float max1, max2, max3;
+ int p_max1, p_max2, p_max3;
+
+ /*--------------------------------------------------------------------*
+* The pitch lag search is divided in three sections. *
+* Each section cannot have a pitch multiple. *
+* We find a maximum for each section. *
+* We compare the maxima of each section by favoring small lag. *
+* *
+* First section: lag delay = PIT_MAX to 80 *
+* Second section: lag delay = 79 to 40 *
+* Third section: lag delay = 39 to 20 *
+*--------------------------------------------------------------------*/
+
+ var maxRef = new FloatReference();
+ p_max1 = lag_max(signal, signal_offset, l_frame, pit_max, 80, maxRef);
+ max1 = maxRef.value;
+ p_max2 = lag_max(signal, signal_offset, l_frame, 79, 40, maxRef);
+ max2 = maxRef.value;
+ p_max3 = lag_max(signal, signal_offset, l_frame, 39, pit_min, maxRef);
+ max3 = maxRef.value;
+
+ /*--------------------------------------------------------------------*
+* Compare the 3 sections maxima, and favor small lag. *
+*--------------------------------------------------------------------*/
+
+ if (max1 * THRESHPIT < max2)
{
- var THRESHPIT = Ld8k.THRESHPIT;
-
- float max1, max2, max3;
- int p_max1, p_max2, p_max3;
-
- /*--------------------------------------------------------------------*
- * The pitch lag search is divided in three sections. *
- * Each section cannot have a pitch multiple. *
- * We find a maximum for each section. *
- * We compare the maxima of each section by favoring small lag. *
- * *
- * First section: lag delay = PIT_MAX to 80 *
- * Second section: lag delay = 79 to 40 *
- * Third section: lag delay = 39 to 20 *
- *--------------------------------------------------------------------*/
-
- var maxRef = new FloatReference();
- p_max1 = lag_max(signal, signal_offset, l_frame, pit_max, 80, maxRef);
- max1 = maxRef.value;
- p_max2 = lag_max(signal, signal_offset, l_frame, 79, 40, maxRef);
- max2 = maxRef.value;
- p_max3 = lag_max(signal, signal_offset, l_frame, 39, pit_min, maxRef);
- max3 = maxRef.value;
-
- /*--------------------------------------------------------------------*
- * Compare the 3 sections maxima, and favor small lag. *
- *--------------------------------------------------------------------*/
-
- if (max1 * THRESHPIT < max2)
- {
- max1 = max2;
- p_max1 = p_max2;
- }
-
- if (max1 * THRESHPIT < max3) p_max1 = p_max3;
-
- return p_max1;
+ max1 = max2;
+ p_max1 = p_max2;
}
- /**
- * Find the lag that has maximum correlation
- *
- * @param signal input : Signal to compute the open loop pitch
- * signal[-142:-1] should be known.
- * @param signal_offset input : signal offset
- * @param l_frame input : Length of frame to compute pitch
- * @param lagmax input : maximum lag
- * @param lagmin input : minimum lag
- * @param cor_max input : normalized correlation of selected lag
- * @return lag found
- */
- private static int lag_max(
- float[] signal,
- int signal_offset,
- int l_frame,
- int lagmax,
- int lagmin,
- FloatReference cor_max
- )
+ if (max1 * THRESHPIT < max3)
{
- var FLT_MIN_G729 = Ld8k.FLT_MIN_G729;
-
- int i, j;
- int p, p1;
- float max, t0;
- var p_max = 0;
-
- max = FLT_MIN_G729;
+ p_max1 = p_max3;
+ }
- for (i = lagmax; i >= lagmin; i--)
- {
- p = signal_offset;
- p1 = signal_offset - i;
- t0 = 0.0f;
+ return p_max1;
+ }
- for (j = 0; j < l_frame; j++, p++, p1++)
- t0 += signal[p] * signal[p1];
+ /**
+* Find the lag that has maximum correlation
+*
+* @param signal input : Signal to compute the open loop pitch
+* signal[-142:-1] should be known.
+* @param signal_offset input : signal offset
+* @param l_frame input : Length of frame to compute pitch
+* @param lagmax input : maximum lag
+* @param lagmin input : minimum lag
+* @param cor_max input : normalized correlation of selected lag
+* @return lag found
+*/
+ private static int lag_max(
+ float[] signal,
+ int signal_offset,
+ int l_frame,
+ int lagmax,
+ int lagmin,
+ FloatReference cor_max
+ )
+ {
+ var FLT_MIN_G729 = Ld8k.FLT_MIN_G729;
- if (t0 >= max)
- {
- max = t0;
- p_max = i;
- }
- }
+ int i, j;
+ int p, p1;
+ float max, t0;
+ var p_max = 0;
- /* compute energy */
+ max = FLT_MIN_G729;
- t0 = 0.01f; /* to avoid division by zero */
- p = signal_offset - p_max;
- for (i = 0; i < l_frame; i++, p++)
- t0 += signal[p] * signal[p];
- t0 = inv_sqrt(t0); /* 1/sqrt(energy) */
+ for (i = lagmax; i >= lagmin; i--)
+ {
+ p = signal_offset;
+ p1 = signal_offset - i;
+ t0 = 0.0f;
- cor_max.value = max * t0; /* max/sqrt(energy) */
+ for (j = 0; j < l_frame; j++, p++, p1++)
+ {
+ t0 += signal[p] * signal[p1];
+ }
- return p_max;
+ if (t0 >= max)
+ {
+ max = t0;
+ p_max = i;
+ }
}
- /**
- * Find the pitch period with 1/3 subsample resolution
- *
- * @param exc input : excitation buffer
- * @param exc_offset input : excitation buffer offset
- * @param xn input : target vector
- * @param h input : impulse response of filters.
- * @param l_subfr input : Length of frame to compute pitch
- * @param t0_min input : minimum value in the searched range
- * @param t0_max input : maximum value in the searched range
- * @param i_subfr input : indicator for first subframe
- * @param pit_frac output: chosen fraction
- * @return integer part of pitch period
- */
+ /* compute energy */
- public static int pitch_fr3(
- float[] exc, /* */
- int exc_offset,
- float[] xn, /* */
- float[] h, /* */
- int l_subfr, /* */
- int t0_min, /* */
- int t0_max, /* */
- int i_subfr, /* */
- IntReference pit_frac /* */
- )
+ t0 = 0.01f; /* to avoid division by zero */
+ p = signal_offset - p_max;
+ for (i = 0; i < l_frame; i++, p++)
{
- var L_INTER4 = Ld8k.L_INTER4;
+ t0 += signal[p] * signal[p];
+ }
- int i, frac;
- int lag, t_min, t_max;
- float max;
- float corr_int;
- var corr_v = new float[10 + 2 * L_INTER4]; /* size: 2*L_INTER4+t0_max-t0_min+1 */
- float[] corr;
- int corr_offset;
+ t0 = inv_sqrt(t0); /* 1/sqrt(energy) */
- /* Find interval to compute normalized correlation */
+ cor_max.value = max * t0; /* max/sqrt(energy) */
- t_min = t0_min - L_INTER4;
- t_max = t0_max + L_INTER4;
+ return p_max;
+ }
- corr = corr_v; /* corr[t_min:t_max] */
- corr_offset = -t_min;
+ /**
+* Find the pitch period with 1/3 subsample resolution
+*
+* @param exc input : excitation buffer
+* @param exc_offset input : excitation buffer offset
+* @param xn input : target vector
+* @param h input : impulse response of filters.
+* @param l_subfr input : Length of frame to compute pitch
+* @param t0_min input : minimum value in the searched range
+* @param t0_max input : maximum value in the searched range
+* @param i_subfr input : indicator for first subframe
+* @param pit_frac output: chosen fraction
+* @return integer part of pitch period
+*/
- /* Compute normalized correlation between target and filtered excitation */
+ public static int pitch_fr3(
+ float[] exc, /* */
+ int exc_offset,
+ float[] xn, /* */
+ float[] h, /* */
+ int l_subfr, /* */
+ int t0_min, /* */
+ int t0_max, /* */
+ int i_subfr, /* */
+ IntReference pit_frac /* */
+ )
+ {
+ var L_INTER4 = Ld8k.L_INTER4;
- norm_corr(exc, exc_offset, xn, h, l_subfr, t_min, t_max, corr, corr_offset);
+ int i, frac;
+ int lag, t_min, t_max;
+ float max;
+ float corr_int;
+ var corr_v = new float[10 + 2 * L_INTER4]; /* size: 2*L_INTER4+t0_max-t0_min+1 */
+ float[] corr;
+ int corr_offset;
- /* find integer pitch */
+ /* Find interval to compute normalized correlation */
- max = corr[corr_offset + t0_min];
- lag = t0_min;
+ t_min = t0_min - L_INTER4;
+ t_max = t0_max + L_INTER4;
- for (i = t0_min + 1; i <= t0_max; i++)
- if (corr[corr_offset + i] >= max)
- {
- max = corr[corr_offset + i];
- lag = i;
- }
+ corr = corr_v; /* corr[t_min:t_max] */
+ corr_offset = -t_min;
- /* If first subframe and lag > 84 do not search fractionnal pitch */
+ /* Compute normalized correlation between target and filtered excitation */
- if (i_subfr == 0 && lag > 84)
- {
- pit_frac.value = 0;
- return lag;
- }
+ norm_corr(exc, exc_offset, xn, h, l_subfr, t_min, t_max, corr, corr_offset);
- /* test the fractions around lag and choose the one which maximizes
- the interpolated normalized correlation */
- corr_offset += lag;
- max = interpol_3(corr, corr_offset, -2);
- frac = -2;
+ /* find integer pitch */
- for (i = -1; i <= 2; i++)
+ max = corr[corr_offset + t0_min];
+ lag = t0_min;
+
+ for (i = t0_min + 1; i <= t0_max; i++)
+ {
+ if (corr[corr_offset + i] >= max)
{
- corr_int = interpol_3(corr, corr_offset, i);
- if (corr_int > max)
- {
- max = corr_int;
- frac = i;
- }
+ max = corr[corr_offset + i];
+ lag = i;
}
+ }
- /* limit the fraction value in the interval [-1,0,1] */
+ /* If first subframe and lag > 84 do not search fractionnal pitch */
- if (frac == -2)
- {
- frac = 1;
- lag -= 1;
- }
+ if (i_subfr == 0 && lag > 84)
+ {
+ pit_frac.value = 0;
+ return lag;
+ }
+
+ /* test the fractions around lag and choose the one which maximizes
+ the interpolated normalized correlation */
+ corr_offset += lag;
+ max = interpol_3(corr, corr_offset, -2);
+ frac = -2;
- if (frac == 2)
+ for (i = -1; i <= 2; i++)
+ {
+ corr_int = interpol_3(corr, corr_offset, i);
+ if (corr_int > max)
{
- frac = -1;
- lag += 1;
+ max = corr_int;
+ frac = i;
}
+ }
- pit_frac.value = frac;
+ /* limit the fraction value in the interval [-1,0,1] */
- return lag;
+ if (frac == -2)
+ {
+ frac = 1;
+ lag -= 1;
}
- /**
- * Find the normalized correlation between the target vector and
- * the filtered past excitation.
- *
- * @param exc input : excitation buffer
- * @param exc_offset input : excitation buffer offset
- * @param xn input : target vector
- * @param h input : imp response of synth and weighting flt
- * @param l_subfr input : Length of frame to compute pitch
- * @param t_min input : minimum value of searched range
- * @param t_max input : maximum value of search range
- * @param corr_norm output: normalized correlation (correlation
- * between target and filtered excitation divided
- * by the square root of energy of filtered
- * excitation)
- * @param corr_norm_offset input: normalized correlation offset
- */
- private static void norm_corr(
- float[] exc,
- int exc_offset,
- float[] xn,
- float[] h,
- int l_subfr,
- int t_min,
- int t_max,
- float[] corr_norm,
- int corr_norm_offset
- )
+ if (frac == 2)
{
- var L_SUBFR = Ld8k.L_SUBFR;
+ frac = -1;
+ lag += 1;
+ }
- int i, j, k;
- var excf = new float[L_SUBFR]; /* filtered past excitation */
- float alp, s, norm;
+ pit_frac.value = frac;
- k = exc_offset - t_min;
+ return lag;
+ }
- /* compute the filtered excitation for the first delay t_min */
+ /**
+* Find the normalized correlation between the target vector and
+* the filtered past excitation.
+*
+* @param exc input : excitation buffer
+* @param exc_offset input : excitation buffer offset
+* @param xn input : target vector
+* @param h input : imp response of synth and weighting flt
+* @param l_subfr input : Length of frame to compute pitch
+* @param t_min input : minimum value of searched range
+* @param t_max input : maximum value of search range
+* @param corr_norm output: normalized correlation (correlation
+* between target and filtered excitation divided
+* by the square root of energy of filtered
+* excitation)
+* @param corr_norm_offset input: normalized correlation offset
+*/
+ private static void norm_corr(
+ float[] exc,
+ int exc_offset,
+ float[] xn,
+ float[] h,
+ int l_subfr,
+ int t_min,
+ int t_max,
+ float[] corr_norm,
+ int corr_norm_offset
+ )
+ {
+ var L_SUBFR = Ld8k.L_SUBFR;
- Filter.convolve(exc, k, h, excf, l_subfr);
+ int i, j, k;
+ var excf = new float[L_SUBFR]; /* filtered past excitation */
+ float alp, s, norm;
- /* loop for every possible period */
+ k = exc_offset - t_min;
- for (i = t_min; i <= t_max; i++)
- {
- /* Compute 1/sqrt(energie of excf[]) */
+ /* compute the filtered excitation for the first delay t_min */
- alp = 0.01f;
- for (j = 0; j < l_subfr; j++)
- alp += excf[j] * excf[j];
+ Filter.convolve(exc, k, h, excf, l_subfr);
- norm = inv_sqrt(alp);
+ /* loop for every possible period */
- /* Compute correlation between xn[] and excf[] */
+ for (i = t_min; i <= t_max; i++)
+ {
+ /* Compute 1/sqrt(energie of excf[]) */
- s = 0.0f;
- for (j = 0; j < l_subfr; j++) s += xn[j] * excf[j];
+ alp = 0.01f;
+ for (j = 0; j < l_subfr; j++)
+ {
+ alp += excf[j] * excf[j];
+ }
+
+ norm = inv_sqrt(alp);
+
+ /* Compute correlation between xn[] and excf[] */
+
+ s = 0.0f;
+ for (j = 0; j < l_subfr; j++)
+ {
+ s += xn[j] * excf[j];
+ }
- /* Normalize correlation = correlation * (1/sqrt(energie)) */
+ /* Normalize correlation = correlation * (1/sqrt(energie)) */
- corr_norm[corr_norm_offset + i] = s * norm;
+ corr_norm[corr_norm_offset + i] = s * norm;
- /* modify the filtered excitation excf[] for the next iteration */
+ /* modify the filtered excitation excf[] for the next iteration */
- if (i != t_max)
+ if (i != t_max)
+ {
+ k--;
+ for (j = l_subfr - 1; j > 0; j--)
{
- k--;
- for (j = l_subfr - 1; j > 0; j--)
- excf[j] = excf[j - 1] + exc[k] * h[j];
- excf[0] = exc[k];
+ excf[j] = excf[j - 1] + exc[k] * h[j];
}
+
+ excf[0] = exc[k];
}
}
+ }
- /** , -2
- *
- * @param xn input : target vector
- * @param y1 input : filtered adaptive codebook vector
- * @param g_coeff output: and -2
- * @param l_subfr input : vector dimension
- * @return pitch gain
- * ]]>
- */
+ /** , -2
+*
+* @param xn input : target vector
+* @param y1 input : filtered adaptive codebook vector
+* @param g_coeff output: and -2
+* @param l_subfr input : vector dimension
+* @return pitch gain
+* ]]>
+*/
+
+ public static float g_pitch(
+ float[] xn,
+ float[] y1,
+ float[] g_coeff,
+ int l_subfr
+ )
+ {
+ var GAIN_PIT_MAX = Ld8k.GAIN_PIT_MAX;
- public static float g_pitch(
- float[] xn,
- float[] y1,
- float[] g_coeff,
- int l_subfr
- )
+ float xy, yy, gain;
+ int i;
+
+ xy = 0.0f;
+ for (i = 0; i < l_subfr; i++)
{
- var GAIN_PIT_MAX = Ld8k.GAIN_PIT_MAX;
+ xy += xn[i] * y1[i];
+ }
- float xy, yy, gain;
- int i;
+ yy = 0.01f;
+ for (i = 0; i < l_subfr; i++)
+ {
+ yy += y1[i] * y1[i]; /* energy of filtered excitation */
+ }
- xy = 0.0f;
- for (i = 0; i < l_subfr; i++)
- xy += xn[i] * y1[i];
- yy = 0.01f;
- for (i = 0; i < l_subfr; i++)
- yy += y1[i] * y1[i]; /* energy of filtered excitation */
- g_coeff[0] = yy;
- g_coeff[1] = -2.0f * xy + 0.01f;
+ g_coeff[0] = yy;
+ g_coeff[1] = -2.0f * xy + 0.01f;
- /* find pitch gain and bound it by [0,1.2] */
+ /* find pitch gain and bound it by [0,1.2] */
- gain = xy / yy;
+ gain = xy / yy;
- if (gain < 0.0f) gain = 0.0f;
- if (gain > GAIN_PIT_MAX) gain = GAIN_PIT_MAX;
+ if (gain < 0.0f)
+ {
+ gain = 0.0f;
+ }
- return gain;
+ if (gain > GAIN_PIT_MAX)
+ {
+ gain = GAIN_PIT_MAX;
}
- /**
- * Function enc_lag3()
- * Encoding of fractional pitch lag with 1/3 resolution.
- *
- * The pitch range for the first subframe is divided as follows:
- * 19 1/3 to 84 2/3 resolution 1/3
- * 85 to 143 resolution 1
- *
- * The period in the first subframe is encoded with 8 bits.
- * For the range with fractions:
- * index = (T-19)*3 + frac - 1; where T=[19..85] and frac=[-1,0,1]
- * and for the integer only range
- * index = (T - 85) + 197; where T=[86..143]
- *----------------------------------------------------------------------
- * For the second subframe a resolution of 1/3 is always used, and the
- * search range is relative to the lag in the first subframe.
- * If t0 is the lag in the first subframe then
- * t_min=t0-5 and t_max=t0+4 and the range is given by
- * t_min - 2/3 to t_max + 2/3
- *
- * The period in the 2nd subframe is encoded with 5 bits:
- * index = (T-(t_min-1))*3 + frac - 1; where T[t_min-1 .. t_max+1]
- *
- *
- * @param T0 input : Pitch delay
- * @param T0_frac input : Fractional pitch delay
- * @param T0_min in/out: Minimum search delay
- * @param T0_max in/out: Maximum search delay
- * @param pit_min input : Minimum pitch delay
- * @param pit_max input : Maximum pitch delay
- * @param pit_flag input : Flag for 1st subframe
- * @return Return index of encoding
- */
+ return gain;
+ }
+
+ /**
+* Function enc_lag3()
+* Encoding of fractional pitch lag with 1/3 resolution.
+*
+* The pitch range for the first subframe is divided as follows:
+* 19 1/3 to 84 2/3 resolution 1/3
+* 85 to 143 resolution 1
+*
+* The period in the first subframe is encoded with 8 bits.
+* For the range with fractions:
+* index = (T-19)*3 + frac - 1; where T=[19..85] and frac=[-1,0,1]
+* and for the integer only range
+* index = (T - 85) + 197; where T=[86..143]
+*----------------------------------------------------------------------
+* For the second subframe a resolution of 1/3 is always used, and the
+* search range is relative to the lag in the first subframe.
+* If t0 is the lag in the first subframe then
+* t_min=t0-5 and t_max=t0+4 and the range is given by
+* t_min - 2/3 to t_max + 2/3
+*
+* The period in the 2nd subframe is encoded with 5 bits:
+* index = (T-(t_min-1))*3 + frac - 1; where T[t_min-1 .. t_max+1]
+*
+*
+* @param T0 input : Pitch delay
+* @param T0_frac input : Fractional pitch delay
+* @param T0_min in/out: Minimum search delay
+* @param T0_max in/out: Maximum search delay
+* @param pit_min input : Minimum pitch delay
+* @param pit_max input : Maximum pitch delay
+* @param pit_flag input : Flag for 1st subframe
+* @return Return index of encoding
+*/
+
+ public static int enc_lag3(
+ int T0,
+ int T0_frac,
+ IntReference T0_min,
+ IntReference T0_max,
+ int pit_min,
+ int pit_max,
+ int pit_flag
+ )
+ {
+ int index;
+ int _T0_min = T0_min.value, _T0_max = T0_max.value;
- public static int enc_lag3(
- int T0,
- int T0_frac,
- IntReference T0_min,
- IntReference T0_max,
- int pit_min,
- int pit_max,
- int pit_flag
- )
+ if (pit_flag == 0) /* if 1st subframe */
{
- int index;
- int _T0_min = T0_min.value, _T0_max = T0_max.value;
+ /* encode pitch delay (with fraction) */
- if (pit_flag == 0) /* if 1st subframe */
+ if (T0 <= 85)
{
- /* encode pitch delay (with fraction) */
-
- if (T0 <= 85)
- index = T0 * 3 - 58 + T0_frac;
- else
- index = T0 + 112;
+ index = T0 * 3 - 58 + T0_frac;
+ }
+ else
+ {
+ index = T0 + 112;
+ }
- /* find T0_min and T0_max for second subframe */
+ /* find T0_min and T0_max for second subframe */
- _T0_min = T0 - 5;
- if (_T0_min < pit_min) _T0_min = pit_min;
- _T0_max = _T0_min + 9;
- if (_T0_max > pit_max)
- {
- _T0_max = pit_max;
- _T0_min = _T0_max - 9;
- }
+ _T0_min = T0 - 5;
+ if (_T0_min < pit_min)
+ {
+ _T0_min = pit_min;
}
- else /* second subframe */
+ _T0_max = _T0_min + 9;
+ if (_T0_max > pit_max)
{
- index = T0 - _T0_min;
- index = index * 3 + 2 + T0_frac;
+ _T0_max = pit_max;
+ _T0_min = _T0_max - 9;
}
-
- T0_min.value = _T0_min;
- T0_max.value = _T0_max;
- return index;
}
- /**
- * For interpolating the normalized correlation
- *
- * @param x input : function to be interpolated
- * @param x_offset input : function offset
- * @param frac input : fraction value to evaluate
- * @return interpolated value
- */
- private static float interpol_3(
- float[] x,
- int x_offset,
- int frac
- )
+ else /* second subframe */
{
- var L_INTER4 = Ld8k.L_INTER4;
- var UP_SAMP = Ld8k.UP_SAMP;
- var inter_3 = TabLd8k.inter_3;
-
- int i;
- float s;
- int x1, x2, c1, c2;
+ index = T0 - _T0_min;
+ index = index * 3 + 2 + T0_frac;
+ }
- if (frac < 0)
- {
- frac += UP_SAMP;
- x_offset--;
- }
+ T0_min.value = _T0_min;
+ T0_max.value = _T0_max;
+ return index;
+ }
- x1 = x_offset;
- x2 = x_offset + 1;
- c1 = frac;
- c2 = UP_SAMP - frac;
+ /**
+* For interpolating the normalized correlation
+*
+* @param x input : function to be interpolated
+* @param x_offset input : function offset
+* @param frac input : fraction value to evaluate
+* @return interpolated value
+*/
+ private static float interpol_3(
+ float[] x,
+ int x_offset,
+ int frac
+ )
+ {
+ var L_INTER4 = Ld8k.L_INTER4;
+ var UP_SAMP = Ld8k.UP_SAMP;
+ var inter_3 = TabLd8k.inter_3;
- s = 0.0f;
- for (i = 0; i < L_INTER4; i++, c1 += UP_SAMP, c2 += UP_SAMP)
- {
- s += x[x1] * inter_3[c1] + x[x2] * inter_3[c2];
- x1--;
- x2++;
- }
+ int i;
+ float s;
+ int x1, x2, c1, c2;
- return s;
+ if (frac < 0)
+ {
+ frac += UP_SAMP;
+ x_offset--;
}
- /**
- * Compute y = 1 / sqrt(x)
- *
- * @param x input : value of x
- * @return output: 1/sqrt(x)
- */
- private static float inv_sqrt(
- float x
- )
+ x1 = x_offset;
+ x2 = x_offset + 1;
+ c1 = frac;
+ c2 = UP_SAMP - frac;
+
+ s = 0.0f;
+ for (i = 0; i < L_INTER4; i++, c1 += UP_SAMP, c2 += UP_SAMP)
{
- return 1.0f / (float)Math.Sqrt(x);
+ s += x[x1] * inter_3[c1] + x[x2] * inter_3[c2];
+ x1--;
+ x2++;
}
+
+ return s;
+ }
+
+ /**
+* Compute y = 1 / sqrt(x)
+*
+* @param x input : value of x
+* @return output: 1/sqrt(x)
+*/
+ private static float inv_sqrt(
+ float x
+ )
+ {
+ return 1.0f / (float)Math.Sqrt(x);
}
}
diff --git a/src/SIPSorcery/app/Media/Codecs/G729Codec/PostPro.cs b/src/SIPSorcery/app/Media/Codecs/G729Codec/PostPro.cs
index a2514bc39..decf3584e 100644
--- a/src/SIPSorcery/app/Media/Codecs/G729Codec/PostPro.cs
+++ b/src/SIPSorcery/app/Media/Codecs/G729Codec/PostPro.cs
@@ -35,86 +35,85 @@
*
* @author Lubomir Marinov (translation of ITU-T C source code to Java)
*/
-namespace SIPSorcery.Media.G729Codec
+namespace SIPSorcery.Media.G729Codec;
+
+internal sealed class PostPro
{
- internal class PostPro
- {
- /* ITU-T G.729 Software Package Release 2 (November 2006) */
- /*
- ITU-T G.729 Annex C - Reference C code for floating point
- implementation of G.729
- Version 1.01 of 15.September.98
+ /* ITU-T G.729 Software Package Release 2 (November 2006) */
+ /*
+ITU-T G.729 Annex C - Reference C code for floating point
+ implementation of G.729
+ Version 1.01 of 15.September.98
*/
- /*
+ /*
----------------------------------------------------------------------
- COPYRIGHT NOTICE
+ COPYRIGHT NOTICE
----------------------------------------------------------------------
- ITU-T G.729 Annex C ANSI C source code
- Copyright (C) 1998, AT&T, France Telecom, NTT, University of
- Sherbrooke. All rights reserved.
+ITU-T G.729 Annex C ANSI C source code
+Copyright (C) 1998, AT&T, France Telecom, NTT, University of
+Sherbrooke. All rights reserved.
----------------------------------------------------------------------
*/
- /*
- File : POST_PRO.C
- Used for the floating point version of both
- G.729 main body and G.729A
+ /*
+File : POST_PRO.C
+Used for the floating point version of both
+G.729 main body and G.729A
*/
- /**
- * High-pass fir memory
- */
- private float x0, x1;
+ /**
+* High-pass fir memory
+*/
+ private float x0, x1;
- /**
- * High-pass iir memory
- */
- private float y1, y2;
+ /**
+* High-pass iir memory
+*/
+ private float y1, y2;
- /**
- * Init Post Process.
- */
+ /**
+* Init Post Process.
+*/
- public void init_post_process()
- {
- x0 = x1 = 0.0f;
- y2 = y1 = 0.0f;
- }
+ public void init_post_process()
+ {
+ x0 = x1 = 0.0f;
+ y2 = y1 = 0.0f;
+ }
- /**
- * Post Process
- *
- * @param signal (i/o) : signal
- * @param lg (i) : lenght of signal
- */
+ /**
+* Post Process
+*
+* @param signal (i/o) : signal
+* @param lg (i) : lenght of signal
+*/
- public void post_process(
- float[] signal,
- int lg
- )
- {
- var a100 = TabLd8k.a100;
- var b100 = TabLd8k.b100;
+ public void post_process(
+ float[] signal,
+ int lg
+ )
+ {
+ var a100 = TabLd8k.a100;
+ var b100 = TabLd8k.b100;
- int i;
- float x2;
- float y0;
+ int i;
+ float x2;
+ float y0;
- for (i = 0; i < lg; i++)
- {
- x2 = x1;
- x1 = x0;
- x0 = signal[i];
+ for (i = 0; i < lg; i++)
+ {
+ x2 = x1;
+ x1 = x0;
+ x0 = signal[i];
- y0 = y1 * a100[1] + y2 * a100[2] + x0 * b100[0] + x1 * b100[1] + x2 * b100[2];
+ y0 = y1 * a100[1] + y2 * a100[2] + x0 * b100[0] + x1 * b100[1] + x2 * b100[2];
- signal[i] = y0;
- y2 = y1;
- y1 = y0;
- }
+ signal[i] = y0;
+ y2 = y1;
+ y1 = y0;
}
}
-}
\ No newline at end of file
+}
diff --git a/src/SIPSorcery/app/Media/Codecs/G729Codec/Postfil.cs b/src/SIPSorcery/app/Media/Codecs/G729Codec/Postfil.cs
index bd730c858..fe679298b 100644
--- a/src/SIPSorcery/app/Media/Codecs/G729Codec/Postfil.cs
+++ b/src/SIPSorcery/app/Media/Codecs/G729Codec/Postfil.cs
@@ -46,864 +46,954 @@
* @author Lubomir Marinov (translation of ITU-T C source code to Java)
*/
using System;
+using System.Diagnostics;
-namespace SIPSorcery.Media.G729Codec
+namespace SIPSorcery.Media.G729Codec;
+
+internal sealed class Postfil : Ld8k
{
- internal class Postfil : Ld8k
- {
- /* ITU-T G.729 Software Package Release 2 (November 2006) */
- /*
- ITU-T G.729 Annex C - Reference C code for floating point
- implementation of G.729
- Version 1.01 of 15.September.98
+ /* ITU-T G.729 Software Package Release 2 (November 2006) */
+ /*
+ITU-T G.729 Annex C - Reference C code for floating point
+ implementation of G.729
+ Version 1.01 of 15.September.98
*/
- /*
+ /*
----------------------------------------------------------------------
- COPYRIGHT NOTICE
+ COPYRIGHT NOTICE
----------------------------------------------------------------------
- ITU-T G.729 Annex C ANSI C source code
- Copyright (C) 1998, AT&T, France Telecom, NTT, University of
- Sherbrooke. All rights reserved.
+ITU-T G.729 Annex C ANSI C source code
+Copyright (C) 1998, AT&T, France Telecom, NTT, University of
+Sherbrooke. All rights reserved.
----------------------------------------------------------------------
*/
- /*
- File : POSTFIL.C
- Used for the floating point version of G.729 main body
- (not for G.729A)
+ /*
+File : POSTFIL.C
+Used for the floating point version of G.729 main body
+(not for G.729A)
*/
- /* Static arrays and variables */
- /**
- * s.t. numerator coeff.
- */
- private readonly float[] apond2 = new float[LONG_H_ST];
+ /* Static arrays and variables */
+ /**
+* s.t. numerator coeff.
+*/
+ private readonly float[] apond2 = new float[LONG_H_ST];
- /**
- * for gain adjustment
- */
- private float gain_prec;
+ /**
+* for gain adjustment
+*/
+ private float gain_prec;
- /**
- * s.t. postfilter memory
- */
- private readonly float[] mem_stp = new float[M];
+ /**
+* s.t. postfilter memory
+*/
+ private readonly float[] mem_stp = new float[M];
- /**
- * null memory to compute h_st
- */
- private readonly float[] mem_zero = new float[M];
+ /**
+* null memory to compute h_st
+*/
+ private readonly float[] mem_zero = new float[M];
- private float[] ptr_mem_stp;
+ private float[]? ptr_mem_stp;
- private int ptr_mem_stp_offset;
+ private int ptr_mem_stp_offset;
- /**
- * A(gamma2) residual
- */
- private readonly float[] res2 = new float[SIZ_RES2];
+ /**
+* A(gamma2) residual
+*/
+ private readonly float[] res2 = new float[SIZ_RES2];
- /* Static pointers */
- private int res2_ptr;
+ /* Static pointers */
+ private int res2_ptr;
- /**
- * Initialize postfilter functions
- */
+ /**
+* Initialize postfilter functions
+*/
- public void init_post_filter()
- {
- int i;
+ public void init_post_filter()
+ {
+ int i;
- /* Initialize arrays and pointers */
+ /* Initialize arrays and pointers */
- /* A(gamma2) residual */
- for (i = 0; i < MEM_RES2; i++) res2[i] = 0.0f;
- res2_ptr = MEM_RES2;
+ /* A(gamma2) residual */
+ for (i = 0; i < MEM_RES2; i++)
+ {
+ res2[i] = 0.0f;
+ }
- /* 1/A(gamma1) memory */
- for (i = 0; i < M; i++) mem_stp[i] = 0.0f;
- ptr_mem_stp = mem_stp;
- ptr_mem_stp_offset = M - 1;
+ res2_ptr = MEM_RES2;
- /* fill apond2[M+1->LONG_H_ST-1] with zeroes */
- for (i = MP1; i < LONG_H_ST; i++) apond2[i] = 0.0f;
+ /* 1/A(gamma1) memory */
+ for (i = 0; i < M; i++)
+ {
+ mem_stp[i] = 0.0f;
+ }
- /* null memory to compute i.r. of A(gamma2)/A(gamma1) */
- for (i = 0; i < M; i++) mem_zero[i] = 0.0f;
+ ptr_mem_stp = mem_stp;
+ ptr_mem_stp_offset = M - 1;
- /* for gain adjustment */
- gain_prec = 1.0f;
+ /* fill apond2[M+1->LONG_H_ST-1] with zeroes */
+ for (i = MP1; i < LONG_H_ST; i++)
+ {
+ apond2[i] = 0.0f;
}
- /**
- * Adaptive postfilter main function
- *
- * @param t0 input : pitch delay given by coder
- * @param signal_ptr input : input signal (pointer to current subframe)
- * @param signal_ptr_offset input : input signal offset
- * @param coeff input : LPC coefficients for current subframe
- * @param coeff_offset input : LPC coefficients offset
- * @param sig_out output: postfiltered output
- * @param sig_out_offset input: postfiltered output offset
- * @return voicing decision 0 = uv, > 0 delay
- */
-
- public int post(
- int t0,
- float[] signal_ptr,
- int signal_ptr_offset,
- float[] coeff,
- int coeff_offset,
- float[] sig_out,
- int sig_out_offset
- )
+ /* null memory to compute i.r. of A(gamma2)/A(gamma1) */
+ for (i = 0; i < M; i++)
{
- int vo; /* output: voicing decision 0 = uv, > 0 delay */
+ mem_zero[i] = 0.0f;
+ }
+
+ /* for gain adjustment */
+ gain_prec = 1.0f;
+ }
+
+ /**
+* Adaptive postfilter main function
+*
+* @param t0 input : pitch delay given by coder
+* @param signal_ptr input : input signal (pointer to current subframe)
+* @param signal_ptr_offset input : input signal offset
+* @param coeff input : LPC coefficients for current subframe
+* @param coeff_offset input : LPC coefficients offset
+* @param sig_out output: postfiltered output
+* @param sig_out_offset input: postfiltered output offset
+* @return voicing decision 0 = uv, > 0 delay
+*/
+
+ public int post(
+ int t0,
+ float[] signal_ptr,
+ int signal_ptr_offset,
+ float[] coeff,
+ int coeff_offset,
+ float[] sig_out,
+ int sig_out_offset
+ )
+ {
+ int vo; /* output: voicing decision 0 = uv, > 0 delay */
- var apond1 = new float[MP1]; /* s.t. denominator coeff. */
- var sig_ltp = new float[L_SUBFRP1]; /* H0 output signal */
- int sig_ltp_ptr;
- float parcor0;
+ var apond1 = new float[MP1]; /* s.t. denominator coeff. */
+ var sig_ltp = new float[L_SUBFRP1]; /* H0 output signal */
+ int sig_ltp_ptr;
+ float parcor0;
- /* Compute weighted LPC coefficients */
- Lpcfunc.weight_az(coeff, coeff_offset, GAMMA1_PST, M, apond1);
- Lpcfunc.weight_az(coeff, coeff_offset, GAMMA2_PST, M, apond2);
+ /* Compute weighted LPC coefficients */
+ Lpcfunc.weight_az(coeff, coeff_offset, GAMMA1_PST, M, apond1);
+ Lpcfunc.weight_az(coeff, coeff_offset, GAMMA2_PST, M, apond2);
- /* Compute A(gamma2) residual */
- Filter.residu(apond2, 0, signal_ptr, signal_ptr_offset, res2, res2_ptr, L_SUBFR);
+ /* Compute A(gamma2) residual */
+ Filter.residu(apond2, 0, signal_ptr, signal_ptr_offset, res2, res2_ptr, L_SUBFR);
- /* Harmonic filtering */
- sig_ltp_ptr = 1;
- vo = pst_ltp(t0, res2, res2_ptr, sig_ltp, sig_ltp_ptr);
+ /* Harmonic filtering */
+ sig_ltp_ptr = 1;
+ vo = pst_ltp(t0, res2, res2_ptr, sig_ltp, sig_ltp_ptr);
- /* Save last output of 1/A(gamma1) */
- /* (from preceding subframe) */
- sig_ltp[0] = ptr_mem_stp[ptr_mem_stp_offset];
+ /* Save last output of 1/A(gamma1) */
+ /* (from preceding subframe) */
+ Debug.Assert(ptr_mem_stp is { } && ptr_mem_stp.Length > ptr_mem_stp_offset);
+ sig_ltp[0] = ptr_mem_stp[ptr_mem_stp_offset];
- /* Control short term pst filter gain and compute parcor0 */
- parcor0 = calc_st_filt(apond2, apond1, sig_ltp, sig_ltp_ptr);
+ /* Control short term pst filter gain and compute parcor0 */
+ parcor0 = calc_st_filt(apond2, apond1, sig_ltp, sig_ltp_ptr);
- /* 1/A(gamma1) filtering, mem_stp is updated */
- Filter.syn_filt(apond1, 0, sig_ltp, sig_ltp_ptr, sig_ltp, sig_ltp_ptr, L_SUBFR, mem_stp, 0, 1);
+ /* 1/A(gamma1) filtering, mem_stp is updated */
+ Filter.syn_filt(apond1, 0, sig_ltp, sig_ltp_ptr, sig_ltp, sig_ltp_ptr, L_SUBFR, mem_stp, 0, 1);
- /* (1 + mu z-1) tilt filtering */
- filt_mu(sig_ltp, sig_out, sig_out_offset, parcor0);
+ /* (1 + mu z-1) tilt filtering */
+ filt_mu(sig_ltp, sig_out, sig_out_offset, parcor0);
- /* gain control */
- gain_prec = scale_st(signal_ptr, signal_ptr_offset, sig_out, sig_out_offset, gain_prec);
+ /* gain control */
+ gain_prec = scale_st(signal_ptr, signal_ptr_offset, sig_out, sig_out_offset, gain_prec);
- /* Update for next frame */
- Util.copy(res2, L_SUBFR, res2, MEM_RES2);
+ /* Update for next frame */
+ Util.copy(res2, L_SUBFR, res2, MEM_RES2);
- return vo;
+ return vo;
+ }
+
+ /**
+* Harmonic postfilter
+*
+* @param t0 input : pitch delay given by coder
+* @param ptr_sig_in input : postfilter input filter (residu2)
+* @param ptr_sig_in_offset input : postfilter input filter offset
+* @param ptr_sig_pst0 output: harmonic postfilter output
+* @param ptr_sig_pst0_offset input: harmonic postfilter offset
+* @return voicing decision 0 = uv, > 0 delay
+*/
+ private int pst_ltp(
+ int t0,
+ float[] ptr_sig_in,
+ int ptr_sig_in_offset,
+ float[] ptr_sig_pst0,
+ int ptr_sig_pst0_offset
+ )
+ {
+ int vo;
+
+ /* Declare variables */
+ int ltpdel, phase;
+ float num_gltp, den_gltp;
+ float num2_gltp, den2_gltp;
+ float gain_plt;
+ var y_up = new float[SIZ_Y_UP];
+ float[] ptr_y_up;
+ int ptr_y_up_offset;
+ int off_yup;
+
+ /* Sub optimal delay search */
+ var _ltpdel = new IntReference();
+ var _phase = new IntReference();
+ var _num_gltp = new FloatReference();
+ var _den_gltp = new FloatReference();
+ var _off_yup = new IntReference();
+ search_del(
+ t0,
+ ptr_sig_in,
+ ptr_sig_in_offset,
+ _ltpdel,
+ _phase,
+ _num_gltp,
+ _den_gltp,
+ y_up,
+ _off_yup);
+ ltpdel = _ltpdel.value;
+ phase = _phase.value;
+ num_gltp = _num_gltp.value;
+ den_gltp = _den_gltp.value;
+ off_yup = _off_yup.value;
+
+ vo = ltpdel;
+
+ if (num_gltp == 0.0f)
+ {
+ Util.copy(ptr_sig_in, ptr_sig_in_offset, ptr_sig_pst0, ptr_sig_pst0_offset, L_SUBFR);
}
+ else
+ {
- /**
- * Harmonic postfilter
- *
- * @param t0 input : pitch delay given by coder
- * @param ptr_sig_in input : postfilter input filter (residu2)
- * @param ptr_sig_in_offset input : postfilter input filter offset
- * @param ptr_sig_pst0 output: harmonic postfilter output
- * @param ptr_sig_pst0_offset input: harmonic postfilter offset
- * @return voicing decision 0 = uv, > 0 delay
- */
- private int pst_ltp(
- int t0,
- float[] ptr_sig_in,
- int ptr_sig_in_offset,
- float[] ptr_sig_pst0,
- int ptr_sig_pst0_offset
- )
- {
- int vo;
-
- /* Declare variables */
- int ltpdel, phase;
- float num_gltp, den_gltp;
- float num2_gltp, den2_gltp;
- float gain_plt;
- var y_up = new float[SIZ_Y_UP];
- float[] ptr_y_up;
- int ptr_y_up_offset;
- int off_yup;
-
- /* Sub optimal delay search */
- var _ltpdel = new IntReference();
- var _phase = new IntReference();
- var _num_gltp = new FloatReference();
- var _den_gltp = new FloatReference();
- var _off_yup = new IntReference();
- search_del(
- t0,
- ptr_sig_in,
- ptr_sig_in_offset,
- _ltpdel,
- _phase,
- _num_gltp,
- _den_gltp,
- y_up,
- _off_yup);
- ltpdel = _ltpdel.value;
- phase = _phase.value;
- num_gltp = _num_gltp.value;
- den_gltp = _den_gltp.value;
- off_yup = _off_yup.value;
-
- vo = ltpdel;
-
- if (num_gltp == 0.0f)
+ if (phase == 0)
{
- Util.copy(ptr_sig_in, ptr_sig_in_offset, ptr_sig_pst0, ptr_sig_pst0_offset, L_SUBFR);
+ ptr_y_up = ptr_sig_in;
+ ptr_y_up_offset = ptr_sig_in_offset - ltpdel;
}
+
else
{
+ /* Filtering with long filter */
+ var _num2_gltp = new FloatReference();
+ var _den2_gltp = new FloatReference();
+ compute_ltp_l(
+ ptr_sig_in,
+ ptr_sig_in_offset,
+ ltpdel,
+ phase,
+ ptr_sig_pst0,
+ ptr_sig_pst0_offset,
+ _num2_gltp,
+ _den2_gltp);
+ num2_gltp = _num2_gltp.value;
+ den2_gltp = _den2_gltp.value;
- if (phase == 0)
+ if (select_ltp(num_gltp, den_gltp, num2_gltp, den2_gltp) == 1)
{
- ptr_y_up = ptr_sig_in;
- ptr_y_up_offset = ptr_sig_in_offset - ltpdel;
- }
+ /* select short filter */
+ ptr_y_up = y_up;
+ ptr_y_up_offset = (phase - 1) * L_SUBFRP1 + off_yup;
+ }
else
{
- /* Filtering with long filter */
- var _num2_gltp = new FloatReference();
- var _den2_gltp = new FloatReference();
- compute_ltp_l(
- ptr_sig_in,
- ptr_sig_in_offset,
- ltpdel,
- phase,
- ptr_sig_pst0,
- ptr_sig_pst0_offset,
- _num2_gltp,
- _den2_gltp);
- num2_gltp = _num2_gltp.value;
- den2_gltp = _den2_gltp.value;
-
- if (select_ltp(num_gltp, den_gltp, num2_gltp, den2_gltp) == 1)
- {
-
- /* select short filter */
- ptr_y_up = y_up;
- ptr_y_up_offset = (phase - 1) * L_SUBFRP1 + off_yup;
- }
- else
- {
- /* select long filter */
- num_gltp = num2_gltp;
- den_gltp = den2_gltp;
- ptr_y_up = ptr_sig_pst0;
- ptr_y_up_offset = ptr_sig_pst0_offset;
- }
+ /* select long filter */
+ num_gltp = num2_gltp;
+ den_gltp = den2_gltp;
+ ptr_y_up = ptr_sig_pst0;
+ ptr_y_up_offset = ptr_sig_pst0_offset;
}
+ }
- if (num_gltp > den_gltp)
- gain_plt = MIN_GPLT;
- else
- gain_plt = den_gltp / (den_gltp + GAMMA_G * num_gltp);
-
- /* filtering by H0(z) (harmonic filter) */
- filt_plt(
- ptr_sig_in,
- ptr_sig_in_offset,
- ptr_y_up,
- ptr_y_up_offset,
- ptr_sig_pst0,
- ptr_sig_pst0_offset,
- gain_plt);
+ if (num_gltp > den_gltp)
+ {
+ gain_plt = MIN_GPLT;
+ }
+ else
+ {
+ gain_plt = den_gltp / (den_gltp + GAMMA_G * num_gltp);
}
- return vo;
+ /* filtering by H0(z) (harmonic filter) */
+ filt_plt(
+ ptr_sig_in,
+ ptr_sig_in_offset,
+ ptr_y_up,
+ ptr_y_up_offset,
+ ptr_sig_pst0,
+ ptr_sig_pst0_offset,
+ gain_plt);
}
- /**
- * Computes best (shortest) integer LTP delay + fine search
- *
- * @param t0 input : pitch delay given by coder
- * @param ptr_sig_in input : input signal (with delay line)
- * @param ptr_sig_in_offset input : input signal offset
- * @param ltpdel output: delay = *ltpdel - *phase / f_up
- * @param phase output: phase
- * @param num_gltp output: numerator of LTP gain
- * @param den_gltp output: denominator of LTP gain
- * @param y_up
- * @param off_yup
- */
- private void search_del(
- int t0,
- float[] ptr_sig_in,
- int ptr_sig_in_offset,
- IntReference ltpdel,
- IntReference phase,
- FloatReference num_gltp,
- FloatReference den_gltp,
- float[] y_up,
- IntReference off_yup
- )
- {
- var tab_hup_s = TabLd8k.tab_hup_s;
-
- /* pointers on tables of constants */
- int ptr_h;
-
- /* Variables and local arrays */
- float[] tab_den0 = new float[F_UP_PST - 1], tab_den1 = new float[F_UP_PST - 1];
- int ptr_den0, ptr_den1;
- int ptr_sig_past, ptr_sig_past0;
- int ptr1;
-
- int i, n, ioff, i_max;
- float ener, num, numsq, den0, den1;
- float den_int, num_int;
- float den_max, num_max, numsq_max;
- int phi_max;
- int lambda, phi;
- float temp0, temp1;
- int ptr_y_up;
-
- /* Compute current signal energy */
- ener = 0.0f;
- for (i = 0; i < L_SUBFR; i++)
- ener += ptr_sig_in[ptr_sig_in_offset + i] * ptr_sig_in[ptr_sig_in_offset + i];
- if (ener < 0.1f)
- {
- num_gltp.value = 0.0f;
- den_gltp.value = 1.0f;
- ltpdel.value = 0;
- phase.value = 0;
- return;
- }
+ return vo;
+ }
- /* Selects best of 3 integer delays */
- /* Maximum of 3 numerators around t0 */
- /* coder LTP delay */
+ /**
+* Computes best (shortest) integer LTP delay + fine search
+*
+* @param t0 input : pitch delay given by coder
+* @param ptr_sig_in input : input signal (with delay line)
+* @param ptr_sig_in_offset input : input signal offset
+* @param ltpdel output: delay = *ltpdel - *phase / f_up
+* @param phase output: phase
+* @param num_gltp output: numerator of LTP gain
+* @param den_gltp output: denominator of LTP gain
+* @param y_up
+* @param off_yup
+*/
+ private void search_del(
+ int t0,
+ float[] ptr_sig_in,
+ int ptr_sig_in_offset,
+ IntReference ltpdel,
+ IntReference phase,
+ FloatReference num_gltp,
+ FloatReference den_gltp,
+ float[] y_up,
+ IntReference off_yup
+ )
+ {
+ var tab_hup_s = TabLd8k.tab_hup_s;
+
+ /* pointers on tables of constants */
+ int ptr_h;
+
+ /* Variables and local arrays */
+ float[] tab_den0 = new float[F_UP_PST - 1], tab_den1 = new float[F_UP_PST - 1];
+ int ptr_den0, ptr_den1;
+ int ptr_sig_past, ptr_sig_past0;
+ int ptr1;
+
+ int i, n, ioff, i_max;
+ float ener, num, numsq, den0, den1;
+ float den_int, num_int;
+ float den_max, num_max, numsq_max;
+ int phi_max;
+ int lambda, phi;
+ float temp0, temp1;
+ int ptr_y_up;
+
+ /* Compute current signal energy */
+ ener = 0.0f;
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ ener += ptr_sig_in[ptr_sig_in_offset + i] * ptr_sig_in[ptr_sig_in_offset + i];
+ }
- lambda = t0 - 1;
+ if (ener < 0.1f)
+ {
+ num_gltp.value = 0.0f;
+ den_gltp.value = 1.0f;
+ ltpdel.value = 0;
+ phase.value = 0;
+ return;
+ }
- ptr_sig_past = ptr_sig_in_offset - lambda;
+ /* Selects best of 3 integer delays */
+ /* Maximum of 3 numerators around t0 */
+ /* coder LTP delay */
- num_int = -1.0e30f;
+ lambda = t0 - 1;
- /* initialization used only to suppress Microsoft Visual C++ warnings */
- i_max = 0;
- for (i = 0; i < 3; i++)
- {
- num = 0.0f;
- for (n = 0; n < L_SUBFR; n++)
- num += ptr_sig_in[ptr_sig_in_offset + n] * ptr_sig_in[ptr_sig_past + n];
- if (num > num_int)
- {
- i_max = i;
- num_int = num;
- }
+ ptr_sig_past = ptr_sig_in_offset - lambda;
- ptr_sig_past--;
- }
+ num_int = -1.0e30f;
- if (num_int <= 0.0f)
+ /* initialization used only to suppress Microsoft Visual C++ warnings */
+ i_max = 0;
+ for (i = 0; i < 3; i++)
+ {
+ num = 0.0f;
+ for (n = 0; n < L_SUBFR; n++)
{
- num_gltp.value = 0.0f;
- den_gltp.value = 1.0f;
- ltpdel.value = 0;
- phase.value = 0;
- return;
+ num += ptr_sig_in[ptr_sig_in_offset + n] * ptr_sig_in[ptr_sig_past + n];
}
- /* Calculates denominator for lambda_max */
- lambda += i_max;
- ptr_sig_past = ptr_sig_in_offset - lambda;
- den_int = 0.0f;
- for (n = 0; n < L_SUBFR; n++)
- den_int += ptr_sig_in[ptr_sig_past + n] * ptr_sig_in[ptr_sig_past + n];
- if (den_int < 0.1f)
+ if (num > num_int)
{
- num_gltp.value = 0.0f;
- den_gltp.value = 1.0f;
- ltpdel.value = 0;
- phase.value = 0;
- return;
+ i_max = i;
+ num_int = num;
}
- /* Select best phase around lambda */
-
- /* Compute y_up & denominators */
- ptr_y_up = 0;
- den_max = den_int;
- ptr_den0 = 0;
- ptr_den1 = 0;
- ptr_h = 0;
- ptr_sig_past0 = ptr_sig_in_offset + LH_UP_S - 1 - lambda; /* points on lambda_max+1 */
-
- /* loop on phase */
- for (phi = 1; phi < F_UP_PST; phi++)
- {
-
- /* Computes criterion for (lambda_max+1) - phi/F_UP_PST */
- /* and lambda_max - phi/F_UP_PST */
- ptr_sig_past = ptr_sig_past0;
- /* computes y_up[n] */
- for (n = 0; n <= L_SUBFR; n++)
- {
- ptr1 = ptr_sig_past++;
- temp0 = 0.0f;
- for (i = 0; i < LH2_S; i++)
- temp0 += tab_hup_s[ptr_h + i] * ptr_sig_in[ptr1 - i];
- y_up[ptr_y_up + n] = temp0;
- }
- /* recursive computation of den0 (lambda_max+1) and den1 (lambda_max) */
+ ptr_sig_past--;
+ }
- /* common part to den0 and den1 */
- temp0 = 0.0f;
- for (n = 1; n < L_SUBFR; n++)
- temp0 += y_up[ptr_y_up + n] * y_up[ptr_y_up + n];
+ if (num_int <= 0.0f)
+ {
+ num_gltp.value = 0.0f;
+ den_gltp.value = 1.0f;
+ ltpdel.value = 0;
+ phase.value = 0;
+ return;
+ }
- /* den0 */
- den0 = temp0 + y_up[ptr_y_up + 0] * y_up[ptr_y_up + 0];
- tab_den0[ptr_den0] = den0;
- ptr_den0++;
+ /* Calculates denominator for lambda_max */
+ lambda += i_max;
+ ptr_sig_past = ptr_sig_in_offset - lambda;
+ den_int = 0.0f;
+ for (n = 0; n < L_SUBFR; n++)
+ {
+ den_int += ptr_sig_in[ptr_sig_past + n] * ptr_sig_in[ptr_sig_past + n];
+ }
- /* den1 */
- den1 = temp0 + y_up[ptr_y_up + L_SUBFR] * y_up[ptr_y_up + L_SUBFR];
- tab_den1[ptr_den1] = den1;
- ptr_den1++;
+ if (den_int < 0.1f)
+ {
+ num_gltp.value = 0.0f;
+ den_gltp.value = 1.0f;
+ ltpdel.value = 0;
+ phase.value = 0;
+ return;
+ }
+ /* Select best phase around lambda */
+
+ /* Compute y_up & denominators */
+ ptr_y_up = 0;
+ den_max = den_int;
+ ptr_den0 = 0;
+ ptr_den1 = 0;
+ ptr_h = 0;
+ ptr_sig_past0 = ptr_sig_in_offset + LH_UP_S - 1 - lambda; /* points on lambda_max+1 */
+
+ /* loop on phase */
+ for (phi = 1; phi < F_UP_PST; phi++)
+ {
- if (Math.Abs(y_up[ptr_y_up + 0]) > Math.Abs(y_up[ptr_y_up + L_SUBFR]))
- {
- if (den0 > den_max)
- den_max = den0;
- }
- else
+ /* Computes criterion for (lambda_max+1) - phi/F_UP_PST */
+ /* and lambda_max - phi/F_UP_PST */
+ ptr_sig_past = ptr_sig_past0;
+ /* computes y_up[n] */
+ for (n = 0; n <= L_SUBFR; n++)
+ {
+ ptr1 = ptr_sig_past++;
+ temp0 = 0.0f;
+ for (i = 0; i < LH2_S; i++)
{
- if (den1 > den_max)
- den_max = den1;
+ temp0 += tab_hup_s[ptr_h + i] * ptr_sig_in[ptr1 - i];
}
- ptr_y_up += L_SUBFRP1;
- ptr_h += LH2_S;
+ y_up[ptr_y_up + n] = temp0;
}
- if (den_max < 0.1f)
+ /* recursive computation of den0 (lambda_max+1) and den1 (lambda_max) */
+
+ /* common part to den0 and den1 */
+ temp0 = 0.0f;
+ for (n = 1; n < L_SUBFR; n++)
{
- num_gltp.value = 0.0f;
- den_gltp.value = 1.0f;
- ltpdel.value = 0;
- phase.value = 0;
- return;
+ temp0 += y_up[ptr_y_up + n] * y_up[ptr_y_up + n];
}
- /* Computation of the numerators */
- /* and selection of best num*num/den */
- /* for non null phases */
-
- /* Initialize with null phase */
- num_max = num_int;
- den_max = den_int;
- numsq_max = num_max * num_max;
- phi_max = 0;
- ioff = 1;
-
- ptr_den0 = 0;
- ptr_den1 = 0;
- ptr_y_up = 0;
-
- /* if den_max = 0 : will be selected and declared unvoiced */
- /* if num!=0 & den=0 : will be selected and declared unvoiced */
- /* degenerated seldom cases, switch off LT is OK */
-
- /* Loop on phase */
- for (phi = 1; phi < F_UP_PST; phi++)
- {
- /* computes num for lambda_max+1 - phi/F_UP_PST */
- num = 0.0f;
- for (n = 0; n < L_SUBFR; n++)
- num += ptr_sig_in[n] * y_up[ptr_y_up + n];
- if (num < 0.0f) num = 0.0f;
- numsq = num * num;
-
- /* selection if num/sqrt(den0) max */
- den0 = tab_den0[ptr_den0];
- ptr_den0++;
- temp0 = numsq * den_max;
- temp1 = numsq_max * den0;
- if (temp0 > temp1)
+ /* den0 */
+ den0 = temp0 + y_up[ptr_y_up + 0] * y_up[ptr_y_up + 0];
+ tab_den0[ptr_den0] = den0;
+ ptr_den0++;
+
+ /* den1 */
+ den1 = temp0 + y_up[ptr_y_up + L_SUBFR] * y_up[ptr_y_up + L_SUBFR];
+ tab_den1[ptr_den1] = den1;
+ ptr_den1++;
+
+ if (Math.Abs(y_up[ptr_y_up + 0]) > Math.Abs(y_up[ptr_y_up + L_SUBFR]))
+ {
+ if (den0 > den_max)
{
- num_max = num;
- numsq_max = numsq;
den_max = den0;
- ioff = 0;
- phi_max = phi;
}
-
- /* computes num for lambda_max - phi/F_UP_PST */
- ptr_y_up++;
- num = 0.0f;
- for (n = 0; n < L_SUBFR; n++)
- num += ptr_sig_in[n] * y_up[ptr_y_up + n];
- if (num < 0.0f) num = 0.0f;
- numsq = num * num;
-
- /* selection if num/sqrt(den1) max */
- den1 = tab_den1[ptr_den1];
- ptr_den1++;
- temp0 = numsq * den_max;
- temp1 = numsq_max * den1;
- if (temp0 > temp1)
+ }
+ else
+ {
+ if (den1 > den_max)
{
- num_max = num;
- numsq_max = numsq;
den_max = den1;
- ioff = 1;
- phi_max = phi;
}
+ }
+
+ ptr_y_up += L_SUBFRP1;
+ ptr_h += LH2_S;
+ }
+
+ if (den_max < 0.1f)
+ {
+ num_gltp.value = 0.0f;
+ den_gltp.value = 1.0f;
+ ltpdel.value = 0;
+ phase.value = 0;
+ return;
+ }
+ /* Computation of the numerators */
+ /* and selection of best num*num/den */
+ /* for non null phases */
+
+ /* Initialize with null phase */
+ num_max = num_int;
+ den_max = den_int;
+ numsq_max = num_max * num_max;
+ phi_max = 0;
+ ioff = 1;
+
+ ptr_den0 = 0;
+ ptr_den1 = 0;
+ ptr_y_up = 0;
+
+ /* if den_max = 0 : will be selected and declared unvoiced */
+ /* if num!=0 & den=0 : will be selected and declared unvoiced */
+ /* degenerated seldom cases, switch off LT is OK */
+
+ /* Loop on phase */
+ for (phi = 1; phi < F_UP_PST; phi++)
+ {
- ptr_y_up += L_SUBFR;
+ /* computes num for lambda_max+1 - phi/F_UP_PST */
+ num = 0.0f;
+ for (n = 0; n < L_SUBFR; n++)
+ {
+ num += ptr_sig_in[n] * y_up[ptr_y_up + n];
}
- /* test if normalised crit0[iopt] > THRESCRIT */
+ if (num < 0.0f)
+ {
+ num = 0.0f;
+ }
+
+ numsq = num * num;
- if (num_max == 0.0f || den_max <= 0.1f)
+ /* selection if num/sqrt(den0) max */
+ den0 = tab_den0[ptr_den0];
+ ptr_den0++;
+ temp0 = numsq * den_max;
+ temp1 = numsq_max * den0;
+ if (temp0 > temp1)
{
- num_gltp.value = 0.0f;
- den_gltp.value = 1.0f;
- ltpdel.value = 0;
- phase.value = 0;
- return;
+ num_max = num;
+ numsq_max = numsq;
+ den_max = den0;
+ ioff = 0;
+ phi_max = phi;
}
- /* comparison num * num */
- /* with ener * den x THRESCRIT */
- temp1 = den_max * ener * THRESCRIT;
- if (numsq_max >= temp1)
+ /* computes num for lambda_max - phi/F_UP_PST */
+ ptr_y_up++;
+ num = 0.0f;
+ for (n = 0; n < L_SUBFR; n++)
{
- ltpdel.value = lambda + 1 - ioff;
- off_yup.value = ioff;
- phase.value = phi_max;
- num_gltp.value = num_max;
- den_gltp.value = den_max;
+ num += ptr_sig_in[n] * y_up[ptr_y_up + n];
}
- else
+
+ if (num < 0.0f)
+ {
+ num = 0.0f;
+ }
+
+ numsq = num * num;
+
+ /* selection if num/sqrt(den1) max */
+ den1 = tab_den1[ptr_den1];
+ ptr_den1++;
+ temp0 = numsq * den_max;
+ temp1 = numsq_max * den1;
+ if (temp0 > temp1)
{
- num_gltp.value = 0.0f;
- den_gltp.value = 1.0f;
- ltpdel.value = 0;
- phase.value = 0;
+ num_max = num;
+ numsq_max = numsq;
+ den_max = den1;
+ ioff = 1;
+ phi_max = phi;
}
+
+ ptr_y_up += L_SUBFR;
}
- /**
- * Ltp postfilter
- *
- * @param s_in input : input signal with past
- * @param s_in_offset input : input signal offset
- * @param s_ltp input : filtered signal with gain 1
- * @param s_ltp_offset input : filtered signal offset
- * @param s_out output: output signal
- * @param s_out_offset input: output signal offset
- * @param gain_plt input : filter gain
- */
- private void filt_plt(
- float[] s_in,
- int s_in_offset,
- float[] s_ltp,
- int s_ltp_offset,
- float[] s_out,
- int s_out_offset,
- float gain_plt
- )
+ /* test if normalised crit0[iopt] > THRESCRIT */
+
+ if (num_max == 0.0f || den_max <= 0.1f)
{
+ num_gltp.value = 0.0f;
+ den_gltp.value = 1.0f;
+ ltpdel.value = 0;
+ phase.value = 0;
+ return;
+ }
- /* Local variables */
- int n;
- float temp;
- float gain_plt_1;
+ /* comparison num * num */
+ /* with ener * den x THRESCRIT */
+ temp1 = den_max * ener * THRESCRIT;
+ if (numsq_max >= temp1)
+ {
+ ltpdel.value = lambda + 1 - ioff;
+ off_yup.value = ioff;
+ phase.value = phi_max;
+ num_gltp.value = num_max;
+ den_gltp.value = den_max;
+ }
+ else
+ {
+ num_gltp.value = 0.0f;
+ den_gltp.value = 1.0f;
+ ltpdel.value = 0;
+ phase.value = 0;
+ }
+ }
- gain_plt_1 = 1.0f - gain_plt;
+ /**
+* Ltp postfilter
+*
+* @param s_in input : input signal with past
+* @param s_in_offset input : input signal offset
+* @param s_ltp input : filtered signal with gain 1
+* @param s_ltp_offset input : filtered signal offset
+* @param s_out output: output signal
+* @param s_out_offset input: output signal offset
+* @param gain_plt input : filter gain
+*/
+ private void filt_plt(
+ float[] s_in,
+ int s_in_offset,
+ float[] s_ltp,
+ int s_ltp_offset,
+ float[] s_out,
+ int s_out_offset,
+ float gain_plt
+ )
+ {
- for (n = 0; n < L_SUBFR; n++)
+ /* Local variables */
+ int n;
+ float temp;
+ float gain_plt_1;
+
+ gain_plt_1 = 1.0f - gain_plt;
+
+ for (n = 0; n < L_SUBFR; n++)
+ {
+ /* s_out(n) = gain_plt x s_in(n) + gain_plt_1 x s_ltp(n) */
+ temp = gain_plt * s_in[s_in_offset + n];
+ temp += gain_plt_1 * s_ltp[s_ltp_offset + n];
+ s_out[s_out_offset + n] = temp;
+ }
+ }
+
+ /**
+* Compute delayed signal,
+* num & den of gain for fractional delay
+* with long interpolation filter
+*
+* @param s_in input signal with past
+* @param s_in_offset input signal with past
+* @param ltpdel delay factor
+* @param phase phase factor
+* @param y_up delayed signal
+* @param y_up_offset delayed signal offset
+* @param num numerator of LTP gain
+* @param den denominator of LTP gain
+*/
+ private void compute_ltp_l(
+ float[] s_in,
+ int s_in_offset,
+ int ltpdel,
+ int phase,
+ float[] y_up,
+ int y_up_offset,
+ FloatReference num,
+ FloatReference den
+ )
+ {
+ var tab_hup_l = TabLd8k.tab_hup_l;
+
+ /* Pointer on table of constants */
+ int ptr_h;
+
+ /* Local variables */
+ int i;
+ int ptr2;
+ float temp;
+
+ /* Filtering with long filter */
+ ptr_h = (phase - 1) * LH2_L;
+ ptr2 = s_in_offset - ltpdel + LH_UP_L;
+
+ /* Compute y_up */
+ for (int n = y_up_offset, toIndex = y_up_offset + L_SUBFR; n < toIndex; n++)
+ {
+ temp = 0.0f;
+ for (i = 0; i < LH2_L; i++)
{
- /* s_out(n) = gain_plt x s_in(n) + gain_plt_1 x s_ltp(n) */
- temp = gain_plt * s_in[s_in_offset + n];
- temp += gain_plt_1 * s_ltp[s_ltp_offset + n];
- s_out[s_out_offset + n] = temp;
+ temp += tab_hup_l[ptr_h + i] * s_in[ptr2];
+ ptr2--;
}
+
+ y_up[n] = temp;
+ ptr2 += LH2_L_P1;
}
- /**
- * Compute delayed signal,
- * num & den of gain for fractional delay
- * with long interpolation filter
- *
- * @param s_in input signal with past
- * @param s_in_offset input signal with past
- * @param ltpdel delay factor
- * @param phase phase factor
- * @param y_up delayed signal
- * @param y_up_offset delayed signal offset
- * @param num numerator of LTP gain
- * @param den denominator of LTP gain
- */
- private void compute_ltp_l(
- float[] s_in,
- int s_in_offset,
- int ltpdel,
- int phase,
- float[] y_up,
- int y_up_offset,
- FloatReference num,
- FloatReference den
- )
- {
- var tab_hup_l = TabLd8k.tab_hup_l;
-
- /* Pointer on table of constants */
- int ptr_h;
-
- /* Local variables */
- int i;
- int ptr2;
- float temp;
-
- /* Filtering with long filter */
- ptr_h = (phase - 1) * LH2_L;
- ptr2 = s_in_offset - ltpdel + LH_UP_L;
-
- /* Compute y_up */
- for (int n = y_up_offset, toIndex = y_up_offset + L_SUBFR; n < toIndex; n++)
- {
- temp = 0.0f;
- for (i = 0; i < LH2_L; i++)
- {
- temp += tab_hup_l[ptr_h + i] * s_in[ptr2];
- ptr2--;
- }
+ var _num = 0.0f;
+ /* Compute num */
+ for (var n = 0; n < L_SUBFR; n++)
+ {
+ _num += y_up[y_up_offset + n] * s_in[s_in_offset + n];
+ }
- y_up[n] = temp;
- ptr2 += LH2_L_P1;
- }
+ if (_num < 0.0f)
+ {
+ _num = 0.0f;
+ }
- var _num = 0.0f;
- /* Compute num */
- for (var n = 0; n < L_SUBFR; n++)
- _num += y_up[y_up_offset + n] * s_in[s_in_offset + n];
- if (_num < 0.0f) _num = 0.0f;
- num.value = _num;
+ num.value = _num;
- var _den = 0.0f;
- /* Compute den */
- for (int n = y_up_offset, toIndex = y_up_offset + L_SUBFR; n < toIndex; n++)
- _den += y_up[n] * y_up[n];
- den.value = _den;
+ var _den = 0.0f;
+ /* Compute den */
+ for (int n = y_up_offset, toIndex = y_up_offset + L_SUBFR; n < toIndex; n++)
+ {
+ _den += y_up[n] * y_up[n];
}
- /**
- * Selects best of (gain1, gain2)
- * with gain1 = num1 / den1
- * and gain2 = num2 / den2
- *
- * @param num1 input : numerator of gain1
- * @param den1 input : denominator of gain1
- * @param num2 input : numerator of gain2
- * @param den2 input : denominator of gain2
- * @return 1 = 1st gain, 2 = 2nd gain
- */
- private int select_ltp(
- float num1,
- float den1,
- float num2,
- float den2
- )
- {
- if (den2 == 0.0f)
- return 1;
- if (num2 * num2 * den1 > num1 * num1 * den2)
- return 2;
+ den.value = _den;
+ }
+
+ /**
+* Selects best of (gain1, gain2)
+* with gain1 = num1 / den1
+* and gain2 = num2 / den2
+*
+* @param num1 input : numerator of gain1
+* @param den1 input : denominator of gain1
+* @param num2 input : numerator of gain2
+* @param den2 input : denominator of gain2
+* @return 1 = 1st gain, 2 = 2nd gain
+*/
+ private int select_ltp(
+ float num1,
+ float den1,
+ float num2,
+ float den2
+ )
+ {
+ if (den2 == 0.0f)
+ {
return 1;
}
- /**
- * Computes impulse response of A(gamma2) / A(gamma1).
- * controls gain : computation of energy impulse response as
- * SUMn (abs (h[n])) and computes parcor0
- *
- * @param apond2 input : coefficients of numerator
- * @param apond1 input : coefficients of denominator
- * @param sig_ltp_ptr in/out: input of 1/A(gamma1) : scaled by 1/g0
- * @param sig_ltp_ptr_offset input : input of 1/A(gamma1) ... offset
- * @return 1st parcor calcul. on composed filter
- */
- private float calc_st_filt(
- float[] apond2,
- float[] apond1,
- float[] sig_ltp_ptr,
- int sig_ltp_ptr_offset
- )
+ if (num2 * num2 * den1 > num1 * num1 * den2)
{
- var h = new float[LONG_H_ST];
- float parcor0; /* output: 1st parcor calcul. on composed filter */
- float g0, temp;
+ return 2;
+ }
- /* computes impulse response of apond1 / apond2 */
- Filter.syn_filt(apond1, 0, apond2, 0, h, 0, LONG_H_ST, mem_zero, 0, 0);
+ return 1;
+ }
- /* computes 1st parcor */
- parcor0 = calc_rc0_h(h);
+ /**
+* Computes impulse response of A(gamma2) / A(gamma1).
+* controls gain : computation of energy impulse response as
+* SUMn (abs (h[n])) and computes parcor0
+*
+* @param apond2 input : coefficients of numerator
+* @param apond1 input : coefficients of denominator
+* @param sig_ltp_ptr in/out: input of 1/A(gamma1) : scaled by 1/g0
+* @param sig_ltp_ptr_offset input : input of 1/A(gamma1) ... offset
+* @return 1st parcor calcul. on composed filter
+*/
+ private float calc_st_filt(
+ float[] apond2,
+ float[] apond1,
+ float[] sig_ltp_ptr,
+ int sig_ltp_ptr_offset
+ )
+ {
+ var h = new float[LONG_H_ST];
+ float parcor0; /* output: 1st parcor calcul. on composed filter */
+ float g0, temp;
- /* computes gain g0 */
- g0 = 0.0f;
- for (var i = 0; i < LONG_H_ST; i++)
- g0 += Math.Abs(h[i]);
+ /* computes impulse response of apond1 / apond2 */
+ Filter.syn_filt(apond1, 0, apond2, 0, h, 0, LONG_H_ST, mem_zero, 0, 0);
+
+ /* computes 1st parcor */
+ parcor0 = calc_rc0_h(h);
- /* Scale signal input of 1/A(gamma1) */
- if (g0 > 1.0f)
+ /* computes gain g0 */
+ g0 = 0.0f;
+ for (var i = 0; i < LONG_H_ST; i++)
+ {
+ g0 += Math.Abs(h[i]);
+ }
+
+ /* Scale signal input of 1/A(gamma1) */
+ if (g0 > 1.0f)
+ {
+ temp = 1.0f / g0;
+ for (int i = sig_ltp_ptr_offset, toIndex = sig_ltp_ptr_offset + L_SUBFR; i < toIndex; i++)
{
- temp = 1.0f / g0;
- for (int i = sig_ltp_ptr_offset, toIndex = sig_ltp_ptr_offset + L_SUBFR; i < toIndex; i++)
- sig_ltp_ptr[i] = sig_ltp_ptr[i] * temp;
+ sig_ltp_ptr[i] = sig_ltp_ptr[i] * temp;
}
+ }
+
+ return parcor0;
+ }
- return parcor0;
+ /**
+* Computes 1st parcor from composed filter impulse response.
+*
+* @param h input : impulse response of composed filter
+* @return 1st parcor
+*/
+ private float calc_rc0_h(
+ float[] h
+ )
+ {
+ float acf0, acf1;
+ float temp, temp2;
+ int ptrs;
+ int i;
+
+ /* computation of the autocorrelation function acf */
+ temp = 0.0f;
+ for (i = 0; i < LONG_H_ST; i++)
+ {
+ temp += h[i] * h[i];
}
- /**
- * Computes 1st parcor from composed filter impulse response.
- *
- * @param h input : impulse response of composed filter
- * @return 1st parcor
- */
- private float calc_rc0_h(
- float[] h
- )
+ acf0 = temp;
+
+ temp = 0.0f;
+ ptrs = 0;
+ for (i = 0; i < LONG_H_ST - 1; i++)
{
- float acf0, acf1;
- float temp, temp2;
- int ptrs;
- int i;
+ temp2 = h[ptrs];
+ ptrs++;
+ temp += temp2 * h[ptrs];
+ }
- /* computation of the autocorrelation function acf */
- temp = 0.0f;
- for (i = 0; i < LONG_H_ST; i++)
- temp += h[i] * h[i];
- acf0 = temp;
+ acf1 = temp;
- temp = 0.0f;
- ptrs = 0;
- for (i = 0; i < LONG_H_ST - 1; i++)
- {
- temp2 = h[ptrs];
- ptrs++;
- temp += temp2 * h[ptrs];
- }
+ /* Initialisation of the calculation */
+ if (acf0 == 0.0f)
+ {
+ return 0.0f; /* output: 1st parcor */
+ }
- acf1 = temp;
+ /* Compute 1st parcor */
+ if (acf0 < Math.Abs(acf1))
+ {
+ return 0.0f; /* output: 1st parcor */
+ }
- /* Initialisation of the calculation */
- if (acf0 == 0.0f)
- return 0.0f; /* output: 1st parcor */
+ return -acf1 / acf0; /* output: 1st parcor */
+ }
- /* Compute 1st parcor */
- if (acf0 < Math.Abs(acf1))
- return 0.0f; /* output: 1st parcor */
- return -acf1 / acf0; /* output: 1st parcor */
+ /**
+* Tilt filtering with : (1 + mu z-1) * (1/1-|mu|).
+* computes y[n] = (1/1-|mu|) (x[n]+mu*x[n-1])
+*
+* @param sig_in input : input signal (beginning at sample -1)
+* @param sig_out output: output signal
+* @param sig_out_offset input: output signal offset
+* @param parcor0 input : parcor0 (mu = parcor0 * gamma3)
+*/
+ private void filt_mu(
+ float[] sig_in,
+ float[] sig_out,
+ int sig_out_offset,
+ float parcor0
+ )
+ {
+ int n;
+ float mu, ga, temp;
+ int ptrs;
+
+ if (parcor0 > 0.0f)
+ {
+ mu = parcor0 * GAMMA3_PLUS;
+ }
+ else
+ {
+ mu = parcor0 * GAMMA3_MINUS;
}
- /**
- * Tilt filtering with : (1 + mu z-1) * (1/1-|mu|).
- * computes y[n] = (1/1-|mu|) (x[n]+mu*x[n-1])
- *
- * @param sig_in input : input signal (beginning at sample -1)
- * @param sig_out output: output signal
- * @param sig_out_offset input: output signal offset
- * @param parcor0 input : parcor0 (mu = parcor0 * gamma3)
- */
- private void filt_mu(
- float[] sig_in,
- float[] sig_out,
- int sig_out_offset,
- float parcor0
- )
- {
- int n;
- float mu, ga, temp;
- int ptrs;
-
- if (parcor0 > 0.0f)
- mu = parcor0 * GAMMA3_PLUS;
- else
- mu = parcor0 * GAMMA3_MINUS;
- ga = 1.0f / (1.0f - Math.Abs(mu));
+ ga = 1.0f / (1.0f - Math.Abs(mu));
- ptrs = 0; /* points on sig_in(-1) */
- for (n = 0; n < L_SUBFR; n++)
- {
- temp = mu * sig_in[ptrs];
- ptrs++;
- temp += sig_in[ptrs];
- sig_out[sig_out_offset + n] = ga * temp;
- }
+ ptrs = 0; /* points on sig_in(-1) */
+ for (n = 0; n < L_SUBFR; n++)
+ {
+ temp = mu * sig_in[ptrs];
+ ptrs++;
+ temp += sig_in[ptrs];
+ sig_out[sig_out_offset + n] = ga * temp;
}
+ }
- /**
- * Control of the subframe gain.
- * gain[n] = AGC_FAC * gain[n-1] + (1 - AGC_FAC) g_in/g_out
- *
- * @param sig_in input : postfilter input signal
- * @param sig_in_offset input : postfilter input signal offset
- * @param sig_out in/out: postfilter output signal
- * @param sig_out_offset input: postfilter output signal offset
- * @param gain_prec input : last value of gain for subframe
- * @return gain_prec last value of gain for subframe
- */
- private float scale_st(
- float[] sig_in,
- int sig_in_offset,
- float[] sig_out,
- int sig_out_offset,
- float gain_prec
- )
- {
- float gain_in, gain_out;
- float g0;
-
- /* compute input gain */
- gain_in = 0.0f;
- for (int i = sig_in_offset, toIndex = sig_in_offset + L_SUBFR; i < toIndex; i++)
- gain_in += Math.Abs(sig_in[i]);
- if (gain_in == 0.0f)
- {
- g0 = 0.0f;
- }
- else
- {
+ /**
+* Control of the subframe gain.
+* gain[n] = AGC_FAC * gain[n-1] + (1 - AGC_FAC) g_in/g_out
+*
+* @param sig_in input : postfilter input signal
+* @param sig_in_offset input : postfilter input signal offset
+* @param sig_out in/out: postfilter output signal
+* @param sig_out_offset input: postfilter output signal offset
+* @param gain_prec input : last value of gain for subframe
+* @return gain_prec last value of gain for subframe
+*/
+ private float scale_st(
+ float[] sig_in,
+ int sig_in_offset,
+ float[] sig_out,
+ int sig_out_offset,
+ float gain_prec
+ )
+ {
+ float gain_in, gain_out;
+ float g0;
- /* Compute output gain */
- gain_out = 0.0f;
- for (int i = sig_out_offset, toIndex = sig_out_offset + L_SUBFR; i < toIndex; i++)
- gain_out += Math.Abs(sig_out[i]);
- if (gain_out == 0.0f)
- {
- gain_prec = 0.0f;
- return gain_prec;
- }
+ /* compute input gain */
+ gain_in = 0.0f;
+ for (int i = sig_in_offset, toIndex = sig_in_offset + L_SUBFR; i < toIndex; i++)
+ {
+ gain_in += Math.Abs(sig_in[i]);
+ }
- g0 = gain_in / gain_out;
- g0 *= AGC_FAC1;
- }
+ if (gain_in == 0.0f)
+ {
+ g0 = 0.0f;
+ }
+ else
+ {
- /* compute gain(n) = AGC_FAC gain(n-1) + (1-AGC_FAC)gain_in/gain_out */
- /* sig_out(n) = gain(n) sig_out(n) */
+ /* Compute output gain */
+ gain_out = 0.0f;
for (int i = sig_out_offset, toIndex = sig_out_offset + L_SUBFR; i < toIndex; i++)
{
- gain_prec *= AGC_FAC;
- gain_prec += g0;
- sig_out[i] *= gain_prec;
+ gain_out += Math.Abs(sig_out[i]);
}
- return gain_prec;
+ if (gain_out == 0.0f)
+ {
+ gain_prec = 0.0f;
+ return gain_prec;
+ }
+
+ g0 = gain_in / gain_out;
+ g0 *= AGC_FAC1;
}
+
+ /* compute gain(n) = AGC_FAC gain(n-1) + (1-AGC_FAC)gain_in/gain_out */
+ /* sig_out(n) = gain(n) sig_out(n) */
+ for (int i = sig_out_offset, toIndex = sig_out_offset + L_SUBFR; i < toIndex; i++)
+ {
+ gain_prec *= AGC_FAC;
+ gain_prec += g0;
+ sig_out[i] *= gain_prec;
+ }
+
+ return gain_prec;
}
}
diff --git a/src/SIPSorcery/app/Media/Codecs/G729Codec/PreProc.cs b/src/SIPSorcery/app/Media/Codecs/G729Codec/PreProc.cs
index 3e4bb80fb..d1b1fb510 100644
--- a/src/SIPSorcery/app/Media/Codecs/G729Codec/PreProc.cs
+++ b/src/SIPSorcery/app/Media/Codecs/G729Codec/PreProc.cs
@@ -1,4 +1,5 @@
-/*
+using System;
+/*
* Copyright @ 2015 Atlassian Pty Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -37,87 +38,84 @@
*
* @author Lubomir Marinov (translation of ITU-T C source code to Java)
*/
-namespace SIPSorcery.Media.G729Codec
+namespace SIPSorcery.Media.G729Codec;
+
+internal sealed class PreProc
{
- internal class PreProc
- {
- /* ITU-T G.729 Software Package Release 2 (November 2006) */
- /*
- ITU-T G.729 Annex C - Reference C code for floating point
- implementation of G.729
- Version 1.01 of 15.September.98
+ /* ITU-T G.729 Software Package Release 2 (November 2006) */
+ /*
+ITU-T G.729 Annex C - Reference C code for floating point
+ implementation of G.729
+ Version 1.01 of 15.September.98
*/
- /*
+ /*
----------------------------------------------------------------------
- COPYRIGHT NOTICE
+ COPYRIGHT NOTICE
----------------------------------------------------------------------
- ITU-T G.729 Annex C ANSI C source code
- Copyright (C) 1998, AT&T, France Telecom, NTT, University of
- Sherbrooke. All rights reserved.
+ITU-T G.729 Annex C ANSI C source code
+Copyright (C) 1998, AT&T, France Telecom, NTT, University of
+Sherbrooke. All rights reserved.
----------------------------------------------------------------------
*/
- /*
- File : PRE_PROC.C
- Used for the floating point version of both
- G.729 main body and G.729A
+ /*
+File : PRE_PROC.C
+Used for the floating point version of both
+G.729 main body and G.729A
*/
- /**
- * High-pass fir memory
- */
- private float x0, x1;
-
- /**
- * High-pass iir memory
- */
- private float y1, y2;
+ /**
+* High-pass fir memory
+*/
+ private float x0, x1;
- /**
- * Init Pre Process
- */
+ /**
+* High-pass iir memory
+*/
+ private float y1, y2;
- public void init_pre_process()
- {
- x0 = x1 = 0.0f;
- y2 = y1 = 0.0f;
- }
+ /**
+* Init Pre Process
+*/
- /**
- * Pre Process
- *
- * @param signal (i/o) : signal
- * @param signal_offset (input) : signal offset
- * @param lg (i) : length of signal
- */
+ public void init_pre_process()
+ {
+ x0 = x1 = 0.0f;
+ y2 = y1 = 0.0f;
+ }
- public void pre_process(
- float[] signal,
- int signal_offset,
- int lg
- )
- {
- var a140 = TabLd8k.a140;
- var b140 = TabLd8k.b140;
+ ///
+ /// Pre Process
+ ///
+ /// Signal buffer to process (in-place).
+ /// Offset in the signal buffer.
+ /// Number of samples to process.
+ public void pre_process(
+ Span signal,
+ int signalOffset,
+ int length
+ )
+ {
+ var a140 = TabLd8k.a140;
+ var b140 = TabLd8k.b140;
- float x2;
- float y0;
+ float x2;
+ float y0;
- for (int i = signal_offset, toIndex = lg + signal_offset; i < toIndex; i++)
- {
- x2 = x1;
- x1 = x0;
- x0 = signal[i];
+ for (int i = signalOffset, toIndex = length + signalOffset; i < toIndex; i++)
+ {
+ x2 = x1;
+ x1 = x0;
+ x0 = signal[i];
- y0 = y1 * a140[1] + y2 * a140[2] + x0 * b140[0] + x1 * b140[1] + x2 * b140[2];
+ y0 = y1 * a140[1] + y2 * a140[2] + x0 * b140[0] + x1 * b140[1] + x2 * b140[2];
- signal[i] = y0;
- y2 = y1;
- y1 = y0;
- }
+ signal[i] = y0;
+ y2 = y1;
+ y1 = y0;
}
}
-}
\ No newline at end of file
+}
diff --git a/src/SIPSorcery/app/Media/Codecs/G729Codec/PredLt3.cs b/src/SIPSorcery/app/Media/Codecs/G729Codec/PredLt3.cs
index 74530fe62..1fc14d3ce 100644
--- a/src/SIPSorcery/app/Media/Codecs/G729Codec/PredLt3.cs
+++ b/src/SIPSorcery/app/Media/Codecs/G729Codec/PredLt3.cs
@@ -22,88 +22,89 @@
/**
* @author Lubomir Marinov (translation of ITU-T C source code to Java)
*/
-namespace SIPSorcery.Media.G729Codec
+namespace SIPSorcery.Media.G729Codec;
+
+internal static class PredLt3
{
- internal class PredLt3
- {
- /* ITU-T G.729 Software Package Release 2 (November 2006) */
- /*
- ITU-T G.729 Annex C - Reference C code for floating point
- implementation of G.729
- Version 1.01 of 15.September.98
+ /* ITU-T G.729 Software Package Release 2 (November 2006) */
+ /*
+ITU-T G.729 Annex C - Reference C code for floating point
+ implementation of G.729
+ Version 1.01 of 15.September.98
*/
- /*
+ /*
----------------------------------------------------------------------
- COPYRIGHT NOTICE
+ COPYRIGHT NOTICE
----------------------------------------------------------------------
- ITU-T G.729 Annex C ANSI C source code
- Copyright (C) 1998, AT&T, France Telecom, NTT, University of
- Sherbrooke. All rights reserved.
+ITU-T G.729 Annex C ANSI C source code
+Copyright (C) 1998, AT&T, France Telecom, NTT, University of
+Sherbrooke. All rights reserved.
----------------------------------------------------------------------
*/
- /*
- File : PRED_LT3.C
- Used for the floating point version of both
- G.729 main body and G.729A
+ /*
+File : PRED_LT3.C
+Used for the floating point version of both
+G.729 main body and G.729A
*/
- /**
- * Compute the result of long term prediction with fractional
- * interpolation of resolution 1/3.
- *
- * On return exc[0..L_subfr-1] contains the interpolated signal
- * (adaptive codebook excitation)
- *
- * @param exc in/out: excitation vector, exc[0:l_sub-1] = out
- * @param exc_offset input: excitation vector offset
- * @param t0 input : pitch lag
- * @param frac input : Fraction of pitch lag (-1, 0, 1) / 3
- * @param l_subfr input : length of subframe.
- */
+ /**
+* Compute the result of long term prediction with fractional
+* interpolation of resolution 1/3.
+*
+* On return exc[0..L_subfr-1] contains the interpolated signal
+* (adaptive codebook excitation)
+*
+* @param exc in/out: excitation vector, exc[0:l_sub-1] = out
+* @param exc_offset input: excitation vector offset
+* @param t0 input : pitch lag
+* @param frac input : Fraction of pitch lag (-1, 0, 1) / 3
+* @param l_subfr input : length of subframe.
+*/
- public static void pred_lt_3(
- float[] exc,
- int exc_offset,
- int t0,
- int frac,
- int l_subfr
- )
- {
- var L_INTER10 = Ld8k.L_INTER10;
- var UP_SAMP = Ld8k.UP_SAMP;
- var inter_3l = TabLd8k.inter_3l;
+ public static void pred_lt_3(
+ float[] exc,
+ int exc_offset,
+ int t0,
+ int frac,
+ int l_subfr
+ )
+ {
+ var L_INTER10 = Ld8k.L_INTER10;
+ var UP_SAMP = Ld8k.UP_SAMP;
+ var inter_3l = TabLd8k.inter_3l;
- int i, j, k;
- float s;
- int x0, x1, x2, c1, c2;
+ int i, j, k;
+ float s;
+ int x0, x1, x2, c1, c2;
- x0 = exc_offset - t0;
+ x0 = exc_offset - t0;
- frac = -frac;
- if (frac < 0)
- {
- frac += UP_SAMP;
- x0--;
- }
-
- for (j = 0; j < l_subfr; j++)
- {
- x1 = x0;
- x0++;
- x2 = x0;
- c1 = frac;
- c2 = UP_SAMP - frac;
+ frac = -frac;
+ if (frac < 0)
+ {
+ frac += UP_SAMP;
+ x0--;
+ }
- s = 0.0f;
- for (i = 0, k = 0; i < L_INTER10; i++, k += UP_SAMP)
- s += exc[x1 - i] * inter_3l[c1 + k] + exc[x2 + i] * inter_3l[c2 + k];
+ for (j = 0; j < l_subfr; j++)
+ {
+ x1 = x0;
+ x0++;
+ x2 = x0;
+ c1 = frac;
+ c2 = UP_SAMP - frac;
- exc[exc_offset + j] = s;
+ s = 0.0f;
+ for (i = 0, k = 0; i < L_INTER10; i++, k += UP_SAMP)
+ {
+ s += exc[x1 - i] * inter_3l[c1 + k] + exc[x2 + i] * inter_3l[c2 + k];
}
+
+ exc[exc_offset + j] = s;
}
}
-}
\ No newline at end of file
+}
diff --git a/src/SIPSorcery/app/Media/Codecs/G729Codec/Pwf.cs b/src/SIPSorcery/app/Media/Codecs/G729Codec/Pwf.cs
index 6fee4a228..49d4e6df9 100644
--- a/src/SIPSorcery/app/Media/Codecs/G729Codec/Pwf.cs
+++ b/src/SIPSorcery/app/Media/Codecs/G729Codec/Pwf.cs
@@ -24,147 +24,170 @@
*/
using System;
-namespace SIPSorcery.Media.G729Codec
+namespace SIPSorcery.Media.G729Codec;
+
+internal sealed class Pwf
{
- internal class Pwf
+ private readonly float[ /* 2 */] lar_old =
{
- private readonly float[ /* 2 */] lar_old =
- {
- 0.0f,
- 0.0f
- };
-
- /* ITU-T G.729 Software Package Release 2 (November 2006) */
- /*
- ITU-T G.729 Annex C - Reference C code for floating point
- implementation of G.729
- Version 1.01 of 15.September.98
+ 0.0f,
+ 0.0f
+ };
+
+ /* ITU-T G.729 Software Package Release 2 (November 2006) */
+ /*
+ITU-T G.729 Annex C - Reference C code for floating point
+ implementation of G.729
+ Version 1.01 of 15.September.98
*/
- /*
+ /*
----------------------------------------------------------------------
- COPYRIGHT NOTICE
+ COPYRIGHT NOTICE
----------------------------------------------------------------------
- ITU-T G.729 Annex C ANSI C source code
- Copyright (C) 1998, AT&T, France Telecom, NTT, University of
- Sherbrooke. All rights reserved.
+ITU-T G.729 Annex C ANSI C source code
+Copyright (C) 1998, AT&T, France Telecom, NTT, University of
+Sherbrooke. All rights reserved.
----------------------------------------------------------------------
*/
- /*
- File : PWF.C
- Used for the floating point version of G.729 main body
- (not for G.729A)
+ /*
+File : PWF.C
+Used for the floating point version of G.729 main body
+(not for G.729A)
*/
- private int smooth = 1;
+ private int smooth = 1;
- /**
- * Adaptive bandwidth expansion for perceptual weighting filter
- *
- * @param gamma1 output: gamma1 value
- * @param gamma2 output: gamma2 value
- * @param lsfint input : Interpolated lsf vector : 1st subframe
- * @param lsfnew input : lsf vector : 2nd subframe
- * @param r_c input : Reflection coefficients
- */
+ /**
+* Adaptive bandwidth expansion for perceptual weighting filter
+*
+* @param gamma1 output: gamma1 value
+* @param gamma2 output: gamma2 value
+* @param lsfint input : Interpolated lsf vector : 1st subframe
+* @param lsfnew input : lsf vector : 2nd subframe
+* @param r_c input : Reflection coefficients
+*/
+
+ public void perc_var(
+ float[] gamma1,
+ float[] gamma2,
+ float[] lsfint,
+ float[] lsfnew,
+ float[] r_c
+ )
+ {
+ var ALPHA = Ld8k.ALPHA;
+ var BETA = Ld8k.BETA;
+ var GAMMA1_0 = Ld8k.GAMMA1_0;
+ var GAMMA1_1 = Ld8k.GAMMA1_1;
+ var GAMMA2_0_H = Ld8k.GAMMA2_0_H;
+ var GAMMA2_0_L = Ld8k.GAMMA2_0_L;
+ var GAMMA2_1 = Ld8k.GAMMA2_1;
+ var M = Ld8k.M;
+ var THRESH_H1 = Ld8k.THRESH_H1;
+ var THRESH_H2 = Ld8k.THRESH_H2;
+ var THRESH_L1 = Ld8k.THRESH_L1;
+ var THRESH_L2 = Ld8k.THRESH_L2;
+
+ var lar = new float[4];
+ float[] lsf;
+ float critlar0, critlar1;
+ float d_min, temp;
+ int i, k;
+
+ var lar_new = lar;
+ var lar_new_offset = 2;
+
+ /* reflection coefficients --> lar */
+ for (i = 0; i < 2; i++)
+ {
+ lar_new[lar_new_offset + i] = (float)Math.Log10((1.0f + r_c[i]) / (1.0f - r_c[i]));
+ }
+
+ /* Interpolation of lar for the 1st subframe */
+ for (i = 0; i < 2; i++)
+ {
+ lar[i] = 0.5f * (lar_new[lar_new_offset + i] + lar_old[i]);
+ lar_old[i] = lar_new[lar_new_offset + i];
+ }
- public void perc_var(
- float[] gamma1,
- float[] gamma2,
- float[] lsfint,
- float[] lsfnew,
- float[] r_c
- )
+ for (k = 0; k < 2; k++)
{
- var ALPHA = Ld8k.ALPHA;
- var BETA = Ld8k.BETA;
- var GAMMA1_0 = Ld8k.GAMMA1_0;
- var GAMMA1_1 = Ld8k.GAMMA1_1;
- var GAMMA2_0_H = Ld8k.GAMMA2_0_H;
- var GAMMA2_0_L = Ld8k.GAMMA2_0_L;
- var GAMMA2_1 = Ld8k.GAMMA2_1;
- var M = Ld8k.M;
- var THRESH_H1 = Ld8k.THRESH_H1;
- var THRESH_H2 = Ld8k.THRESH_H2;
- var THRESH_L1 = Ld8k.THRESH_L1;
- var THRESH_L2 = Ld8k.THRESH_L2;
-
- var lar = new float[4];
- float[] lsf;
- float critlar0, critlar1;
- float d_min, temp;
- int i, k;
-
- var lar_new = lar;
- var lar_new_offset = 2;
-
- /* reflection coefficients --> lar */
- for (i = 0; i < 2; i++)
- lar_new[lar_new_offset + i] = (float)Math.Log10((1.0f + r_c[i]) / (1.0f - r_c[i]));
-
- /* Interpolation of lar for the 1st subframe */
- for (i = 0; i < 2; i++)
+ /* LOOP : gamma2 for 1st to 2nd subframes */
+
+ /* ----------------------------------------------------- */
+ /* First criterion based on the first two lars */
+ /* */
+ /* smooth == 1 ==> gamma2 is set to 0.6 */
+ /* gamma1 is set to 0.94 */
+ /* */
+ /* smooth == 0 ==> gamma2 can vary from 0.4 to 0.7 */
+ /* (gamma2 = -6.0 dmin + 1.0) */
+ /* gamma1 is set to 0.98 */
+ /* ----------------------------------------------------- */
+ critlar0 = lar[2 * k];
+ critlar1 = lar[2 * k + 1];
+
+ if (smooth != 0)
{
- lar[i] = 0.5f * (lar_new[lar_new_offset + i] + lar_old[i]);
- lar_old[i] = lar_new[lar_new_offset + i];
+ if (critlar0 < THRESH_L1 && critlar1 > THRESH_H1)
+ {
+ smooth = 0;
+ }
+ }
+ else
+ {
+ if (critlar0 > THRESH_L2 || critlar1 < THRESH_H2)
+ {
+ smooth = 1;
+ }
}
- for (k = 0; k < 2; k++)
+ if (smooth == 0)
{
- /* LOOP : gamma2 for 1st to 2nd subframes */
-
- /* ----------------------------------------------------- */
- /* First criterion based on the first two lars */
- /* */
- /* smooth == 1 ==> gamma2 is set to 0.6 */
- /* gamma1 is set to 0.94 */
- /* */
- /* smooth == 0 ==> gamma2 can vary from 0.4 to 0.7 */
- /* (gamma2 = -6.0 dmin + 1.0) */
- /* gamma1 is set to 0.98 */
- /* ----------------------------------------------------- */
- critlar0 = lar[2 * k];
- critlar1 = lar[2 * k + 1];
-
- if (smooth != 0)
+ /* ------------------------------------------------------ */
+ /* Second criterion based on the minimum distance between */
+ /* two successives lsfs */
+ /* ------------------------------------------------------ */
+ gamma1[k] = GAMMA1_0;
+ if (k == 0)
{
- if (critlar0 < THRESH_L1 && critlar1 > THRESH_H1) smooth = 0;
+ lsf = lsfint;
}
else
{
- if (critlar0 > THRESH_L2 || critlar1 < THRESH_H2) smooth = 1;
+ lsf = lsfnew;
}
- if (smooth == 0)
+ d_min = lsf[1] - lsf[0];
+ for (i = 1; i < M - 1; i++)
{
- /* ------------------------------------------------------ */
- /* Second criterion based on the minimum distance between */
- /* two successives lsfs */
- /* ------------------------------------------------------ */
- gamma1[k] = GAMMA1_0;
- if (k == 0) lsf = lsfint;
- else lsf = lsfnew;
- d_min = lsf[1] - lsf[0];
- for (i = 1; i < M - 1; i++)
+ temp = lsf[i + 1] - lsf[i];
+ if (temp < d_min)
{
- temp = lsf[i + 1] - lsf[i];
- if (temp < d_min) d_min = temp;
+ d_min = temp;
}
+ }
- gamma2[k] = ALPHA * d_min + BETA;
+ gamma2[k] = ALPHA * d_min + BETA;
- if (gamma2[k] > GAMMA2_0_H) gamma2[k] = GAMMA2_0_H;
- if (gamma2[k] < GAMMA2_0_L) gamma2[k] = GAMMA2_0_L;
+ if (gamma2[k] > GAMMA2_0_H)
+ {
+ gamma2[k] = GAMMA2_0_H;
}
- else
+
+ if (gamma2[k] < GAMMA2_0_L)
{
- gamma1[k] = GAMMA1_1;
- gamma2[k] = GAMMA2_1;
- ;
+ gamma2[k] = GAMMA2_0_L;
}
}
+ else
+ {
+ gamma1[k] = GAMMA1_1;
+ gamma2[k] = GAMMA2_1;
+ }
}
}
-}
\ No newline at end of file
+}
diff --git a/src/SIPSorcery/app/Media/Codecs/G729Codec/QuaGain.cs b/src/SIPSorcery/app/Media/Codecs/G729Codec/QuaGain.cs
index a0d0c9f53..ce3984484 100644
--- a/src/SIPSorcery/app/Media/Codecs/G729Codec/QuaGain.cs
+++ b/src/SIPSorcery/app/Media/Codecs/G729Codec/QuaGain.cs
@@ -22,148 +22,135 @@
/**
* @author Lubomir Marinov (translation of ITU-T C source code to Java)
*/
-namespace SIPSorcery.Media.G729Codec
+namespace SIPSorcery.Media.G729Codec;
+
+internal sealed class QuaGain
{
- internal class QuaGain
- {
- /* ITU-T G.729 Software Package Release 2 (November 2006) */
- /*
- ITU-T G.729 Annex C - Reference C code for floating point
- implementation of G.729
- Version 1.01 of 15.September.98
+ /* ITU-T G.729 Software Package Release 2 (November 2006) */
+ /*
+ITU-T G.729 Annex C - Reference C code for floating point
+ implementation of G.729
+ Version 1.01 of 15.September.98
*/
- /*
+ /*
----------------------------------------------------------------------
- COPYRIGHT NOTICE
+ COPYRIGHT NOTICE
----------------------------------------------------------------------
- ITU-T G.729 Annex C ANSI C source code
- Copyright (C) 1998, AT&T, France Telecom, NTT, University of
- Sherbrooke. All rights reserved.
+ITU-T G.729 Annex C ANSI C source code
+Copyright (C) 1998, AT&T, France Telecom, NTT, University of
+Sherbrooke. All rights reserved.
----------------------------------------------------------------------
*/
- /*
- File : QUA_GAIN.C
- Used for the floating point version of both
- G.729 main body and G.729A
+ /*
+File : QUA_GAIN.C
+Used for the floating point version of both
+G.729 main body and G.729A
*/
- /* gain quantizer routines */
+ /* gain quantizer routines */
- private readonly float[ /* 4 */] past_qua_en =
- {
- -14.0f,
- -14.0f,
- -14.0f,
- -14.0f
- };
+ private readonly float[ /* 4 */] past_qua_en =
+ {
+ -14.0f,
+ -14.0f,
+ -14.0f,
+ -14.0f
+ };
- /**
- * Quantization of pitch and codebook gains
- *
- * @param code input : fixed codebook vector
- * @param g_coeff input : correlation factors
- * @param l_subfr input : fcb vector length
- * @param gain_pit output: quantized acb gain
- * @param gain_code output: quantized fcb gain
- * @param tameflag input : flag set to 1 if taming is needed
- * @return quantizer index
- */
+ /**
+* Quantization of pitch and codebook gains
+*
+* @param code input : fixed codebook vector
+* @param g_coeff input : correlation factors
+* @param l_subfr input : fcb vector length
+* @param gain_pit output: quantized acb gain
+* @param gain_code output: quantized fcb gain
+* @param tameflag input : flag set to 1 if taming is needed
+* @return quantizer index
+*/
- public int qua_gain(
- float[] code,
- float[] g_coeff,
- int l_subfr,
- FloatReference gain_pit,
- FloatReference gain_code,
- int tameflag
- )
- {
- var FLT_MAX_G729 = Ld8k.FLT_MAX_G729;
- var GP0999 = Ld8k.GP0999;
- var GPCLIP2 = Ld8k.GPCLIP2;
- var NCAN1 = Ld8k.NCAN1;
- var NCAN2 = Ld8k.NCAN2;
- var NCODE2 = Ld8k.NCODE2;
- var gbk1 = TabLd8k.gbk1;
- var gbk2 = TabLd8k.gbk2;
- var map1 = TabLd8k.map1;
- var map2 = TabLd8k.map2;
+ public int qua_gain(
+ float[] code,
+ float[] g_coeff,
+ int l_subfr,
+ FloatReference gain_pit,
+ FloatReference gain_code,
+ int tameflag
+ )
+ {
+ var FLT_MAX_G729 = Ld8k.FLT_MAX_G729;
+ var GP0999 = Ld8k.GP0999;
+ var GPCLIP2 = Ld8k.GPCLIP2;
+ var NCAN1 = Ld8k.NCAN1;
+ var NCAN2 = Ld8k.NCAN2;
+ var NCODE2 = Ld8k.NCODE2;
+ var gbk1 = TabLd8k.gbk1;
+ var gbk2 = TabLd8k.gbk2;
+ var map1 = TabLd8k.map1;
+ var map2 = TabLd8k.map2;
- /*
- * MA prediction is performed on the innovation energy (in dB with mean *
- * removed). *
- * An initial predicted gain, g_0, is first determined and the correction *
- * factor alpha = gain / g_0 is quantized. *
- * The pitch gain and the correction factor are vector quantized and the *
- * mean-squared weighted error criterion is used in the quantizer search. *
- * CS Codebook , fast pre-selection version *
- */
+ /*
+* MA prediction is performed on the innovation energy (in dB with mean *
+* removed). *
+* An initial predicted gain, g_0, is first determined and the correction *
+* factor alpha = gain / g_0 is quantized. *
+* The pitch gain and the correction factor are vector quantized and the *
+* mean-squared weighted error criterion is used in the quantizer search. *
+* CS Codebook , fast pre-selection version *
+*/
- int i, j, index1 = 0, index2 = 0;
- int cand1, cand2;
- float gcode0;
- float dist, dist_min, g_pitch, g_code;
- var best_gain = new float[2];
- float tmp;
+ int i, j, index1 = 0, index2 = 0;
+ int cand1, cand2;
+ float gcode0;
+ float dist, dist_min, g_pitch, g_code;
+ var best_gain = new float[2];
+ float tmp;
- /*---------------------------------------------------*
- *- energy due to innovation -*
- *- predicted energy -*
- *- predicted codebook gain => gcode0[exp_gcode0] -*
- *---------------------------------------------------*/
+ /*---------------------------------------------------*
+*- energy due to innovation -*
+*- predicted energy -*
+*- predicted codebook gain => gcode0[exp_gcode0] -*
+*---------------------------------------------------*/
- gcode0 = Gainpred.gain_predict(past_qua_en, code, l_subfr);
+ gcode0 = Gainpred.gain_predict(past_qua_en, code, l_subfr);
- /*-- pre-selection --*/
- tmp = -1.0f / (4.0f * g_coeff[0] * g_coeff[2] - g_coeff[4] * g_coeff[4]);
- best_gain[0] = (2.0f * g_coeff[2] * g_coeff[1] - g_coeff[3] * g_coeff[4]) * tmp;
- best_gain[1] = (2.0f * g_coeff[0] * g_coeff[3] - g_coeff[1] * g_coeff[4]) * tmp;
+ /*-- pre-selection --*/
+ tmp = -1.0f / (4.0f * g_coeff[0] * g_coeff[2] - g_coeff[4] * g_coeff[4]);
+ best_gain[0] = (2.0f * g_coeff[2] * g_coeff[1] - g_coeff[3] * g_coeff[4]) * tmp;
+ best_gain[1] = (2.0f * g_coeff[0] * g_coeff[3] - g_coeff[1] * g_coeff[4]) * tmp;
- if (tameflag == 1)
- if (best_gain[0] > GPCLIP2)
- best_gain[0] = GPCLIP2;
- /*----------------------------------------------*
- * - presearch for gain codebook - *
- *----------------------------------------------*/
+ if (tameflag == 1)
+ {
+ if (best_gain[0] > GPCLIP2)
+ {
+ best_gain[0] = GPCLIP2;
+ }
+ }
+ /*----------------------------------------------*
+* - presearch for gain codebook - *
+*----------------------------------------------*/
- var cand1Ref = new IntReference();
- var cand2Ref = new IntReference();
- gbk_presel(best_gain, cand1Ref, cand2Ref, gcode0);
- cand1 = cand1Ref.value;
- cand2 = cand2Ref.value;
+ var cand1Ref = new IntReference();
+ var cand2Ref = new IntReference();
+ gbk_presel(best_gain, cand1Ref, cand2Ref, gcode0);
+ cand1 = cand1Ref.value;
+ cand2 = cand2Ref.value;
- /*-- selection --*/
- dist_min = FLT_MAX_G729;
- if (tameflag == 1)
- for (i = 0; i < NCAN1; i++)
- for (j = 0; j < NCAN2; j++)
- {
- g_pitch = gbk1[cand1 + i][0] + gbk2[cand2 + j][0];
- if (g_pitch < GP0999)
- {
- g_code = gcode0 * (gbk1[cand1 + i][1] + gbk2[cand2 + j][1]);
- dist = g_pitch * g_pitch * g_coeff[0]
- + g_pitch * g_coeff[1]
- + g_code * g_code * g_coeff[2]
- + g_code * g_coeff[3]
- + g_pitch * g_code * g_coeff[4];
- if (dist < dist_min)
- {
- dist_min = dist;
- index1 = cand1 + i;
- index2 = cand2 + j;
- }
- }
- }
- else
- for (i = 0; i < NCAN1; i++)
+ /*-- selection --*/
+ dist_min = FLT_MAX_G729;
+ if (tameflag == 1)
+ {
+ for (i = 0; i < NCAN1; i++)
+ {
for (j = 0; j < NCAN2; j++)
+ {
+ g_pitch = gbk1[cand1 + i][0] + gbk2[cand2 + j][0];
+ if (g_pitch < GP0999)
{
- g_pitch = gbk1[cand1 + i][0] + gbk2[cand2 + j][0];
g_code = gcode0 * (gbk1[cand1 + i][1] + gbk2[cand2 + j][1]);
dist = g_pitch * g_pitch * g_coeff[0]
+ g_pitch * g_coeff[1]
@@ -177,94 +164,142 @@ int tameflag
index2 = cand2 + j;
}
}
+ }
+ }
+ }
+ else
+ {
+ for (i = 0; i < NCAN1; i++)
+ {
+ for (j = 0; j < NCAN2; j++)
+ {
+ g_pitch = gbk1[cand1 + i][0] + gbk2[cand2 + j][0];
+ g_code = gcode0 * (gbk1[cand1 + i][1] + gbk2[cand2 + j][1]);
+ dist = g_pitch * g_pitch * g_coeff[0]
+ + g_pitch * g_coeff[1]
+ + g_code * g_code * g_coeff[2]
+ + g_code * g_coeff[3]
+ + g_pitch * g_code * g_coeff[4];
+ if (dist < dist_min)
+ {
+ dist_min = dist;
+ index1 = cand1 + i;
+ index2 = cand2 + j;
+ }
+ }
+ }
+ }
- gain_pit.value = gbk1[index1][0] + gbk2[index2][0];
- g_code = gbk1[index1][1] + gbk2[index2][1];
- gain_code.value = g_code * gcode0;
- /*----------------------------------------------*
- * update table of past quantized energies *
- *----------------------------------------------*/
- Gainpred.gain_update(past_qua_en, g_code);
+ gain_pit.value = gbk1[index1][0] + gbk2[index2][0];
+ g_code = gbk1[index1][1] + gbk2[index2][1];
+ gain_code.value = g_code * gcode0;
+ /*----------------------------------------------*
+* update table of past quantized energies *
+*----------------------------------------------*/
+ Gainpred.gain_update(past_qua_en, g_code);
- return map1[index1] * NCODE2 + map2[index2];
- }
+ return map1[index1] * NCODE2 + map2[index2];
+ }
- /**
- * Presearch for gain codebook
- *
- * @param best_gain input : [0] unquantized pitch gain
- * [1] unquantized code gain
- * @param cand1 output: index of best 1st stage vector
- * @param cand2 output: index of best 2nd stage vector
- * @param gcode0 input : presearch for gain codebook
- */
- private void gbk_presel(
- float[] best_gain,
- IntReference cand1,
- IntReference cand2,
- float gcode0
- )
- {
- var INV_COEF = Ld8k.INV_COEF;
- var NCAN1 = Ld8k.NCAN1;
- var NCAN2 = Ld8k.NCAN2;
- var NCODE1 = Ld8k.NCODE1;
- var NCODE2 = Ld8k.NCODE2;
- var coef = TabLd8k.coef;
- var thr1 = TabLd8k.thr1;
- var thr2 = TabLd8k.thr2;
+ /**
+* Presearch for gain codebook
+*
+* @param best_gain input : [0] unquantized pitch gain
+* [1] unquantized code gain
+* @param cand1 output: index of best 1st stage vector
+* @param cand2 output: index of best 2nd stage vector
+* @param gcode0 input : presearch for gain codebook
+*/
+ private void gbk_presel(
+ float[] best_gain,
+ IntReference cand1,
+ IntReference cand2,
+ float gcode0
+ )
+ {
+ var INV_COEF = Ld8k.INV_COEF;
+ var NCAN1 = Ld8k.NCAN1;
+ var NCAN2 = Ld8k.NCAN2;
+ var NCODE1 = Ld8k.NCODE1;
+ var NCODE2 = Ld8k.NCODE2;
+ var coef = TabLd8k.coef;
+ var thr1 = TabLd8k.thr1;
+ var thr2 = TabLd8k.thr2;
- int _cand1 = cand1.value, _cand2 = cand2.value;
+ int _cand1 = cand1.value, _cand2 = cand2.value;
- float x, y;
+ float x, y;
- x = (best_gain[1] - (coef[0][0] * best_gain[0] + coef[1][1]) * gcode0) * INV_COEF;
- y = (coef[1][0] * (-coef[0][1] + best_gain[0] * coef[0][0]) * gcode0
- - coef[0][0] * best_gain[1]) * INV_COEF;
+ x = (best_gain[1] - (coef[0][0] * best_gain[0] + coef[1][1]) * gcode0) * INV_COEF;
+ y = (coef[1][0] * (-coef[0][1] + best_gain[0] * coef[0][0]) * gcode0
+ - coef[0][0] * best_gain[1]) * INV_COEF;
- if (gcode0 > 0.0f)
+ if (gcode0 > 0.0f)
+ {
+ /* pre select codebook #1 */
+ _cand1 = 0;
+ do
{
- /* pre select codebook #1 */
- _cand1 = 0;
- do
+ if (y > thr1[_cand1] * gcode0)
{
- if (y > thr1[_cand1] * gcode0) _cand1++;
- else break;
+ _cand1++;
}
- while (_cand1 < NCODE1 - NCAN1);
+ else
+ {
+ break;
+ }
+ }
+ while (_cand1 < NCODE1 - NCAN1);
- /* pre select codebook #2 */
- _cand2 = 0;
- do
+ /* pre select codebook #2 */
+ _cand2 = 0;
+ do
+ {
+ if (x > thr2[_cand2] * gcode0)
+ {
+ _cand2++;
+ }
+ else
{
- if (x > thr2[_cand2] * gcode0) _cand2++;
- else break;
+ break;
}
- while (_cand2 < NCODE2 - NCAN2);
}
- else
+ while (_cand2 < NCODE2 - NCAN2);
+ }
+ else
+ {
+ /* pre select codebook #1 */
+ _cand1 = 0;
+ do
{
- /* pre select codebook #1 */
- _cand1 = 0;
- do
+ if (y < thr1[_cand1] * gcode0)
{
- if (y < thr1[_cand1] * gcode0) _cand1++;
- else break;
+ _cand1++;
}
- while (_cand1 < NCODE1 - NCAN1);
-
- /* pre select codebook #2 */
- _cand2 = 0;
- do
+ else
{
- if (x < thr2[_cand2] * gcode0) _cand2++;
- else break;
+ break;
}
- while (_cand2 < NCODE2 - NCAN2);
}
+ while (_cand1 < NCODE1 - NCAN1);
- cand1.value = _cand1;
- cand2.value = _cand2;
+ /* pre select codebook #2 */
+ _cand2 = 0;
+ do
+ {
+ if (x < thr2[_cand2] * gcode0)
+ {
+ _cand2++;
+ }
+ else
+ {
+ break;
+ }
+ }
+ while (_cand2 < NCODE2 - NCAN2);
}
+
+ cand1.value = _cand1;
+ cand2.value = _cand2;
}
-}
\ No newline at end of file
+}
diff --git a/src/SIPSorcery/app/Media/Codecs/G729Codec/QuaLsp.cs b/src/SIPSorcery/app/Media/Codecs/G729Codec/QuaLsp.cs
index f2fa501ff..8986a216a 100644
--- a/src/SIPSorcery/app/Media/Codecs/G729Codec/QuaLsp.cs
+++ b/src/SIPSorcery/app/Media/Codecs/G729Codec/QuaLsp.cs
@@ -26,466 +26,504 @@
*/
using System;
-namespace SIPSorcery.Media.G729Codec
+namespace SIPSorcery.Media.G729Codec;
+
+internal sealed class QuaLsp
{
- internal class QuaLsp
- {
- /**
- * previous LSP vector(init)
- */
- private static readonly float[ /* M */] FREQ_PREV_RESET =
- {
- 0.285599f,
- 0.571199f,
- 0.856798f,
- 1.142397f,
- 1.427997f,
- 1.713596f,
- 1.999195f,
- 2.284795f,
- 2.570394f,
- 2.855993f
- }; /* PI*(float)(j+1)/(float)(M+1) */
-
- /* ITU-T G.729 Software Package Release 2 (November 2006) */
- /*
- ITU-T G.729 Annex C - Reference C code for floating point
- implementation of G.729
- Version 1.01 of 15.September.98
+ /**
+* previous LSP vector(init)
+*/
+ private static readonly float[ /* M */] FREQ_PREV_RESET =
+ {
+ 0.285599f,
+ 0.571199f,
+ 0.856798f,
+ 1.142397f,
+ 1.427997f,
+ 1.713596f,
+ 1.999195f,
+ 2.284795f,
+ 2.570394f,
+ 2.855993f
+ }; /* PI*(float)(j+1)/(float)(M+1) */
+
+ /* ITU-T G.729 Software Package Release 2 (November 2006) */
+ /*
+ITU-T G.729 Annex C - Reference C code for floating point
+ implementation of G.729
+ Version 1.01 of 15.September.98
*/
- /*
+ /*
----------------------------------------------------------------------
- COPYRIGHT NOTICE
+ COPYRIGHT NOTICE
----------------------------------------------------------------------
- ITU-T G.729 Annex C ANSI C source code
- Copyright (C) 1998, AT&T, France Telecom, NTT, University of
- Sherbrooke. All rights reserved.
+ITU-T G.729 Annex C ANSI C source code
+Copyright (C) 1998, AT&T, France Telecom, NTT, University of
+Sherbrooke. All rights reserved.
----------------------------------------------------------------------
*/
- /*
- File : QUA_LSP.C
- Used for the floating point version of both
- G.729 main body and G.729A
+ /*
+File : QUA_LSP.C
+Used for the floating point version of both
+G.729 main body and G.729A
*/
- /* static memory */
- /**
- * previous LSP vector
- */
- private readonly float[][] freq_prev = new float[Ld8k.MA_NP][ /* Ld8k.M */];
+ /* static memory */
+ /**
+* previous LSP vector
+*/
+ private readonly float[][] freq_prev = new float[Ld8k.MA_NP][ /* Ld8k.M */];
- public QuaLsp()
+ public QuaLsp()
+ {
+ // need this to initialize freq_prev
+ for (var i = 0; i < freq_prev.Length; i++)
{
- // need this to initialize freq_prev
- for (var i = 0; i < freq_prev.Length; i++)
- freq_prev[i] = new float[Ld8k.M];
+ freq_prev[i] = new float[Ld8k.M];
}
+ }
- /**
- * @param lsp (i) : Unquantized LSP
- * @param lsp_q (o) : Quantized LSP
- * @param ana (o) : indexes
- */
+ /**
+* @param lsp (i) : Unquantized LSP
+* @param lsp_q (o) : Quantized LSP
+* @param ana (o) : indexes
+*/
- public void qua_lsp(
- float[] lsp,
- float[] lsp_q,
- int[] ana
- )
- {
- var M = Ld8k.M;
+ public void qua_lsp(
+ float[] lsp,
+ float[] lsp_q,
+ int[] ana
+ )
+ {
+ var M = Ld8k.M;
- int i;
- float[] lsf = new float[M], lsf_q = new float[M]; /* domain 0.0<= lsf 0.0f) wegt[0] = 1.0f;
- else wegt[0] = tmp * tmp * 10.0f + 1.0f;
+ tmp = flsp[1] - PI04 - 1.0f;
+ if (tmp > 0.0f)
+ {
+ wegt[0] = 1.0f;
+ }
+ else
+ {
+ wegt[0] = tmp * tmp * 10.0f + 1.0f;
+ }
- for (i = 1; i < M - 1; i++)
+ for (i = 1; i < M - 1; i++)
+ {
+ tmp = flsp[i + 1] - flsp[i - 1] - 1.0f;
+ if (tmp > 0.0f)
{
- tmp = flsp[i + 1] - flsp[i - 1] - 1.0f;
- if (tmp > 0.0f) wegt[i] = 1.0f;
- else wegt[i] = tmp * tmp * 10.0f + 1.0f;
+ wegt[i] = 1.0f;
}
+ else
+ {
+ wegt[i] = tmp * tmp * 10.0f + 1.0f;
+ }
+ }
- tmp = PI92 - flsp[M - 2] - 1.0f;
- if (tmp > 0.0f) wegt[M - 1] = 1.0f;
- else wegt[M - 1] = tmp * tmp * 10.0f + 1.0f;
-
- wegt[4] *= CONST12;
- wegt[5] *= CONST12;
+ tmp = PI92 - flsp[M - 2] - 1.0f;
+ if (tmp > 0.0f)
+ {
+ wegt[M - 1] = 1.0f;
}
+ else
+ {
+ wegt[M - 1] = tmp * tmp * 10.0f + 1.0f;
+ }
+
+ wegt[4] *= CONST12;
+ wegt[5] *= CONST12;
}
-}
\ No newline at end of file
+}
diff --git a/src/SIPSorcery/app/Media/Codecs/G729Codec/TabLd8k.cs b/src/SIPSorcery/app/Media/Codecs/G729Codec/TabLd8k.cs
index 9b1e1fc7c..3ac2706ab 100644
--- a/src/SIPSorcery/app/Media/Codecs/G729Codec/TabLd8k.cs
+++ b/src/SIPSorcery/app/Media/Codecs/G729Codec/TabLd8k.cs
@@ -22,3323 +22,3322 @@
/**
* @author Lubomir Marinov (translation of ITU-T C source code to Java)
*/
-namespace SIPSorcery.Media.G729Codec
+namespace SIPSorcery.Media.G729Codec;
+
+public static class TabLd8k
{
- public class TabLd8k
+
+ public static readonly float[ /* 3 */] a100 =
{
+ 1.00000000E+00f,
+ 0.19330735E+01f,
+ -0.93589199E+00f
+ };
- public static float[ /* 3 */] a100 =
- {
- 1.00000000E+00f,
- 0.19330735E+01f,
- -0.93589199E+00f
- };
+ public static readonly float[ /* 3 */] a140 =
+ {
+ 1.00000000E+00f,
+ 0.19059465E+01f,
+ -0.91140240E+00f
+ };
- public static float[ /* 3 */] a140 =
- {
- 1.00000000E+00f,
- 0.19059465E+01f,
- -0.91140240E+00f
- };
+ /* filter coefficients (fc = 100 Hz ) */
- /* filter coefficients (fc = 100 Hz ) */
+ public static readonly float[ /* 3 */] b100 =
+ {
+ 0.93980581E+00f,
+ -0.18795834E+01f,
+ 0.93980581E+00f
+ };
- public static float[ /* 3 */] b100 =
- {
- 0.93980581E+00f,
- -0.18795834E+01f,
- 0.93980581E+00f
- };
+ /* filter coefficients (fc = 140 Hz) */
- /* filter coefficients (fc = 140 Hz) */
+ public static readonly float[ /* 3 */] b140 =
+ {
+ 0.92727435E+00f,
+ -0.18544941E+01f,
+ 0.92727435E+00f
+ };
- public static float[ /* 3 */] b140 =
+ public static readonly int[ /* PRM_SIZE */] bitsno =
+ {
+ 1 + Ld8k.NC0_B, /* MA + 1st stage */
+ Ld8k.NC1_B * 2, /* 2nd stage */
+ 8,
+ 1,
+ 13,
+ 4,
+ 7, /* first subframe */
+ 5,
+ 13,
+ 4,
+ 7
+ }; /* second subframe */
+
+ public static readonly float[ /* 2 */][ /* 2 */] coef =
+ {
+ new[]
{
- 0.92727435E+00f,
- -0.18544941E+01f,
- 0.92727435E+00f
- };
+ 31.134575f,
+ 1.612322f
+ },
- public static int[ /* PRM_SIZE */] bitsno =
+ new[]
{
- 1 + Ld8k.NC0_B, /* MA + 1st stage */
- Ld8k.NC1_B * 2, /* 2nd stage */
- 8,
- 1,
- 13,
- 4,
- 7, /* first subframe */
- 5,
- 13,
- 4,
- 7
- }; /* second subframe */
+ 0.481389f,
+ 0.053056f
+ }
+ };
- public static float[ /* 2 */][ /* 2 */] coef =
+ /*MA prediction coef. */
+
+ public static readonly float[ /* MODE */][ /* MA_NP */][ /* M */] fg =
+ {
+ new[]
{
new[]
{
- 31.134575f,
- 1.612322f
+ 0.2570f,
+ 0.2780f,
+ 0.2800f,
+ 0.2736f,
+ 0.2757f,
+ 0.2764f,
+ 0.2675f,
+ 0.2678f,
+ 0.2779f,
+ 0.2647f
},
new[]
{
- 0.481389f,
- 0.053056f
- }
- };
-
- /*MA prediction coef. */
+ 0.2142f,
+ 0.2194f,
+ 0.2331f,
+ 0.2230f,
+ 0.2272f,
+ 0.2252f,
+ 0.2148f,
+ 0.2123f,
+ 0.2115f,
+ 0.2096f
+ },
- public static float[ /* MODE */][ /* MA_NP */][ /* M */] fg =
- {
new[]
{
- new[]
- {
- 0.2570f,
- 0.2780f,
- 0.2800f,
- 0.2736f,
- 0.2757f,
- 0.2764f,
- 0.2675f,
- 0.2678f,
- 0.2779f,
- 0.2647f
- },
-
- new[]
- {
- 0.2142f,
- 0.2194f,
- 0.2331f,
- 0.2230f,
- 0.2272f,
- 0.2252f,
- 0.2148f,
- 0.2123f,
- 0.2115f,
- 0.2096f
- },
-
- new[]
- {
- 0.1670f,
- 0.1523f,
- 0.1567f,
- 0.1580f,
- 0.1601f,
- 0.1569f,
- 0.1589f,
- 0.1555f,
- 0.1474f,
- 0.1571f
- },
-
- new[]
- {
- 0.1238f,
- 0.0925f,
- 0.0798f,
- 0.0923f,
- 0.0890f,
- 0.0828f,
- 0.1010f,
- 0.0988f,
- 0.0872f,
- 0.1060f
- }
+ 0.1670f,
+ 0.1523f,
+ 0.1567f,
+ 0.1580f,
+ 0.1601f,
+ 0.1569f,
+ 0.1589f,
+ 0.1555f,
+ 0.1474f,
+ 0.1571f
},
new[]
{
- new[]
- {
- 0.2360f,
- 0.2405f,
- 0.2499f,
- 0.2495f,
- 0.2517f,
- 0.2591f,
- 0.2636f,
- 0.2625f,
- 0.2551f,
- 0.2310f
- },
-
- new[]
- {
- 0.1285f,
- 0.0925f,
- 0.0779f,
- 0.1060f,
- 0.1183f,
- 0.1176f,
- 0.1277f,
- 0.1268f,
- 0.1193f,
- 0.1211f
- },
-
- new[]
- {
- 0.0981f,
- 0.0589f,
- 0.0401f,
- 0.0654f,
- 0.0761f,
- 0.0728f,
- 0.0841f,
- 0.0826f,
- 0.0776f,
- 0.0891f
- },
-
- new[]
- {
- 0.0923f,
- 0.0486f,
- 0.0287f,
- 0.0498f,
- 0.0526f,
- 0.0482f,
- 0.0621f,
- 0.0636f,
- 0.0584f,
- 0.0794f
- }
+ 0.1238f,
+ 0.0925f,
+ 0.0798f,
+ 0.0923f,
+ 0.0890f,
+ 0.0828f,
+ 0.1010f,
+ 0.0988f,
+ 0.0872f,
+ 0.1060f
}
+ },
- };
-
- /*present MA prediction coef.*/
-
- public static float[ /* MODE */][ /* M */] fg_sum =
+ new[]
{
new[]
{
- 0.2380000054836f,
- 0.2578000128269f,
- 0.2504000067711f,
- 0.2531000375748f,
- 0.2480000108480f,
- 0.2587000429630f,
- 0.2577999532223f,
- 0.2656000256538f,
- 0.2760000228882f,
- 0.2625999450684f
+ 0.2360f,
+ 0.2405f,
+ 0.2499f,
+ 0.2495f,
+ 0.2517f,
+ 0.2591f,
+ 0.2636f,
+ 0.2625f,
+ 0.2551f,
+ 0.2310f
},
new[]
{
- 0.4451000094414f,
- 0.5595000386238f,
- 0.6034000515938f,
- 0.5292999744415f,
- 0.5012999176979f,
- 0.5023000240326f,
- 0.4625000357628f,
- 0.4645000100136f,
- 0.4895999729633f,
- 0.4793999791145f
- }
- };
-
- /*inverse coef. */
+ 0.1285f,
+ 0.0925f,
+ 0.0779f,
+ 0.1060f,
+ 0.1183f,
+ 0.1176f,
+ 0.1277f,
+ 0.1268f,
+ 0.1193f,
+ 0.1211f
+ },
- public static float[ /* MODE */][ /* M */] fg_sum_inv =
- {
new[]
{
- 4.2016806602478f,
- 3.8789758682251f,
- 3.9936101436615f,
- 3.9510068893433f,
- 4.0322580337524f,
- 3.8654806613922f,
- 3.8789765834808f,
- 3.7650599479675f,
- 3.6231880187988f,
- 3.8080739974976f
+ 0.0981f,
+ 0.0589f,
+ 0.0401f,
+ 0.0654f,
+ 0.0761f,
+ 0.0728f,
+ 0.0841f,
+ 0.0826f,
+ 0.0776f,
+ 0.0891f
},
new[]
{
- 2.2466859817505f,
- 1.7873100042343f,
- 1.6572753190994f,
- 1.8892878293991f,
- 1.9948137998581f,
- 1.9908419847488f,
- 2.1621620655060f,
- 2.1528525352478f,
- 2.0424838066101f,
- 2.0859408378601f
+ 0.0923f,
+ 0.0486f,
+ 0.0287f,
+ 0.0498f,
+ 0.0526f,
+ 0.0482f,
+ 0.0621f,
+ 0.0636f,
+ 0.0584f,
+ 0.0794f
}
- };
+ }
+
+ };
+
+ /*present MA prediction coef.*/
- public static float[ /* NCODE1 */][ /* 2 */] gbk1 =
+ public static readonly float[ /* MODE */][ /* M */] fg_sum =
+ {
+ new[]
{
- new[]
- {
- 0.000010f,
- 0.185084f
- },
+ 0.2380000054836f,
+ 0.2578000128269f,
+ 0.2504000067711f,
+ 0.2531000375748f,
+ 0.2480000108480f,
+ 0.2587000429630f,
+ 0.2577999532223f,
+ 0.2656000256538f,
+ 0.2760000228882f,
+ 0.2625999450684f
+ },
+
+ new[]
+ {
+ 0.4451000094414f,
+ 0.5595000386238f,
+ 0.6034000515938f,
+ 0.5292999744415f,
+ 0.5012999176979f,
+ 0.5023000240326f,
+ 0.4625000357628f,
+ 0.4645000100136f,
+ 0.4895999729633f,
+ 0.4793999791145f
+ }
+ };
+
+ /*inverse coef. */
+
+ public static readonly float[ /* MODE */][ /* M */] fg_sum_inv =
+ {
+ new[]
+ {
+ 4.2016806602478f,
+ 3.8789758682251f,
+ 3.9936101436615f,
+ 3.9510068893433f,
+ 4.0322580337524f,
+ 3.8654806613922f,
+ 3.8789765834808f,
+ 3.7650599479675f,
+ 3.6231880187988f,
+ 3.8080739974976f
+ },
+
+ new[]
+ {
+ 2.2466859817505f,
+ 1.7873100042343f,
+ 1.6572753190994f,
+ 1.8892878293991f,
+ 1.9948137998581f,
+ 1.9908419847488f,
+ 2.1621620655060f,
+ 2.1528525352478f,
+ 2.0424838066101f,
+ 2.0859408378601f
+ }
+ };
+
+ public static readonly float[ /* NCODE1 */][ /* 2 */] gbk1 =
+ {
+ new[]
+ {
+ 0.000010f,
+ 0.185084f
+ },
- new[]
- {
- 0.094719f,
- 0.296035f
- },
+ new[]
+ {
+ 0.094719f,
+ 0.296035f
+ },
- new[]
- {
- 0.111779f,
- 0.613122f
- },
+ new[]
+ {
+ 0.111779f,
+ 0.613122f
+ },
- new[]
- {
- 0.003516f,
- 0.659780f
- },
+ new[]
+ {
+ 0.003516f,
+ 0.659780f
+ },
- new[]
- {
- 0.117258f,
- 1.134277f
- },
+ new[]
+ {
+ 0.117258f,
+ 1.134277f
+ },
- new[]
- {
- 0.197901f,
- 1.214512f
- },
+ new[]
+ {
+ 0.197901f,
+ 1.214512f
+ },
- new[]
- {
- 0.021772f,
- 1.801288f
- },
+ new[]
+ {
+ 0.021772f,
+ 1.801288f
+ },
- new[]
- {
- 0.163457f,
- 3.315700f
- }
- };
+ new[]
+ {
+ 0.163457f,
+ 3.315700f
+ }
+ };
- public static float[ /* NCODE2*/][ /* 2 */] gbk2 =
+ public static readonly float[ /* NCODE2*/][ /* 2 */] gbk2 =
+ {
+ new[]
{
- new[]
- {
- 0.050466f,
- 0.244769f
- },
+ 0.050466f,
+ 0.244769f
+ },
- new[]
- {
- 0.121711f,
- 0.000010f
- },
+ new[]
+ {
+ 0.121711f,
+ 0.000010f
+ },
- new[]
- {
- 0.313871f,
- 0.072357f
- },
+ new[]
+ {
+ 0.313871f,
+ 0.072357f
+ },
- new[]
- {
- 0.375977f,
- 0.292399f
- },
+ new[]
+ {
+ 0.375977f,
+ 0.292399f
+ },
- new[]
- {
- 0.493870f,
- 0.593410f
- },
+ new[]
+ {
+ 0.493870f,
+ 0.593410f
+ },
- new[]
- {
- 0.556641f,
- 0.064087f
- },
+ new[]
+ {
+ 0.556641f,
+ 0.064087f
+ },
- new[]
- {
- 0.645363f,
- 0.362118f
- },
+ new[]
+ {
+ 0.645363f,
+ 0.362118f
+ },
- new[]
- {
- 0.706138f,
- 0.146110f
- },
+ new[]
+ {
+ 0.706138f,
+ 0.146110f
+ },
- new[]
- {
- 0.809357f,
- 0.397579f
- },
+ new[]
+ {
+ 0.809357f,
+ 0.397579f
+ },
- new[]
- {
- 0.866379f,
- 0.199087f
- },
+ new[]
+ {
+ 0.866379f,
+ 0.199087f
+ },
- new[]
- {
- 0.923602f,
- 0.599938f
- },
+ new[]
+ {
+ 0.923602f,
+ 0.599938f
+ },
- new[]
- {
- 0.925376f,
- 1.742757f
- },
+ new[]
+ {
+ 0.925376f,
+ 1.742757f
+ },
- new[]
- {
- 0.942028f,
- 0.029027f
- },
+ new[]
+ {
+ 0.942028f,
+ 0.029027f
+ },
- new[]
- {
- 0.983459f,
- 0.414166f
- },
+ new[]
+ {
+ 0.983459f,
+ 0.414166f
+ },
- new[]
- {
- 1.055892f,
- 0.227186f
- },
+ new[]
+ {
+ 1.055892f,
+ 0.227186f
+ },
- new[]
- {
- 1.158039f,
- 0.724592f
- }
- };
-
- public static float[ /* GRID_POINTS+1 */] grid =
- {
- 0.9997559f,
- 0.9986295f,
- 0.9945219f,
- 0.9876884f,
- 0.9781476f,
- 0.9659258f,
- 0.9510565f,
- 0.9335804f,
- 0.9135454f,
- 0.8910065f,
- 0.8660254f,
- 0.8386706f,
- 0.8090170f,
- 0.7771460f,
- 0.7431448f,
- 0.7071068f,
- 0.6691306f,
- 0.6293204f,
- 0.5877852f,
- 0.5446391f,
- 0.5000000f,
- 0.4539905f,
- 0.4067366f,
- 0.3583679f,
- 0.3090170f,
- 0.2588190f,
- 0.2079117f,
- 0.1564345f,
- 0.1045285f,
- 0.0523360f,
- 0.0000000f,
- -0.0523360f,
- -0.1045285f,
- -0.1564345f,
- -0.2079117f,
- -0.2588190f,
- -0.3090170f,
- -0.3583679f,
- -0.4067366f,
- -0.4539905f,
- -0.5000000f,
- -0.5446391f,
- -0.5877852f,
- -0.6293204f,
- -0.6691306f,
- -0.7071068f,
- -0.7431448f,
- -0.7771460f,
- -0.8090170f,
- -0.8386706f,
- -0.8660254f,
- -0.8910065f,
- -0.9135454f,
- -0.9335804f,
- -0.9510565f,
- -0.9659258f,
- -0.9781476f,
- -0.9876884f,
- -0.9945219f,
- -0.9986295f,
- -0.9997559f
- };
-
- /* ITU-T G.729 Software Package Release 2 (November 2006) */
- /*
- ITU-T G.729 Annex C - Reference C code for floating point
- implementation of G.729
- Version 1.01 of 15.September.98
+ new[]
+ {
+ 1.158039f,
+ 0.724592f
+ }
+ };
+
+ public static readonly float[ /* GRID_POINTS+1 */] grid =
+ {
+ 0.9997559f,
+ 0.9986295f,
+ 0.9945219f,
+ 0.9876884f,
+ 0.9781476f,
+ 0.9659258f,
+ 0.9510565f,
+ 0.9335804f,
+ 0.9135454f,
+ 0.8910065f,
+ 0.8660254f,
+ 0.8386706f,
+ 0.8090170f,
+ 0.7771460f,
+ 0.7431448f,
+ 0.7071068f,
+ 0.6691306f,
+ 0.6293204f,
+ 0.5877852f,
+ 0.5446391f,
+ 0.5000000f,
+ 0.4539905f,
+ 0.4067366f,
+ 0.3583679f,
+ 0.3090170f,
+ 0.2588190f,
+ 0.2079117f,
+ 0.1564345f,
+ 0.1045285f,
+ 0.0523360f,
+ 0.0000000f,
+ -0.0523360f,
+ -0.1045285f,
+ -0.1564345f,
+ -0.2079117f,
+ -0.2588190f,
+ -0.3090170f,
+ -0.3583679f,
+ -0.4067366f,
+ -0.4539905f,
+ -0.5000000f,
+ -0.5446391f,
+ -0.5877852f,
+ -0.6293204f,
+ -0.6691306f,
+ -0.7071068f,
+ -0.7431448f,
+ -0.7771460f,
+ -0.8090170f,
+ -0.8386706f,
+ -0.8660254f,
+ -0.8910065f,
+ -0.9135454f,
+ -0.9335804f,
+ -0.9510565f,
+ -0.9659258f,
+ -0.9781476f,
+ -0.9876884f,
+ -0.9945219f,
+ -0.9986295f,
+ -0.9997559f
+ };
+
+ /* ITU-T G.729 Software Package Release 2 (November 2006) */
+ /*
+ITU-T G.729 Annex C - Reference C code for floating point
+ implementation of G.729
+ Version 1.01 of 15.September.98
*/
- /*
+ /*
----------------------------------------------------------------------
- COPYRIGHT NOTICE
+ COPYRIGHT NOTICE
----------------------------------------------------------------------
- ITU-T G.729 Annex C ANSI C source code
- Copyright (C) 1998, AT&T, France Telecom, NTT, University of
- Sherbrooke. All rights reserved.
+ITU-T G.729 Annex C ANSI C source code
+Copyright (C) 1998, AT&T, France Telecom, NTT, University of
+Sherbrooke. All rights reserved.
----------------------------------------------------------------------
*/
- /*
- File : TAB_LD8K.H
- Used for the floating point version of G.729 main body
- (not for G.729A)
+ /*
+File : TAB_LD8K.H
+Used for the floating point version of G.729 main body
+(not for G.729A)
*/
- /* ITU-T G.729 Software Package Release 2 (November 2006) */
- /*
- ITU-T G.729 Annex C - Reference C code for floating point
- implementation of G.729
- Version 1.01 of 15.September.98
+ /* ITU-T G.729 Software Package Release 2 (November 2006) */
+ /*
+ITU-T G.729 Annex C - Reference C code for floating point
+ implementation of G.729
+ Version 1.01 of 15.September.98
*/
- /*
+ /*
----------------------------------------------------------------------
- COPYRIGHT NOTICE
+ COPYRIGHT NOTICE
----------------------------------------------------------------------
- ITU-T G.729 Annex C ANSI C source code
- Copyright (C) 1998, AT&T, France Telecom, NTT, University of
- Sherbrooke. All rights reserved.
+ITU-T G.729 Annex C ANSI C source code
+Copyright (C) 1998, AT&T, France Telecom, NTT, University of
+Sherbrooke. All rights reserved.
u----------------------------------------------------------------------
*/
- /*
- File : TAB_LD8K.C
- Used for the floating point version of G.729 main body
- (not for G.729A)
+ /*
+File : TAB_LD8K.C
+Used for the floating point version of G.729 main body
+(not for G.729A)
*/
- public static float[ /* L_WINDOW */] hamwindow =
- {
- 0.08000000f,
- 0.08005703f,
- 0.08022812f,
- 0.08051321f,
- 0.08091225f,
- 0.08142514f,
- 0.08205172f,
- 0.08279188f,
- 0.08364540f,
- 0.08461212f,
- 0.08569173f,
- 0.08688401f,
- 0.08818865f,
- 0.08960532f,
- 0.09113365f,
- 0.09277334f,
- 0.09452391f,
- 0.09638494f,
- 0.09835598f,
- 0.10043652f,
- 0.10262608f,
- 0.10492408f,
- 0.10732999f,
- 0.10984316f,
- 0.11246302f,
- 0.11518890f,
- 0.11802010f,
- 0.12095598f,
- 0.12399574f,
- 0.12713866f,
- 0.13038395f,
- 0.13373083f,
- 0.13717847f,
- 0.14072597f,
- 0.14437246f,
- 0.14811710f,
- 0.15195890f,
- 0.15589692f,
- 0.15993017f,
- 0.16405767f,
- 0.16827843f,
- 0.17259133f,
- 0.17699537f,
- 0.18148938f,
- 0.18607232f,
- 0.19074300f,
- 0.19550033f,
- 0.20034306f,
- 0.20527001f,
- 0.21027996f,
- 0.21537170f,
- 0.22054392f,
- 0.22579536f,
- 0.23112471f,
- 0.23653066f,
- 0.24201185f,
- 0.24756692f,
- 0.25319457f,
- 0.25889328f,
- 0.26466170f,
- 0.27049842f,
- 0.27640197f,
- 0.28237087f,
- 0.28840363f,
- 0.29449883f,
- 0.30065489f,
- 0.30687031f,
- 0.31314352f,
- 0.31947297f,
- 0.32585713f,
- 0.33229437f,
- 0.33878314f,
- 0.34532180f,
- 0.35190874f,
- 0.35854232f,
- 0.36522087f,
- 0.37194279f,
- 0.37870640f,
- 0.38550997f,
- 0.39235184f,
- 0.39923036f,
- 0.40614375f,
- 0.41309035f,
- 0.42006844f,
- 0.42707625f,
- 0.43411207f,
- 0.44117412f,
- 0.44826069f,
- 0.45537004f,
- 0.46250033f,
- 0.46964988f,
- 0.47681686f,
- 0.48399949f,
- 0.49119604f,
- 0.49840465f,
- 0.50562358f,
- 0.51285106f,
- 0.52008528f,
- 0.52732444f,
- 0.53456670f,
- 0.54181033f,
- 0.54905349f,
- 0.55629444f,
- 0.56353134f,
- 0.57076240f,
- 0.57798582f,
- 0.58519983f,
- 0.59240264f,
- 0.59959245f,
- 0.60676748f,
- 0.61392599f,
- 0.62106609f,
- 0.62818617f,
- 0.63528436f,
- 0.64235890f,
- 0.64940804f,
- 0.65643007f,
- 0.66342324f,
- 0.67038584f,
- 0.67731601f,
- 0.68421221f,
- 0.69107264f,
- 0.69789559f,
- 0.70467937f,
- 0.71142232f,
- 0.71812278f,
- 0.72477907f,
- 0.73138952f,
- 0.73795253f,
- 0.74446648f,
- 0.75092971f,
- 0.75734061f,
- 0.76369762f,
- 0.76999915f,
- 0.77624369f,
- 0.78242958f,
- 0.78855544f,
- 0.79461962f,
- 0.80062068f,
- 0.80655706f,
- 0.81242740f,
- 0.81823015f,
- 0.82396388f,
- 0.82962728f,
- 0.83521879f,
- 0.84073710f,
- 0.84618086f,
- 0.85154873f,
- 0.85683930f,
- 0.86205131f,
- 0.86718345f,
- 0.87223446f,
- 0.87720311f,
- 0.88208807f,
- 0.88688827f,
- 0.89160240f,
- 0.89622939f,
- 0.90076804f,
- 0.90521723f,
- 0.90957582f,
- 0.91384280f,
- 0.91801709f,
- 0.92209762f,
- 0.92608339f,
- 0.92997342f,
- 0.93376678f,
- 0.93746245f,
- 0.94105959f,
- 0.94455731f,
- 0.94795465f,
- 0.95125085f,
- 0.95444512f,
- 0.95753652f,
- 0.96052444f,
- 0.96340811f,
- 0.96618676f,
- 0.96885973f,
- 0.97142631f,
- 0.97388595f,
- 0.97623801f,
- 0.97848189f,
- 0.98061699f,
- 0.98264289f,
- 0.98455900f,
- 0.98636484f,
- 0.98806006f,
- 0.98964417f,
- 0.99111670f,
- 0.99247742f,
- 0.99372596f,
- 0.99486196f,
- 0.99588519f,
- 0.99679530f,
- 0.99759221f,
- 0.99827564f,
- 0.99884540f,
- 0.99930143f,
- 0.99964350f,
- 0.99987161f,
- 0.99998569f,
- 1.00000000f,
- 0.99921930f,
- 0.99687845f,
- 0.99298108f,
- 0.98753333f,
- 0.98054361f,
- 0.97202289f,
- 0.96198452f,
- 0.95044410f,
- 0.93741965f,
- 0.92293155f,
- 0.90700239f,
- 0.88965708f,
- 0.87092263f,
- 0.85082841f,
- 0.82940567f,
- 0.80668795f,
- 0.78271067f,
- 0.75751126f,
- 0.73112911f,
- 0.70360541f,
- 0.67498308f,
- 0.64530689f,
- 0.61462307f,
- 0.58297962f,
- 0.55042595f,
- 0.51701277f,
- 0.48279238f,
- 0.44781810f,
- 0.41214463f,
- 0.37582767f,
- 0.33892387f,
- 0.30149087f,
- 0.26358715f,
- 0.22527184f,
- 0.18660481f,
- 0.14764643f,
- 0.10845750f,
- 0.06909923f,
- 0.02963307f
- };
-
- public static int[ /* NCODE1 */] imap1 =
- {
- 5,
- 1,
- 7,
- 4,
- 2,
- 0,
- 6,
- 3
- };
-
- public static int[ /* NCODE2 */] imap2 =
- {
- 2,
- 14,
- 3,
- 13,
- 0,
- 15,
- 1,
- 12,
- 6,
- 10,
- 7,
- 9,
- 4,
- 11,
- 5,
- 8
- };
-
- public static float[ /* FIR_SIZE_ANA */] inter_3 =
- {
- 0.900839f,
- 0.760084f,
- 0.424082f,
- 0.084078f,
- -0.105570f,
- -0.121120f,
- -0.047624f,
- 0.016285f,
- 0.031217f,
- 0.015738f,
- 0.000000f,
- -0.005925f,
- 0.000000f
- };
-
- public static float[ /* FIR_SIZE_SYN */] inter_3l =
- {
- 0.898517f,
- 0.769271f,
- 0.448635f,
- 0.095915f,
- -0.134333f,
- -0.178528f,
- -0.084919f,
- 0.036952f,
- 0.095533f,
- 0.068936f,
- -0.000000f,
- -0.050404f,
- -0.050835f,
- -0.014169f,
- 0.023083f,
- 0.033543f,
- 0.016774f,
- -0.007466f,
- -0.019340f,
- -0.013755f,
- 0.000000f,
- 0.009400f,
- 0.009029f,
- 0.002381f,
- -0.003658f,
- -0.005027f,
- -0.002405f,
- 0.001050f,
- 0.002780f,
- 0.002145f,
- 0.000000f
- };
-
- /*First Stage Codebook */
- public static float[ /* NC0 */][ /* M */] lspcb1 =
+ public static readonly float[ /* L_WINDOW */] hamwindow =
+ {
+ 0.08000000f,
+ 0.08005703f,
+ 0.08022812f,
+ 0.08051321f,
+ 0.08091225f,
+ 0.08142514f,
+ 0.08205172f,
+ 0.08279188f,
+ 0.08364540f,
+ 0.08461212f,
+ 0.08569173f,
+ 0.08688401f,
+ 0.08818865f,
+ 0.08960532f,
+ 0.09113365f,
+ 0.09277334f,
+ 0.09452391f,
+ 0.09638494f,
+ 0.09835598f,
+ 0.10043652f,
+ 0.10262608f,
+ 0.10492408f,
+ 0.10732999f,
+ 0.10984316f,
+ 0.11246302f,
+ 0.11518890f,
+ 0.11802010f,
+ 0.12095598f,
+ 0.12399574f,
+ 0.12713866f,
+ 0.13038395f,
+ 0.13373083f,
+ 0.13717847f,
+ 0.14072597f,
+ 0.14437246f,
+ 0.14811710f,
+ 0.15195890f,
+ 0.15589692f,
+ 0.15993017f,
+ 0.16405767f,
+ 0.16827843f,
+ 0.17259133f,
+ 0.17699537f,
+ 0.18148938f,
+ 0.18607232f,
+ 0.19074300f,
+ 0.19550033f,
+ 0.20034306f,
+ 0.20527001f,
+ 0.21027996f,
+ 0.21537170f,
+ 0.22054392f,
+ 0.22579536f,
+ 0.23112471f,
+ 0.23653066f,
+ 0.24201185f,
+ 0.24756692f,
+ 0.25319457f,
+ 0.25889328f,
+ 0.26466170f,
+ 0.27049842f,
+ 0.27640197f,
+ 0.28237087f,
+ 0.28840363f,
+ 0.29449883f,
+ 0.30065489f,
+ 0.30687031f,
+ 0.31314352f,
+ 0.31947297f,
+ 0.32585713f,
+ 0.33229437f,
+ 0.33878314f,
+ 0.34532180f,
+ 0.35190874f,
+ 0.35854232f,
+ 0.36522087f,
+ 0.37194279f,
+ 0.37870640f,
+ 0.38550997f,
+ 0.39235184f,
+ 0.39923036f,
+ 0.40614375f,
+ 0.41309035f,
+ 0.42006844f,
+ 0.42707625f,
+ 0.43411207f,
+ 0.44117412f,
+ 0.44826069f,
+ 0.45537004f,
+ 0.46250033f,
+ 0.46964988f,
+ 0.47681686f,
+ 0.48399949f,
+ 0.49119604f,
+ 0.49840465f,
+ 0.50562358f,
+ 0.51285106f,
+ 0.52008528f,
+ 0.52732444f,
+ 0.53456670f,
+ 0.54181033f,
+ 0.54905349f,
+ 0.55629444f,
+ 0.56353134f,
+ 0.57076240f,
+ 0.57798582f,
+ 0.58519983f,
+ 0.59240264f,
+ 0.59959245f,
+ 0.60676748f,
+ 0.61392599f,
+ 0.62106609f,
+ 0.62818617f,
+ 0.63528436f,
+ 0.64235890f,
+ 0.64940804f,
+ 0.65643007f,
+ 0.66342324f,
+ 0.67038584f,
+ 0.67731601f,
+ 0.68421221f,
+ 0.69107264f,
+ 0.69789559f,
+ 0.70467937f,
+ 0.71142232f,
+ 0.71812278f,
+ 0.72477907f,
+ 0.73138952f,
+ 0.73795253f,
+ 0.74446648f,
+ 0.75092971f,
+ 0.75734061f,
+ 0.76369762f,
+ 0.76999915f,
+ 0.77624369f,
+ 0.78242958f,
+ 0.78855544f,
+ 0.79461962f,
+ 0.80062068f,
+ 0.80655706f,
+ 0.81242740f,
+ 0.81823015f,
+ 0.82396388f,
+ 0.82962728f,
+ 0.83521879f,
+ 0.84073710f,
+ 0.84618086f,
+ 0.85154873f,
+ 0.85683930f,
+ 0.86205131f,
+ 0.86718345f,
+ 0.87223446f,
+ 0.87720311f,
+ 0.88208807f,
+ 0.88688827f,
+ 0.89160240f,
+ 0.89622939f,
+ 0.90076804f,
+ 0.90521723f,
+ 0.90957582f,
+ 0.91384280f,
+ 0.91801709f,
+ 0.92209762f,
+ 0.92608339f,
+ 0.92997342f,
+ 0.93376678f,
+ 0.93746245f,
+ 0.94105959f,
+ 0.94455731f,
+ 0.94795465f,
+ 0.95125085f,
+ 0.95444512f,
+ 0.95753652f,
+ 0.96052444f,
+ 0.96340811f,
+ 0.96618676f,
+ 0.96885973f,
+ 0.97142631f,
+ 0.97388595f,
+ 0.97623801f,
+ 0.97848189f,
+ 0.98061699f,
+ 0.98264289f,
+ 0.98455900f,
+ 0.98636484f,
+ 0.98806006f,
+ 0.98964417f,
+ 0.99111670f,
+ 0.99247742f,
+ 0.99372596f,
+ 0.99486196f,
+ 0.99588519f,
+ 0.99679530f,
+ 0.99759221f,
+ 0.99827564f,
+ 0.99884540f,
+ 0.99930143f,
+ 0.99964350f,
+ 0.99987161f,
+ 0.99998569f,
+ 1.00000000f,
+ 0.99921930f,
+ 0.99687845f,
+ 0.99298108f,
+ 0.98753333f,
+ 0.98054361f,
+ 0.97202289f,
+ 0.96198452f,
+ 0.95044410f,
+ 0.93741965f,
+ 0.92293155f,
+ 0.90700239f,
+ 0.88965708f,
+ 0.87092263f,
+ 0.85082841f,
+ 0.82940567f,
+ 0.80668795f,
+ 0.78271067f,
+ 0.75751126f,
+ 0.73112911f,
+ 0.70360541f,
+ 0.67498308f,
+ 0.64530689f,
+ 0.61462307f,
+ 0.58297962f,
+ 0.55042595f,
+ 0.51701277f,
+ 0.48279238f,
+ 0.44781810f,
+ 0.41214463f,
+ 0.37582767f,
+ 0.33892387f,
+ 0.30149087f,
+ 0.26358715f,
+ 0.22527184f,
+ 0.18660481f,
+ 0.14764643f,
+ 0.10845750f,
+ 0.06909923f,
+ 0.02963307f
+ };
+
+ public static readonly int[ /* NCODE1 */] imap1 =
+ {
+ 5,
+ 1,
+ 7,
+ 4,
+ 2,
+ 0,
+ 6,
+ 3
+ };
+
+ public static readonly int[ /* NCODE2 */] imap2 =
+ {
+ 2,
+ 14,
+ 3,
+ 13,
+ 0,
+ 15,
+ 1,
+ 12,
+ 6,
+ 10,
+ 7,
+ 9,
+ 4,
+ 11,
+ 5,
+ 8
+ };
+
+ public static readonly float[ /* FIR_SIZE_ANA */] inter_3 =
+ {
+ 0.900839f,
+ 0.760084f,
+ 0.424082f,
+ 0.084078f,
+ -0.105570f,
+ -0.121120f,
+ -0.047624f,
+ 0.016285f,
+ 0.031217f,
+ 0.015738f,
+ 0.000000f,
+ -0.005925f,
+ 0.000000f
+ };
+
+ public static readonly float[ /* FIR_SIZE_SYN */] inter_3l =
+ {
+ 0.898517f,
+ 0.769271f,
+ 0.448635f,
+ 0.095915f,
+ -0.134333f,
+ -0.178528f,
+ -0.084919f,
+ 0.036952f,
+ 0.095533f,
+ 0.068936f,
+ -0.000000f,
+ -0.050404f,
+ -0.050835f,
+ -0.014169f,
+ 0.023083f,
+ 0.033543f,
+ 0.016774f,
+ -0.007466f,
+ -0.019340f,
+ -0.013755f,
+ 0.000000f,
+ 0.009400f,
+ 0.009029f,
+ 0.002381f,
+ -0.003658f,
+ -0.005027f,
+ -0.002405f,
+ 0.001050f,
+ 0.002780f,
+ 0.002145f,
+ 0.000000f
+ };
+
+ /*First Stage Codebook */
+ public static readonly float[ /* NC0 */][ /* M */] lspcb1 =
+ {
+ new[]
{
- new[]
- {
- 0.1814f,
- 0.2647f,
- 0.4580f,
- 1.1077f,
- 1.4813f,
- 1.7022f,
- 2.1953f,
- 2.3405f,
- 2.5867f,
- 2.6636f
- },
-
- new[]
- {
- 0.2113f,
- 0.3223f,
- 0.4212f,
- 0.5946f,
- 0.7479f,
- 0.9615f,
- 1.9097f,
- 2.1750f,
- 2.4773f,
- 2.6737f
- },
-
- new[]
- {
- 0.1915f,
- 0.2755f,
- 0.3770f,
- 0.5950f,
- 1.3505f,
- 1.6349f,
- 2.2348f,
- 2.3552f,
- 2.5768f,
- 2.6540f
- },
-
- new[]
- {
- 0.2116f,
- 0.3067f,
- 0.4099f,
- 0.5748f,
- 0.8518f,
- 1.2569f,
- 2.0782f,
- 2.1920f,
- 2.3371f,
- 2.4842f
- },
-
- new[]
- {
- 0.2129f,
- 0.2974f,
- 0.4039f,
- 1.0659f,
- 1.2735f,
- 1.4658f,
- 1.9061f,
- 2.0312f,
- 2.6074f,
- 2.6750f
- },
-
- new[]
- {
- 0.2181f,
- 0.2893f,
- 0.4117f,
- 0.5519f,
- 0.8295f,
- 1.5825f,
- 2.1575f,
- 2.3179f,
- 2.5458f,
- 2.6417f
- },
-
- new[]
- {
- 0.1991f,
- 0.2971f,
- 0.4104f,
- 0.7725f,
- 1.3073f,
- 1.4665f,
- 1.6208f,
- 1.6973f,
- 2.3732f,
- 2.5743f
- },
-
- new[]
- {
- 0.1818f,
- 0.2886f,
- 0.4018f,
- 0.7630f,
- 1.1264f,
- 1.2699f,
- 1.6899f,
- 1.8650f,
- 2.1633f,
- 2.6186f
- },
-
- new[]
- {
- 0.2282f,
- 0.3093f,
- 0.4243f,
- 0.5329f,
- 1.1173f,
- 1.7717f,
- 1.9420f,
- 2.0780f,
- 2.5160f,
- 2.6137f
- },
-
- new[]
- {
- 0.2528f,
- 0.3693f,
- 0.5290f,
- 0.7146f,
- 0.9528f,
- 1.1269f,
- 1.2936f,
- 1.9589f,
- 2.4548f,
- 2.6653f
- },
-
- new[]
- {
- 0.2332f,
- 0.3263f,
- 0.4174f,
- 0.5202f,
- 1.3633f,
- 1.8447f,
- 2.0236f,
- 2.1474f,
- 2.3572f,
- 2.4738f
- },
-
- new[]
- {
- 0.1393f,
- 0.2216f,
- 0.3204f,
- 0.5644f,
- 0.7929f,
- 1.1705f,
- 1.7051f,
- 2.0054f,
- 2.3623f,
- 2.5985f
- },
-
- new[]
- {
- 0.2677f,
- 0.3871f,
- 0.5746f,
- 0.7091f,
- 1.3311f,
- 1.5260f,
- 1.7288f,
- 1.9122f,
- 2.5787f,
- 2.6598f
- },
-
- new[]
- {
- 0.1570f,
- 0.2328f,
- 0.3111f,
- 0.4216f,
- 1.1688f,
- 1.4605f,
- 1.9505f,
- 2.1173f,
- 2.4038f,
- 2.7460f
- },
-
- new[]
- {
- 0.2346f,
- 0.3321f,
- 0.5621f,
- 0.8160f,
- 1.4042f,
- 1.5860f,
- 1.7518f,
- 1.8631f,
- 2.0749f,
- 2.5380f
- },
-
- new[]
- {
- 0.2505f,
- 0.3368f,
- 0.4758f,
- 0.6405f,
- 0.8104f,
- 1.2533f,
- 1.9329f,
- 2.0526f,
- 2.2155f,
- 2.6459f
- },
-
- new[]
- {
- 0.2196f,
- 0.3049f,
- 0.6857f,
- 1.3976f,
- 1.6100f,
- 1.7958f,
- 2.0813f,
- 2.2211f,
- 2.4789f,
- 2.5857f
- },
-
- new[]
- {
- 0.1232f,
- 0.2011f,
- 0.3527f,
- 0.6969f,
- 1.1647f,
- 1.5081f,
- 1.8593f,
- 2.2576f,
- 2.5594f,
- 2.6896f
- },
-
- new[]
- {
- 0.3682f,
- 0.4632f,
- 0.6600f,
- 0.9118f,
- 1.5245f,
- 1.7071f,
- 1.8712f,
- 1.9939f,
- 2.4356f,
- 2.5380f
- },
-
- new[]
- {
- 0.2690f,
- 0.3711f,
- 0.4635f,
- 0.6644f,
- 1.4633f,
- 1.6495f,
- 1.8227f,
- 1.9983f,
- 2.1797f,
- 2.2954f
- },
-
- new[]
- {
- 0.3555f,
- 0.5240f,
- 0.9751f,
- 1.1685f,
- 1.4114f,
- 1.6168f,
- 1.7769f,
- 2.0178f,
- 2.4420f,
- 2.5724f
- },
-
- new[]
- {
- 0.3493f,
- 0.4404f,
- 0.7231f,
- 0.8587f,
- 1.1272f,
- 1.4715f,
- 1.6760f,
- 2.2042f,
- 2.4735f,
- 2.5604f
- },
-
- new[]
- {
- 0.3747f,
- 0.5263f,
- 0.7284f,
- 0.8994f,
- 1.4017f,
- 1.5502f,
- 1.7468f,
- 1.9816f,
- 2.2380f,
- 2.3404f
- },
-
- new[]
- {
- 0.2972f,
- 0.4470f,
- 0.5941f,
- 0.7078f,
- 1.2675f,
- 1.4310f,
- 1.5930f,
- 1.9126f,
- 2.3026f,
- 2.4208f
- },
-
- new[]
- {
- 0.2467f,
- 0.3180f,
- 0.4712f,
- 1.1281f,
- 1.6206f,
- 1.7876f,
- 1.9544f,
- 2.0873f,
- 2.3521f,
- 2.4721f
- },
-
- new[]
- {
- 0.2292f,
- 0.3430f,
- 0.4383f,
- 0.5747f,
- 1.3497f,
- 1.5187f,
- 1.9070f,
- 2.0958f,
- 2.2902f,
- 2.4301f
- },
-
- new[]
- {
- 0.2573f,
- 0.3508f,
- 0.4484f,
- 0.7079f,
- 1.6577f,
- 1.7929f,
- 1.9456f,
- 2.0847f,
- 2.3060f,
- 2.4208f
- },
-
- new[]
- {
- 0.1968f,
- 0.2789f,
- 0.3594f,
- 0.4361f,
- 1.0034f,
- 1.7040f,
- 1.9439f,
- 2.1044f,
- 2.2696f,
- 2.4558f
- },
-
- new[]
- {
- 0.2955f,
- 0.3853f,
- 0.7986f,
- 1.2470f,
- 1.4723f,
- 1.6522f,
- 1.8684f,
- 2.0084f,
- 2.2849f,
- 2.4268f
- },
-
- new[]
- {
- 0.2036f,
- 0.3189f,
- 0.4314f,
- 0.6393f,
- 1.2834f,
- 1.4278f,
- 1.5796f,
- 2.0506f,
- 2.2044f,
- 2.3656f
- },
-
- new[]
- {
- 0.2916f,
- 0.3684f,
- 0.5907f,
- 1.1394f,
- 1.3933f,
- 1.5540f,
- 1.8341f,
- 1.9835f,
- 2.1301f,
- 2.2800f
- },
-
- new[]
- {
- 0.2289f,
- 0.3402f,
- 0.5166f,
- 0.7716f,
- 1.0614f,
- 1.2389f,
- 1.4386f,
- 2.0769f,
- 2.2715f,
- 2.4366f
- },
-
- new[]
- {
- 0.0829f,
- 0.1723f,
- 0.5682f,
- 0.9773f,
- 1.3973f,
- 1.6174f,
- 1.9242f,
- 2.2128f,
- 2.4855f,
- 2.6327f
- },
-
- new[]
- {
- 0.2244f,
- 0.3169f,
- 0.4368f,
- 0.5625f,
- 0.6897f,
- 1.3763f,
- 1.7524f,
- 1.9393f,
- 2.5121f,
- 2.6556f
- },
-
- new[]
- {
- 0.1591f,
- 0.2387f,
- 0.2924f,
- 0.4056f,
- 1.4677f,
- 1.6802f,
- 1.9389f,
- 2.2067f,
- 2.4635f,
- 2.5919f
- },
-
- new[]
- {
- 0.1756f,
- 0.2566f,
- 0.3251f,
- 0.4227f,
- 1.0167f,
- 1.2649f,
- 1.6801f,
- 2.1055f,
- 2.4088f,
- 2.7276f
- },
-
- new[]
- {
- 0.1050f,
- 0.2325f,
- 0.7445f,
- 0.9491f,
- 1.1982f,
- 1.4658f,
- 1.8093f,
- 2.0397f,
- 2.4155f,
- 2.5797f
- },
-
- new[]
- {
- 0.2043f,
- 0.3324f,
- 0.4522f,
- 0.7477f,
- 0.9361f,
- 1.1533f,
- 1.6703f,
- 1.7631f,
- 2.5071f,
- 2.6528f
- },
-
- new[]
- {
- 0.1522f,
- 0.2258f,
- 0.3543f,
- 0.5504f,
- 0.8815f,
- 1.5516f,
- 1.8110f,
- 1.9915f,
- 2.3603f,
- 2.7735f
- },
-
- new[]
- {
- 0.1862f,
- 0.2759f,
- 0.4715f,
- 0.6908f,
- 0.8963f,
- 1.4341f,
- 1.6322f,
- 1.7630f,
- 2.2027f,
- 2.6043f
- },
-
- new[]
- {
- 0.1460f,
- 0.2254f,
- 0.3790f,
- 0.8622f,
- 1.3394f,
- 1.5754f,
- 1.8084f,
- 2.0798f,
- 2.4319f,
- 2.7632f
- },
-
- new[]
- {
- 0.2621f,
- 0.3792f,
- 0.5463f,
- 0.7948f,
- 1.0043f,
- 1.1921f,
- 1.3409f,
- 1.4845f,
- 2.3159f,
- 2.6002f
- },
-
- new[]
- {
- 0.1935f,
- 0.2937f,
- 0.3656f,
- 0.4927f,
- 1.4015f,
- 1.6086f,
- 1.7724f,
- 1.8837f,
- 2.4374f,
- 2.5971f
- },
-
- new[]
- {
- 0.2171f,
- 0.3282f,
- 0.4412f,
- 0.5713f,
- 1.1554f,
- 1.3506f,
- 1.5227f,
- 1.9923f,
- 2.4100f,
- 2.5391f
- },
-
- new[]
- {
- 0.2274f,
- 0.3157f,
- 0.4263f,
- 0.8202f,
- 1.4293f,
- 1.5884f,
- 1.7535f,
- 1.9688f,
- 2.3939f,
- 2.4934f
- },
-
- new[]
- {
- 0.1704f,
- 0.2633f,
- 0.3259f,
- 0.4134f,
- 1.2948f,
- 1.4802f,
- 1.6619f,
- 2.0393f,
- 2.3165f,
- 2.6083f
- },
-
- new[]
- {
- 0.1763f,
- 0.2585f,
- 0.4012f,
- 0.7609f,
- 1.1503f,
- 1.5847f,
- 1.8309f,
- 1.9352f,
- 2.0982f,
- 2.6681f
- },
-
- new[]
- {
- 0.2447f,
- 0.3535f,
- 0.4618f,
- 0.5979f,
- 0.7530f,
- 0.8908f,
- 1.5393f,
- 2.0075f,
- 2.3557f,
- 2.6203f
- },
-
- new[]
- {
- 0.1826f,
- 0.3496f,
- 0.7764f,
- 0.9888f,
- 1.3915f,
- 1.7421f,
- 1.9412f,
- 2.1620f,
- 2.4999f,
- 2.6931f
- },
-
- new[]
- {
- 0.3033f,
- 0.3802f,
- 0.6981f,
- 0.8664f,
- 1.0254f,
- 1.5401f,
- 1.7180f,
- 1.8124f,
- 2.5068f,
- 2.6119f
- },
-
- new[]
- {
- 0.2960f,
- 0.4001f,
- 0.6465f,
- 0.7672f,
- 1.3782f,
- 1.5751f,
- 1.9559f,
- 2.1373f,
- 2.3601f,
- 2.4760f
- },
-
- new[]
- {
- 0.3132f,
- 0.4613f,
- 0.6544f,
- 0.8532f,
- 1.0721f,
- 1.2730f,
- 1.7566f,
- 1.9217f,
- 2.1693f,
- 2.6531f
- },
-
- new[]
- {
- 0.3329f,
- 0.4131f,
- 0.8073f,
- 1.1297f,
- 1.2869f,
- 1.4937f,
- 1.7885f,
- 1.9150f,
- 2.4505f,
- 2.5760f
- },
-
- new[]
- {
- 0.2340f,
- 0.3605f,
- 0.7659f,
- 0.9874f,
- 1.1854f,
- 1.3337f,
- 1.5128f,
- 2.0062f,
- 2.4427f,
- 2.5859f
- },
-
- new[]
- {
- 0.4131f,
- 0.5330f,
- 0.6530f,
- 0.9360f,
- 1.3648f,
- 1.5388f,
- 1.6994f,
- 1.8707f,
- 2.4294f,
- 2.5335f
- },
-
- new[]
- {
- 0.3754f,
- 0.5229f,
- 0.7265f,
- 0.9301f,
- 1.1724f,
- 1.3440f,
- 1.5118f,
- 1.7098f,
- 2.5218f,
- 2.6242f
- },
-
- new[]
- {
- 0.2138f,
- 0.2998f,
- 0.6283f,
- 1.2166f,
- 1.4187f,
- 1.6084f,
- 1.7992f,
- 2.0106f,
- 2.5377f,
- 2.6558f
- },
-
- new[]
- {
- 0.1761f,
- 0.2672f,
- 0.4065f,
- 0.8317f,
- 1.0900f,
- 1.4814f,
- 1.7672f,
- 1.8685f,
- 2.3969f,
- 2.5079f
- },
-
- new[]
- {
- 0.2801f,
- 0.3535f,
- 0.4969f,
- 0.9809f,
- 1.4934f,
- 1.6378f,
- 1.8021f,
- 2.1200f,
- 2.3135f,
- 2.4034f
- },
-
- new[]
- {
- 0.2365f,
- 0.3246f,
- 0.5618f,
- 0.8176f,
- 1.1073f,
- 1.5702f,
- 1.7331f,
- 1.8592f,
- 1.9589f,
- 2.3044f
- },
-
- new[]
- {
- 0.2529f,
- 0.3251f,
- 0.5147f,
- 1.1530f,
- 1.3291f,
- 1.5005f,
- 1.7028f,
- 1.8200f,
- 2.3482f,
- 2.4831f
- },
-
- new[]
- {
- 0.2125f,
- 0.3041f,
- 0.4259f,
- 0.9935f,
- 1.1788f,
- 1.3615f,
- 1.6121f,
- 1.7930f,
- 2.5509f,
- 2.6742f
- },
-
- new[]
- {
- 0.2685f,
- 0.3518f,
- 0.5707f,
- 1.0410f,
- 1.2270f,
- 1.3927f,
- 1.7622f,
- 1.8876f,
- 2.0985f,
- 2.5144f
- },
-
- new[]
- {
- 0.2373f,
- 0.3648f,
- 0.5099f,
- 0.7373f,
- 0.9129f,
- 1.0421f,
- 1.7312f,
- 1.8984f,
- 2.1512f,
- 2.6342f
- },
-
- new[]
- {
- 0.2229f,
- 0.3876f,
- 0.8621f,
- 1.1986f,
- 1.5655f,
- 1.8861f,
- 2.2376f,
- 2.4239f,
- 2.6648f,
- 2.7359f
- },
-
- new[]
- {
- 0.3009f,
- 0.3719f,
- 0.5887f,
- 0.7297f,
- 0.9395f,
- 1.8797f,
- 2.0423f,
- 2.1541f,
- 2.5132f,
- 2.6026f
- },
-
- new[]
- {
- 0.3114f,
- 0.4142f,
- 0.6476f,
- 0.8448f,
- 1.2495f,
- 1.7192f,
- 2.2148f,
- 2.3432f,
- 2.5246f,
- 2.6046f
- },
-
- new[]
- {
- 0.3666f,
- 0.4638f,
- 0.6496f,
- 0.7858f,
- 0.9667f,
- 1.4213f,
- 1.9300f,
- 2.0564f,
- 2.2119f,
- 2.3170f
- },
-
- new[]
- {
- 0.4218f,
- 0.5075f,
- 0.8348f,
- 1.0009f,
- 1.2057f,
- 1.5032f,
- 1.9416f,
- 2.0540f,
- 2.4352f,
- 2.5504f
- },
-
- new[]
- {
- 0.3726f,
- 0.4602f,
- 0.5971f,
- 0.7093f,
- 0.8517f,
- 1.2361f,
- 1.8052f,
- 1.9520f,
- 2.4137f,
- 2.5518f
- },
-
- new[]
- {
- 0.4482f,
- 0.5318f,
- 0.7114f,
- 0.8542f,
- 1.0328f,
- 1.4751f,
- 1.7278f,
- 1.8237f,
- 2.3496f,
- 2.4931f
- },
-
- new[]
- {
- 0.3316f,
- 0.4498f,
- 0.6404f,
- 0.8162f,
- 1.0332f,
- 1.2209f,
- 1.5130f,
- 1.7250f,
- 1.9715f,
- 2.4141f
- },
-
- new[]
- {
- 0.2375f,
- 0.3221f,
- 0.5042f,
- 0.9760f,
- 1.7503f,
- 1.9014f,
- 2.0822f,
- 2.2225f,
- 2.4689f,
- 2.5632f
- },
-
- new[]
- {
- 0.2813f,
- 0.3575f,
- 0.5032f,
- 0.5889f,
- 0.6885f,
- 1.6040f,
- 1.9318f,
- 2.0677f,
- 2.4546f,
- 2.5701f
- },
-
- new[]
- {
- 0.2198f,
- 0.3072f,
- 0.4090f,
- 0.6371f,
- 1.6365f,
- 1.9468f,
- 2.1507f,
- 2.2633f,
- 2.5063f,
- 2.5943f
- },
-
- new[]
- {
- 0.1754f,
- 0.2716f,
- 0.3361f,
- 0.5550f,
- 1.1789f,
- 1.3728f,
- 1.8527f,
- 1.9919f,
- 2.1349f,
- 2.3359f
- },
-
- new[]
- {
- 0.2832f,
- 0.3540f,
- 0.6080f,
- 0.8467f,
- 1.0259f,
- 1.6467f,
- 1.8987f,
- 1.9875f,
- 2.4744f,
- 2.5527f
- },
-
- new[]
- {
- 0.2670f,
- 0.3564f,
- 0.5628f,
- 0.7172f,
- 0.9021f,
- 1.5328f,
- 1.7131f,
- 2.0501f,
- 2.5633f,
- 2.6574f
- },
-
- new[]
- {
- 0.2729f,
- 0.3569f,
- 0.6252f,
- 0.7641f,
- 0.9887f,
- 1.6589f,
- 1.8726f,
- 1.9947f,
- 2.1884f,
- 2.4609f
- },
-
- new[]
- {
- 0.2155f,
- 0.3221f,
- 0.4580f,
- 0.6995f,
- 0.9623f,
- 1.2339f,
- 1.6642f,
- 1.8823f,
- 2.0518f,
- 2.2674f
- },
-
- new[]
- {
- 0.4224f,
- 0.7009f,
- 1.1714f,
- 1.4334f,
- 1.7595f,
- 1.9629f,
- 2.2185f,
- 2.3304f,
- 2.5446f,
- 2.6369f
- },
-
- new[]
- {
- 0.4560f,
- 0.5403f,
- 0.7568f,
- 0.8989f,
- 1.1292f,
- 1.7687f,
- 1.9575f,
- 2.0784f,
- 2.4260f,
- 2.5484f
- },
-
- new[]
- {
- 0.4299f,
- 0.5833f,
- 0.8408f,
- 1.0596f,
- 1.5524f,
- 1.7484f,
- 1.9471f,
- 2.2034f,
- 2.4617f,
- 2.5812f
- },
-
- new[]
- {
- 0.2614f,
- 0.3624f,
- 0.8381f,
- 0.9829f,
- 1.2220f,
- 1.6064f,
- 1.8083f,
- 1.9362f,
- 2.1397f,
- 2.2773f
- },
-
- new[]
- {
- 0.5064f,
- 0.7481f,
- 1.1021f,
- 1.3271f,
- 1.5486f,
- 1.7096f,
- 1.9503f,
- 2.1006f,
- 2.3911f,
- 2.5141f
- },
-
- new[]
- {
- 0.5375f,
- 0.6552f,
- 0.8099f,
- 1.0219f,
- 1.2407f,
- 1.4160f,
- 1.8266f,
- 1.9936f,
- 2.1951f,
- 2.2911f
- },
-
- new[]
- {
- 0.4994f,
- 0.6575f,
- 0.8365f,
- 1.0706f,
- 1.4116f,
- 1.6224f,
- 1.9200f,
- 2.0667f,
- 2.3262f,
- 2.4539f
- },
-
- new[]
- {
- 0.3353f,
- 0.4426f,
- 0.6469f,
- 0.9161f,
- 1.2528f,
- 1.3956f,
- 1.6080f,
- 1.8909f,
- 2.0600f,
- 2.1380f
- },
-
- new[]
- {
- 0.2745f,
- 0.4341f,
- 1.0424f,
- 1.2928f,
- 1.5461f,
- 1.7940f,
- 2.0161f,
- 2.1758f,
- 2.4742f,
- 2.5937f
- },
-
- new[]
- {
- 0.1562f,
- 0.2393f,
- 0.4786f,
- 0.9513f,
- 1.2395f,
- 1.8010f,
- 2.0320f,
- 2.2143f,
- 2.5243f,
- 2.6204f
- },
-
- new[]
- {
- 0.2979f,
- 0.4242f,
- 0.8224f,
- 1.0564f,
- 1.4881f,
- 1.7808f,
- 2.0898f,
- 2.1882f,
- 2.3328f,
- 2.4389f
- },
-
- new[]
- {
- 0.2294f,
- 0.3070f,
- 0.5490f,
- 0.9244f,
- 1.2229f,
- 1.8248f,
- 1.9704f,
- 2.0627f,
- 2.2458f,
- 2.3653f
- },
-
- new[]
- {
- 0.3423f,
- 0.4502f,
- 0.9144f,
- 1.2313f,
- 1.3694f,
- 1.5517f,
- 1.9907f,
- 2.1326f,
- 2.4509f,
- 2.5789f
- },
-
- new[]
- {
- 0.2470f,
- 0.3275f,
- 0.4729f,
- 1.0093f,
- 1.2519f,
- 1.4216f,
- 1.8540f,
- 2.0877f,
- 2.3151f,
- 2.4156f
- },
-
- new[]
- {
- 0.3447f,
- 0.4401f,
- 0.7099f,
- 1.0493f,
- 1.2312f,
- 1.4001f,
- 2.0225f,
- 2.1317f,
- 2.2894f,
- 2.4263f
- },
-
- new[]
- {
- 0.3481f,
- 0.4494f,
- 0.6446f,
- 0.9336f,
- 1.1198f,
- 1.2620f,
- 1.8264f,
- 1.9712f,
- 2.1435f,
- 2.2552f
- },
-
- new[]
- {
- 0.1646f,
- 0.3229f,
- 0.7112f,
- 1.0725f,
- 1.2964f,
- 1.5663f,
- 1.9843f,
- 2.2363f,
- 2.5798f,
- 2.7572f
- },
-
- new[]
- {
- 0.2614f,
- 0.3707f,
- 0.5241f,
- 0.7425f,
- 0.9269f,
- 1.2976f,
- 2.0945f,
- 2.2014f,
- 2.6204f,
- 2.6959f
- },
-
- new[]
- {
- 0.1963f,
- 0.2900f,
- 0.4131f,
- 0.8397f,
- 1.2171f,
- 1.3705f,
- 2.0665f,
- 2.1546f,
- 2.4640f,
- 2.5782f
- },
-
- new[]
- {
- 0.3387f,
- 0.4415f,
- 0.6121f,
- 0.8005f,
- 0.9507f,
- 1.0937f,
- 2.0836f,
- 2.2342f,
- 2.3849f,
- 2.5076f
- },
-
- new[]
- {
- 0.2362f,
- 0.5876f,
- 0.7574f,
- 0.8804f,
- 1.0961f,
- 1.4240f,
- 1.9519f,
- 2.1742f,
- 2.4935f,
- 2.6493f
- },
-
- new[]
- {
- 0.2793f,
- 0.4282f,
- 0.6149f,
- 0.8352f,
- 1.0106f,
- 1.1766f,
- 1.8392f,
- 2.0119f,
- 2.6433f,
- 2.7117f
- },
-
- new[]
- {
- 0.3603f,
- 0.4604f,
- 0.5955f,
- 0.9251f,
- 1.1006f,
- 1.2572f,
- 1.7688f,
- 1.8607f,
- 2.4687f,
- 2.5623f
- },
-
- new[]
- {
- 0.3975f,
- 0.5849f,
- 0.8059f,
- 0.9182f,
- 1.0552f,
- 1.1850f,
- 1.6356f,
- 1.9627f,
- 2.3318f,
- 2.4719f
- },
-
- new[]
- {
- 0.2231f,
- 0.3192f,
- 0.4256f,
- 0.7373f,
- 1.4831f,
- 1.6874f,
- 1.9765f,
- 2.1097f,
- 2.6152f,
- 2.6906f
- },
-
- new[]
- {
- 0.1221f,
- 0.2081f,
- 0.3665f,
- 0.7734f,
- 1.0341f,
- 1.2818f,
- 1.8162f,
- 2.0727f,
- 2.4446f,
- 2.7377f
- },
-
- new[]
- {
- 0.2010f,
- 0.2791f,
- 0.3796f,
- 0.8845f,
- 1.4030f,
- 1.5615f,
- 2.0538f,
- 2.1567f,
- 2.3171f,
- 2.4686f
- },
-
- new[]
- {
- 0.2086f,
- 0.3053f,
- 0.4047f,
- 0.8224f,
- 1.0656f,
- 1.2115f,
- 1.9641f,
- 2.0871f,
- 2.2430f,
- 2.4313f
- },
-
- new[]
- {
- 0.3203f,
- 0.4285f,
- 0.5467f,
- 0.6891f,
- 1.2039f,
- 1.3569f,
- 1.8578f,
- 2.2055f,
- 2.3906f,
- 2.4881f
- },
-
- new[]
- {
- 0.3074f,
- 0.4192f,
- 0.5772f,
- 0.7799f,
- 0.9866f,
- 1.1335f,
- 1.6068f,
- 2.2441f,
- 2.4194f,
- 2.5089f
- },
-
- new[]
- {
- 0.2108f,
- 0.2910f,
- 0.4993f,
- 0.7695f,
- 0.9528f,
- 1.5681f,
- 1.7838f,
- 2.1495f,
- 2.3522f,
- 2.4636f
- },
-
- new[]
- {
- 0.3492f,
- 0.4560f,
- 0.5906f,
- 0.7379f,
- 0.8855f,
- 1.0257f,
- 1.7128f,
- 1.9997f,
- 2.2019f,
- 2.3694f
- },
-
- new[]
- {
- 0.5185f,
- 0.7316f,
- 0.9708f,
- 1.1954f,
- 1.5066f,
- 1.7887f,
- 2.1396f,
- 2.2918f,
- 2.5429f,
- 2.6489f
- },
-
- new[]
- {
- 0.4276f,
- 0.4946f,
- 0.6934f,
- 0.8308f,
- 0.9944f,
- 1.4582f,
- 2.0324f,
- 2.1294f,
- 2.4891f,
- 2.6324f
- },
-
- new[]
- {
- 0.3847f,
- 0.5973f,
- 0.7202f,
- 0.8787f,
- 1.3938f,
- 1.5959f,
- 1.8463f,
- 2.1574f,
- 2.5050f,
- 2.6687f
- },
-
- new[]
- {
- 0.4835f,
- 0.5919f,
- 0.7235f,
- 0.8862f,
- 1.0756f,
- 1.2853f,
- 1.9118f,
- 2.0215f,
- 2.2213f,
- 2.4638f
- },
-
- new[]
- {
- 0.5492f,
- 0.8062f,
- 0.9810f,
- 1.1293f,
- 1.3189f,
- 1.5415f,
- 1.9385f,
- 2.1378f,
- 2.4439f,
- 2.5691f
- },
-
- new[]
- {
- 0.5190f,
- 0.6764f,
- 0.8123f,
- 1.0154f,
- 1.2085f,
- 1.4266f,
- 1.8433f,
- 2.0866f,
- 2.5113f,
- 2.6474f
- },
-
- new[]
- {
- 0.4602f,
- 0.6503f,
- 0.9602f,
- 1.1427f,
- 1.3043f,
- 1.4427f,
- 1.6676f,
- 1.8758f,
- 2.2868f,
- 2.4271f
- },
-
- new[]
- {
- 0.3764f,
- 0.4845f,
- 0.7627f,
- 0.9914f,
- 1.1961f,
- 1.3421f,
- 1.5129f,
- 1.6707f,
- 2.1836f,
- 2.3322f
- },
-
- new[]
- {
- 0.3334f,
- 0.5701f,
- 0.8622f,
- 1.1232f,
- 1.3851f,
- 1.6767f,
- 2.0600f,
- 2.2946f,
- 2.5375f,
- 2.7295f
- },
-
- new[]
- {
- 0.1449f,
- 0.2719f,
- 0.5783f,
- 0.8807f,
- 1.1746f,
- 1.5422f,
- 1.8804f,
- 2.1934f,
- 2.4734f,
- 2.8728f
- },
-
- new[]
- {
- 0.2333f,
- 0.3024f,
- 0.4780f,
- 1.2327f,
- 1.4180f,
- 1.5815f,
- 1.9804f,
- 2.0921f,
- 2.3524f,
- 2.5304f
- },
-
- new[]
- {
- 0.2154f,
- 0.3075f,
- 0.4746f,
- 0.8477f,
- 1.1170f,
- 1.5369f,
- 1.9847f,
- 2.0733f,
- 2.1880f,
- 2.2504f
- },
-
- new[]
- {
- 0.1709f,
- 0.4486f,
- 0.8705f,
- 1.0643f,
- 1.3047f,
- 1.5269f,
- 1.9175f,
- 2.1621f,
- 2.4073f,
- 2.5718f
- },
-
- new[]
- {
- 0.2835f,
- 0.3752f,
- 0.5234f,
- 0.9898f,
- 1.1484f,
- 1.2974f,
- 1.9363f,
- 2.0378f,
- 2.4065f,
- 2.6214f
- },
-
- new[]
- {
- 0.3211f,
- 0.4077f,
- 0.5809f,
- 1.0206f,
- 1.2542f,
- 1.3835f,
- 1.5723f,
- 2.1209f,
- 2.3464f,
- 2.4336f
- },
-
- new[]
- {
- 0.2101f,
- 0.3146f,
- 0.6779f,
- 0.8783f,
- 1.0561f,
- 1.3045f,
- 1.8395f,
- 2.0695f,
- 2.2831f,
- 2.4328f
- }
- };
-
- /*Second Stage Codebook*/
-
- public static float[ /* NC1 */][ /* M */] lspcb2 =
+ 0.1814f,
+ 0.2647f,
+ 0.4580f,
+ 1.1077f,
+ 1.4813f,
+ 1.7022f,
+ 2.1953f,
+ 2.3405f,
+ 2.5867f,
+ 2.6636f
+ },
+
+ new[]
+ {
+ 0.2113f,
+ 0.3223f,
+ 0.4212f,
+ 0.5946f,
+ 0.7479f,
+ 0.9615f,
+ 1.9097f,
+ 2.1750f,
+ 2.4773f,
+ 2.6737f
+ },
+
+ new[]
+ {
+ 0.1915f,
+ 0.2755f,
+ 0.3770f,
+ 0.5950f,
+ 1.3505f,
+ 1.6349f,
+ 2.2348f,
+ 2.3552f,
+ 2.5768f,
+ 2.6540f
+ },
+
+ new[]
+ {
+ 0.2116f,
+ 0.3067f,
+ 0.4099f,
+ 0.5748f,
+ 0.8518f,
+ 1.2569f,
+ 2.0782f,
+ 2.1920f,
+ 2.3371f,
+ 2.4842f
+ },
+
+ new[]
+ {
+ 0.2129f,
+ 0.2974f,
+ 0.4039f,
+ 1.0659f,
+ 1.2735f,
+ 1.4658f,
+ 1.9061f,
+ 2.0312f,
+ 2.6074f,
+ 2.6750f
+ },
+
+ new[]
+ {
+ 0.2181f,
+ 0.2893f,
+ 0.4117f,
+ 0.5519f,
+ 0.8295f,
+ 1.5825f,
+ 2.1575f,
+ 2.3179f,
+ 2.5458f,
+ 2.6417f
+ },
+
+ new[]
+ {
+ 0.1991f,
+ 0.2971f,
+ 0.4104f,
+ 0.7725f,
+ 1.3073f,
+ 1.4665f,
+ 1.6208f,
+ 1.6973f,
+ 2.3732f,
+ 2.5743f
+ },
+
+ new[]
+ {
+ 0.1818f,
+ 0.2886f,
+ 0.4018f,
+ 0.7630f,
+ 1.1264f,
+ 1.2699f,
+ 1.6899f,
+ 1.8650f,
+ 2.1633f,
+ 2.6186f
+ },
+
+ new[]
+ {
+ 0.2282f,
+ 0.3093f,
+ 0.4243f,
+ 0.5329f,
+ 1.1173f,
+ 1.7717f,
+ 1.9420f,
+ 2.0780f,
+ 2.5160f,
+ 2.6137f
+ },
+
+ new[]
+ {
+ 0.2528f,
+ 0.3693f,
+ 0.5290f,
+ 0.7146f,
+ 0.9528f,
+ 1.1269f,
+ 1.2936f,
+ 1.9589f,
+ 2.4548f,
+ 2.6653f
+ },
+
+ new[]
+ {
+ 0.2332f,
+ 0.3263f,
+ 0.4174f,
+ 0.5202f,
+ 1.3633f,
+ 1.8447f,
+ 2.0236f,
+ 2.1474f,
+ 2.3572f,
+ 2.4738f
+ },
+
+ new[]
+ {
+ 0.1393f,
+ 0.2216f,
+ 0.3204f,
+ 0.5644f,
+ 0.7929f,
+ 1.1705f,
+ 1.7051f,
+ 2.0054f,
+ 2.3623f,
+ 2.5985f
+ },
+
+ new[]
+ {
+ 0.2677f,
+ 0.3871f,
+ 0.5746f,
+ 0.7091f,
+ 1.3311f,
+ 1.5260f,
+ 1.7288f,
+ 1.9122f,
+ 2.5787f,
+ 2.6598f
+ },
+
+ new[]
+ {
+ 0.1570f,
+ 0.2328f,
+ 0.3111f,
+ 0.4216f,
+ 1.1688f,
+ 1.4605f,
+ 1.9505f,
+ 2.1173f,
+ 2.4038f,
+ 2.7460f
+ },
+
+ new[]
+ {
+ 0.2346f,
+ 0.3321f,
+ 0.5621f,
+ 0.8160f,
+ 1.4042f,
+ 1.5860f,
+ 1.7518f,
+ 1.8631f,
+ 2.0749f,
+ 2.5380f
+ },
+
+ new[]
+ {
+ 0.2505f,
+ 0.3368f,
+ 0.4758f,
+ 0.6405f,
+ 0.8104f,
+ 1.2533f,
+ 1.9329f,
+ 2.0526f,
+ 2.2155f,
+ 2.6459f
+ },
+
+ new[]
+ {
+ 0.2196f,
+ 0.3049f,
+ 0.6857f,
+ 1.3976f,
+ 1.6100f,
+ 1.7958f,
+ 2.0813f,
+ 2.2211f,
+ 2.4789f,
+ 2.5857f
+ },
+
+ new[]
+ {
+ 0.1232f,
+ 0.2011f,
+ 0.3527f,
+ 0.6969f,
+ 1.1647f,
+ 1.5081f,
+ 1.8593f,
+ 2.2576f,
+ 2.5594f,
+ 2.6896f
+ },
+
+ new[]
+ {
+ 0.3682f,
+ 0.4632f,
+ 0.6600f,
+ 0.9118f,
+ 1.5245f,
+ 1.7071f,
+ 1.8712f,
+ 1.9939f,
+ 2.4356f,
+ 2.5380f
+ },
+
+ new[]
+ {
+ 0.2690f,
+ 0.3711f,
+ 0.4635f,
+ 0.6644f,
+ 1.4633f,
+ 1.6495f,
+ 1.8227f,
+ 1.9983f,
+ 2.1797f,
+ 2.2954f
+ },
+
+ new[]
+ {
+ 0.3555f,
+ 0.5240f,
+ 0.9751f,
+ 1.1685f,
+ 1.4114f,
+ 1.6168f,
+ 1.7769f,
+ 2.0178f,
+ 2.4420f,
+ 2.5724f
+ },
+
+ new[]
+ {
+ 0.3493f,
+ 0.4404f,
+ 0.7231f,
+ 0.8587f,
+ 1.1272f,
+ 1.4715f,
+ 1.6760f,
+ 2.2042f,
+ 2.4735f,
+ 2.5604f
+ },
+
+ new[]
+ {
+ 0.3747f,
+ 0.5263f,
+ 0.7284f,
+ 0.8994f,
+ 1.4017f,
+ 1.5502f,
+ 1.7468f,
+ 1.9816f,
+ 2.2380f,
+ 2.3404f
+ },
+
+ new[]
+ {
+ 0.2972f,
+ 0.4470f,
+ 0.5941f,
+ 0.7078f,
+ 1.2675f,
+ 1.4310f,
+ 1.5930f,
+ 1.9126f,
+ 2.3026f,
+ 2.4208f
+ },
+
+ new[]
+ {
+ 0.2467f,
+ 0.3180f,
+ 0.4712f,
+ 1.1281f,
+ 1.6206f,
+ 1.7876f,
+ 1.9544f,
+ 2.0873f,
+ 2.3521f,
+ 2.4721f
+ },
+
+ new[]
+ {
+ 0.2292f,
+ 0.3430f,
+ 0.4383f,
+ 0.5747f,
+ 1.3497f,
+ 1.5187f,
+ 1.9070f,
+ 2.0958f,
+ 2.2902f,
+ 2.4301f
+ },
+
+ new[]
+ {
+ 0.2573f,
+ 0.3508f,
+ 0.4484f,
+ 0.7079f,
+ 1.6577f,
+ 1.7929f,
+ 1.9456f,
+ 2.0847f,
+ 2.3060f,
+ 2.4208f
+ },
+
+ new[]
+ {
+ 0.1968f,
+ 0.2789f,
+ 0.3594f,
+ 0.4361f,
+ 1.0034f,
+ 1.7040f,
+ 1.9439f,
+ 2.1044f,
+ 2.2696f,
+ 2.4558f
+ },
+
+ new[]
+ {
+ 0.2955f,
+ 0.3853f,
+ 0.7986f,
+ 1.2470f,
+ 1.4723f,
+ 1.6522f,
+ 1.8684f,
+ 2.0084f,
+ 2.2849f,
+ 2.4268f
+ },
+
+ new[]
+ {
+ 0.2036f,
+ 0.3189f,
+ 0.4314f,
+ 0.6393f,
+ 1.2834f,
+ 1.4278f,
+ 1.5796f,
+ 2.0506f,
+ 2.2044f,
+ 2.3656f
+ },
+
+ new[]
+ {
+ 0.2916f,
+ 0.3684f,
+ 0.5907f,
+ 1.1394f,
+ 1.3933f,
+ 1.5540f,
+ 1.8341f,
+ 1.9835f,
+ 2.1301f,
+ 2.2800f
+ },
+
+ new[]
+ {
+ 0.2289f,
+ 0.3402f,
+ 0.5166f,
+ 0.7716f,
+ 1.0614f,
+ 1.2389f,
+ 1.4386f,
+ 2.0769f,
+ 2.2715f,
+ 2.4366f
+ },
+
+ new[]
+ {
+ 0.0829f,
+ 0.1723f,
+ 0.5682f,
+ 0.9773f,
+ 1.3973f,
+ 1.6174f,
+ 1.9242f,
+ 2.2128f,
+ 2.4855f,
+ 2.6327f
+ },
+
+ new[]
+ {
+ 0.2244f,
+ 0.3169f,
+ 0.4368f,
+ 0.5625f,
+ 0.6897f,
+ 1.3763f,
+ 1.7524f,
+ 1.9393f,
+ 2.5121f,
+ 2.6556f
+ },
+
+ new[]
+ {
+ 0.1591f,
+ 0.2387f,
+ 0.2924f,
+ 0.4056f,
+ 1.4677f,
+ 1.6802f,
+ 1.9389f,
+ 2.2067f,
+ 2.4635f,
+ 2.5919f
+ },
+
+ new[]
+ {
+ 0.1756f,
+ 0.2566f,
+ 0.3251f,
+ 0.4227f,
+ 1.0167f,
+ 1.2649f,
+ 1.6801f,
+ 2.1055f,
+ 2.4088f,
+ 2.7276f
+ },
+
+ new[]
+ {
+ 0.1050f,
+ 0.2325f,
+ 0.7445f,
+ 0.9491f,
+ 1.1982f,
+ 1.4658f,
+ 1.8093f,
+ 2.0397f,
+ 2.4155f,
+ 2.5797f
+ },
+
+ new[]
+ {
+ 0.2043f,
+ 0.3324f,
+ 0.4522f,
+ 0.7477f,
+ 0.9361f,
+ 1.1533f,
+ 1.6703f,
+ 1.7631f,
+ 2.5071f,
+ 2.6528f
+ },
+
+ new[]
+ {
+ 0.1522f,
+ 0.2258f,
+ 0.3543f,
+ 0.5504f,
+ 0.8815f,
+ 1.5516f,
+ 1.8110f,
+ 1.9915f,
+ 2.3603f,
+ 2.7735f
+ },
+
+ new[]
+ {
+ 0.1862f,
+ 0.2759f,
+ 0.4715f,
+ 0.6908f,
+ 0.8963f,
+ 1.4341f,
+ 1.6322f,
+ 1.7630f,
+ 2.2027f,
+ 2.6043f
+ },
+
+ new[]
+ {
+ 0.1460f,
+ 0.2254f,
+ 0.3790f,
+ 0.8622f,
+ 1.3394f,
+ 1.5754f,
+ 1.8084f,
+ 2.0798f,
+ 2.4319f,
+ 2.7632f
+ },
+
+ new[]
{
- new[]
- {
- -0.0532f,
- -0.0995f,
- -0.0906f,
- 0.1261f,
- -0.0633f,
- 0.0711f,
- -0.1467f,
- 0.1012f,
- 0.0106f,
- 0.0470f
- },
-
- new[]
- {
- -0.1017f,
- -0.1088f,
- 0.0566f,
- -0.0010f,
- -0.1528f,
- 0.1771f,
- 0.0089f,
- -0.0282f,
- 0.1055f,
- 0.0808f
- },
-
- new[]
- {
- -0.1247f,
- 0.0283f,
- -0.0374f,
- 0.0393f,
- -0.0269f,
- -0.0200f,
- -0.0643f,
- -0.0921f,
- -0.1994f,
- 0.0327f
- },
-
- new[]
- {
- 0.0070f,
- -0.0242f,
- -0.0415f,
- -0.0041f,
- -0.1793f,
- 0.0700f,
- 0.0972f,
- -0.0207f,
- -0.0771f,
- 0.0997f
- },
-
- new[]
- {
- 0.0209f,
- -0.0428f,
- 0.0359f,
- 0.2027f,
- 0.0554f,
- 0.0634f,
- 0.0356f,
- 0.0195f,
- -0.0782f,
- -0.1583f
- },
-
- new[]
- {
- -0.0856f,
- -0.1028f,
- -0.0071f,
- 0.1160f,
- 0.1089f,
- 0.1892f,
- 0.0874f,
- 0.0644f,
- -0.0872f,
- -0.0236f
- },
-
- new[]
- {
- 0.0713f,
- 0.0039f,
- -0.0353f,
- 0.0435f,
- -0.0407f,
- -0.0558f,
- 0.0748f,
- -0.0346f,
- -0.1686f,
- -0.0905f
- },
-
- new[]
- {
- -0.0134f,
- -0.0987f,
- 0.0283f,
- 0.0095f,
- -0.0107f,
- -0.0420f,
- 0.1638f,
- 0.1328f,
- -0.0799f,
- -0.0695f
- },
-
- new[]
- {
- -0.1049f,
- 0.1510f,
- 0.0672f,
- 0.1043f,
- 0.0872f,
- -0.0663f,
- -0.2139f,
- -0.0239f,
- -0.0120f,
- -0.0338f
- },
-
- new[]
- {
- -0.1071f,
- -0.1165f,
- -0.1524f,
- -0.0365f,
- 0.0260f,
- -0.0288f,
- -0.0889f,
- 0.1159f,
- 0.1852f,
- 0.1093f
- },
-
- new[]
- {
- -0.0094f,
- 0.0420f,
- -0.0758f,
- 0.0932f,
- 0.0505f,
- 0.0614f,
- -0.0443f,
- -0.1172f,
- -0.0590f,
- 0.1693f
- },
-
- new[]
- {
- -0.0384f,
- -0.0375f,
- -0.0313f,
- -0.1539f,
- -0.0524f,
- 0.0550f,
- -0.0569f,
- -0.0133f,
- 0.1233f,
- 0.2714f
- },
-
- new[]
- {
- 0.0869f,
- 0.0847f,
- 0.0637f,
- 0.0794f,
- 0.1594f,
- -0.0035f,
- -0.0462f,
- 0.0909f,
- -0.1227f,
- 0.0294f
- },
-
- new[]
- {
- -0.0137f,
- -0.0332f,
- -0.0611f,
- 0.1156f,
- 0.2116f,
- 0.0332f,
- -0.0019f,
- 0.1110f,
- -0.0317f,
- 0.2061f
- },
-
- new[]
- {
- 0.0703f,
- -0.0013f,
- -0.0572f,
- -0.0243f,
- 0.1345f,
- -0.1235f,
- 0.0710f,
- -0.0065f,
- -0.0912f,
- 0.1072f
- },
-
- new[]
- {
- 0.0178f,
- -0.0349f,
- -0.1563f,
- -0.0487f,
- 0.0044f,
- -0.0609f,
- -0.1682f,
- 0.0023f,
- -0.0542f,
- 0.1811f
- },
-
- new[]
- {
- -0.1384f,
- -0.1020f,
- 0.1649f,
- 0.1568f,
- -0.0116f,
- 0.1240f,
- -0.0271f,
- 0.0541f,
- 0.0455f,
- -0.0433f
- },
-
- new[]
- {
- -0.1782f,
- -0.1511f,
- 0.0509f,
- -0.0261f,
- 0.0570f,
- 0.0817f,
- 0.0805f,
- 0.2003f,
- 0.1138f,
- 0.0653f
- },
-
- new[]
- {
- -0.0019f,
- 0.0081f,
- 0.0572f,
- 0.1245f,
- -0.0914f,
- 0.1691f,
- -0.0223f,
- -0.1108f,
- -0.0881f,
- -0.0320f
- },
-
- new[]
- {
- -0.0413f,
- 0.0181f,
- 0.1764f,
- 0.0092f,
- -0.0928f,
- 0.0695f,
- 0.1523f,
- 0.0412f,
- 0.0508f,
- -0.0148f
- },
-
- new[]
- {
- 0.0476f,
- 0.0292f,
- 0.1915f,
- 0.1198f,
- 0.0139f,
- 0.0451f,
- -0.1225f,
- -0.0619f,
- -0.0717f,
- -0.1104f
- },
-
- new[]
- {
- -0.0382f,
- -0.0120f,
- 0.1159f,
- 0.0039f,
- 0.1348f,
- 0.0088f,
- -0.0173f,
- 0.1789f,
- 0.0078f,
- -0.0959f
- },
-
- new[]
- {
- 0.1376f,
- 0.0713f,
- 0.1020f,
- 0.0339f,
- -0.1415f,
- 0.0254f,
- 0.0368f,
- -0.1077f,
- 0.0143f,
- -0.0494f
- },
-
- new[]
- {
- 0.0658f,
- -0.0140f,
- 0.1046f,
- -0.0603f,
- 0.0273f,
- -0.1114f,
- 0.0761f,
- -0.0093f,
- 0.0338f,
- -0.0538f
- },
-
- new[]
- {
- 0.2683f,
- 0.2853f,
- 0.1549f,
- 0.0819f,
- 0.0372f,
- -0.0327f,
- -0.0642f,
- 0.0172f,
- 0.1077f,
- -0.0170f
- },
-
- new[]
- {
- -0.1949f,
- 0.0672f,
- 0.0978f,
- -0.0557f,
- -0.0069f,
- -0.0851f,
- 0.1057f,
- 0.1294f,
- 0.0505f,
- 0.0545f
- },
-
- new[]
- {
- 0.1409f,
- 0.0724f,
- -0.0094f,
- 0.1511f,
- -0.0039f,
- 0.0710f,
- -0.1266f,
- -0.1093f,
- 0.0817f,
- 0.0363f
- },
-
- new[]
- {
- 0.0485f,
- 0.0682f,
- 0.0248f,
- -0.0974f,
- -0.1122f,
- 0.0004f,
- 0.0845f,
- -0.0357f,
- 0.1282f,
- 0.0955f
- },
-
- new[]
- {
- 0.0408f,
- 0.1801f,
- 0.0772f,
- -0.0098f,
- 0.0059f,
- -0.1296f,
- -0.0591f,
- 0.0443f,
- -0.0729f,
- -0.1041f
- },
-
- new[]
- {
- -0.0666f,
- -0.0403f,
- -0.0524f,
- -0.0831f,
- 0.1384f,
- -0.1443f,
- -0.0909f,
- 0.1636f,
- 0.0320f,
- 0.0077f
- },
+ 0.2621f,
+ 0.3792f,
+ 0.5463f,
+ 0.7948f,
+ 1.0043f,
+ 1.1921f,
+ 1.3409f,
+ 1.4845f,
+ 2.3159f,
+ 2.6002f
+ },
+
+ new[]
+ {
+ 0.1935f,
+ 0.2937f,
+ 0.3656f,
+ 0.4927f,
+ 1.4015f,
+ 1.6086f,
+ 1.7724f,
+ 1.8837f,
+ 2.4374f,
+ 2.5971f
+ },
+
+ new[]
+ {
+ 0.2171f,
+ 0.3282f,
+ 0.4412f,
+ 0.5713f,
+ 1.1554f,
+ 1.3506f,
+ 1.5227f,
+ 1.9923f,
+ 2.4100f,
+ 2.5391f
+ },
+
+ new[]
+ {
+ 0.2274f,
+ 0.3157f,
+ 0.4263f,
+ 0.8202f,
+ 1.4293f,
+ 1.5884f,
+ 1.7535f,
+ 1.9688f,
+ 2.3939f,
+ 2.4934f
+ },
+
+ new[]
+ {
+ 0.1704f,
+ 0.2633f,
+ 0.3259f,
+ 0.4134f,
+ 1.2948f,
+ 1.4802f,
+ 1.6619f,
+ 2.0393f,
+ 2.3165f,
+ 2.6083f
+ },
+
+ new[]
+ {
+ 0.1763f,
+ 0.2585f,
+ 0.4012f,
+ 0.7609f,
+ 1.1503f,
+ 1.5847f,
+ 1.8309f,
+ 1.9352f,
+ 2.0982f,
+ 2.6681f
+ },
+
+ new[]
+ {
+ 0.2447f,
+ 0.3535f,
+ 0.4618f,
+ 0.5979f,
+ 0.7530f,
+ 0.8908f,
+ 1.5393f,
+ 2.0075f,
+ 2.3557f,
+ 2.6203f
+ },
+
+ new[]
+ {
+ 0.1826f,
+ 0.3496f,
+ 0.7764f,
+ 0.9888f,
+ 1.3915f,
+ 1.7421f,
+ 1.9412f,
+ 2.1620f,
+ 2.4999f,
+ 2.6931f
+ },
+
+ new[]
+ {
+ 0.3033f,
+ 0.3802f,
+ 0.6981f,
+ 0.8664f,
+ 1.0254f,
+ 1.5401f,
+ 1.7180f,
+ 1.8124f,
+ 2.5068f,
+ 2.6119f
+ },
+
+ new[]
+ {
+ 0.2960f,
+ 0.4001f,
+ 0.6465f,
+ 0.7672f,
+ 1.3782f,
+ 1.5751f,
+ 1.9559f,
+ 2.1373f,
+ 2.3601f,
+ 2.4760f
+ },
+
+ new[]
+ {
+ 0.3132f,
+ 0.4613f,
+ 0.6544f,
+ 0.8532f,
+ 1.0721f,
+ 1.2730f,
+ 1.7566f,
+ 1.9217f,
+ 2.1693f,
+ 2.6531f
+ },
+
+ new[]
+ {
+ 0.3329f,
+ 0.4131f,
+ 0.8073f,
+ 1.1297f,
+ 1.2869f,
+ 1.4937f,
+ 1.7885f,
+ 1.9150f,
+ 2.4505f,
+ 2.5760f
+ },
+
+ new[]
+ {
+ 0.2340f,
+ 0.3605f,
+ 0.7659f,
+ 0.9874f,
+ 1.1854f,
+ 1.3337f,
+ 1.5128f,
+ 2.0062f,
+ 2.4427f,
+ 2.5859f
+ },
+
+ new[]
+ {
+ 0.4131f,
+ 0.5330f,
+ 0.6530f,
+ 0.9360f,
+ 1.3648f,
+ 1.5388f,
+ 1.6994f,
+ 1.8707f,
+ 2.4294f,
+ 2.5335f
+ },
+
+ new[]
+ {
+ 0.3754f,
+ 0.5229f,
+ 0.7265f,
+ 0.9301f,
+ 1.1724f,
+ 1.3440f,
+ 1.5118f,
+ 1.7098f,
+ 2.5218f,
+ 2.6242f
+ },
+
+ new[]
+ {
+ 0.2138f,
+ 0.2998f,
+ 0.6283f,
+ 1.2166f,
+ 1.4187f,
+ 1.6084f,
+ 1.7992f,
+ 2.0106f,
+ 2.5377f,
+ 2.6558f
+ },
+
+ new[]
+ {
+ 0.1761f,
+ 0.2672f,
+ 0.4065f,
+ 0.8317f,
+ 1.0900f,
+ 1.4814f,
+ 1.7672f,
+ 1.8685f,
+ 2.3969f,
+ 2.5079f
+ },
+
+ new[]
+ {
+ 0.2801f,
+ 0.3535f,
+ 0.4969f,
+ 0.9809f,
+ 1.4934f,
+ 1.6378f,
+ 1.8021f,
+ 2.1200f,
+ 2.3135f,
+ 2.4034f
+ },
+
+ new[]
+ {
+ 0.2365f,
+ 0.3246f,
+ 0.5618f,
+ 0.8176f,
+ 1.1073f,
+ 1.5702f,
+ 1.7331f,
+ 1.8592f,
+ 1.9589f,
+ 2.3044f
+ },
+
+ new[]
+ {
+ 0.2529f,
+ 0.3251f,
+ 0.5147f,
+ 1.1530f,
+ 1.3291f,
+ 1.5005f,
+ 1.7028f,
+ 1.8200f,
+ 2.3482f,
+ 2.4831f
+ },
+
+ new[]
+ {
+ 0.2125f,
+ 0.3041f,
+ 0.4259f,
+ 0.9935f,
+ 1.1788f,
+ 1.3615f,
+ 1.6121f,
+ 1.7930f,
+ 2.5509f,
+ 2.6742f
+ },
+
+ new[]
+ {
+ 0.2685f,
+ 0.3518f,
+ 0.5707f,
+ 1.0410f,
+ 1.2270f,
+ 1.3927f,
+ 1.7622f,
+ 1.8876f,
+ 2.0985f,
+ 2.5144f
+ },
+
+ new[]
+ {
+ 0.2373f,
+ 0.3648f,
+ 0.5099f,
+ 0.7373f,
+ 0.9129f,
+ 1.0421f,
+ 1.7312f,
+ 1.8984f,
+ 2.1512f,
+ 2.6342f
+ },
+
+ new[]
+ {
+ 0.2229f,
+ 0.3876f,
+ 0.8621f,
+ 1.1986f,
+ 1.5655f,
+ 1.8861f,
+ 2.2376f,
+ 2.4239f,
+ 2.6648f,
+ 2.7359f
+ },
+
+ new[]
+ {
+ 0.3009f,
+ 0.3719f,
+ 0.5887f,
+ 0.7297f,
+ 0.9395f,
+ 1.8797f,
+ 2.0423f,
+ 2.1541f,
+ 2.5132f,
+ 2.6026f
+ },
+
+ new[]
+ {
+ 0.3114f,
+ 0.4142f,
+ 0.6476f,
+ 0.8448f,
+ 1.2495f,
+ 1.7192f,
+ 2.2148f,
+ 2.3432f,
+ 2.5246f,
+ 2.6046f
+ },
+
+ new[]
+ {
+ 0.3666f,
+ 0.4638f,
+ 0.6496f,
+ 0.7858f,
+ 0.9667f,
+ 1.4213f,
+ 1.9300f,
+ 2.0564f,
+ 2.2119f,
+ 2.3170f
+ },
+
+ new[]
+ {
+ 0.4218f,
+ 0.5075f,
+ 0.8348f,
+ 1.0009f,
+ 1.2057f,
+ 1.5032f,
+ 1.9416f,
+ 2.0540f,
+ 2.4352f,
+ 2.5504f
+ },
+
+ new[]
+ {
+ 0.3726f,
+ 0.4602f,
+ 0.5971f,
+ 0.7093f,
+ 0.8517f,
+ 1.2361f,
+ 1.8052f,
+ 1.9520f,
+ 2.4137f,
+ 2.5518f
+ },
+
+ new[]
+ {
+ 0.4482f,
+ 0.5318f,
+ 0.7114f,
+ 0.8542f,
+ 1.0328f,
+ 1.4751f,
+ 1.7278f,
+ 1.8237f,
+ 2.3496f,
+ 2.4931f
+ },
+
+ new[]
+ {
+ 0.3316f,
+ 0.4498f,
+ 0.6404f,
+ 0.8162f,
+ 1.0332f,
+ 1.2209f,
+ 1.5130f,
+ 1.7250f,
+ 1.9715f,
+ 2.4141f
+ },
+
+ new[]
+ {
+ 0.2375f,
+ 0.3221f,
+ 0.5042f,
+ 0.9760f,
+ 1.7503f,
+ 1.9014f,
+ 2.0822f,
+ 2.2225f,
+ 2.4689f,
+ 2.5632f
+ },
+
+ new[]
+ {
+ 0.2813f,
+ 0.3575f,
+ 0.5032f,
+ 0.5889f,
+ 0.6885f,
+ 1.6040f,
+ 1.9318f,
+ 2.0677f,
+ 2.4546f,
+ 2.5701f
+ },
+
+ new[]
+ {
+ 0.2198f,
+ 0.3072f,
+ 0.4090f,
+ 0.6371f,
+ 1.6365f,
+ 1.9468f,
+ 2.1507f,
+ 2.2633f,
+ 2.5063f,
+ 2.5943f
+ },
+
+ new[]
+ {
+ 0.1754f,
+ 0.2716f,
+ 0.3361f,
+ 0.5550f,
+ 1.1789f,
+ 1.3728f,
+ 1.8527f,
+ 1.9919f,
+ 2.1349f,
+ 2.3359f
+ },
+
+ new[]
+ {
+ 0.2832f,
+ 0.3540f,
+ 0.6080f,
+ 0.8467f,
+ 1.0259f,
+ 1.6467f,
+ 1.8987f,
+ 1.9875f,
+ 2.4744f,
+ 2.5527f
+ },
+
+ new[]
+ {
+ 0.2670f,
+ 0.3564f,
+ 0.5628f,
+ 0.7172f,
+ 0.9021f,
+ 1.5328f,
+ 1.7131f,
+ 2.0501f,
+ 2.5633f,
+ 2.6574f
+ },
+
+ new[]
+ {
+ 0.2729f,
+ 0.3569f,
+ 0.6252f,
+ 0.7641f,
+ 0.9887f,
+ 1.6589f,
+ 1.8726f,
+ 1.9947f,
+ 2.1884f,
+ 2.4609f
+ },
+
+ new[]
+ {
+ 0.2155f,
+ 0.3221f,
+ 0.4580f,
+ 0.6995f,
+ 0.9623f,
+ 1.2339f,
+ 1.6642f,
+ 1.8823f,
+ 2.0518f,
+ 2.2674f
+ },
+
+ new[]
+ {
+ 0.4224f,
+ 0.7009f,
+ 1.1714f,
+ 1.4334f,
+ 1.7595f,
+ 1.9629f,
+ 2.2185f,
+ 2.3304f,
+ 2.5446f,
+ 2.6369f
+ },
+
+ new[]
+ {
+ 0.4560f,
+ 0.5403f,
+ 0.7568f,
+ 0.8989f,
+ 1.1292f,
+ 1.7687f,
+ 1.9575f,
+ 2.0784f,
+ 2.4260f,
+ 2.5484f
+ },
+
+ new[]
+ {
+ 0.4299f,
+ 0.5833f,
+ 0.8408f,
+ 1.0596f,
+ 1.5524f,
+ 1.7484f,
+ 1.9471f,
+ 2.2034f,
+ 2.4617f,
+ 2.5812f
+ },
+
+ new[]
+ {
+ 0.2614f,
+ 0.3624f,
+ 0.8381f,
+ 0.9829f,
+ 1.2220f,
+ 1.6064f,
+ 1.8083f,
+ 1.9362f,
+ 2.1397f,
+ 2.2773f
+ },
+
+ new[]
+ {
+ 0.5064f,
+ 0.7481f,
+ 1.1021f,
+ 1.3271f,
+ 1.5486f,
+ 1.7096f,
+ 1.9503f,
+ 2.1006f,
+ 2.3911f,
+ 2.5141f
+ },
+
+ new[]
+ {
+ 0.5375f,
+ 0.6552f,
+ 0.8099f,
+ 1.0219f,
+ 1.2407f,
+ 1.4160f,
+ 1.8266f,
+ 1.9936f,
+ 2.1951f,
+ 2.2911f
+ },
+
+ new[]
+ {
+ 0.4994f,
+ 0.6575f,
+ 0.8365f,
+ 1.0706f,
+ 1.4116f,
+ 1.6224f,
+ 1.9200f,
+ 2.0667f,
+ 2.3262f,
+ 2.4539f
+ },
+
+ new[]
+ {
+ 0.3353f,
+ 0.4426f,
+ 0.6469f,
+ 0.9161f,
+ 1.2528f,
+ 1.3956f,
+ 1.6080f,
+ 1.8909f,
+ 2.0600f,
+ 2.1380f
+ },
+
+ new[]
+ {
+ 0.2745f,
+ 0.4341f,
+ 1.0424f,
+ 1.2928f,
+ 1.5461f,
+ 1.7940f,
+ 2.0161f,
+ 2.1758f,
+ 2.4742f,
+ 2.5937f
+ },
+
+ new[]
+ {
+ 0.1562f,
+ 0.2393f,
+ 0.4786f,
+ 0.9513f,
+ 1.2395f,
+ 1.8010f,
+ 2.0320f,
+ 2.2143f,
+ 2.5243f,
+ 2.6204f
+ },
+
+ new[]
+ {
+ 0.2979f,
+ 0.4242f,
+ 0.8224f,
+ 1.0564f,
+ 1.4881f,
+ 1.7808f,
+ 2.0898f,
+ 2.1882f,
+ 2.3328f,
+ 2.4389f
+ },
+
+ new[]
+ {
+ 0.2294f,
+ 0.3070f,
+ 0.5490f,
+ 0.9244f,
+ 1.2229f,
+ 1.8248f,
+ 1.9704f,
+ 2.0627f,
+ 2.2458f,
+ 2.3653f
+ },
+
+ new[]
+ {
+ 0.3423f,
+ 0.4502f,
+ 0.9144f,
+ 1.2313f,
+ 1.3694f,
+ 1.5517f,
+ 1.9907f,
+ 2.1326f,
+ 2.4509f,
+ 2.5789f
+ },
+
+ new[]
+ {
+ 0.2470f,
+ 0.3275f,
+ 0.4729f,
+ 1.0093f,
+ 1.2519f,
+ 1.4216f,
+ 1.8540f,
+ 2.0877f,
+ 2.3151f,
+ 2.4156f
+ },
+
+ new[]
+ {
+ 0.3447f,
+ 0.4401f,
+ 0.7099f,
+ 1.0493f,
+ 1.2312f,
+ 1.4001f,
+ 2.0225f,
+ 2.1317f,
+ 2.2894f,
+ 2.4263f
+ },
+
+ new[]
+ {
+ 0.3481f,
+ 0.4494f,
+ 0.6446f,
+ 0.9336f,
+ 1.1198f,
+ 1.2620f,
+ 1.8264f,
+ 1.9712f,
+ 2.1435f,
+ 2.2552f
+ },
+
+ new[]
+ {
+ 0.1646f,
+ 0.3229f,
+ 0.7112f,
+ 1.0725f,
+ 1.2964f,
+ 1.5663f,
+ 1.9843f,
+ 2.2363f,
+ 2.5798f,
+ 2.7572f
+ },
+
+ new[]
+ {
+ 0.2614f,
+ 0.3707f,
+ 0.5241f,
+ 0.7425f,
+ 0.9269f,
+ 1.2976f,
+ 2.0945f,
+ 2.2014f,
+ 2.6204f,
+ 2.6959f
+ },
+
+ new[]
+ {
+ 0.1963f,
+ 0.2900f,
+ 0.4131f,
+ 0.8397f,
+ 1.2171f,
+ 1.3705f,
+ 2.0665f,
+ 2.1546f,
+ 2.4640f,
+ 2.5782f
+ },
+
+ new[]
+ {
+ 0.3387f,
+ 0.4415f,
+ 0.6121f,
+ 0.8005f,
+ 0.9507f,
+ 1.0937f,
+ 2.0836f,
+ 2.2342f,
+ 2.3849f,
+ 2.5076f
+ },
+
+ new[]
+ {
+ 0.2362f,
+ 0.5876f,
+ 0.7574f,
+ 0.8804f,
+ 1.0961f,
+ 1.4240f,
+ 1.9519f,
+ 2.1742f,
+ 2.4935f,
+ 2.6493f
+ },
+
+ new[]
+ {
+ 0.2793f,
+ 0.4282f,
+ 0.6149f,
+ 0.8352f,
+ 1.0106f,
+ 1.1766f,
+ 1.8392f,
+ 2.0119f,
+ 2.6433f,
+ 2.7117f
+ },
+
+ new[]
+ {
+ 0.3603f,
+ 0.4604f,
+ 0.5955f,
+ 0.9251f,
+ 1.1006f,
+ 1.2572f,
+ 1.7688f,
+ 1.8607f,
+ 2.4687f,
+ 2.5623f
+ },
+
+ new[]
+ {
+ 0.3975f,
+ 0.5849f,
+ 0.8059f,
+ 0.9182f,
+ 1.0552f,
+ 1.1850f,
+ 1.6356f,
+ 1.9627f,
+ 2.3318f,
+ 2.4719f
+ },
+
+ new[]
+ {
+ 0.2231f,
+ 0.3192f,
+ 0.4256f,
+ 0.7373f,
+ 1.4831f,
+ 1.6874f,
+ 1.9765f,
+ 2.1097f,
+ 2.6152f,
+ 2.6906f
+ },
+
+ new[]
+ {
+ 0.1221f,
+ 0.2081f,
+ 0.3665f,
+ 0.7734f,
+ 1.0341f,
+ 1.2818f,
+ 1.8162f,
+ 2.0727f,
+ 2.4446f,
+ 2.7377f
+ },
+
+ new[]
+ {
+ 0.2010f,
+ 0.2791f,
+ 0.3796f,
+ 0.8845f,
+ 1.4030f,
+ 1.5615f,
+ 2.0538f,
+ 2.1567f,
+ 2.3171f,
+ 2.4686f
+ },
+
+ new[]
+ {
+ 0.2086f,
+ 0.3053f,
+ 0.4047f,
+ 0.8224f,
+ 1.0656f,
+ 1.2115f,
+ 1.9641f,
+ 2.0871f,
+ 2.2430f,
+ 2.4313f
+ },
+
+ new[]
+ {
+ 0.3203f,
+ 0.4285f,
+ 0.5467f,
+ 0.6891f,
+ 1.2039f,
+ 1.3569f,
+ 1.8578f,
+ 2.2055f,
+ 2.3906f,
+ 2.4881f
+ },
+
+ new[]
+ {
+ 0.3074f,
+ 0.4192f,
+ 0.5772f,
+ 0.7799f,
+ 0.9866f,
+ 1.1335f,
+ 1.6068f,
+ 2.2441f,
+ 2.4194f,
+ 2.5089f
+ },
+
+ new[]
+ {
+ 0.2108f,
+ 0.2910f,
+ 0.4993f,
+ 0.7695f,
+ 0.9528f,
+ 1.5681f,
+ 1.7838f,
+ 2.1495f,
+ 2.3522f,
+ 2.4636f
+ },
+
+ new[]
+ {
+ 0.3492f,
+ 0.4560f,
+ 0.5906f,
+ 0.7379f,
+ 0.8855f,
+ 1.0257f,
+ 1.7128f,
+ 1.9997f,
+ 2.2019f,
+ 2.3694f
+ },
+
+ new[]
+ {
+ 0.5185f,
+ 0.7316f,
+ 0.9708f,
+ 1.1954f,
+ 1.5066f,
+ 1.7887f,
+ 2.1396f,
+ 2.2918f,
+ 2.5429f,
+ 2.6489f
+ },
+
+ new[]
+ {
+ 0.4276f,
+ 0.4946f,
+ 0.6934f,
+ 0.8308f,
+ 0.9944f,
+ 1.4582f,
+ 2.0324f,
+ 2.1294f,
+ 2.4891f,
+ 2.6324f
+ },
+
+ new[]
+ {
+ 0.3847f,
+ 0.5973f,
+ 0.7202f,
+ 0.8787f,
+ 1.3938f,
+ 1.5959f,
+ 1.8463f,
+ 2.1574f,
+ 2.5050f,
+ 2.6687f
+ },
+
+ new[]
+ {
+ 0.4835f,
+ 0.5919f,
+ 0.7235f,
+ 0.8862f,
+ 1.0756f,
+ 1.2853f,
+ 1.9118f,
+ 2.0215f,
+ 2.2213f,
+ 2.4638f
+ },
+
+ new[]
+ {
+ 0.5492f,
+ 0.8062f,
+ 0.9810f,
+ 1.1293f,
+ 1.3189f,
+ 1.5415f,
+ 1.9385f,
+ 2.1378f,
+ 2.4439f,
+ 2.5691f
+ },
+
+ new[]
+ {
+ 0.5190f,
+ 0.6764f,
+ 0.8123f,
+ 1.0154f,
+ 1.2085f,
+ 1.4266f,
+ 1.8433f,
+ 2.0866f,
+ 2.5113f,
+ 2.6474f
+ },
+
+ new[]
+ {
+ 0.4602f,
+ 0.6503f,
+ 0.9602f,
+ 1.1427f,
+ 1.3043f,
+ 1.4427f,
+ 1.6676f,
+ 1.8758f,
+ 2.2868f,
+ 2.4271f
+ },
+
+ new[]
+ {
+ 0.3764f,
+ 0.4845f,
+ 0.7627f,
+ 0.9914f,
+ 1.1961f,
+ 1.3421f,
+ 1.5129f,
+ 1.6707f,
+ 2.1836f,
+ 2.3322f
+ },
+
+ new[]
+ {
+ 0.3334f,
+ 0.5701f,
+ 0.8622f,
+ 1.1232f,
+ 1.3851f,
+ 1.6767f,
+ 2.0600f,
+ 2.2946f,
+ 2.5375f,
+ 2.7295f
+ },
+
+ new[]
+ {
+ 0.1449f,
+ 0.2719f,
+ 0.5783f,
+ 0.8807f,
+ 1.1746f,
+ 1.5422f,
+ 1.8804f,
+ 2.1934f,
+ 2.4734f,
+ 2.8728f
+ },
+
+ new[]
+ {
+ 0.2333f,
+ 0.3024f,
+ 0.4780f,
+ 1.2327f,
+ 1.4180f,
+ 1.5815f,
+ 1.9804f,
+ 2.0921f,
+ 2.3524f,
+ 2.5304f
+ },
+
+ new[]
+ {
+ 0.2154f,
+ 0.3075f,
+ 0.4746f,
+ 0.8477f,
+ 1.1170f,
+ 1.5369f,
+ 1.9847f,
+ 2.0733f,
+ 2.1880f,
+ 2.2504f
+ },
+
+ new[]
+ {
+ 0.1709f,
+ 0.4486f,
+ 0.8705f,
+ 1.0643f,
+ 1.3047f,
+ 1.5269f,
+ 1.9175f,
+ 2.1621f,
+ 2.4073f,
+ 2.5718f
+ },
+
+ new[]
+ {
+ 0.2835f,
+ 0.3752f,
+ 0.5234f,
+ 0.9898f,
+ 1.1484f,
+ 1.2974f,
+ 1.9363f,
+ 2.0378f,
+ 2.4065f,
+ 2.6214f
+ },
+
+ new[]
+ {
+ 0.3211f,
+ 0.4077f,
+ 0.5809f,
+ 1.0206f,
+ 1.2542f,
+ 1.3835f,
+ 1.5723f,
+ 2.1209f,
+ 2.3464f,
+ 2.4336f
+ },
+
+ new[]
+ {
+ 0.2101f,
+ 0.3146f,
+ 0.6779f,
+ 0.8783f,
+ 1.0561f,
+ 1.3045f,
+ 1.8395f,
+ 2.0695f,
+ 2.2831f,
+ 2.4328f
+ }
+ };
+
+ /*Second Stage Codebook*/
+
+ public static readonly float[ /* NC1 */][ /* M */] lspcb2 =
+ {
+ new[]
+ {
+ -0.0532f,
+ -0.0995f,
+ -0.0906f,
+ 0.1261f,
+ -0.0633f,
+ 0.0711f,
+ -0.1467f,
+ 0.1012f,
+ 0.0106f,
+ 0.0470f
+ },
+
+ new[]
+ {
+ -0.1017f,
+ -0.1088f,
+ 0.0566f,
+ -0.0010f,
+ -0.1528f,
+ 0.1771f,
+ 0.0089f,
+ -0.0282f,
+ 0.1055f,
+ 0.0808f
+ },
+
+ new[]
+ {
+ -0.1247f,
+ 0.0283f,
+ -0.0374f,
+ 0.0393f,
+ -0.0269f,
+ -0.0200f,
+ -0.0643f,
+ -0.0921f,
+ -0.1994f,
+ 0.0327f
+ },
+
+ new[]
+ {
+ 0.0070f,
+ -0.0242f,
+ -0.0415f,
+ -0.0041f,
+ -0.1793f,
+ 0.0700f,
+ 0.0972f,
+ -0.0207f,
+ -0.0771f,
+ 0.0997f
+ },
+
+ new[]
+ {
+ 0.0209f,
+ -0.0428f,
+ 0.0359f,
+ 0.2027f,
+ 0.0554f,
+ 0.0634f,
+ 0.0356f,
+ 0.0195f,
+ -0.0782f,
+ -0.1583f
+ },
+
+ new[]
+ {
+ -0.0856f,
+ -0.1028f,
+ -0.0071f,
+ 0.1160f,
+ 0.1089f,
+ 0.1892f,
+ 0.0874f,
+ 0.0644f,
+ -0.0872f,
+ -0.0236f
+ },
+
+ new[]
+ {
+ 0.0713f,
+ 0.0039f,
+ -0.0353f,
+ 0.0435f,
+ -0.0407f,
+ -0.0558f,
+ 0.0748f,
+ -0.0346f,
+ -0.1686f,
+ -0.0905f
+ },
+
+ new[]
+ {
+ -0.0134f,
+ -0.0987f,
+ 0.0283f,
+ 0.0095f,
+ -0.0107f,
+ -0.0420f,
+ 0.1638f,
+ 0.1328f,
+ -0.0799f,
+ -0.0695f
+ },
+
+ new[]
+ {
+ -0.1049f,
+ 0.1510f,
+ 0.0672f,
+ 0.1043f,
+ 0.0872f,
+ -0.0663f,
+ -0.2139f,
+ -0.0239f,
+ -0.0120f,
+ -0.0338f
+ },
+
+ new[]
+ {
+ -0.1071f,
+ -0.1165f,
+ -0.1524f,
+ -0.0365f,
+ 0.0260f,
+ -0.0288f,
+ -0.0889f,
+ 0.1159f,
+ 0.1852f,
+ 0.1093f
+ },
+
+ new[]
+ {
+ -0.0094f,
+ 0.0420f,
+ -0.0758f,
+ 0.0932f,
+ 0.0505f,
+ 0.0614f,
+ -0.0443f,
+ -0.1172f,
+ -0.0590f,
+ 0.1693f
+ },
+
+ new[]
+ {
+ -0.0384f,
+ -0.0375f,
+ -0.0313f,
+ -0.1539f,
+ -0.0524f,
+ 0.0550f,
+ -0.0569f,
+ -0.0133f,
+ 0.1233f,
+ 0.2714f
+ },
+
+ new[]
+ {
+ 0.0869f,
+ 0.0847f,
+ 0.0637f,
+ 0.0794f,
+ 0.1594f,
+ -0.0035f,
+ -0.0462f,
+ 0.0909f,
+ -0.1227f,
+ 0.0294f
+ },
+
+ new[]
+ {
+ -0.0137f,
+ -0.0332f,
+ -0.0611f,
+ 0.1156f,
+ 0.2116f,
+ 0.0332f,
+ -0.0019f,
+ 0.1110f,
+ -0.0317f,
+ 0.2061f
+ },
+
+ new[]
+ {
+ 0.0703f,
+ -0.0013f,
+ -0.0572f,
+ -0.0243f,
+ 0.1345f,
+ -0.1235f,
+ 0.0710f,
+ -0.0065f,
+ -0.0912f,
+ 0.1072f
+ },
+
+ new[]
+ {
+ 0.0178f,
+ -0.0349f,
+ -0.1563f,
+ -0.0487f,
+ 0.0044f,
+ -0.0609f,
+ -0.1682f,
+ 0.0023f,
+ -0.0542f,
+ 0.1811f
+ },
+
+ new[]
+ {
+ -0.1384f,
+ -0.1020f,
+ 0.1649f,
+ 0.1568f,
+ -0.0116f,
+ 0.1240f,
+ -0.0271f,
+ 0.0541f,
+ 0.0455f,
+ -0.0433f
+ },
+
+ new[]
+ {
+ -0.1782f,
+ -0.1511f,
+ 0.0509f,
+ -0.0261f,
+ 0.0570f,
+ 0.0817f,
+ 0.0805f,
+ 0.2003f,
+ 0.1138f,
+ 0.0653f
+ },
+
+ new[]
+ {
+ -0.0019f,
+ 0.0081f,
+ 0.0572f,
+ 0.1245f,
+ -0.0914f,
+ 0.1691f,
+ -0.0223f,
+ -0.1108f,
+ -0.0881f,
+ -0.0320f
+ },
+
+ new[]
+ {
+ -0.0413f,
+ 0.0181f,
+ 0.1764f,
+ 0.0092f,
+ -0.0928f,
+ 0.0695f,
+ 0.1523f,
+ 0.0412f,
+ 0.0508f,
+ -0.0148f
+ },
+
+ new[]
+ {
+ 0.0476f,
+ 0.0292f,
+ 0.1915f,
+ 0.1198f,
+ 0.0139f,
+ 0.0451f,
+ -0.1225f,
+ -0.0619f,
+ -0.0717f,
+ -0.1104f
+ },
+
+ new[]
+ {
+ -0.0382f,
+ -0.0120f,
+ 0.1159f,
+ 0.0039f,
+ 0.1348f,
+ 0.0088f,
+ -0.0173f,
+ 0.1789f,
+ 0.0078f,
+ -0.0959f
+ },
+
+ new[]
+ {
+ 0.1376f,
+ 0.0713f,
+ 0.1020f,
+ 0.0339f,
+ -0.1415f,
+ 0.0254f,
+ 0.0368f,
+ -0.1077f,
+ 0.0143f,
+ -0.0494f
+ },
+
+ new[]
+ {
+ 0.0658f,
+ -0.0140f,
+ 0.1046f,
+ -0.0603f,
+ 0.0273f,
+ -0.1114f,
+ 0.0761f,
+ -0.0093f,
+ 0.0338f,
+ -0.0538f
+ },
+
+ new[]
+ {
+ 0.2683f,
+ 0.2853f,
+ 0.1549f,
+ 0.0819f,
+ 0.0372f,
+ -0.0327f,
+ -0.0642f,
+ 0.0172f,
+ 0.1077f,
+ -0.0170f
+ },
+
+ new[]
+ {
+ -0.1949f,
+ 0.0672f,
+ 0.0978f,
+ -0.0557f,
+ -0.0069f,
+ -0.0851f,
+ 0.1057f,
+ 0.1294f,
+ 0.0505f,
+ 0.0545f
+ },
+
+ new[]
+ {
+ 0.1409f,
+ 0.0724f,
+ -0.0094f,
+ 0.1511f,
+ -0.0039f,
+ 0.0710f,
+ -0.1266f,
+ -0.1093f,
+ 0.0817f,
+ 0.0363f
+ },
+
+ new[]
+ {
+ 0.0485f,
+ 0.0682f,
+ 0.0248f,
+ -0.0974f,
+ -0.1122f,
+ 0.0004f,
+ 0.0845f,
+ -0.0357f,
+ 0.1282f,
+ 0.0955f
+ },
+
+ new[]
+ {
+ 0.0408f,
+ 0.1801f,
+ 0.0772f,
+ -0.0098f,
+ 0.0059f,
+ -0.1296f,
+ -0.0591f,
+ 0.0443f,
+ -0.0729f,
+ -0.1041f
+ },
+
+ new[]
+ {
+ -0.0666f,
+ -0.0403f,
+ -0.0524f,
+ -0.0831f,
+ 0.1384f,
+ -0.1443f,
+ -0.0909f,
+ 0.1636f,
+ 0.0320f,
+ 0.0077f
+ },
+
+ new[]
+ {
+ 0.1612f,
+ 0.1010f,
+ -0.0486f,
+ -0.0704f,
+ 0.0417f,
+ -0.0945f,
+ -0.0590f,
+ -0.1523f,
+ -0.0086f,
+ 0.0120f
+ },
+
+ new[]
+ {
+ -0.0199f,
+ 0.0823f,
+ -0.0014f,
+ -0.1082f,
+ 0.0649f,
+ -0.1374f,
+ -0.0324f,
+ -0.0296f,
+ 0.0885f,
+ 0.1141f
+ }
+ };
+
+ public static readonly float[ /* M */] lwindow =
+ {
+ 0.99879038f,
+ 0.99546894f,
+ 0.98995779f,
+ 0.98229335f,
+ 0.97252620f,
+ 0.96072035f,
+ 0.94695264f,
+ 0.93131180f,
+ 0.91389754f,
+ 0.89481964f
+ };
+
+ public static readonly int[ /* NCODE1 */] map1 =
+ {
+ 5,
+ 1,
+ 4,
+ 7,
+ 3,
+ 0,
+ 6,
+ 2
+ };
+
+ public static readonly int[ /* NCODE2 */] map2 =
+ {
+ 4,
+ 6,
+ 0,
+ 2,
+ 12,
+ 14,
+ 8,
+ 10,
+ 15,
+ 11,
+ 9,
+ 13,
+ 7,
+ 3,
+ 1,
+ 5
+ };
+
+ public static readonly float[ /* 4 */] pred =
+ {
+ 0.68f,
+ 0.58f,
+ 0.34f,
+ 0.19f
+ };
- new[]
- {
- 0.1612f,
- 0.1010f,
- -0.0486f,
- -0.0704f,
- 0.0417f,
- -0.0945f,
- -0.0590f,
- -0.1523f,
- -0.0086f,
- 0.0120f
- },
+ public static readonly float[ /* SIZ_TAB_HUP_L */] tab_hup_l =
+ {
+ -0.001246f,
+ 0.002200f,
+ -0.004791f,
+ 0.009621f,
+ -0.017685f,
+ 0.031212f,
+ -0.057225f,
+ 0.135470f,
+ 0.973955f,
+ -0.103495f,
+ 0.048663f,
+ -0.027090f,
+ 0.015280f,
+ -0.008160f,
+ 0.003961f,
+ -0.001827f,
+ -0.002388f,
+ 0.004479f,
+ -0.009715f,
+ 0.019261f,
+ -0.035118f,
+ 0.061945f,
+ -0.115187f,
+ 0.294161f,
+ 0.898322f,
+ -0.170283f,
+ 0.083211f,
+ -0.046645f,
+ 0.026210f,
+ -0.013854f,
+ 0.006641f,
+ -0.003099f,
+ -0.003277f,
+ 0.006456f,
+ -0.013906f,
+ 0.027229f,
+ -0.049283f,
+ 0.086990f,
+ -0.164590f,
+ 0.464041f,
+ 0.780309f,
+ -0.199879f,
+ 0.100795f,
+ -0.056792f,
+ 0.031761f,
+ -0.016606f,
+ 0.007866f,
+ -0.003740f,
+ -0.003770f,
+ 0.007714f,
+ -0.016462f,
+ 0.031849f,
+ -0.057272f,
+ 0.101294f,
+ -0.195755f,
+ 0.630993f,
+ 0.630993f,
+ -0.195755f,
+ 0.101294f,
+ -0.057272f,
+ 0.031849f,
+ -0.016462f,
+ 0.007714f,
+ -0.003770f,
+ -0.003740f,
+ 0.007866f,
+ -0.016606f,
+ 0.031761f,
+ -0.056792f,
+ 0.100795f,
+ -0.199879f,
+ 0.780309f,
+ 0.464041f,
+ -0.164590f,
+ 0.086990f,
+ -0.049283f,
+ 0.027229f,
+ -0.013906f,
+ 0.006456f,
+ -0.003277f,
+ -0.003099f,
+ 0.006641f,
+ -0.013854f,
+ 0.026210f,
+ -0.046645f,
+ 0.083211f,
+ -0.170283f,
+ 0.898322f,
+ 0.294161f,
+ -0.115187f,
+ 0.061945f,
+ -0.035118f,
+ 0.019261f,
+ -0.009715f,
+ 0.004479f,
+ -0.002388f,
+ -0.001827f,
+ 0.003961f,
+ -0.008160f,
+ 0.015280f,
+ -0.027090f,
+ 0.048663f,
+ -0.103495f,
+ 0.973955f,
+ 0.135470f,
+ -0.057225f,
+ 0.031212f,
+ -0.017685f,
+ 0.009621f,
+ -0.004791f,
+ 0.002200f,
+ -0.001246f
+ };
+
+ public static readonly float[ /* SIZ_TAB_HUP_S */] tab_hup_s =
+ {
+ -0.005772f,
+ 0.087669f,
+ 0.965882f,
+ -0.048753f,
+ -0.014793f,
+ 0.214886f,
+ 0.868791f,
+ -0.065537f,
+ -0.028507f,
+ 0.374334f,
+ 0.723418f,
+ -0.060834f,
+ -0.045567f,
+ 0.550847f,
+ 0.550847f,
+ -0.045567f,
+ -0.060834f,
+ 0.723418f,
+ 0.374334f,
+ -0.028507f,
+ -0.065537f,
+ 0.868791f,
+ 0.214886f,
+ -0.014793f,
+ -0.048753f,
+ 0.965882f,
+ 0.087669f,
+ -0.005772f
+ };
+
+ public static readonly float[ /* NCODE1-NCAN1 */] thr1 =
+ {
+ 0.659681f,
+ 0.755274f,
+ 1.207205f,
+ 1.987740f
+ };
- new[]
- {
- -0.0199f,
- 0.0823f,
- -0.0014f,
- -0.1082f,
- 0.0649f,
- -0.1374f,
- -0.0324f,
- -0.0296f,
- 0.0885f,
- 0.1141f
- }
- };
-
- public static float[ /* M */] lwindow =
- {
- 0.99879038f,
- 0.99546894f,
- 0.98995779f,
- 0.98229335f,
- 0.97252620f,
- 0.96072035f,
- 0.94695264f,
- 0.93131180f,
- 0.91389754f,
- 0.89481964f
- };
-
- public static int[ /* NCODE1 */] map1 =
- {
- 5,
- 1,
- 4,
- 7,
- 3,
- 0,
- 6,
- 2
- };
-
- public static int[ /* NCODE2 */] map2 =
- {
- 4,
- 6,
- 0,
- 2,
- 12,
- 14,
- 8,
- 10,
- 15,
- 11,
- 9,
- 13,
- 7,
- 3,
- 1,
- 5
- };
-
- public static float[ /* 4 */] pred =
- {
- 0.68f,
- 0.58f,
- 0.34f,
- 0.19f
- };
-
- public static float[ /* SIZ_TAB_HUP_L */] tab_hup_l =
- {
- -0.001246f,
- 0.002200f,
- -0.004791f,
- 0.009621f,
- -0.017685f,
- 0.031212f,
- -0.057225f,
- 0.135470f,
- 0.973955f,
- -0.103495f,
- 0.048663f,
- -0.027090f,
- 0.015280f,
- -0.008160f,
- 0.003961f,
- -0.001827f,
- -0.002388f,
- 0.004479f,
- -0.009715f,
- 0.019261f,
- -0.035118f,
- 0.061945f,
- -0.115187f,
- 0.294161f,
- 0.898322f,
- -0.170283f,
- 0.083211f,
- -0.046645f,
- 0.026210f,
- -0.013854f,
- 0.006641f,
- -0.003099f,
- -0.003277f,
- 0.006456f,
- -0.013906f,
- 0.027229f,
- -0.049283f,
- 0.086990f,
- -0.164590f,
- 0.464041f,
- 0.780309f,
- -0.199879f,
- 0.100795f,
- -0.056792f,
- 0.031761f,
- -0.016606f,
- 0.007866f,
- -0.003740f,
- -0.003770f,
- 0.007714f,
- -0.016462f,
- 0.031849f,
- -0.057272f,
- 0.101294f,
- -0.195755f,
- 0.630993f,
- 0.630993f,
- -0.195755f,
- 0.101294f,
- -0.057272f,
- 0.031849f,
- -0.016462f,
- 0.007714f,
- -0.003770f,
- -0.003740f,
- 0.007866f,
- -0.016606f,
- 0.031761f,
- -0.056792f,
- 0.100795f,
- -0.199879f,
- 0.780309f,
- 0.464041f,
- -0.164590f,
- 0.086990f,
- -0.049283f,
- 0.027229f,
- -0.013906f,
- 0.006456f,
- -0.003277f,
- -0.003099f,
- 0.006641f,
- -0.013854f,
- 0.026210f,
- -0.046645f,
- 0.083211f,
- -0.170283f,
- 0.898322f,
- 0.294161f,
- -0.115187f,
- 0.061945f,
- -0.035118f,
- 0.019261f,
- -0.009715f,
- 0.004479f,
- -0.002388f,
- -0.001827f,
- 0.003961f,
- -0.008160f,
- 0.015280f,
- -0.027090f,
- 0.048663f,
- -0.103495f,
- 0.973955f,
- 0.135470f,
- -0.057225f,
- 0.031212f,
- -0.017685f,
- 0.009621f,
- -0.004791f,
- 0.002200f,
- -0.001246f
- };
-
- public static float[ /* SIZ_TAB_HUP_S */] tab_hup_s =
- {
- -0.005772f,
- 0.087669f,
- 0.965882f,
- -0.048753f,
- -0.014793f,
- 0.214886f,
- 0.868791f,
- -0.065537f,
- -0.028507f,
- 0.374334f,
- 0.723418f,
- -0.060834f,
- -0.045567f,
- 0.550847f,
- 0.550847f,
- -0.045567f,
- -0.060834f,
- 0.723418f,
- 0.374334f,
- -0.028507f,
- -0.065537f,
- 0.868791f,
- 0.214886f,
- -0.014793f,
- -0.048753f,
- 0.965882f,
- 0.087669f,
- -0.005772f
- };
-
- public static float[ /* NCODE1-NCAN1 */] thr1 =
- {
- 0.659681f,
- 0.755274f,
- 1.207205f,
- 1.987740f
- };
-
- public static float[ /* NCODE2-NCAN2 */] thr2 =
- {
- 0.429912f,
- 0.494045f,
- 0.618737f,
- 0.650676f,
- 0.717949f,
- 0.770050f,
- 0.850628f,
- 0.932089f
- };
- }
-}
\ No newline at end of file
+ public static readonly float[ /* NCODE2-NCAN2 */] thr2 =
+ {
+ 0.429912f,
+ 0.494045f,
+ 0.618737f,
+ 0.650676f,
+ 0.717949f,
+ 0.770050f,
+ 0.850628f,
+ 0.932089f
+ };
+}
diff --git a/src/SIPSorcery/app/Media/Codecs/G729Codec/Taming.cs b/src/SIPSorcery/app/Media/Codecs/G729Codec/Taming.cs
index a8a09711d..fa601a299 100644
--- a/src/SIPSorcery/app/Media/Codecs/G729Codec/Taming.cs
+++ b/src/SIPSorcery/app/Media/Codecs/G729Codec/Taming.cs
@@ -24,131 +24,159 @@
*
* @author Lubomir Marinov (translation of ITU-T C source code to Java)
*/
-namespace SIPSorcery.Media.G729Codec
+namespace SIPSorcery.Media.G729Codec;
+
+internal sealed class Taming
{
- internal class Taming
- {
- /* ITU-T G.729 Software Package Release 2 (November 2006) */
- /*
- ITU-T G.729 Annex C - Reference C code for floating point
- implementation of G.729
- Version 1.01 of 15.September.98
+ /* ITU-T G.729 Software Package Release 2 (November 2006) */
+ /*
+ITU-T G.729 Annex C - Reference C code for floating point
+ implementation of G.729
+ Version 1.01 of 15.September.98
*/
- /*
+ /*
----------------------------------------------------------------------
- COPYRIGHT NOTICE
+ COPYRIGHT NOTICE
----------------------------------------------------------------------
- ITU-T G.729 Annex C ANSI C source code
- Copyright (C) 1998, AT&T, France Telecom, NTT, University of
- Sherbrooke. All rights reserved.
+ITU-T G.729 Annex C ANSI C source code
+Copyright (C) 1998, AT&T, France Telecom, NTT, University of
+Sherbrooke. All rights reserved.
----------------------------------------------------------------------
*/
- /*
- File : TAMING.C
- Used for the floating point version of both
- G.729 main body and G.729A
+ /*
+File : TAMING.C
+Used for the floating point version of both
+G.729 main body and G.729A
*/
- private readonly float[] exc_err = new float[4];
+ private readonly float[] exc_err = new float[4];
- public void init_exc_err()
+ public void init_exc_err()
+ {
+ int i;
+ for (i = 0; i < 4; i++)
{
- int i;
- for (i = 0; i < 4; i++) exc_err[i] = 1.0f;
+ exc_err[i] = 1.0f;
}
+ }
- /**
- * Computes the accumulated potential error in the
- * adaptive codebook contribution
- *
- * @param t0 (i) integer part of pitch delay
- * @param t0_frac (i) fractional part of pitch delay
- * @return flag set to 1 if taming is necessary
- */
+ /**
+* Computes the accumulated potential error in the
+* adaptive codebook contribution
+*
+* @param t0 (i) integer part of pitch delay
+* @param t0_frac (i) fractional part of pitch delay
+* @return flag set to 1 if taming is necessary
+*/
- public int test_err(
- int t0,
- int t0_frac
- )
- {
- var INV_L_SUBFR = Ld8k.INV_L_SUBFR;
- var L_INTER10 = Ld8k.L_INTER10;
- var L_SUBFR = Ld8k.L_SUBFR;
- var THRESH_ERR = Ld8k.THRESH_ERR;
+ public int test_err(
+ int t0,
+ int t0_frac
+ )
+ {
+ var INV_L_SUBFR = Ld8k.INV_L_SUBFR;
+ var L_INTER10 = Ld8k.L_INTER10;
+ var L_SUBFR = Ld8k.L_SUBFR;
+ var THRESH_ERR = Ld8k.THRESH_ERR;
- int i, t1, zone1, zone2, flag;
- float maxloc;
+ int i, t1, zone1, zone2, flag;
+ float maxloc;
- t1 = t0_frac > 0 ? t0 + 1 : t0;
+ t1 = t0_frac > 0 ? t0 + 1 : t0;
- i = t1 - L_SUBFR - L_INTER10;
- if (i < 0) i = 0;
- zone1 = (int)(i * INV_L_SUBFR);
+ i = t1 - L_SUBFR - L_INTER10;
+ if (i < 0)
+ {
+ i = 0;
+ }
- i = t1 + L_INTER10 - 2;
- zone2 = (int)(i * INV_L_SUBFR);
+ zone1 = (int)(i * INV_L_SUBFR);
- maxloc = -1.0f;
- flag = 0;
- for (i = zone2; i >= zone1; i--)
- if (exc_err[i] > maxloc)
- maxloc = exc_err[i];
- if (maxloc > THRESH_ERR)
- flag = 1;
- return flag;
- }
+ i = t1 + L_INTER10 - 2;
+ zone2 = (int)(i * INV_L_SUBFR);
- /**
- * Maintains the memory used to compute the error
- * function due to an adaptive codebook mismatch between encoder and
- * decoder
- *
- * @param gain_pit (i) pitch gain
- * @param t0 (i) integer part of pitch delay
- */
+ maxloc = -1.0f;
+ flag = 0;
+ for (i = zone2; i >= zone1; i--)
+ {
+ if (exc_err[i] > maxloc)
+ {
+ maxloc = exc_err[i];
+ }
+ }
- public void update_exc_err(
- float gain_pit,
- int t0
- )
+ if (maxloc > THRESH_ERR)
{
- var INV_L_SUBFR = Ld8k.INV_L_SUBFR;
- var L_SUBFR = Ld8k.L_SUBFR;
+ flag = 1;
+ }
- int i, zone1, zone2, n;
- float worst, temp;
+ return flag;
+ }
- worst = (float)-1.0;
+ /**
+* Maintains the memory used to compute the error
+* function due to an adaptive codebook mismatch between encoder and
+* decoder
+*
+* @param gain_pit (i) pitch gain
+* @param t0 (i) integer part of pitch delay
+*/
- n = t0 - L_SUBFR;
- if (n < 0)
+ public void update_exc_err(
+ float gain_pit,
+ int t0
+ )
+ {
+ var INV_L_SUBFR = Ld8k.INV_L_SUBFR;
+ var L_SUBFR = Ld8k.L_SUBFR;
+
+ int i, zone1, zone2, n;
+ float worst, temp;
+
+ worst = (float)-1.0;
+
+ n = t0 - L_SUBFR;
+ if (n < 0)
+ {
+ temp = 1.0f + gain_pit * exc_err[0];
+ if (temp > worst)
{
- temp = 1.0f + gain_pit * exc_err[0];
- if (temp > worst) worst = temp;
- temp = 1.0f + gain_pit * temp;
- if (temp > worst) worst = temp;
+ worst = temp;
}
- else
+ temp = 1.0f + gain_pit * temp;
+ if (temp > worst)
{
- zone1 = (int)(n * INV_L_SUBFR);
+ worst = temp;
+ }
+ }
- i = t0 - 1;
- zone2 = (int)(i * INV_L_SUBFR);
+ else
+ {
+ zone1 = (int)(n * INV_L_SUBFR);
+
+ i = t0 - 1;
+ zone2 = (int)(i * INV_L_SUBFR);
- for (i = zone1; i <= zone2; i++)
+ for (i = zone1; i <= zone2; i++)
+ {
+ temp = 1.0f + gain_pit * exc_err[i];
+ if (temp > worst)
{
- temp = 1.0f + gain_pit * exc_err[i];
- if (temp > worst) worst = temp;
+ worst = temp;
}
}
+ }
- for (i = 3; i >= 1; i--) exc_err[i] = exc_err[i - 1];
- exc_err[0] = worst;
+ for (i = 3; i >= 1; i--)
+ {
+ exc_err[i] = exc_err[i - 1];
}
+
+ exc_err[0] = worst;
}
-}
\ No newline at end of file
+}
diff --git a/src/SIPSorcery/app/Media/Codecs/G729Codec/Util.cs b/src/SIPSorcery/app/Media/Codecs/G729Codec/Util.cs
index 5b4aa554a..f37729d82 100644
--- a/src/SIPSorcery/app/Media/Codecs/G729Codec/Util.cs
+++ b/src/SIPSorcery/app/Media/Codecs/G729Codec/Util.cs
@@ -26,189 +26,144 @@
*/
using System.IO;
-namespace SIPSorcery.Media.G729Codec
+namespace SIPSorcery.Media.G729Codec;
+
+public static class Util
{
- public class Util
- {
- /* Random generator */
- private static short seed = 21845;
+ /* Random generator */
+ private static short seed = 21845;
- /* ITU-T G.729 Software Package Release 2 (November 2006) */
- /*
- ITU-T G.729 Annex C - Reference C code for floating point
- implementation of G.729
- Version 1.01 of 15.September.98
+ /* ITU-T G.729 Software Package Release 2 (November 2006) */
+ /*
+ITU-T G.729 Annex C - Reference C code for floating point
+ implementation of G.729
+ Version 1.01 of 15.September.98
*/
- /*
+ /*
----------------------------------------------------------------------
- COPYRIGHT NOTICE
+ COPYRIGHT NOTICE
----------------------------------------------------------------------
- ITU-T G.729 Annex C ANSI C source code
- Copyright (C) 1998, AT&T, France Telecom, NTT, University of
- Sherbrooke. All rights reserved.
+ITU-T G.729 Annex C ANSI C source code
+Copyright (C) 1998, AT&T, France Telecom, NTT, University of
+Sherbrooke. All rights reserved.
----------------------------------------------------------------------
*/
- /*
- File : UTIL.C
- Used for the floating point version of both
- G.729 main body and G.729A
+ /*
+File : UTIL.C
+Used for the floating point version of both
+G.729 main body and G.729A
*/
- /**
- * Assigns the value zero to element of the specified array of floats.
- * The number of components set to zero equal to the length argument.
- *
- * @param x (o) : vector to clear
- * @param L (i) : length of vector
- */
- public static void set_zero(
- float[] x,
- int L
- )
- {
- set_zero(x, 0, L);
- }
-
- /**
- * Assigns the value zero to element of the specified array of floats.
- * The number of components set to zero equal to the length argument.
- * The components at positions offset through offset+length-1 in the
- * array are set to zero.
- *
- * @param x (o) : vector to clear
- * @param offset (i) : offset of vector
- * @param length (i) : length of vector
- */
- public static void set_zero(float[] x, int offset, int length)
- {
- for (int i = offset, toIndex = offset + length; i < toIndex; i++)
- x[i] = 0.0f;
- }
-
- /**
- * Copies an array from the specified x array, to the specified y array.
- * The number of components copied is equal to the length argument.
- *
- * @param x (i) : input vector
- * @param y (o) : output vector
- * @param L (i) : vector length
- */
- public static void copy(
- float[] x,
- float[] y,
- int L
- )
- {
- copy(x, 0, y, L);
- }
-
- /**
- * Copies an array from the specified source array,
- * beginning at the specified destination array.
- * A subsequence of array components are copied from the source array referenced
- * by x to the destination array referenced by y.
- * The number of components copied is equal to the length argument.
- * The components at positions x_offset through x_offset+length-1 in the source
- * array are copied into positions 0 through length-1,
- * respectively, of the destination array.
- *
- * @param x (i) : input vector
- * @param x_offset (i) : input vector offset
- * @param y (o) : output vector
- * @param L (i) : vector length
- */
- public static void copy(float[] x, int x_offset, float[] y, int L)
- {
- copy(x, x_offset, y, 0, L);
- }
+ /**
+* Assigns the value zero to element of the specified array of floats.
+* The number of components set to zero equal to the length argument.
+*
+* @param x (o) : vector to clear
+* @param L (i) : length of vector
+*/
+ public static void set_zero(
+ float[] x,
+ int L
+ )
+ {
+ set_zero(x, 0, L);
+ }
- /**
- * Copies an array from the specified source array,
- * beginning at the specified position,
- * to the specified position of the destination array.
- * A subsequence of array components are copied from the source array referenced
- * by x to the destination array referenced by y.
- * The number of components copied is equal to the length argument.
- * The components at positions x_offset through x_offset+length-1 in the source
- * array are copied into positions y_offset through y_offset+length-1,
- * respectively, of the destination array.
- *
- * @param x (i) : input vector
- * @param x_offset (i) : input vector offset
- * @param y (o) : output vector
- * @param y_offset (i) : output vector offset
- * @param L (i) : vector length
- */
- public static void copy(float[] x, int x_offset, float[] y, int y_offset, int L)
+ /**
+* Assigns the value zero to element of the specified array of floats.
+* The number of components set to zero equal to the length argument.
+* The components at positions offset through offset+length-1 in the
+* array are set to zero.
+*
+* @param x (o) : vector to clear
+* @param offset (i) : offset of vector
+* @param length (i) : length of vector
+*/
+ public static void set_zero(float[] x, int offset, int length)
+ {
+ for (int i = offset, toIndex = offset + length; i < toIndex; i++)
{
- int i;
-
- for (i = 0; i < L; i++)
- y[y_offset + i] = x[x_offset + i];
+ x[i] = 0.0f;
}
+ }
- /**
- * Return random short.
- *
- * @return random short
- */
- public static short random_g729()
- {
- seed = (short)(seed * 31821L + 13849L);
+ /**
+* Copies an array from the specified x array, to the specified y array.
+* The number of components copied is equal to the length argument.
+*
+* @param x (i) : input vector
+* @param y (o) : output vector
+* @param L (i) : vector length
+*/
+ public static void copy(
+ float[] x,
+ float[] y,
+ int L
+ )
+ {
+ copy(x, 0, y, L);
+ }
- return seed;
- }
+ /**
+* Copies an array from the specified source array,
+* beginning at the specified destination array.
+* A subsequence of array components are copied from the source array referenced
+* by x to the destination array referenced by y.
+* The number of components copied is equal to the length argument.
+* The components at positions x_offset through x_offset+length-1 in the source
+* array are copied into positions 0 through length-1,
+* respectively, of the destination array.
+*
+* @param x (i) : input vector
+* @param x_offset (i) : input vector offset
+* @param y (o) : output vector
+* @param L (i) : vector length
+*/
+ public static void copy(float[] x, int x_offset, float[] y, int L)
+ {
+ copy(x, x_offset, y, 0, L);
+ }
- /**
- * Write data in fp
- *
- * @param data
- * @param length
- * @param fp
- * @throws java.io.IOException
- */
- public static void fwrite(short[] data, int length, Stream fp)
+ /**
+* Copies an array from the specified source array,
+* beginning at the specified position,
+* to the specified position of the destination array.
+* A subsequence of array components are copied from the source array referenced
+* by x to the destination array referenced by y.
+* The number of components copied is equal to the length argument.
+* The components at positions x_offset through x_offset+length-1 in the source
+* array are copied into positions y_offset through y_offset+length-1,
+* respectively, of the destination array.
+*
+* @param x (i) : input vector
+* @param x_offset (i) : input vector offset
+* @param y (o) : output vector
+* @param y_offset (i) : output vector offset
+* @param L (i) : vector length
+*/
+ public static void copy(float[] x, int x_offset, float[] y, int y_offset, int L)
+ {
+ int i;
+ for (i = 0; i < L; i++)
{
- var bytes = new byte[2];
-
- for (var i = 0; i < length; i++)
- {
- int value = data[i];
- bytes[0] = (byte)(value & 0xFF);
- bytes[1] = (byte)(value >> 8);
- fp.Write(bytes, 0, bytes.Length);
- }
+ y[y_offset + i] = x[x_offset + i];
}
+ }
- /**
- * Read data from fp.
- *
- * @param data
- * @param length
- * @param fp
- * @return length of resulting data array
- * @throws java.io.IOException
- */
- public static int fread(short[] data, int length, Stream fp)
+ /**
+* Return random short.
+*
+* @return random short
+*/
+ public static short random_g729()
+ {
+ seed = (short)(seed * 31821L + 13849L);
- {
- var bytes = new byte[2];
- var readLength = 0;
-
- for (var i = 0; i < length; i++)
- {
- if (fp.Read(bytes, 0, bytes.Length) != 2)
- break;
- data[i] = (short)((bytes[1] << 8) | (bytes[0] & 0x00FF));
- readLength++;
- }
-
- return readLength;
- }
+ return seed;
}
-}
\ No newline at end of file
+}
diff --git a/src/SIPSorcery/app/Media/Codecs/G729Decoder.cs b/src/SIPSorcery/app/Media/Codecs/G729Decoder.cs
index bd8af0799..bbf50685a 100644
--- a/src/SIPSorcery/app/Media/Codecs/G729Decoder.cs
+++ b/src/SIPSorcery/app/Media/Codecs/G729Decoder.cs
@@ -43,211 +43,235 @@ Sherbrooke. All rights reserved.
*/
using System;
-using System.IO;
+using System.Buffers;
+using System.Runtime.InteropServices;
+using CommunityToolkit.HighPerformance.Buffers;
using SIPSorcery.Media.G729Codec;
-namespace SIPSorcery.Media
-{
- public class G729Decoder : Ld8k
- {
-
- /**
- * Synthesis parameters + BFI
- */
- private readonly float[] Az_dec = new float[2 * MP1];
-
- /**
- * DecLd8k reference
- */
- private readonly DecLd8k decLd8k = new DecLd8k();
-
- /**
- * Synthesis parameters + BFI
- */
- private readonly int[] parm = new int[PRM_SIZE + 1];
+namespace SIPSorcery.Media;
- /**
- * Postfil reference
- */
- private readonly Postfil postfil = new Postfil();
-
- /**
- * PostPro reference
- */
- private readonly PostPro postPro = new PostPro();
-
- /**
- * postfilter output
- */
- private readonly float[] pst_out = new float[L_FRAME];
-
- /**
- * Synthesis
- */
- private readonly float[] synth;
+public class G729Decoder : Ld8k
+{
- /**
- * Synthesis
- */
- private readonly float[] synth_buf = new float[L_FRAME + M];
+ /**
+ * Synthesis parameters + BFI
+ */
+ private readonly float[] Az_dec = new float[2 * MP1];
+
+ /**
+ * DecLd8k reference
+ */
+ private readonly DecLd8k decLd8k = new DecLd8k();
+
+ /**
+ * Synthesis parameters + BFI
+ */
+ private readonly int[] parm = new int[PRM_SIZE + 1];
+
+ /**
+ * Postfil reference
+ */
+ private readonly Postfil postfil = new Postfil();
+
+ /**
+ * PostPro reference
+ */
+ private readonly PostPro postPro = new PostPro();
+
+ /**
+ * postfilter output
+ */
+ private readonly float[] pst_out = new float[L_FRAME];
+
+ /**
+ * Synthesis
+ */
+ private readonly float[] synth;
+
+ /**
+ * Synthesis
+ */
+ private readonly float[] synth_buf = new float[L_FRAME + M];
+
+ /**
+ * Synthesis
+ */
+ private readonly int synth_offset;
+
+ /**
+ * voicing for previous subframe
+ */
+ private int voicing;
+
+ /**
+ * Initialization of decoder
+ */
+
+ public G729Decoder()
+ {
- /**
- * Synthesis
- */
- private readonly int synth_offset;
+ synth = synth_buf;
+ synth_offset = M;
- /**
- * voicing for previous subframe
- */
- private int voicing;
+ decLd8k.init_decod_ld8k();
+ postfil.init_post_filter();
+ postPro.init_post_process();
- /**
- * Initialization of decoder
- */
+ voicing = 60;
+ }
- public G729Decoder()
+ /**
+ * Converts floats array into shorts span.
+ *
+ * @param floats
+ * @param shorts
+ */
+ private static void floats2shorts(ReadOnlySpan floats, Span shorts)
+ {
+ for (var i = 0; i < floats.Length && i < shorts.Length; i++)
{
+ /* round and convert to int */
+ var f = floats[i];
+ if (f >= 0.0f)
+ {
+ f += 0.5f;
+ }
+ else
+ {
+ f -= 0.5f;
+ }
- synth = synth_buf;
- synth_offset = M;
-
- decLd8k.init_decod_ld8k();
- postfil.init_post_filter();
- postPro.init_post_process();
-
- voicing = 60;
- }
+ if (f > 32767.0f)
+ {
+ f = 32767.0f;
+ }
- /**
- * Converts floats array into shorts array.
- *
- * @param floats
- * @param shorts
- */
- private static void floats2shorts(float[] floats, short[] shorts)
- {
- for (var i = 0; i < floats.Length; i++)
+ if (f < -32768.0f)
{
- /* round and convert to int */
- var f = floats[i];
- if (f >= 0.0f)
- f += 0.5f;
- else
- f -= 0.5f;
- if (f > 32767.0f)
- f = 32767.0f;
- if (f < -32768.0f)
- f = -32768.0f;
- shorts[i] = (short)f;
+ f = -32768.0f;
}
+
+ shorts[i] = (short)f;
}
+ }
- private void depacketize(byte[] inFrame, int inFrameOffset, short[] serial)
+ private void depacketize(ReadOnlySpan inFrame, int inFrameOffset, Span serial)
+ {
+ serial[0] = SYNC_WORD;
+ serial[1] = SIZE_WORD;
+ for (var s = 0; s < L_FRAME; s++)
{
- serial[0] = SYNC_WORD;
- serial[1] = SIZE_WORD;
- for (var s = 0; s < L_FRAME; s++)
- {
- int in_ = inFrame[inFrameOffset + s / 8];
+ int in_ = inFrame[inFrameOffset + s / 8];
- in_ &= 1 << (7 - s % 8);
- serial[2 + s] = 0 != in_ ? BIT_1 : BIT_0;
- }
+ in_ &= 1 << (7 - s % 8);
+ serial[2 + s] = 0 != in_ ? BIT_1 : BIT_0;
}
+ }
+
+ /**
+ * Process SERIAL_SIZE short of speech using spans.
+ *
+ * @param serial input : serial array encoded in bits_ld8k
+ * @param sp16 output : speech short span
+ */
+ private void ProcessPacket(ReadOnlySpan serial, Span sp16)
+ {
+ Bits.bits2prm_ld8k(serial, 2, parm, 1);
- /**
- * Process SERIAL_SIZE short of speech.
- *
- * @param serial input : serial array encoded in bits_ld8k
- * @param sp16 output : speech short array
+ /* the hardware detects frame erasures by checking if all bits
+ * are set to zero
*/
- private void ProcessPacket(short[] serial, short[] sp16)
+ parm[0] = 0; /* No frame erasure */
+ for (var i = 2; i < SERIAL_SIZE; i++)
{
- Bits.bits2prm_ld8k(serial, 2, parm, 1);
+ if (serial[i] == 0)
+ {
+ parm[0] = 1; /* frame erased */
+ }
+ }
- /* the hardware detects frame erasures by checking if all bits
- * are set to zero
- */
- parm[0] = 0; /* No frame erasure */
- for (var i = 2; i < SERIAL_SIZE; i++)
- if (serial[i] == 0)
- parm[0] = 1; /* frame erased */
+ /* check parity and put 1 in parm[4] if parity error */
- /* check parity and put 1 in parm[4] if parity error */
+ parm[4] = PParity.check_parity_pitch(parm[3], parm[4]);
- parm[4] = PParity.check_parity_pitch(parm[3], parm[4]);
+ var t0_first = decLd8k.decod_ld8k(parm, voicing, synth, synth_offset, Az_dec); /* Decoder */
- var t0_first = decLd8k.decod_ld8k(parm, voicing, synth, synth_offset, Az_dec); /* Decoder */
+ /* Post-filter and decision on voicing parameter */
+ voicing = 0;
- /* Post-filter and decision on voicing parameter */
- voicing = 0;
+ var ptr_Az = Az_dec; /* Decoded Az for post-filter */
+ var ptr_Az_offset = 0;
- var ptr_Az = Az_dec; /* Decoded Az for post-filter */
- var ptr_Az_offset = 0;
+ for (var i = 0; i < L_FRAME; i += L_SUBFR)
+ {
+ int sf_voic; /* voicing for subframe */
- for (var i = 0; i < L_FRAME; i += L_SUBFR)
+ sf_voic = postfil.post(t0_first, synth, synth_offset + i, ptr_Az, ptr_Az_offset, pst_out, i);
+ if (sf_voic != 0)
{
- int sf_voic; /* voicing for subframe */
-
- sf_voic = postfil.post(t0_first, synth, synth_offset + i, ptr_Az, ptr_Az_offset, pst_out, i);
- if (sf_voic != 0)
- voicing = sf_voic;
- ptr_Az_offset += MP1;
+ voicing = sf_voic;
}
+ ptr_Az_offset += MP1;
+ }
- Util.copy(synth_buf, L_FRAME, synth_buf, M);
+ Util.copy(synth_buf, L_FRAME, synth_buf, M);
- postPro.post_process(pst_out, L_FRAME);
+ postPro.post_process(pst_out, L_FRAME);
- floats2shorts(pst_out, sp16);
- }
+ floats2shorts(pst_out, sp16);
+ }
- /**
- * Main decoder routine
- * Usage :Decoder bitstream_file outputspeech_file
- *
- * Format for bitstream_file:
- * One (2-byte) synchronization word
- * One (2-byte) size word,
- * 80 words (2-byte) containing 80 bits.
- *
- * Format for outputspeech_file:
- * Synthesis is written to a binary file of 16 bits data.
- *
- * @param args bitstream_file outputspeech_file
- * @throws java.io.IOException
- */
- public byte[] Process(byte[] source)
- {
- var serial = new short[SERIAL_SIZE]; /* Serial stream */
- var sp16 = new short[L_FRAME]; /* Buffer to write 16 bits speech */
- var speech = new byte[L_FRAME * 2];
- var output = new MemoryStream();
+ ///
+ /// Decodes G729 audio using spans and IBufferWriter for efficient memory usage.
+ ///
+ /// Input encoded data
+ /// IBufferWriter to receive decoded PCM samples
+ /// Number of samples written
+ ///
+ /// Main decoder routine
+ /// Usage :Decoder bitstream_file outputspeech_file
+ ///
+ /// Format for bitstream_file:
+ /// One(2-byte) synchronization word
+ /// One(2-byte) size word,
+ /// 80 words(2-byte) containing 80 bits.
+ ///
+ /// Format for outputspeech_file:
+ /// Synthesis is written to a binary file of 16 bits data.
+ ///
+ /// @param args bitstream_file outputspeech_file
+ /// @throws java.io.IOException
+ ///
+ public int Process(ReadOnlySpan source, IBufferWriter destination)
+ {
+ // Use stackalloc for the serial buffer since it's very small (82 shorts = 164 bytes)
+ Span serial = stackalloc short[SERIAL_SIZE];
+ var samplesWritten = 0;
+ Span sp16 = stackalloc short[L_FRAME];
- /*-----------------------------------------------------------------*
- * Loop for each "L_FRAME" speech data *
- *-----------------------------------------------------------------*/
+ /*-----------------------------------------------------------------*
+ * Loop for each "L_FRAME" speech data *
+ *-----------------------------------------------------------------*/
- var frame = 0;
- try
- {
- // Iterate over each frame
- int i;
- for (i = 0; i <= source.Length - L_FRAME / 8 /* must have a complete frame left */; i += L_FRAME / 8)
- {
- frame++;
- depacketize(source, i, serial);
- ProcessPacket(serial, sp16);
- Buffer.BlockCopy(sp16, 0, speech, 0, speech.Length);
- output.Write(speech, 0, speech.Length);
- }
- }
- catch (Exception)
+ try
+ {
+ // Iterate over each frame
+ int i;
+ for (i = 0; i <= source.Length - L_FRAME / 8 /* must have a complete frame left */; i += L_FRAME / 8)
{
- // No logging as we could get huge log files if any issues arises decoding
- }
+ depacketize(source, i, serial);
- return output.ToArray();
+ // Get span for this frame's output
+ ProcessPacket(serial, sp16);
+ destination.Write(MemoryMarshal.AsBytes(sp16));
+ samplesWritten += L_FRAME;
+ }
}
+ catch (Exception)
+ {
+ // No logging as we could get huge log files if any issues arises decoding
+ }
+
+ return samplesWritten;
}
-}
\ No newline at end of file
+}
diff --git a/src/SIPSorcery/app/Media/Codecs/G729Encoder.cs b/src/SIPSorcery/app/Media/Codecs/G729Encoder.cs
index 20167d1eb..e01833e69 100644
--- a/src/SIPSorcery/app/Media/Codecs/G729Encoder.cs
+++ b/src/SIPSorcery/app/Media/Codecs/G729Encoder.cs
@@ -43,163 +43,225 @@ Sherbrooke. All rights reserved.
*/
using System;
-using System.IO;
+using System.Buffers;
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using CommunityToolkit.HighPerformance.Buffers;
using SIPSorcery.Media.G729Codec;
-namespace SIPSorcery.Media
+namespace SIPSorcery.Media;
+
+public class G729Encoder : Ld8k
{
- public class G729Encoder : Ld8k
- {
- /**
- * Initialization of the coder.
- */
+ /**
+ * Initialization of the coder.
+ */
- private byte[] _leftover = new byte[0];
+ private readonly ArrayPoolBufferWriter _leftover = new();
+ private int _leftoverOffset;
- /**
- * Init the Ld8k Coder
- */
- private readonly CodLd8k codLd8k = new CodLd8k();
+ /**
+ * Init the Ld8k Coder
+ */
+ private readonly CodLd8k codLd8k = new CodLd8k();
- /**
- * Init the PreProc
- */
- private readonly PreProc preProc = new PreProc();
+ /**
+ * Init the PreProc
+ */
+ private readonly PreProc preProc = new PreProc();
- /**
- * Transmitted parameters
- */
- private readonly int[] prm = new int[PRM_SIZE];
+ /**
+ * Transmitted parameters
+ */
+ private readonly int[] prm = new int[PRM_SIZE];
- public G729Encoder()
+ public G729Encoder()
+ {
+ preProc.init_pre_process();
+ codLd8k.init_coder_ld8k(); /* Initialize the coder */
+ }
+
+ ///
+ /// Fills a span with a specified value from start to end index.
+ ///
+ private static void Fill(Span span, int start, int end, T value)
+ {
+ for (var i = start; i < end; i++)
{
- preProc.init_pre_process();
- codLd8k.init_coder_ld8k(); /* Initialize the coder */
+ span[i] = value;
}
+ }
+
+ ///
+ /// Writes the encoded serial bits to the output packet using spans.
+ ///
+ /// Input serial bits as Span.
+ /// Output packet as Span.
+ private void packetize(ReadOnlySpan serial, Span outFrame)
+ {
+ Fill(outFrame, 0, L_FRAME / 8, (byte)0);
- private static void Fill(T[] array, int start, int end, T value)
+ for (var s = 0; s < L_FRAME; s++)
{
- for (var i = start; i < end; i++)
- array[i] = value;
+ if (BIT_1 == serial[2 + s])
+ {
+ var o = s / 8;
+ int out_ = outFrame[o];
+
+ out_ |= 1 << (7 - s % 8);
+ outFrame[o] = (byte)(out_ & 0xFF);
+ }
}
+ }
+
+ /**
+ * Process L_FRAME short of speech.
+ *
+ * @param sp16 input : speach short array
+ * @param serial output : serial array encoded in bits_ld8k
+ */
+ private void ProcessPacket(ReadOnlySpan sp16, Span serial)
+ {
+ var new_speech = codLd8k.new_speech; /* Pointer to new speech data */
+ Debug.Assert(new_speech is { });
+ var new_speech_offset = codLd8k.new_speech_offset;
- private void packetize(short[] serial, byte[] outFrame, int outFrameOffset)
+ for (var i = 0; i < L_FRAME; i++)
{
- Fill(outFrame, outFrameOffset, outFrameOffset + L_FRAME / 8, (byte)0);
+ new_speech[new_speech_offset + i] = sp16[i];
+ }
- for (var s = 0; s < L_FRAME; s++)
- if (BIT_1 == serial[2 + s])
- {
- var o = outFrameOffset + s / 8;
- int out_ = outFrame[o];
+ preProc.pre_process(new_speech.AsSpan(), new_speech_offset, L_FRAME);
- out_ |= 1 << (7 - s % 8);
- outFrame[o] = (byte)(out_ & 0xFF);
- }
- }
+ codLd8k.coder_ld8k(prm);
- /**
- * Process L_FRAME short of speech.
- *
- * @param sp16 input : speach short array
- * @param serial output : serial array encoded in bits_ld8k
+ Bits.prm2bits_ld8k(prm, serial);
+ }
+
+ ///
+ /// Processes speech data using spans and writes output to an of .
+ ///
+ /// Input speech data as of .
+ /// Output buffer writer for encoded bytes.
+ ///
+ /// Format for speech_file:
+ /// Speech is read form a binary file of 16 bits data.
+ ///
+ /// Format for bitstream_file:
+ /// One word (2-bytes) to indicate erasure.
+ /// One word (2 bytes) to indicate bit rate
+ /// 80 words (2-bytes) containing 80 bits.
+ ///
+ [SkipLocalsInit]
+ public void Process(ReadOnlySpan speech, IBufferWriter output)
+ {
+ const int frameSizeInBytes = L_FRAME * 2;
+ Span frameBytes = stackalloc byte[frameSizeInBytes];
+ Span serial = stackalloc short[SERIAL_SIZE];
+ const int packetLength = L_FRAME / 8;
+ Span packet = stackalloc byte[packetLength];
+
+ // Combine leftover and new speech
+ _leftover.Write(speech);
+ var totalLength = _leftover.WrittenCount - _leftoverOffset;
+ var framesToProcess = totalLength / frameSizeInBytes;
+ var processedBytes = 0;
+
+ /*-------------------------------------------------------------------------*
+ * Loop for every analysis/transmission frame. *
+ * -New L_FRAME data are read. (L_FRAME = number of speech data per frame) *
+ * -Conversion of the speech data from 16 bit integer to real *
+ * -Call cod_ld8k to encode the speech. *
+ * -The compressed serial output stream is written to a file. *
+ * -The synthesis speech is written to a file *
+ *-------------------------------------------------------------------------*
*/
- private void ProcessPacket(short[] sp16, short[] serial)
+
+ for (var frame = 0; frame < framesToProcess; frame++)
{
- var new_speech = codLd8k.new_speech; /* Pointer to new speech data */
- var new_speech_offset = codLd8k.new_speech_offset;
+ _leftover.WrittenSpan.Slice(_leftoverOffset + processedBytes, frameSizeInBytes).CopyTo(frameBytes);
+ processedBytes += frameSizeInBytes;
- for (var i = 0; i < L_FRAME; i++)
- new_speech[new_speech_offset + i] = sp16[i];
+ var sp16 = MemoryMarshal.Cast(frameBytes);
- preProc.pre_process(new_speech, new_speech_offset, L_FRAME);
- codLd8k.coder_ld8k(prm);
+ ProcessPacket(sp16, serial);
+ packet.Clear();
+ packetize(serial, packet);
+ output.GetSpan(packetLength).Slice(0, packetLength).CopyTo(packet);
+ output.Advance(packetLength);
+ }
- Bits.prm2bits_ld8k(prm, serial);
+ // Keep only unprocessed bytes in the leftover buffer.
+ _leftoverOffset += processedBytes;
+ CompactLeftoverIfNeeded();
+ }
- }
+ ///
+ /// Flushes any remaining buffered audio, encoding and writing to the provided output buffer.
+ ///
+ /// Output buffer writer for encoded bytes.
+ [SkipLocalsInit]
+ public void Flush(IBufferWriter output)
+ {
+ var leftoverLength = _leftover.WrittenCount - _leftoverOffset;
- /**
- * Usage : coder speech_file bitstream_file
- *
- * Format for speech_file:
- * Speech is read form a binary file of 16 bits data.
- *
- * Format for bitstream_file:
- * One word (2-bytes) to indicate erasure.
- * One word (2 bytes) to indicate bit rate
- * 80 words (2-bytes) containing 80 bits.
- *
- * @param args speech_file bitstream_file
- * @throws java.io.IOException
- */
- public byte[] Process(byte[] speech)
+ if (leftoverLength > 0)
{
- var sp16 = new short[L_FRAME]; /* Buffer to read 16 bits speech */
- var serial = new short[SERIAL_SIZE]; /* Output bit stream buffer */
- var packet = new byte[L_FRAME / 8];
- var output = new MemoryStream();
- var buffer = new MemoryStream();
-
- buffer.Write(_leftover, 0, _leftover.Length);
- buffer.Write(speech, 0, speech.Length);
- var input = buffer.ToArray();
-
- /*-------------------------------------------------------------------------*
- * Loop for every analysis/transmission frame. *
- * -New L_FRAME data are read. (L_FRAME = number of speech data per frame) *
- * -Conversion of the speech data from 16 bit integer to real *
- * -Call cod_ld8k to encode the speech. *
- * -The compressed serial output stream is written to a file. *
- * -The synthesis speech is written to a file *
- *-------------------------------------------------------------------------*
- */
-
- var frame = 0;
- try
- {
- // Iterate over each frame
- int i;
- for (i = 0; i <= input.Length - L_FRAME * 2 /* must have a complete frame left */; i += L_FRAME * 2)
- {
- frame++;
- Buffer.BlockCopy(input, i, sp16, 0, L_FRAME * 2);
- ProcessPacket(sp16, serial);
- packetize(serial, packet, 0);
- output.Write(packet, 0, packet.Length);
- }
-
- _leftover = new byte[input.Length - i];
- Array.Copy(input, i, _leftover, 0, _leftover.Length);
- }
- catch (Exception)
+ const int frameSizeInBytes = L_FRAME * 2;
+ Span frameBytes = stackalloc byte[frameSizeInBytes];
+ Debug.Assert(leftoverLength <= frameSizeInBytes);
+ // Copy leftover bytes into frameBytes
+ _leftover.WrittenSpan.Slice(_leftoverOffset, leftoverLength).CopyTo(frameBytes.Slice(0, leftoverLength));
+ // Zero-fill any missing bytes
+ if (leftoverLength < frameSizeInBytes)
{
- // No logging as we could get huge log files if any issues arises decoding
+ frameBytes.Slice(leftoverLength, frameSizeInBytes - leftoverLength).Clear();
}
+ var sp16 = MemoryMarshal.Cast(frameBytes);
+ Span serial = stackalloc short[SERIAL_SIZE];
+ Span packet = stackalloc byte[L_FRAME / 8];
+ ProcessPacket(sp16, serial);
+ packet.Clear();
+ packetize(serial, packet);
+ output.GetSpan(packet.Length).Slice(0, packet.Length).CopyTo(packet);
+ output.Advance(packet.Length);
- return output.ToArray();
+ _leftover.Clear();
+ _leftoverOffset = 0;
}
+ }
- // TODO: pad out _leftover with silence, and return one last frame
- public byte[] Flush()
+ private void CompactLeftoverIfNeeded()
+ {
+ var remaining = _leftover.WrittenCount - _leftoverOffset;
+
+ if (remaining <= 0)
{
- var output = new MemoryStream();
- if (_leftover.Length > 0)
- {
- var sp16 = new short[L_FRAME]; /* Buffer to read 16 bits speech */
- var serial = new short[SERIAL_SIZE]; /* Output bit stream buffer */
- var packet = new byte[L_FRAME / 8];
-
- Buffer.BlockCopy(_leftover, 0, sp16, 0, _leftover.Length);
- Fill(sp16, _leftover.Length / 2, sp16.Length, (short)0);
- ProcessPacket(sp16, serial);
- packetize(serial, packet, 0);
- output.Write(packet, 0, packet.Length);
- }
+ _leftover.Clear();
+ _leftoverOffset = 0;
+ return;
+ }
- return output.ToArray();
+ if (_leftoverOffset <= 0)
+ {
+ return;
+ }
+
+ var rented = ArrayPool.Shared.Rent(remaining);
+
+ try
+ {
+ _leftover.WrittenSpan.Slice(_leftoverOffset, remaining).CopyTo(rented.AsSpan(0, remaining));
+ _leftover.Clear();
+ _leftover.Write(rented.AsSpan(0, remaining));
+ _leftoverOffset = 0;
+ }
+ finally
+ {
+ ArrayPool.Shared.Return(rented);
}
}
-}
\ No newline at end of file
+}
diff --git a/src/SIPSorcery/app/Media/Codecs/PcmResampler.cs b/src/SIPSorcery/app/Media/Codecs/PcmResampler.cs
index 6ae863d40..3e5f1b91c 100644
--- a/src/SIPSorcery/app/Media/Codecs/PcmResampler.cs
+++ b/src/SIPSorcery/app/Media/Codecs/PcmResampler.cs
@@ -1,5 +1,4 @@
using System;
-using System.Linq;
namespace SIPSorcery.Media
{
@@ -7,34 +6,28 @@ internal static class PcmResampler
{
public static short[] Resample(short[] pcm, int inRate, int outRate)
{
- if (inRate == outRate)
+ if (inRate == outRate || pcm.Length == 0)
{
return pcm;
}
- else if (inRate == 8000 && outRate == 16000)
- {
- // Crude up-sample to 16Khz by doubling each sample.
- return pcm.SelectMany(x => new short[] { x, x }).ToArray();
- }
- else if (inRate == 8000 && outRate == 48000)
- {
- // Crude up-sample to 48Khz by 6x each sample. This sounds bad, use for testing only.
- return pcm.SelectMany(x => new short[] { x, x, x, x, x, x }).ToArray();
- }
- else if (inRate == 16000 && outRate == 8000)
- {
- // Crude down-sample to 8Khz by skipping every second sample.
- return pcm.Where((x, i) => i % 2 == 0).ToArray();
- }
- else if (inRate == 16000 && outRate == 48000)
- {
- // Crude up-sample to 48Khz by 3x each sample. This sounds bad, use for testing only.
- return pcm.SelectMany(x => new short[] { x, x, x }).ToArray();
- }
- else
+
+ var outLength = (int)((long)pcm.Length * outRate / inRate);
+ var resampled = new short[outLength];
+ var step = (double)inRate / outRate;
+
+ for (var i = 0; i < outLength; i++)
{
- throw new ApplicationException($"Sorry don't know how to re-sample PCM from {inRate} to {outRate}. Pull requests welcome!");
+ var srcPos = i * step;
+ var srcIndex = (int)srcPos;
+ var frac = srcPos - srcIndex;
+
+ var s0 = pcm[srcIndex];
+ var s1 = pcm[Math.Min(srcIndex + 1, pcm.Length - 1)];
+
+ resampled[i] = (short)Math.Round(s0 + (s1 - s0) * frac);
}
+
+ return resampled;
}
}
}
diff --git a/src/SIPSorcery/app/Media/EchoMediaSession.cs b/src/SIPSorcery/app/Media/EchoMediaSession.cs
index c1874b6a9..da42e28bd 100644
--- a/src/SIPSorcery/app/Media/EchoMediaSession.cs
+++ b/src/SIPSorcery/app/Media/EchoMediaSession.cs
@@ -19,6 +19,7 @@
using System.Linq;
using System.Net;
using System.Threading.Tasks;
+using CommunityToolkit.HighPerformance.Buffers;
using Microsoft.Extensions.Logging;
using SIPSorcery.Net;
using SIPSorcery.SIP.App;
@@ -54,7 +55,7 @@ private void AudioFormatsNegotiated(List audoFormats)
var audioFormat = audoFormats.First();
logger.LogDebug("{session} setting audio source format to {FormatID}:{Codec} {ClockRate} (RTP clock rate {RtpClockRate}).", nameof(EchoMediaSession), audioFormat.FormatID, audioFormat.Codec, audioFormat.ClockRate, audioFormat.RtpClockRate);
- if (AudioStream != null && AudioStream.LocalTrack.NoDtmfSupport == false)
+ if (AudioStream?.LocalTrack?.NoDtmfSupport == false)
{
logger.LogDebug("Audio track negotiated DTMF payload ID {AudioStreamNegotiatedRtpEventPayloadID}.", AudioStream.NegotiatedRtpEventPayloadID);
}
@@ -64,7 +65,7 @@ private void AudioFormatsNegotiated(List audoFormats)
AudioStream.OnAudioFrameReceived += (audioFrame) =>
{
// Echo the received audio frame back to the sender.
- AudioStream?.SendAudio(audioFrame.DurationMilliSeconds, audioFrame.EncodedAudio);
+ AudioStream?.SendAudio(audioFrame.DurationMilliSeconds, audioFrame.EncodedAudio.Span);
};
}
}
@@ -81,7 +82,7 @@ private void VideoFormatsNegotiated(List videoFormats)
if (VideoStream != null && VideoStream.RemoteTrack != null && VideoStream.LocalTrack != null)
{
- VideoStream.OnVideoFrameReceivedByIndex += (int index, IPEndPoint from, uint ts, byte[] payload, VideoFormat format) =>
+ VideoStream.OnVideoFrameReceivedByIndex += (index, from, ts, payload, format) =>
{
// TODO.
logger.LogWarning("Video frame received, echoing not yet implemented.");
@@ -98,7 +99,7 @@ private void TextFormatsNegotiated(List textFormats)
{
TextStream.OnRtpPacketReceivedByIndex += (int index, IPEndPoint from, SDPMediaTypesEnum mediaType, RTPPacket pkt) =>
{
- TextStream.SendText(pkt.Payload);
+ TextStream.SendText(pkt.Payload.Span);
};
}
}
@@ -127,7 +128,9 @@ private void EncodeAndSend(short[] pcm, AudioFormat audioFormat)
{
if (pcm.Length > 0)
{
- byte[] encodedSample = _audioEncoder.EncodeAudio(pcm, audioFormat);
+ using var buffer = new ArrayPoolBufferWriter(8192);
+ _audioEncoder.EncodeAudio(pcm, audioFormat, buffer);
+ var encodedSample = buffer.WrittenSpan;
uint rtpUnits = RtpTimestampExtensions.ToRtpUnits(SILENCE_SAMPLE_PERIOD_MILLISECONDS, audioFormat.RtpClockRate);
diff --git a/src/SIPSorcery/app/Media/IMediaSession.cs b/src/SIPSorcery/app/Media/IMediaSession.cs
index 2514d6af1..47f0ec2ab 100644
--- a/src/SIPSorcery/app/Media/IMediaSession.cs
+++ b/src/SIPSorcery/app/Media/IMediaSession.cs
@@ -19,139 +19,138 @@
using System.Threading.Tasks;
using SIPSorcery.Net;
-namespace SIPSorcery.SIP.App
+namespace SIPSorcery.SIP.App;
+
+///
+/// The type of the SDP packet being set.
+///
+public enum SdpType
+{
+ answer = 0,
+ offer = 1
+}
+
+///
+/// Offering and Answering SDP messages so that it can be
+/// signaled to the other party using the SIPUserAgent.
+///
+/// The implementing class is responsible for ensuring that the client
+/// can send media to the other party including creating and managing
+/// the RTP streams and processing the audio and video.
+///
+public interface IMediaSession
{
///
- /// The type of the SDP packet being set.
+ /// Indicates whether the session supports real time text.
+ ///
+ bool HasText { get; }
+
+ ///
+ /// Indicates whether the session supports audio.
+ ///
+ bool HasAudio { get; }
+
+ ///
+ /// Indicates whether the session supports video.
+ ///
+ bool HasVideo { get; }
+
+ ///
+ /// Indicates whether the session has been closed.
+ ///
+ bool IsClosed { get; }
+
+ ///
+ /// The SDP description from the remote party describing
+ /// their audio/video sending and receive capabilities.
+ ///
+ SDP? RemoteDescription { get; }
+
+ ///
+ /// Set if the session has been bound to a specific IP address.
+ /// Normally not required but some esoteric call or network set ups may need.
+ ///
+ IPAddress RtpBindAddress { get; }
+
+ ///
+ /// Fired when the RTP channel is closed.
///
- public enum SdpType
- {
- answer = 0,
- offer = 1
- }
-
- ///
- /// Offering and Answering SDP messages so that it can be
- /// signaled to the other party using the SIPUserAgent.
- ///
- /// The implementing class is responsible for ensuring that the client
- /// can send media to the other party including creating and managing
- /// the RTP streams and processing the audio and video.
+ event Action? OnRtpClosed;
+
+ ///
+ /// Fired when an RTP event (typically representing a DTMF tone) is
+ /// detected.
+ ///
+ event Action OnRtpEvent;
+
+ ///
+ /// Fired when no RTP or RTCP packets are received for a pre-defined period (typically 30s).
+ ///
+ event Action OnTimeout;
+
+ ///
+ /// Creates a new SDP offer based on the local media tracks in the session.
+ /// Calling this method does NOT change the state of the media tracks. It is
+ /// safe to call at any time if a session description of the local media state is
+ /// required.
+ ///
+ /// Optional. If set this address will be used
+ /// as the Connection address in the SDP offer. If not set an attempt will be
+ /// made to determine the best matching address.
+ /// A new SDP offer representing the session's local media tracks.
+ SDP? CreateOffer(IPAddress? connectionAddress = default);
+
+ ///
+ /// Sets the remote description. Calling this method can result in the local
+ /// media tracks being disabled if not supported or setting the RTP/RTCP end points
+ /// if they are.
+ ///
+ /// Whether the SDP being set is an offer or answer.
+ /// The SDP description from the remote party.
+ /// If successful an OK enum result. If not an enum result indicating the
+ /// failure cause.
+ SetDescriptionResultEnum SetRemoteDescription(SdpType sdpType, SDP sessionDescription);
+
+ ///
+ /// Generates an SDP answer to an offer based on the local media tracks. Calling
+ /// this method does NOT result in any changes to the local tracks. To apply the
+ /// changes the SetRemoteDescription method must be called.
+ ///
+ /// Optional. If set this address will be used as
+ /// the SDP Connection address. If not specified the Operating System routing table
+ /// will be used to lookup the address used to connect to the SDP connection address
+ /// from the remote offer.
+ /// An SDP answer matching the offer and the local media tracks contained
+ /// in the session.
+ SDP? CreateAnswer(IPAddress? connectionAddress = default);
+
+ ///
+ /// Needs to be called prior to sending media. Performs any set up tasks such as
+ /// starting audio/video capture devices and starting RTCP reporting.
+ ///
+ Task Start();
+
+ ///
+ /// Sets the stream status on all local audio or all video media track.
+ ///
+ /// The type of the media track. Must be audio or video.
+ /// The stream status for the media track.
+ void SetMediaStreamStatus(SDPMediaTypesEnum kind, MediaStreamStatusEnum status);
+
+ ///
+ /// Attempts to send a DTMF tone to the remote party.
+ ///
+ /// The digit representing the DTMF tone to send.
+ /// A cancellation token that should be set if the DTMF send should be
+ /// cancelled before completing. Depending on the duration a DTMF send can require
+ /// multiple RTP packets. This token can be used to cancel any further RTP packets
+ /// being sent for the tone.
+ Task SendDtmf(byte tone, CancellationToken ct);
+
+ ///
+ /// Closes the session. This will stop any audio/video capturing and rendering devices as
+ /// well as the RTP and RTCP sessions and sockets.
///
- public interface IMediaSession
- {
- ///
- /// Indicates whether the session supports real time text.
- ///
- bool HasText { get; }
-
- ///
- /// Indicates whether the session supports audio.
- ///
- bool HasAudio { get; }
-
- ///
- /// Indicates whether the session supports video.
- ///
- bool HasVideo { get; }
-
- ///
- /// Indicates whether the session has been closed.
- ///
- bool IsClosed { get; }
-
- ///
- /// The SDP description from the remote party describing
- /// their audio/video sending and receive capabilities.
- ///
- SDP RemoteDescription { get; }
-
- ///
- /// Set if the session has been bound to a specific IP address.
- /// Normally not required but some esoteric call or network set ups may need.
- ///
- IPAddress RtpBindAddress { get; }
-
- ///
- /// Fired when the RTP channel is closed.
- ///
- event Action OnRtpClosed;
-
- ///
- /// Fired when an RTP event (typically representing a DTMF tone) is
- /// detected.
- ///
- event Action OnRtpEvent;
-
- ///
- /// Fired when no RTP or RTCP packets are received for a pre-defined period (typically 30s).
- ///
- event Action OnTimeout;
-
- ///
- /// Creates a new SDP offer based on the local media tracks in the session.
- /// Calling this method does NOT change the state of the media tracks. It is
- /// safe to call at any time if a session description of the local media state is
- /// required.
- ///
- /// Optional. If set this address will be used
- /// as the Connection address in the SDP offer. If not set an attempt will be
- /// made to determine the best matching address.
- /// A new SDP offer representing the session's local media tracks.
- SDP CreateOffer(IPAddress connectionAddress = null);
-
- ///
- /// Sets the remote description. Calling this method can result in the local
- /// media tracks being disabled if not supported or setting the RTP/RTCP end points
- /// if they are.
- ///
- /// Whether the SDP being set is an offer or answer.
- /// The SDP description from the remote party.
- /// If successful an OK enum result. If not an enum result indicating the
- /// failure cause.
- SetDescriptionResultEnum SetRemoteDescription(SdpType sdpType, SDP sessionDescription);
-
- ///
- /// Generates an SDP answer to an offer based on the local media tracks. Calling
- /// this method does NOT result in any changes to the local tracks. To apply the
- /// changes the SetRemoteDescription method must be called.
- ///
- /// Optional. If set this address will be used as
- /// the SDP Connection address. If not specified the Operating System routing table
- /// will be used to lookup the address used to connect to the SDP connection address
- /// from the remote offer.
- /// An SDP answer matching the offer and the local media tracks contained
- /// in the session.
- SDP CreateAnswer(IPAddress connectionAddress = null);
-
- ///
- /// Needs to be called prior to sending media. Performs any set up tasks such as
- /// starting audio/video capture devices and starting RTCP reporting.
- ///
- Task Start();
-
- ///
- /// Sets the stream status on all local audio or all video media track.
- ///
- /// The type of the media track. Must be audio or video.
- /// The stream status for the media track.
- void SetMediaStreamStatus(SDPMediaTypesEnum kind, MediaStreamStatusEnum status);
-
- ///
- /// Attempts to send a DTMF tone to the remote party.
- ///
- /// The digit representing the DTMF tone to send.
- /// A cancellation token that should be set if the DTMF send should be
- /// cancelled before completing. Depending on the duration a DTMF send can require
- /// multiple RTP packets. This token can be used to cancel any further RTP packets
- /// being sent for the tone.
- Task SendDtmf(byte tone, CancellationToken ct);
-
- ///
- /// Closes the session. This will stop any audio/video capturing and rendering devices as
- /// well as the RTP and RTCP sessions and sockets.
- ///
- /// Optional. A descriptive reason for closing the session.
- void Close(string reason);
- }
+ /// Optional. A descriptive reason for closing the session.
+ void Close(string reason);
}
diff --git a/src/SIPSorcery/app/Media/MediaLoggingExtensions.cs b/src/SIPSorcery/app/Media/MediaLoggingExtensions.cs
new file mode 100644
index 000000000..57e32a408
--- /dev/null
+++ b/src/SIPSorcery/app/Media/MediaLoggingExtensions.cs
@@ -0,0 +1,229 @@
+using System;
+using System.Net;
+using Microsoft.Extensions.Logging;
+using SIPSorceryMedia.Abstractions;
+
+namespace SIPSorcery.Media;
+
+internal static partial class MediaLoggingExtensions
+{
+ [LoggerMessage(
+ EventId = 0,
+ EventName = "SettingAudioSourceFormat",
+ Level = LogLevel.Debug,
+ Message = "Setting audio source format to {AudioFormatID}:{AudioFormatCodec}.")]
+ public static partial void LogSettingAudioSourceFormat(
+ this ILogger logger,
+ int audioFormatID,
+ AudioCodecsEnum audioFormatCodec);
+
+ [LoggerMessage(
+ EventId = 0,
+ EventName = "MusicFileNotSetOrFound",
+ Level = LogLevel.Warning,
+ Message = "Music file not set or not found, using default music resource.")]
+ public static partial void LogMusicFileNotSetOrFound(
+ this ILogger logger);
+
+ [LoggerMessage(
+ EventId = 0,
+ EventName = "SendingAudioSteamLength",
+ Level = LogLevel.Debug,
+ Message = "Sending audio stream length {AudioStreamLength}.")]
+ public static partial void LogSendingAudioSteamLength(
+ this ILogger logger,
+ long audioStreamLength);
+
+ [LoggerMessage(
+ EventId = 0,
+ EventName = "RtpAudioPacketReceived",
+ Level = LogLevel.Trace,
+ Message = "audio RTP packet received from {RemoteEndPoint} ssrc {SyncSource} seqnum {SequenceNumber} timestamp {Timestamp} payload type {PayloadType}.")]
+ public static partial void LogRtpAudioPacketReceived(
+ this ILogger logger,
+ IPEndPoint remoteEndPoint,
+ uint syncSource,
+ ushort sequenceNumber,
+ uint timestamp,
+ int payloadType);
+
+ [LoggerMessage(
+ EventId = 0,
+ EventName = "RtpTextPacketReceived",
+ Level = LogLevel.Trace,
+ Message = "RtpMediaPacketReceived text RTP packet received from {RemoteEndPoint} ssrc {SyncSource} seqnum {SequenceNumber} timestamp {Timestamp} payload type {PayloadType}.")]
+ public static partial void LogRtpTextPacketReceived(
+ this ILogger logger,
+ IPEndPoint remoteEndPoint,
+ uint syncSource,
+ ushort sequenceNumber,
+ uint timestamp,
+ int payloadType);
+
+ [LoggerMessage(
+ EventId = 0,
+ EventName = "SendAudioFromStreamCompleted",
+ Level = LogLevel.Debug,
+ Message = "Send audio from stream completed.")]
+ public static partial void LogSendAudioFromStreamCompleted(
+ this ILogger logger);
+
+ [LoggerMessage(
+ EventId = 0,
+ EventName = "SettingAudioFormat",
+ Level = LogLevel.Debug,
+ Message = "Setting audio source format to {FormatID}:{Codec} {ClockRate} (RTP clock rate {RtpClockRate}).")]
+ public static partial void LogSettingAudioFormat(
+ this ILogger logger,
+ int formatID,
+ AudioCodecsEnum codec,
+ int clockRate,
+ int rtpClockRate);
+
+ [LoggerMessage(
+ EventId = 0,
+ EventName = "SettingVideoFormat",
+ Level = LogLevel.Debug,
+ Message = "Setting video sink and source format to {VideoFormatID}:{VideoCodec}.")]
+ public static partial void LogSettingVideoFormat(
+ this ILogger logger,
+ int videoFormatID,
+ VideoCodecsEnum videoCodec);
+
+ [LoggerMessage(
+ EventId = 0,
+ EventName = "TextFormatNegotiated",
+ Level = LogLevel.Debug,
+ Message = "Setting text sink and source format to {TextFormatID}:{TextCodec}")]
+ public static partial void LogTextFormatNegotiated(
+ this ILogger logger,
+ int textFormatID,
+ TextCodecsEnum textCodec);
+
+ [LoggerMessage(
+ EventId = 0,
+ EventName = "AudioTrackDtmfNegotiated",
+ Level = LogLevel.Debug,
+ Message = "Audio track negotiated DTMF payload ID {AudioStreamNegotiatedRtpEventPayloadID}.")]
+ public static partial void LogAudioTrackDtmfNegotiated(
+ this ILogger logger,
+ int audioStreamNegotiatedRtpEventPayloadID);
+
+ [LoggerMessage(
+ EventId = 0,
+ EventName = "VideoCaptureDeviceFailure",
+ Level = LogLevel.Warning,
+ Message = "Video source for capture device failure. {errorMessage}")]
+ public static partial void LogVideoCaptureDeviceFailure(
+ this ILogger logger,
+ string errorMessage);
+
+ [LoggerMessage(
+ EventId = 0,
+ EventName = "WebcamVideoSourceFailed",
+ Level = LogLevel.Warning,
+ Message = "Webcam video source failed before start, switching to test pattern source.")]
+ public static partial void LogWebcamFailedSwitchingToPattern(
+ this ILogger logger);
+
+ [LoggerMessage(
+ EventId = 0,
+ EventName = "StreamClosedWarning",
+ Level = LogLevel.Warning,
+ Message = "Stream Closed.")]
+ public static partial void LogStreamClosedWarning(
+ this ILogger logger,
+ Exception exception);
+
+ [LoggerMessage(
+ EventId = 0,
+ EventName = "AudioStreamReadError",
+ Level = LogLevel.Warning,
+ Message = "Failed to read from audio stream source.")]
+ public static partial void LogAudioStreamReadError(
+ this ILogger logger);
+
+ [LoggerMessage(
+ EventId = 0,
+ EventName = "AudioStreamNullError",
+ Level = LogLevel.Warning,
+ Message = "Failed to read from audio stream source, stream null or closed.")]
+ public static partial void LogAudioStreamNullError(
+ this ILogger logger);
+
+ [LoggerMessage(
+ EventId = 0,
+ EventName = "UnhandledStreamException",
+ Level = LogLevel.Warning,
+ Message = "Caught unhandled exception")]
+ public static partial void LogUnhandledStreamException(
+ this ILogger logger,
+ Exception exception);
+
+ [LoggerMessage(
+ EventId = 0,
+ EventName = "StreamReaderCloseError",
+ Level = LogLevel.Warning,
+ Message = "Error occurred whilst trying to close the stream source reader.")]
+ public static partial void LogStreamReaderCloseError(
+ this ILogger logger,
+ Exception exception);
+
+ [LoggerMessage(
+ EventId = 0,
+ EventName = "FrameRateError",
+ Level = LogLevel.Warning,
+ Message = "{framesPerSecond} fames per second not in the allowed range of {minimumFramesPerSecond} to {maximumFramesPerSecond}, ignoring.")]
+ public static partial void LogFrameRateError(
+ this ILogger logger,
+ int framesPerSecond,
+ int minimumFramesPerSecond,
+ int maximumFramesPerSecond);
+
+ [LoggerMessage(
+ EventId = 0,
+ EventName = "SilenceSampleError",
+ Level = LogLevel.Error,
+ Message = "Exception sending silence sample")]
+ public static partial void LogSendingSilenceSampleError(
+ this ILogger logger,
+ Exception exception);
+
+ [LoggerMessage(
+ EventId = 0,
+ EventName = "SignalGeneratorError",
+ Level = LogLevel.Error,
+ Message = "Exception sending signal generator sample")]
+ public static partial void LogSignalGeneratorError(
+ this ILogger logger,
+ Exception exception);
+
+ [LoggerMessage(
+ EventId = 0,
+ EventName = "MediaEngineStartError",
+ Level = LogLevel.Error,
+ Message = "Error starting media engine. {ErrorMessage}")]
+ public static partial void LogMediaEngineStartError(
+ this ILogger logger,
+ string errorMessage,
+ Exception ex);
+
+ [LoggerMessage(
+ EventId = 0,
+ EventName = "MediaEngineStop",
+ Level = LogLevel.Debug,
+ Message = "Media engine stopped")]
+ public static partial void LogMediaEngineStop(
+ this ILogger logger);
+
+ [LoggerMessage(
+ EventId = 1,
+ EventName = "SettingAudioFormatWarning",
+ Level = LogLevel.Warning,
+ Message = "{audioEncoder} input sample of length {inputSize} supplied to OPUS encoder exceeded maximum limit of {maxLimit}. Reduce sampling period.")]
+ public static partial void LogSettingAudioFormatWarning(
+ this ILogger logger,
+ string audioEncoder,
+ int inputSize,
+ int maxLimit);
+}
diff --git a/src/SIPSorcery/app/Media/Sources/AudioExtrasSource.cs b/src/SIPSorcery/app/Media/Sources/AudioExtrasSource.cs
index 56ebf8d41..f5b51d36d 100644
--- a/src/SIPSorcery/app/Media/Sources/AudioExtrasSource.cs
+++ b/src/SIPSorcery/app/Media/Sources/AudioExtrasSource.cs
@@ -20,6 +20,8 @@
// BSD 3-Clause "New" or "Revised" License, see included LICENSE.md file.
//-----------------------------------------------------------------------------
+#nullable disable
+
using System;
using System.Collections.Generic;
using System.IO;
@@ -27,6 +29,7 @@
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
+using CommunityToolkit.HighPerformance.Buffers;
using Microsoft.Extensions.Logging;
using SIPSorcery.Net;
using SIPSorceryMedia.Abstractions;
@@ -165,7 +168,7 @@ public int AudioSamplePeriodMilliseconds
get => _audioSamplePeriodMilliseconds;
set
{
- if (value < AUDIO_SAMPLE_PERIOD_MILLISECONDS_MIN || value > AUDIO_SAMPLE_PERIOD_MILLISECONDS_MAX)
+ if (value is < AUDIO_SAMPLE_PERIOD_MILLISECONDS_MIN or > AUDIO_SAMPLE_PERIOD_MILLISECONDS_MAX)
{
throw new ApplicationException($"Invalid value for the audio sample period. Must be between {AUDIO_SAMPLE_PERIOD_MILLISECONDS_MIN} and {AUDIO_SAMPLE_PERIOD_MILLISECONDS_MAX}ms.");
}
@@ -332,9 +335,9 @@ public void SetSource(AudioSourceOptions sourceOptions)
_sendSampleTimer = new Timer(SendSilenceSample);
_sendSampleTimer.Change(0, _audioSamplePeriodMilliseconds);
}
- else if (_audioOpts.AudioSource == AudioSourcesEnum.PinkNoise ||
- _audioOpts.AudioSource == AudioSourcesEnum.WhiteNoise ||
- _audioOpts.AudioSource == AudioSourcesEnum.SineWave)
+ else if (_audioOpts.AudioSource is AudioSourcesEnum.PinkNoise or
+ AudioSourcesEnum.WhiteNoise or
+ AudioSourcesEnum.SineWave)
{
_signalGenerator = new SignalGenerator(_audioFormatManager.SelectedFormat.ClockRate, 1);
@@ -646,7 +649,9 @@ private void EncodeAndSend(short[] pcm, int pcmSampleRate)
pcm = PcmResampler.Resample(pcm, pcmSampleRate, _audioFormatManager.SelectedFormat.ClockRate);
}
- byte[] encodedSample = _audioEncoder.EncodeAudio(pcm, _audioFormatManager.SelectedFormat);
+ using var buffer = new ArrayPoolBufferWriter(8192);
+ _audioEncoder.EncodeAudio(pcm, _audioFormatManager.SelectedFormat, buffer);
+ var encodedSample = buffer.WrittenMemory;
uint rtpUnits = RtpTimestampExtensions.ToRtpUnits(_audioSamplePeriodMilliseconds, _audioFormatManager.SelectedFormat.RtpClockRate);
diff --git a/src/SIPSorcery/app/Media/Sources/VideoTestPatternSource.cs b/src/SIPSorcery/app/Media/Sources/VideoTestPatternSource.cs
index 9578dfe88..5bc73cc98 100644
--- a/src/SIPSorcery/app/Media/Sources/VideoTestPatternSource.cs
+++ b/src/SIPSorcery/app/Media/Sources/VideoTestPatternSource.cs
@@ -15,6 +15,8 @@
// BSD 3-Clause "New" or "Revised" License, see included LICENSE.md file.
//-----------------------------------------------------------------------------
+#nullable disable
+
using System;
using System.Collections.Generic;
using System.Reflection;
@@ -129,7 +131,7 @@ public Task InitialiseVideoSourceDevice() =>
public void SetFrameRate(int framesPerSecond)
{
- if (framesPerSecond < MINIMUM_FRAMES_PER_SECOND || framesPerSecond > MAXIMUM_FRAMES_PER_SECOND)
+ if (framesPerSecond is < MINIMUM_FRAMES_PER_SECOND or > MAXIMUM_FRAMES_PER_SECOND)
{
logger.LogWarning("{FramesPerSecond} fames per second not in the allowed range of {MinimumFramesPerSecond} to {MaximumFramesPerSecond}, ignoring.", framesPerSecond, MINIMUM_FRAMES_PER_SECOND, MAXIMUM_FRAMES_PER_SECOND);
}
@@ -246,8 +248,8 @@ private void GenerateTestPattern(object state)
if (encodedBuffer != null)
{
- uint fps = (_frameSpacing > 0) ? 1000 / (uint)_frameSpacing : DEFAULT_FRAMES_PER_SECOND;
- uint durationRtpTS = VIDEO_SAMPLING_RATE / fps;
+ var fps = (_frameSpacing > 0) ? 1000 / (uint)_frameSpacing : DEFAULT_FRAMES_PER_SECOND;
+ var durationRtpTS = VIDEO_SAMPLING_RATE / fps;
// Use ?.Invoke so the null-check and the call are
// a single atomic delegate read. Without this a
// subscriber unsubscribing on another thread
@@ -283,12 +285,12 @@ private void GenerateRawSample(int width, int height, byte[] i420Buffer)
public static void StampI420Buffer(byte[] i420Buffer, int width, int height, int frameNumber)
{
// Draws a varying grey scale square in the bottom right corner on the base I420 buffer.
- int startX = width - STAMP_BOX_SIZE - STAMP_BOX_PADDING;
- int startY = height - STAMP_BOX_SIZE - STAMP_BOX_PADDING;
+ var startX = width - STAMP_BOX_SIZE - STAMP_BOX_PADDING;
+ var startY = height - STAMP_BOX_SIZE - STAMP_BOX_PADDING;
- for (int y = startY; y < startY + STAMP_BOX_SIZE; y++)
+ for (var y = startY; y < startY + STAMP_BOX_SIZE; y++)
{
- for (int x = startX; x < startX + STAMP_BOX_SIZE; x++)
+ for (var x = startX; x < startX + STAMP_BOX_SIZE; x++)
{
i420Buffer[y * width + x] = (byte)(frameNumber % 255);
}
diff --git a/src/SIPSorcery/app/Media/VoIPMediaSession.cs b/src/SIPSorcery/app/Media/VoIPMediaSession.cs
index 7c603c67e..65df030fa 100644
--- a/src/SIPSorcery/app/Media/VoIPMediaSession.cs
+++ b/src/SIPSorcery/app/Media/VoIPMediaSession.cs
@@ -17,6 +17,8 @@
// BSD 3-Clause "New" or "Revised" License, see included LICENSE.md file.
//-----------------------------------------------------------------------------
+#nullable disable
+
using System;
using System.Collections.Generic;
using System.Linq;
@@ -162,7 +164,7 @@ public VoIPMediaSession(VoIPMediaSessionConfig config)
if (Media.AudioSink != null)
{
- base.OnAudioFrameReceived += Media.AudioSink.GotEncodedMediaFrame;
+ base.OnAudioFrameReceived += Media.AudioSink.GotEncodedMediaFrame;
}
if (Media.TextSink != null)
@@ -339,7 +341,10 @@ protected void RtpMediaPacketReceived(IPEndPoint remoteEndPoint, SDPMediaTypesEn
{
logger.LogTrace(nameof(RtpMediaPacketReceived) + " text RTP packet received from {RemoteEndPoint} ssrc {SyncSource} seqnum {SequenceNumber} timestamp {Timestamp} payload type {PayloadType}.", remoteEndPoint, hdr.SyncSource, hdr.SequenceNumber, hdr.Timestamp, hdr.PayloadType);
- Media.TextSink.GotTextRtp(remoteEndPoint, hdr.SyncSource, hdr.SequenceNumber, hdr.Timestamp, hdr.PayloadType, hdr.MarkerBit, rtpPacket.GetPayloadBytes());
+ var rtpPacketBytes = new byte[rtpPacket.GetByteCount()];
+ rtpPacket.WriteBytes(rtpPacketBytes);
+
+ Media.TextSink.GotTextRtp(remoteEndPoint, hdr.SyncSource, hdr.SequenceNumber, hdr.Timestamp, hdr.PayloadType, hdr.MarkerBit, rtpPacketBytes);
}
else
{
diff --git a/src/SIPSorcery/app/Media/VoIPMediaSessionConfig.cs b/src/SIPSorcery/app/Media/VoIPMediaSessionConfig.cs
index f96a9c698..1710a6194 100644
--- a/src/SIPSorcery/app/Media/VoIPMediaSessionConfig.cs
+++ b/src/SIPSorcery/app/Media/VoIPMediaSessionConfig.cs
@@ -13,6 +13,8 @@
// BSD 3-Clause "New" or "Revised" License, see included LICENSE.md file.
//-----------------------------------------------------------------------------
+#nullable disable
+
using System.Net;
using SIPSorcery.Net;
using SIPSorcery.Sys;
@@ -36,4 +38,4 @@ public sealed class VoIPMediaSessionConfig
public IAudioEncoder AudioExtrasEncoder { get; set; } = new AudioEncoder();
}
-}
\ No newline at end of file
+}
diff --git a/src/SIPSorcery/app/SIPPacketMangler.cs b/src/SIPSorcery/app/SIPPacketMangler.cs
index 5b118e7d8..3af3deaac 100644
--- a/src/SIPSorcery/app/SIPPacketMangler.cs
+++ b/src/SIPSorcery/app/SIPPacketMangler.cs
@@ -16,6 +16,8 @@
// BSD 3-Clause "New" or "Revised" License, see included LICENSE.md file.
// ============================================================================
+#nullable disable
+
using System;
using System.Net;
using System.Net.Sockets;
diff --git a/src/SIPSorcery/app/SIPRequestAuthoriser/SIPRequestAuthenticationResult.cs b/src/SIPSorcery/app/SIPRequestAuthoriser/SIPRequestAuthenticationResult.cs
index c272e6257..dd1a2e17a 100644
--- a/src/SIPSorcery/app/SIPRequestAuthoriser/SIPRequestAuthenticationResult.cs
+++ b/src/SIPSorcery/app/SIPRequestAuthoriser/SIPRequestAuthenticationResult.cs
@@ -13,6 +13,8 @@
// BSD 3-Clause "New" or "Revised" License, see included LICENSE.md file.
//-----------------------------------------------------------------------------
+#nullable disable
+
namespace SIPSorcery.SIP.App
{
public class SIPRequestAuthenticationResult
diff --git a/src/SIPSorcery/app/SIPRequestAuthoriser/SIPRequestAuthenticator.cs b/src/SIPSorcery/app/SIPRequestAuthoriser/SIPRequestAuthenticator.cs
index 5d307309f..13bdc0ca5 100644
--- a/src/SIPSorcery/app/SIPRequestAuthoriser/SIPRequestAuthenticator.cs
+++ b/src/SIPSorcery/app/SIPRequestAuthoriser/SIPRequestAuthenticator.cs
@@ -13,6 +13,8 @@
// BSD 3-Clause "New" or "Revised" License, see included LICENSE.md file.
//-----------------------------------------------------------------------------
+#nullable disable
+
using System;
using System.Linq;
using Microsoft.Extensions.Logging;
diff --git a/src/SIPSorcery/app/SIPUserAgents/ISIPAccount.cs b/src/SIPSorcery/app/SIPUserAgents/ISIPAccount.cs
index 8180e4e0a..2cfe8162c 100644
--- a/src/SIPSorcery/app/SIPUserAgents/ISIPAccount.cs
+++ b/src/SIPSorcery/app/SIPUserAgents/ISIPAccount.cs
@@ -17,6 +17,8 @@
// BSD 3-Clause "New" or "Revised" License, see included LICENSE.md file.
// ============================================================================
+#nullable disable
+
using System;
namespace SIPSorcery.SIP.App
diff --git a/src/SIPSorcery/app/SIPUserAgents/ISIPClientUserAgent.cs b/src/SIPSorcery/app/SIPUserAgents/ISIPClientUserAgent.cs
index 3600b2efa..abecf46d6 100644
--- a/src/SIPSorcery/app/SIPUserAgents/ISIPClientUserAgent.cs
+++ b/src/SIPSorcery/app/SIPUserAgents/ISIPClientUserAgent.cs
@@ -14,6 +14,8 @@
// BSD 3-Clause "New" or "Revised" License, see included LICENSE.md file.
//-----------------------------------------------------------------------------
+#nullable disable
+
namespace SIPSorcery.SIP.App
{
public delegate void SIPCallResponseDelegate(ISIPClientUserAgent uac, SIPResponse sipResponse);
diff --git a/src/SIPSorcery/app/SIPUserAgents/ISIPServerUserAgent.cs b/src/SIPSorcery/app/SIPUserAgents/ISIPServerUserAgent.cs
index e13ae16aa..da26f984d 100644
--- a/src/SIPSorcery/app/SIPUserAgents/ISIPServerUserAgent.cs
+++ b/src/SIPSorcery/app/SIPUserAgents/ISIPServerUserAgent.cs
@@ -14,6 +14,8 @@
// BSD 3-Clause "New" or "Revised" License, see included LICENSE.md file.
//-----------------------------------------------------------------------------
+#nullable disable
+
namespace SIPSorcery.SIP.App
{
public delegate void SIPUASDelegate(ISIPServerUserAgent uas);
diff --git a/src/SIPSorcery/app/SIPUserAgents/SIPB2BUserAgent.cs b/src/SIPSorcery/app/SIPUserAgents/SIPB2BUserAgent.cs
index 22d54d30f..86f1f9adc 100644
--- a/src/SIPSorcery/app/SIPUserAgents/SIPB2BUserAgent.cs
+++ b/src/SIPSorcery/app/SIPUserAgents/SIPB2BUserAgent.cs
@@ -14,6 +14,8 @@
// BSD 3-Clause "New" or "Revised" License, see included LICENSE.md file.
//-----------------------------------------------------------------------------
+#nullable disable
+
using Microsoft.Extensions.Logging;
using SIPSorcery.Sys;
diff --git a/src/SIPSorcery/app/SIPUserAgents/SIPCallDescriptor.cs b/src/SIPSorcery/app/SIPUserAgents/SIPCallDescriptor.cs
index c509f04ec..f87c520cf 100644
--- a/src/SIPSorcery/app/SIPUserAgents/SIPCallDescriptor.cs
+++ b/src/SIPSorcery/app/SIPUserAgents/SIPCallDescriptor.cs
@@ -15,6 +15,8 @@
// BSD 3-Clause "New" or "Revised" License, see included LICENSE.md file.
// ============================================================================
+#nullable disable
+
using System;
using System.Collections.Generic;
using System.Net;
@@ -540,13 +542,13 @@ public static List ParseCustomHeaders(string customHeaders)
//string headerValue = (customHeader.Length > colonIndex) ? customHeader.Substring(colonIndex + 1).Trim() : String.Empty;
var trimmedCustomHeader = customHeader.AsSpan().Trim();
- if (trimmedCustomHeader.Equals(SIPHeaders.SIP_HEADER_VIA, StringComparison.OrdinalIgnoreCase) ||
- trimmedCustomHeader.Equals(SIPHeaders.SIP_HEADER_FROM, StringComparison.OrdinalIgnoreCase) ||
- trimmedCustomHeader.Equals(SIPHeaders.SIP_HEADER_CONTACT, StringComparison.OrdinalIgnoreCase) ||
- trimmedCustomHeader.Equals(SIPHeaders.SIP_HEADER_CSEQ, StringComparison.OrdinalIgnoreCase) ||
- trimmedCustomHeader.Equals(SIPHeaders.SIP_HEADER_CALLID, StringComparison.OrdinalIgnoreCase) ||
- trimmedCustomHeader.Equals(SIPHeaders.SIP_HEADER_MAXFORWARDS, StringComparison.OrdinalIgnoreCase) ||
- trimmedCustomHeader.Equals(SIPHeaders.SIP_HEADER_CONTENTLENGTH, StringComparison.OrdinalIgnoreCase))
+ if (SIPHeaders.SIP_HEADER_VIA.Equals(trimmedCustomHeader, StringComparison.OrdinalIgnoreCase) ||
+ SIPHeaders.SIP_HEADER_FROM.Equals(trimmedCustomHeader, StringComparison.OrdinalIgnoreCase) ||
+ SIPHeaders.SIP_HEADER_CONTACT.Equals(trimmedCustomHeader, StringComparison.OrdinalIgnoreCase) ||
+ SIPHeaders.SIP_HEADER_CSEQ.Equals(trimmedCustomHeader, StringComparison.OrdinalIgnoreCase) ||
+ SIPHeaders.SIP_HEADER_CALLID.Equals(trimmedCustomHeader, StringComparison.OrdinalIgnoreCase) ||
+ SIPHeaders.SIP_HEADER_MAXFORWARDS.Equals(trimmedCustomHeader, StringComparison.OrdinalIgnoreCase) ||
+ SIPHeaders.SIP_HEADER_CONTENTLENGTH.Equals(trimmedCustomHeader, StringComparison.OrdinalIgnoreCase))
{
logger.LogWarning("ParseCustomHeaders skipping custom header due to an non-permitted string in header name, {CustomHeader}.", customHeader);
continue;
diff --git a/src/SIPSorcery/app/SIPUserAgents/SIPClientUserAgent.cs b/src/SIPSorcery/app/SIPUserAgents/SIPClientUserAgent.cs
index ffda6e131..1b8799943 100644
--- a/src/SIPSorcery/app/SIPUserAgents/SIPClientUserAgent.cs
+++ b/src/SIPSorcery/app/SIPUserAgents/SIPClientUserAgent.cs
@@ -16,6 +16,8 @@
// BSD 3-Clause "New" or "Revised" License, see included LICENSE.md file.
//-----------------------------------------------------------------------------
+#nullable disable
+
using System;
using System.Collections.Generic;
using System.Linq;
@@ -410,7 +412,7 @@ private Task ServerFinalResponseReceived(SIPEndPoint localSIPEndPoi
#endregion
}
- else if (sipResponse.Status == SIPResponseStatusCodesEnum.ProxyAuthenticationRequired || sipResponse.Status == SIPResponseStatusCodesEnum.Unauthorised)
+ else if (sipResponse.Status is SIPResponseStatusCodesEnum.ProxyAuthenticationRequired or SIPResponseStatusCodesEnum.Unauthorised)
{
#region Authenticate client call to third party server.
@@ -453,7 +455,7 @@ private Task ServerFinalResponseReceived(SIPEndPoint localSIPEndPoi
}
else
{
- if (sipResponse.StatusCode >= 200 && sipResponse.StatusCode <= 299)
+ if (sipResponse.StatusCode is >= 200 and <= 299)
{
m_sipDialogue = new SIPDialogue(m_serverTransaction);
m_sipDialogue.CallDurationLimit = m_sipCallDescriptor.CallDurationLimit;
@@ -482,7 +484,7 @@ private Task ServerInformationResponseReceived(SIPEndPoint localSIP
}
else
{
- if (sipResponse.Status == SIPResponseStatusCodesEnum.Ringing || sipResponse.Status == SIPResponseStatusCodesEnum.SessionProgress)
+ if (sipResponse.Status is SIPResponseStatusCodesEnum.Ringing or SIPResponseStatusCodesEnum.SessionProgress)
{
CallRinging?.Invoke(this, sipResponse);
}
@@ -527,7 +529,7 @@ private Task ByeServerFinalResponseReceived(SIPEndPoint localSIPEnd
SIPNonInviteTransaction transaction = sipTransaction as SIPNonInviteTransaction;
transaction.NonInviteTransactionFinalResponseReceived -= ByeServerFinalResponseReceived;
- if (sipResponse.Status == SIPResponseStatusCodesEnum.ProxyAuthenticationRequired || sipResponse.Status == SIPResponseStatusCodesEnum.Unauthorised)
+ if (sipResponse.Status is SIPResponseStatusCodesEnum.ProxyAuthenticationRequired or SIPResponseStatusCodesEnum.Unauthorised)
{
var username = string.IsNullOrWhiteSpace(m_sipCallDescriptor.AuthUsername) ? m_sipCallDescriptor.Username : m_sipCallDescriptor.AuthUsername;
var authRequest = transaction.TransactionRequest.DuplicateAndAuthenticate(sipResponse.Header.AuthenticationHeaders,
diff --git a/src/SIPSorcery/app/SIPUserAgents/SIPNonInviteClientUserAgent.cs b/src/SIPSorcery/app/SIPUserAgents/SIPNonInviteClientUserAgent.cs
index ca8551896..b874001b6 100644
--- a/src/SIPSorcery/app/SIPUserAgents/SIPNonInviteClientUserAgent.cs
+++ b/src/SIPSorcery/app/SIPUserAgents/SIPNonInviteClientUserAgent.cs
@@ -15,6 +15,8 @@
// BSD 3-Clause "New" or "Revised" License, see included LICENSE.md file.
// ============================================================================
+#nullable disable
+
using System;
using System.Net.Sockets;
using System.Threading;
@@ -75,7 +77,7 @@ private Task ServerResponseReceived(SIPEndPoint localSIPEndPoint, S
string reasonPhrase = (sipResponse.ReasonPhrase.IsNullOrBlank()) ? sipResponse.Status.ToString() : sipResponse.ReasonPhrase;
logger.LogDebug("Server response {StatusCode} {ReasonPhrase} received for {Method} to {Uri}.", sipResponse.StatusCode, reasonPhrase, sipTransaction.TransactionRequest.Method, m_callDescriptor.Uri);
- if (sipResponse.Status == SIPResponseStatusCodesEnum.ProxyAuthenticationRequired || sipResponse.Status == SIPResponseStatusCodesEnum.Unauthorised)
+ if (sipResponse.Status is SIPResponseStatusCodesEnum.ProxyAuthenticationRequired or SIPResponseStatusCodesEnum.Unauthorised)
{
if (sipResponse.Header.HasAuthenticationHeader)
{
diff --git a/src/SIPSorcery/app/SIPUserAgents/SIPNonInviteServerUserAgent.cs b/src/SIPSorcery/app/SIPUserAgents/SIPNonInviteServerUserAgent.cs
index 86ff19044..af1c10b44 100644
--- a/src/SIPSorcery/app/SIPUserAgents/SIPNonInviteServerUserAgent.cs
+++ b/src/SIPSorcery/app/SIPUserAgents/SIPNonInviteServerUserAgent.cs
@@ -16,6 +16,8 @@
// BSD 3-Clause "New" or "Revised" License, see included LICENSE.md file.
// ============================================================================
+#nullable disable
+
using System;
using Microsoft.Extensions.Logging;
using SIPSorcery.Sys;
diff --git a/src/SIPSorcery/app/SIPUserAgents/SIPNotifierClient.cs b/src/SIPSorcery/app/SIPUserAgents/SIPNotifierClient.cs
index 7661689d6..167c9d225 100644
--- a/src/SIPSorcery/app/SIPUserAgents/SIPNotifierClient.cs
+++ b/src/SIPSorcery/app/SIPUserAgents/SIPNotifierClient.cs
@@ -15,6 +15,8 @@
// BSD 3-Clause "New" or "Revised" License, see included LICENSE.md file.
// ============================================================================
+#nullable disable
+
using System;
using System.Collections.Generic;
using System.Net.Sockets;
@@ -328,7 +330,7 @@ private Task SubscribeTransactionFinalResponseReceived(SIPEndPoint
SubscriptionFailed?.Invoke(m_resourceURI, sipResponse.Status, $"Subscribe failed with response {sipResponse.StatusCode} {sipResponse.ReasonPhrase}.");
m_waitForSubscribeResponse.Set();
}
- else if (sipResponse.Status == SIPResponseStatusCodesEnum.ProxyAuthenticationRequired || sipResponse.Status == SIPResponseStatusCodesEnum.Unauthorised)
+ else if (sipResponse.Status is SIPResponseStatusCodesEnum.ProxyAuthenticationRequired or SIPResponseStatusCodesEnum.Unauthorised)
{
if (m_authUsername.IsNullOrBlank() || m_authPassword.IsNullOrBlank())
{
@@ -377,7 +379,7 @@ private Task SubscribeTransactionFinalResponseReceived(SIPEndPoint
m_waitForSubscribeResponse.Set();
}
}
- else if (sipResponse.StatusCode >= 200 && sipResponse.StatusCode <= 299)
+ else if (sipResponse.StatusCode is >= 200 and <= 299)
{
logger.LogDebug("Authenticating subscribe request for event package {EventPackage} and {ResourceURI} was successful.", m_sipEventPackage, m_resourceURI);
diff --git a/src/SIPSorcery/app/SIPUserAgents/SIPRegistrationUserAgent.cs b/src/SIPSorcery/app/SIPUserAgents/SIPRegistrationUserAgent.cs
index 469861dca..786d6e45c 100644
--- a/src/SIPSorcery/app/SIPUserAgents/SIPRegistrationUserAgent.cs
+++ b/src/SIPSorcery/app/SIPUserAgents/SIPRegistrationUserAgent.cs
@@ -15,6 +15,8 @@
// BSD 3-Clause "New" or "Revised" License, see included LICENSE.md file.
// ============================================================================
+#nullable disable
+
using System;
using System.Collections.Generic;
using System.Linq;
@@ -150,7 +152,7 @@ public SIPRegistrationUserAgent(
m_authUsername = username;
m_password = password;
m_registrarHost = server;
- m_expiry = (expiry >= REGISTER_MINIMUM_EXPIRY && expiry <= MAX_EXPIRY) ? expiry : DEFAULT_REGISTER_EXPIRY;
+ m_expiry = (expiry is >= REGISTER_MINIMUM_EXPIRY and <= MAX_EXPIRY) ? expiry : DEFAULT_REGISTER_EXPIRY;
m_originalExpiry = m_expiry;
m_callID = Guid.NewGuid().ToString();
m_maxRegistrationAttemptTimeout = maxRegistrationAttemptTimeout;
@@ -191,7 +193,7 @@ public SIPRegistrationUserAgent(
m_realm = realm;
m_registrarHost = registrarHost;
m_contactURI = contactURI;
- m_expiry = (expiry >= REGISTER_MINIMUM_EXPIRY && expiry <= MAX_EXPIRY) ? expiry : DEFAULT_REGISTER_EXPIRY;
+ m_expiry = (expiry is >= REGISTER_MINIMUM_EXPIRY and <= MAX_EXPIRY) ? expiry : DEFAULT_REGISTER_EXPIRY;
m_originalExpiry = m_expiry;
m_customHeaders = customHeaders;
m_callID = CallProperties.CreateNewCallId();
@@ -314,7 +316,7 @@ IEnumerable splitMethodsString(string methodsString)
/// The new expiry value.
public void SetExpiry(int expiry)
{
- int newExpiry = (expiry >= REGISTER_MINIMUM_EXPIRY && expiry <= MAX_EXPIRY) ? expiry : DEFAULT_REGISTER_EXPIRY;
+ int newExpiry = (expiry is >= REGISTER_MINIMUM_EXPIRY and <= MAX_EXPIRY) ? expiry : DEFAULT_REGISTER_EXPIRY;
if (newExpiry != m_expiry)
{
@@ -434,7 +436,7 @@ private void ServerResponseReceived(SIPEndPoint localSIPEndPoint, SIPEndPoint re
{
logger.LogDebug("Server response {SipResponseStatus} received for {SipAccountAOR}.", sipResponse.Status, m_sipAccountAOR);
- if (sipResponse.Status == SIPResponseStatusCodesEnum.ProxyAuthenticationRequired || sipResponse.Status == SIPResponseStatusCodesEnum.Unauthorised)
+ if (sipResponse.Status is SIPResponseStatusCodesEnum.ProxyAuthenticationRequired or SIPResponseStatusCodesEnum.Unauthorised)
{
if (sipResponse.Header.HasAuthenticationHeader)
{
@@ -515,7 +517,7 @@ private void ServerResponseReceived(SIPEndPoint localSIPEndPoint, SIPEndPoint re
m_waitForRegistrationMRE.Set();
}
- else if (sipResponse.Status == SIPResponseStatusCodesEnum.Forbidden || sipResponse.Status == SIPResponseStatusCodesEnum.NotFound)
+ else if (sipResponse.Status is SIPResponseStatusCodesEnum.Forbidden or SIPResponseStatusCodesEnum.NotFound)
{
// SIP account does not appear to exist.
m_exit = m_exitOnUnequivocalFailure;
@@ -578,7 +580,7 @@ private void AuthResponseReceived(SIPEndPoint localSIPEndPoint, SIPEndPoint remo
logger.LogDebug("Registration for {SIPAccountAOR} had a too short expiry, updated to {Expiry} and trying again.", m_sipAccountAOR, m_expiry);
SendInitialRegister();
}
- else if (sipResponse.Status == SIPResponseStatusCodesEnum.Forbidden || sipResponse.Status == SIPResponseStatusCodesEnum.NotFound || sipResponse.Status == SIPResponseStatusCodesEnum.PaymentRequired)
+ else if (sipResponse.Status is SIPResponseStatusCodesEnum.Forbidden or SIPResponseStatusCodesEnum.NotFound or SIPResponseStatusCodesEnum.PaymentRequired)
{
// SIP account does not appear to exist.
m_exit = m_exitOnUnequivocalFailure;
@@ -589,7 +591,7 @@ private void AuthResponseReceived(SIPEndPoint localSIPEndPoint, SIPEndPoint remo
m_waitForRegistrationMRE.Set();
}
- else if (sipResponse.Status == SIPResponseStatusCodesEnum.ProxyAuthenticationRequired || sipResponse.Status == SIPResponseStatusCodesEnum.Unauthorised)
+ else if (sipResponse.Status is SIPResponseStatusCodesEnum.ProxyAuthenticationRequired or SIPResponseStatusCodesEnum.Unauthorised)
{
// SIP account credentials failed.
m_exit = m_exitOnUnequivocalFailure;
diff --git a/src/SIPSorcery/app/SIPUserAgents/SIPServerUserAgent.cs b/src/SIPSorcery/app/SIPUserAgents/SIPServerUserAgent.cs
index be8b72252..0c9fb2a32 100644
--- a/src/SIPSorcery/app/SIPUserAgents/SIPServerUserAgent.cs
+++ b/src/SIPSorcery/app/SIPUserAgents/SIPServerUserAgent.cs
@@ -14,6 +14,8 @@
// BSD 3-Clause "New" or "Revised" License, see included LICENSE.md file.
//-----------------------------------------------------------------------------
+#nullable disable
+
using System;
using System.Linq;
using System.Net.Sockets;
diff --git a/src/SIPSorcery/app/SIPUserAgents/SIPUserAgent.cs b/src/SIPSorcery/app/SIPUserAgents/SIPUserAgent.cs
index e106c9a05..fefcdff9b 100644
--- a/src/SIPSorcery/app/SIPUserAgents/SIPUserAgent.cs
+++ b/src/SIPSorcery/app/SIPUserAgents/SIPUserAgent.cs
@@ -22,6 +22,8 @@
// BSD 3-Clause "New" or "Revised" License, see included LICENSE.md file.
//-----------------------------------------------------------------------------
+#nullable disable
+
using System;
using System.Collections.Generic;
using System.Linq;
@@ -153,8 +155,8 @@ public bool IsCalling
{
if (!IsCallActive && m_uac != null && m_uac.ServerTransaction != null)
{
- return m_uac.ServerTransaction.TransactionState == SIPTransactionStatesEnum.Calling ||
- m_uac.ServerTransaction.TransactionState == SIPTransactionStatesEnum.Trying;
+ return m_uac.ServerTransaction.TransactionState is SIPTransactionStatesEnum.Calling or
+ SIPTransactionStatesEnum.Trying;
}
else
{
@@ -1754,7 +1756,7 @@ private async void ClientCallAnsweredHandler(ISIPClientUserAgent uac, SIPRespons
{
_ringTimeout?.Dispose();
- if (sipResponse.StatusCode >= 200 && sipResponse.StatusCode <= 299)
+ if (sipResponse.StatusCode is >= 200 and <= 299)
{
if (sipResponse.Body == null && ((MediaSession as RTPSession)?.IsAudioStarted ?? false))
{
diff --git a/src/SIPSorcery/core/CallProperties.cs b/src/SIPSorcery/core/CallProperties.cs
index 9eb91d3da..cde0c6586 100644
--- a/src/SIPSorcery/core/CallProperties.cs
+++ b/src/SIPSorcery/core/CallProperties.cs
@@ -1,4 +1,4 @@
-//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
// Filename: CallProperties.cs
//
// Description: Helper functions for setting SIP headers.
@@ -13,6 +13,8 @@
// BSD 3-Clause "New" or "Revised" License, see included LICENSE.md file.
//-----------------------------------------------------------------------------
+#nullable disable
+
using System;
using SIPSorcery.Sys;
diff --git a/src/SIPSorcery/core/DNS/SIPDns.cs b/src/SIPSorcery/core/DNS/SIPDns.cs
index c14028550..d732c4b77 100644
--- a/src/SIPSorcery/core/DNS/SIPDns.cs
+++ b/src/SIPSorcery/core/DNS/SIPDns.cs
@@ -14,6 +14,8 @@
// BSD 3-Clause "New" or "Revised" License, see included LICENSE.md file.
//-----------------------------------------------------------------------------
+#nullable disable
+
using System;
using System.Linq;
using System.Net;
@@ -64,7 +66,7 @@ private class SipDNS { }
public const int DNS_RETRIES_PER_SERVER = 1;
public const int CACHE_FAILED_RESULTS_DURATION = 10; // Cache failed DNS responses for this duration in seconds.
- private static readonly ILogger logger = LogFactory.CreateLogger();
+ private static readonly ILogger logger = LogFactory.CreateLogger(typeof(SIPDns).FullName!);
///
/// Don't use IN_ANY queries by default. These are useful if a DNS server supports them as they can
diff --git a/src/SIPSorcery/core/SIP/Channels/SIPChannel.cs b/src/SIPSorcery/core/SIP/Channels/SIPChannel.cs
index 967f2326f..c9121ffe2 100644
--- a/src/SIPSorcery/core/SIP/Channels/SIPChannel.cs
+++ b/src/SIPSorcery/core/SIP/Channels/SIPChannel.cs
@@ -13,6 +13,8 @@
// BSD 3-Clause "New" or "Revised" License, see included LICENSE.md file.
//-----------------------------------------------------------------------------
+#nullable disable
+
using System;
using System.Collections.Generic;
using System.Linq;
@@ -77,7 +79,7 @@ public abstract class SIPChannel : IDisposable
{
private static int _lastUsedChannelID = 0;
- protected ILogger logger = LogFactory.CreateLogger();
+ protected static readonly ILogger logger = LogFactory.CreateLogger();
///
/// A unique ID for the channel. Useful for ensuring a transmission can occur
diff --git a/src/SIPSorcery/core/SIP/Channels/SIPClientWebSocketChannel.cs b/src/SIPSorcery/core/SIP/Channels/SIPClientWebSocketChannel.cs
index aef33dd37..5dec79b27 100644
--- a/src/SIPSorcery/core/SIP/Channels/SIPClientWebSocketChannel.cs
+++ b/src/SIPSorcery/core/SIP/Channels/SIPClientWebSocketChannel.cs
@@ -17,6 +17,8 @@
// BSD 3-Clause "New" or "Revised" License, see included LICENSE.md file.
//-----------------------------------------------------------------------------
+#nullable disable
+
using System;
using System.Collections.Concurrent;
using System.Linq;
@@ -283,7 +285,7 @@ public override bool IsAddressFamilySupported(AddressFamily addresFamily)
public override bool IsProtocolSupported(SIPProtocolsEnum protocol)
{
// We can establish client web sockets to both ws and wss servers.
- return protocol == SIPProtocolsEnum.ws || protocol == SIPProtocolsEnum.wss;
+ return protocol is SIPProtocolsEnum.ws or SIPProtocolsEnum.wss;
}
///
diff --git a/src/SIPSorcery/core/SIP/Channels/SIPStreamConnection.cs b/src/SIPSorcery/core/SIP/Channels/SIPStreamConnection.cs
index 37270e54d..6b79152a7 100644
--- a/src/SIPSorcery/core/SIP/Channels/SIPStreamConnection.cs
+++ b/src/SIPSorcery/core/SIP/Channels/SIPStreamConnection.cs
@@ -17,6 +17,8 @@
// BSD 3-Clause "New" or "Revised" License, see included LICENSE.md file.
//-----------------------------------------------------------------------------
+#nullable disable
+
using System;
using System.Net;
using System.Net.Security;
diff --git a/src/SIPSorcery/core/SIP/Channels/SIPStreamWrapper.cs b/src/SIPSorcery/core/SIP/Channels/SIPStreamWrapper.cs
index 2a72207fa..3892dc164 100644
--- a/src/SIPSorcery/core/SIP/Channels/SIPStreamWrapper.cs
+++ b/src/SIPSorcery/core/SIP/Channels/SIPStreamWrapper.cs
@@ -1,4 +1,4 @@
-//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
// Filename: SIPStreamWrapper.cs
//
// Description: Helper class for Stream with a thread-safe function WriteAsync.
@@ -13,6 +13,8 @@
// BSD 3-Clause "New" or "Revised" License, see included LICENSE.md file.
//-----------------------------------------------------------------------------
+#nullable disable
+
using System;
using System.Collections.Generic;
using System.IO;
@@ -111,4 +113,4 @@ public void SetStatus(Task task)
}
}
}
-}
\ No newline at end of file
+}
diff --git a/src/SIPSorcery/core/SIP/Channels/SIPTCPChannel.cs b/src/SIPSorcery/core/SIP/Channels/SIPTCPChannel.cs
index 8e5a11f2e..710252269 100644
--- a/src/SIPSorcery/core/SIP/Channels/SIPTCPChannel.cs
+++ b/src/SIPSorcery/core/SIP/Channels/SIPTCPChannel.cs
@@ -42,6 +42,8 @@
// BSD 3-Clause "New" or "Revised" License, see included LICENSE.md file.
//-----------------------------------------------------------------------------
+#nullable disable
+
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
diff --git a/src/SIPSorcery/core/SIP/Channels/SIPTLSChannel.cs b/src/SIPSorcery/core/SIP/Channels/SIPTLSChannel.cs
index 3f83e59e4..b4162f119 100644
--- a/src/SIPSorcery/core/SIP/Channels/SIPTLSChannel.cs
+++ b/src/SIPSorcery/core/SIP/Channels/SIPTLSChannel.cs
@@ -15,6 +15,8 @@
// BSD 3-Clause "New" or "Revised" License, see included LICENSE.md file.
//-----------------------------------------------------------------------------
+#nullable disable
+
using System;
using System.IO;
using System.Net;
diff --git a/src/SIPSorcery/core/SIP/Channels/SIPUDPChannel.cs b/src/SIPSorcery/core/SIP/Channels/SIPUDPChannel.cs
index 4e6aa5c5d..b61f22707 100644
--- a/src/SIPSorcery/core/SIP/Channels/SIPUDPChannel.cs
+++ b/src/SIPSorcery/core/SIP/Channels/SIPUDPChannel.cs
@@ -1,4 +1,4 @@
-//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
// Filename: SIPUDPChannel.cs
//
// Description: SIP transport for UDP.
@@ -22,6 +22,8 @@
// BSD 3-Clause "New" or "Revised" License, see included LICENSE.md file.
//-----------------------------------------------------------------------------
+#nullable disable
+
using System;
using System.Collections.Concurrent;
using System.Linq;
diff --git a/src/SIPSorcery/core/SIP/Channels/SIPWebSocketChannel.cs b/src/SIPSorcery/core/SIP/Channels/SIPWebSocketChannel.cs
index 5b9c39003..1f148ea38 100644
--- a/src/SIPSorcery/core/SIP/Channels/SIPWebSocketChannel.cs
+++ b/src/SIPSorcery/core/SIP/Channels/SIPWebSocketChannel.cs
@@ -23,6 +23,8 @@
// BSD 3-Clause "New" or "Revised" License, see included LICENSE.md file.
//-----------------------------------------------------------------------------
+#nullable disable
+
using System;
using System.Collections.Concurrent;
using System.Linq;
@@ -205,7 +207,7 @@ public SIPWebSocketChannel(
m_webSocketServer.AddWebSocketService("/", (behaviour) =>
{
behaviour.Channel = this;
- behaviour.Logger = this.logger;
+ behaviour.Logger = logger;
behaviour.OnClientClose += (id) => m_ingressConnections.TryRemove(id, out _);
});
diff --git a/src/SIPSorcery/core/SIP/SIPAuthChallenge.cs b/src/SIPSorcery/core/SIP/SIPAuthChallenge.cs
index 3846c1069..d39133ea9 100644
--- a/src/SIPSorcery/core/SIP/SIPAuthChallenge.cs
+++ b/src/SIPSorcery/core/SIP/SIPAuthChallenge.cs
@@ -1,4 +1,4 @@
-//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
// Filename: SIPAuthChallenge.cs
//
// Description: Common logic when having to add auth to SIP Requests
@@ -11,6 +11,8 @@
// BSD 3-Clause "New" or "Revised" License, see included LICENSE.md file.
//-----------------------------------------------------------------------------
+#nullable disable
+
using System.Collections.Generic;
using System.Linq;
using SIPSorcery.SIP;
diff --git a/src/SIPSorcery/core/SIP/SIPAuthorisationDigest.cs b/src/SIPSorcery/core/SIP/SIPAuthorisationDigest.cs
index 5b7a3fb05..ec59fa4e5 100644
--- a/src/SIPSorcery/core/SIP/SIPAuthorisationDigest.cs
+++ b/src/SIPSorcery/core/SIP/SIPAuthorisationDigest.cs
@@ -13,6 +13,8 @@
// BSD 3-Clause "New" or "Revised" License, see included LICENSE.md file.
//-----------------------------------------------------------------------------
+#nullable disable
+
using System;
using System.Security.Cryptography;
using System.Text;
diff --git a/src/SIPSorcery/core/SIP/SIPConstants.cs b/src/SIPSorcery/core/SIP/SIPConstants.cs
index 79c3bb696..ed376f62b 100644
--- a/src/SIPSorcery/core/SIP/SIPConstants.cs
+++ b/src/SIPSorcery/core/SIP/SIPConstants.cs
@@ -13,6 +13,8 @@
// BSD 3-Clause "New" or "Revised" License, see included LICENSE.md file.
//-----------------------------------------------------------------------------
+#nullable disable
+
using System;
using System.Collections.Generic;
using System.Reflection;
diff --git a/src/SIPSorcery/core/SIP/SIPDialogue.cs b/src/SIPSorcery/core/SIP/SIPDialogue.cs
index 3816a8039..57b90a93d 100644
--- a/src/SIPSorcery/core/SIP/SIPDialogue.cs
+++ b/src/SIPSorcery/core/SIP/SIPDialogue.cs
@@ -13,6 +13,8 @@
// BSD 3-Clause "New" or "Revised" License, see included LICENSE.md file.
//-----------------------------------------------------------------------------
+#nullable disable
+
using System;
using System.Net;
using System.Text;
diff --git a/src/SIPSorcery/core/SIP/SIPEndPoint.cs b/src/SIPSorcery/core/SIP/SIPEndPoint.cs
index efd9ae5af..054134e3c 100644
--- a/src/SIPSorcery/core/SIP/SIPEndPoint.cs
+++ b/src/SIPSorcery/core/SIP/SIPEndPoint.cs
@@ -15,6 +15,8 @@
// BSD 3-Clause "New" or "Revised" License, see included LICENSE.md file.
//-----------------------------------------------------------------------------
+#nullable disable
+
using System;
using System.Net;
using System.Net.Sockets;
diff --git a/src/SIPSorcery/core/SIP/SIPHeader.cs b/src/SIPSorcery/core/SIP/SIPHeader.cs
index 8f7be1b09..03700c5bd 100644
--- a/src/SIPSorcery/core/SIP/SIPHeader.cs
+++ b/src/SIPSorcery/core/SIP/SIPHeader.cs
@@ -13,6 +13,8 @@
// BSD 3-Clause "New" or "Revised" License, see included LICENSE.md file.
//-----------------------------------------------------------------------------
+#nullable disable
+
using System;
using System.Collections.Generic;
using System.Net;
@@ -757,7 +759,7 @@ public static bool AreEqual(SIPContactHeader contact1, SIPContactHeader contact2
{
foreach (string key in contact1Keys)
{
- if (key == EXPIRES_PARAMETER_KEY || key == QVALUE_PARAMETER_KEY)
+ if (key is EXPIRES_PARAMETER_KEY or QVALUE_PARAMETER_KEY)
{
continue;
}
@@ -775,7 +777,7 @@ public static bool AreEqual(SIPContactHeader contact1, SIPContactHeader contact2
{
foreach (string key in contact2Keys)
{
- if (key == EXPIRES_PARAMETER_KEY || key == QVALUE_PARAMETER_KEY)
+ if (key is EXPIRES_PARAMETER_KEY or QVALUE_PARAMETER_KEY)
{
continue;
}
@@ -1590,7 +1592,7 @@ private void Initialise(List contact, SIPFromHeader from, SIPT
Contact = contact;
CallId = callId;
- if (cseq >= 0 && cseq < Int32.MaxValue)
+ if (cseq is >= 0 and < int.MaxValue)
{
CSeq = cseq;
}
diff --git a/src/SIPSorcery/core/SIP/SIPMessageBase.cs b/src/SIPSorcery/core/SIP/SIPMessageBase.cs
index 234a2da33..e6fe9384d 100644
--- a/src/SIPSorcery/core/SIP/SIPMessageBase.cs
+++ b/src/SIPSorcery/core/SIP/SIPMessageBase.cs
@@ -1,4 +1,4 @@
-//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
// Filename: SIPMessageBase.cs
//
// Description: Common base class for SIPRequest and SIPResponse classes.
@@ -15,6 +15,8 @@
// BSD 3-Clause "New" or "Revised" License, see included LICENSE.md file.
//-----------------------------------------------------------------------------
+#nullable disable
+
using System;
using System.Text;
using Microsoft.Extensions.Logging;
diff --git a/src/SIPSorcery/core/SIP/SIPMessageBuffer.cs b/src/SIPSorcery/core/SIP/SIPMessageBuffer.cs
index e694a3820..05bf4e1bf 100644
--- a/src/SIPSorcery/core/SIP/SIPMessageBuffer.cs
+++ b/src/SIPSorcery/core/SIP/SIPMessageBuffer.cs
@@ -14,6 +14,8 @@
// BSD 3-Clause "New" or "Revised" License, see included LICENSE.md file.
//-----------------------------------------------------------------------------
+#nullable disable
+
using System;
using System.Text;
using Microsoft.Extensions.Logging;
@@ -309,7 +311,7 @@ public static int GetContentLength(byte[] buffer, int start, int end,Encoding si
contentLengthValueStartPosn = index + 1;
break;
}
- else if (buffer[index] == ' ' || buffer[index] == '\t')
+ else if (buffer[index] is (byte)' ' or (byte)'\t')
{
// Skip any whitespace between the header and the colon.
continue;
@@ -364,7 +366,7 @@ public static int GetContentLength(byte[] buffer, int start, int end,Encoding si
// Skip any whitespace at the start of the header value.
continue;
}
- else if (buffer[index] >= '0' && buffer[index] <= '9')
+ else if (buffer[index] is >= (byte)'0' and <= (byte)'9')
{
contentLengthValue += ((char)buffer[index]).ToString();
}
diff --git a/src/SIPSorcery/core/SIP/SIPParameterlessURI.cs b/src/SIPSorcery/core/SIP/SIPParameterlessURI.cs
index 22e89b0d6..0f57fb29d 100644
--- a/src/SIPSorcery/core/SIP/SIPParameterlessURI.cs
+++ b/src/SIPSorcery/core/SIP/SIPParameterlessURI.cs
@@ -14,6 +14,8 @@
// BSD 3-Clause "New" or "Revised" License, see included LICENSE.md file.
//-----------------------------------------------------------------------------
+#nullable disable
+
using System;
using System.Runtime.Serialization;
using Microsoft.Extensions.Logging;
diff --git a/src/SIPSorcery/core/SIP/SIPParameters.cs b/src/SIPSorcery/core/SIP/SIPParameters.cs
index 6924686b4..2d3c6c1fa 100644
--- a/src/SIPSorcery/core/SIP/SIPParameters.cs
+++ b/src/SIPSorcery/core/SIP/SIPParameters.cs
@@ -13,6 +13,8 @@
// BSD 3-Clause "New" or "Revised" License, see included LICENSE.md file.
//-----------------------------------------------------------------------------
+#nullable disable
+
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
diff --git a/src/SIPSorcery/core/SIP/SIPReplacesParameter.cs b/src/SIPSorcery/core/SIP/SIPReplacesParameter.cs
index df9fed8d5..8472b31db 100644
--- a/src/SIPSorcery/core/SIP/SIPReplacesParameter.cs
+++ b/src/SIPSorcery/core/SIP/SIPReplacesParameter.cs
@@ -1,4 +1,4 @@
-//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
// Filename: SIPReplacesParameter.cs
//
// Description: Represents the Replaces parameter on a Refer-To header. The Replaces parameter
@@ -14,6 +14,8 @@
// BSD 3-Clause "New" or "Revised" License, see included LICENSE.md file.
//-----------------------------------------------------------------------------
+#nullable disable
+
using System.Text.RegularExpressions;
namespace SIPSorcery.SIP
diff --git a/src/SIPSorcery/core/SIP/SIPRequest.cs b/src/SIPSorcery/core/SIP/SIPRequest.cs
index 16d3663f6..94adc12f8 100644
--- a/src/SIPSorcery/core/SIP/SIPRequest.cs
+++ b/src/SIPSorcery/core/SIP/SIPRequest.cs
@@ -15,6 +15,8 @@
// BSD 3-Clause "New" or "Revised" License, see included LICENSE.md file.
//-----------------------------------------------------------------------------
+#nullable disable
+
using System;
using System.Collections.Generic;
using System.Linq;
diff --git a/src/SIPSorcery/core/SIP/SIPResponse.cs b/src/SIPSorcery/core/SIP/SIPResponse.cs
index 14be4b894..f4541b376 100644
--- a/src/SIPSorcery/core/SIP/SIPResponse.cs
+++ b/src/SIPSorcery/core/SIP/SIPResponse.cs
@@ -14,6 +14,8 @@
// BSD 3-Clause "New" or "Revised" License, see included LICENSE.md file.
//-----------------------------------------------------------------------------
+#nullable disable
+
using System;
using System.Text;
using Microsoft.Extensions.Logging;
@@ -52,7 +54,7 @@ public class SIPResponse : SIPMessageBase
///
public bool IsSuccessStatusCode
{
- get { return (StatusCode >= 200) && (StatusCode <= 204); }
+ get { return StatusCode is >= 200 and <= 204; }
}
///
diff --git a/src/SIPSorcery/core/SIP/SIPTransport.cs b/src/SIPSorcery/core/SIP/SIPTransport.cs
index e787d0a03..f8b22bc5d 100644
--- a/src/SIPSorcery/core/SIP/SIPTransport.cs
+++ b/src/SIPSorcery/core/SIP/SIPTransport.cs
@@ -18,6 +18,8 @@
// BSD 3-Clause "New" or "Revised" License, see included LICENSE.md file.
//-----------------------------------------------------------------------------
+#nullable disable
+
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
@@ -844,8 +846,8 @@ internal SIPHeader AdjustHeadersForEndPoint(SIPEndPoint sendFromSIPEndPoint, SIP
{
if (contactHeader.ContactURI.Host.StartsWith(IPAddress.Any.ToString()) ||
contactHeader.ContactURI.Host.StartsWith(IPAddress.IPv6Any.ToString()))
- {
- copy = copy ?? header.Copy();
+ {
+ copy = copy ?? header.Copy();
Debug.Assert(copy.Contact.Count == 1);
copy.Contact[0].ContactURI.Host = sendFromEndPoint.ToString();
}
@@ -1015,8 +1017,7 @@ private Task SIPMessageReceived(
}
else if (sipRequest.Method == SIPMethodsEnum.ACK)
{
- if (requestTransaction.TransactionState == SIPTransactionStatesEnum.Completed ||
- requestTransaction.TransactionState == SIPTransactionStatesEnum.Cancelled)
+ if (requestTransaction.TransactionState is SIPTransactionStatesEnum.Completed or SIPTransactionStatesEnum.Cancelled)
{
sipRequest.Header.Vias.UpateTopViaHeader(remoteEndPoint.GetIPEndPoint());
requestTransaction.ACKReceived(localEndPoint, remoteEndPoint, sipRequest);
diff --git a/src/SIPSorcery/core/SIP/SIPURI.cs b/src/SIPSorcery/core/SIP/SIPURI.cs
index ba3133d93..f7ed98381 100644
--- a/src/SIPSorcery/core/SIP/SIPURI.cs
+++ b/src/SIPSorcery/core/SIP/SIPURI.cs
@@ -13,6 +13,8 @@
// BSD 3-Clause "New" or "Revised" License, see included LICENSE.md file.
//-----------------------------------------------------------------------------
+#nullable disable
+
using System;
using System.Net;
using System.Runtime.Serialization;
diff --git a/src/SIPSorcery/core/SIP/SIPUserAgentsRolesEnum.cs b/src/SIPSorcery/core/SIP/SIPUserAgentsRolesEnum.cs
index 19a417933..729941cb8 100644
--- a/src/SIPSorcery/core/SIP/SIPUserAgentsRolesEnum.cs
+++ b/src/SIPSorcery/core/SIP/SIPUserAgentsRolesEnum.cs
@@ -16,6 +16,8 @@
// BSD 3-Clause "New" or "Revised" License, see included LICENSE.md file.
//-----------------------------------------------------------------------------
+#nullable disable
+
using System;
namespace SIPSorcery.SIP
diff --git a/src/SIPSorcery/core/SIP/SIPUserField.cs b/src/SIPSorcery/core/SIP/SIPUserField.cs
index 1335c8596..eb4a4f38f 100644
--- a/src/SIPSorcery/core/SIP/SIPUserField.cs
+++ b/src/SIPSorcery/core/SIP/SIPUserField.cs
@@ -16,6 +16,8 @@
// BSD 3-Clause "New" or "Revised" License, see included LICENSE.md file.
//-----------------------------------------------------------------------------
+#nullable disable
+
using System;
using System.Runtime.Serialization;
using Microsoft.Extensions.Logging;
diff --git a/src/SIPSorcery/core/SIP/SIPValidationException.cs b/src/SIPSorcery/core/SIP/SIPValidationException.cs
index 0a50b6d8a..463378e2f 100644
--- a/src/SIPSorcery/core/SIP/SIPValidationException.cs
+++ b/src/SIPSorcery/core/SIP/SIPValidationException.cs
@@ -1,4 +1,4 @@
-//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
// Filename: SIPValidationException.cs
//
// Description: Exception class for SIP validation errors.
@@ -13,6 +13,8 @@
// BSD 3-Clause "New" or "Revised" License, see included LICENSE.md file.
//-----------------------------------------------------------------------------
+#nullable disable
+
using System;
namespace SIPSorcery.SIP
diff --git a/src/SIPSorcery/core/SIPCDR/SIPCDR.cs b/src/SIPSorcery/core/SIPCDR/SIPCDR.cs
index 96a9b39a6..36c9c292f 100644
--- a/src/SIPSorcery/core/SIPCDR/SIPCDR.cs
+++ b/src/SIPSorcery/core/SIPCDR/SIPCDR.cs
@@ -13,6 +13,8 @@
// BSD 3-Clause "New" or "Revised" License, see included LICENSE.md file.
//-----------------------------------------------------------------------------
+#nullable disable
+
using System;
using System.Runtime.Serialization;
using Microsoft.Extensions.Logging;
diff --git a/src/SIPSorcery/core/SIPEvents/Dialog/SIPEventDialog.cs b/src/SIPSorcery/core/SIPEvents/Dialog/SIPEventDialog.cs
index 6dd52ca98..31108a9cc 100644
--- a/src/SIPSorcery/core/SIPEvents/Dialog/SIPEventDialog.cs
+++ b/src/SIPSorcery/core/SIPEvents/Dialog/SIPEventDialog.cs
@@ -1,4 +1,4 @@
-// ============================================================================
+// ============================================================================
// FileName: SIPEventDialog.cs
//
// Description:
@@ -16,6 +16,8 @@
// BSD 3-Clause "New" or "Revised" License, see included LICENSE.md file.
// ============================================================================
+#nullable disable
+
using System;
using System.Xml.Linq;
using SIPSorcery.Sys;
diff --git a/src/SIPSorcery/core/SIPEvents/Dialog/SIPEventDialogInfo.cs b/src/SIPSorcery/core/SIPEvents/Dialog/SIPEventDialogInfo.cs
index 8cb134e21..fac386feb 100644
--- a/src/SIPSorcery/core/SIPEvents/Dialog/SIPEventDialogInfo.cs
+++ b/src/SIPSorcery/core/SIPEvents/Dialog/SIPEventDialogInfo.cs
@@ -15,6 +15,8 @@
// BSD 3-Clause "New" or "Revised" License, see included LICENSE.md file.
// ============================================================================
+#nullable disable
+
using System;
using System.Collections.Generic;
using System.Text;
diff --git a/src/SIPSorcery/core/SIPEvents/Dialog/SIPEventDialogParticipant.cs b/src/SIPSorcery/core/SIPEvents/Dialog/SIPEventDialogParticipant.cs
index ad6120986..f5fb6befe 100644
--- a/src/SIPSorcery/core/SIPEvents/Dialog/SIPEventDialogParticipant.cs
+++ b/src/SIPSorcery/core/SIPEvents/Dialog/SIPEventDialogParticipant.cs
@@ -1,4 +1,4 @@
-// ============================================================================
+// ============================================================================
// FileName: SIPEventDialog.cs
//
// Description:
@@ -16,6 +16,8 @@
// BSD 3-Clause "New" or "Revised" License, see included LICENSE.md file.
// ============================================================================
+#nullable disable
+
using System;
using System.Xml.Linq;
using SIPSorcery.Sys;
diff --git a/src/SIPSorcery/core/SIPEvents/Presence/SIPEventPresence.cs b/src/SIPSorcery/core/SIPEvents/Presence/SIPEventPresence.cs
index 3dee5fba8..e83600158 100644
--- a/src/SIPSorcery/core/SIPEvents/Presence/SIPEventPresence.cs
+++ b/src/SIPSorcery/core/SIPEvents/Presence/SIPEventPresence.cs
@@ -1,4 +1,4 @@
-// ============================================================================
+// ============================================================================
// FileName: SIPEventPresence.cs
//
// Description:
@@ -15,6 +15,8 @@
// BSD 3-Clause "New" or "Revised" License, see included LICENSE.md file.
// ============================================================================
+#nullable disable
+
using System;
using System.Collections.Generic;
using System.Text;
diff --git a/src/SIPSorcery/core/SIPEvents/Presence/SIPEventPresenceTuple.cs b/src/SIPSorcery/core/SIPEvents/Presence/SIPEventPresenceTuple.cs
index 45bf63764..e936dbe91 100644
--- a/src/SIPSorcery/core/SIPEvents/Presence/SIPEventPresenceTuple.cs
+++ b/src/SIPSorcery/core/SIPEvents/Presence/SIPEventPresenceTuple.cs
@@ -1,4 +1,4 @@
-// ============================================================================
+// ============================================================================
// FileName: SIPEventPresenceTuple.cs
//
// Description:
@@ -13,6 +13,8 @@
// BSD 3-Clause "New" or "Revised" License, see included LICENSE.md file.
// ============================================================================
+#nullable disable
+
using System;
using System.Xml.Linq;
diff --git a/src/SIPSorcery/core/SIPEvents/SIPEventPackages.cs b/src/SIPSorcery/core/SIPEvents/SIPEventPackages.cs
index 88c9bfc8d..5bd49bac3 100644
--- a/src/SIPSorcery/core/SIPEvents/SIPEventPackages.cs
+++ b/src/SIPSorcery/core/SIPEvents/SIPEventPackages.cs
@@ -16,6 +16,8 @@
// BSD 3-Clause "New" or "Revised" License, see included LICENSE.md file.
// ============================================================================
+#nullable disable
+
using System;
using SIPSorcery.Sys;
diff --git a/src/SIPSorcery/core/SIPTransactions/SIPNonInviteTransaction.cs b/src/SIPSorcery/core/SIPTransactions/SIPNonInviteTransaction.cs
index ff47e33bd..a7417ccfc 100644
--- a/src/SIPSorcery/core/SIPTransactions/SIPNonInviteTransaction.cs
+++ b/src/SIPSorcery/core/SIPTransactions/SIPNonInviteTransaction.cs
@@ -14,6 +14,8 @@
// BSD 3-Clause "New" or "Revised" License, see included LICENSE.md file.
//-----------------------------------------------------------------------------
+#nullable disable
+
using System.Net.Sockets;
using System.Threading.Tasks;
diff --git a/src/SIPSorcery/core/SIPTransactions/SIPTransaction.cs b/src/SIPSorcery/core/SIPTransactions/SIPTransaction.cs
index de81ab056..9c929aa7d 100644
--- a/src/SIPSorcery/core/SIPTransactions/SIPTransaction.cs
+++ b/src/SIPSorcery/core/SIPTransactions/SIPTransaction.cs
@@ -15,6 +15,8 @@
// BSD 3-Clause "New" or "Revised" License, see included LICENSE.md file.
//-----------------------------------------------------------------------------
+#nullable disable
+
using System;
using System.Net.Sockets;
using System.Threading.Tasks;
@@ -291,14 +293,14 @@ public static string GetRequestTransactionId(string branchId, SIPMethodsEnum met
public Task GotResponse(SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPResponse sipResponse)
{
- if (TransactionState == SIPTransactionStatesEnum.Completed || TransactionState == SIPTransactionStatesEnum.Confirmed)
+ if (TransactionState is SIPTransactionStatesEnum.Completed or SIPTransactionStatesEnum.Confirmed)
{
TransactionTraceMessage?.Invoke(this, $"Transaction received duplicate response {localSIPEndPoint}<-{remoteEndPoint}: {sipResponse.ShortDescription}");
TransactionDuplicateResponse?.Invoke(localSIPEndPoint, remoteEndPoint, this, sipResponse);
if (sipResponse.Header.CSeqMethod == SIPMethodsEnum.INVITE)
{
- if (sipResponse.StatusCode > 100 && sipResponse.StatusCode <= 199)
+ if (sipResponse.StatusCode is > 100 and <= 199)
{
return ResendPrackRequest();
}
@@ -316,7 +318,7 @@ public Task GotResponse(SIPEndPoint localSIPEndPoint, SIPEndPoint r
{
TransactionTraceMessage?.Invoke(this, $"Transaction received Response {localSIPEndPoint}<-{remoteEndPoint}: {sipResponse.ShortDescription}");
- if (sipResponse.StatusCode >= 100 && sipResponse.StatusCode <= 199)
+ if (sipResponse.StatusCode is >= 100 and <= 199)
{
UpdateTransactionState(SIPTransactionStatesEnum.Proceeding);
return TransactionInformationResponseReceived(localSIPEndPoint, remoteEndPoint, this, sipResponse);
@@ -344,9 +346,9 @@ protected void UpdateTransactionState(SIPTransactionStatesEnum transactionState)
{
m_transactionState = transactionState;
- if (transactionState == SIPTransactionStatesEnum.Confirmed ||
- transactionState == SIPTransactionStatesEnum.Terminated ||
- transactionState == SIPTransactionStatesEnum.Cancelled)
+ if (transactionState is SIPTransactionStatesEnum.Confirmed or
+ SIPTransactionStatesEnum.Terminated or
+ SIPTransactionStatesEnum.Cancelled)
{
if (transactionState == SIPTransactionStatesEnum.Cancelled && CancelledAt == DateTime.MinValue)
{
@@ -395,7 +397,7 @@ protected virtual Task SendProvisionalResponse(SIPResponse sipRespo
UnreliableProvisionalResponse = sipResponse;
return m_sipTransport.SendResponseAsync(sipResponse);
}
- else if (sipResponse.StatusCode > 100 && sipResponse.StatusCode <= 199)
+ else if (sipResponse.StatusCode is > 100 and <= 199)
{
UpdateTransactionState(SIPTransactionStatesEnum.Proceeding);
diff --git a/src/SIPSorcery/core/SIPTransactions/SIPTransactionEngine.cs b/src/SIPSorcery/core/SIPTransactions/SIPTransactionEngine.cs
index 9e877f073..25cfd84e3 100644
--- a/src/SIPSorcery/core/SIPTransactions/SIPTransactionEngine.cs
+++ b/src/SIPSorcery/core/SIPTransactions/SIPTransactionEngine.cs
@@ -15,6 +15,8 @@
// BSD 3-Clause "New" or "Revised" License, see included LICENSE.md file.
//-----------------------------------------------------------------------------
+#nullable disable
+
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
@@ -480,7 +482,7 @@ private void ProcessPendingTransactions()
break;
}
- if (sendResult != SocketError.Success && sendResult != SocketError.InProgress)
+ if (sendResult is not SocketError.Success and not SocketError.InProgress)
{
logger.LogWarning("SIP transaction send failed in state {TransactionState} with error {SendResult}.", transaction.TransactionState, sendResult);
@@ -644,7 +646,7 @@ private void RemoveExpiredTransactions()
foreach (var (_, transaction) in m_pendingTransactions)
{
- if (transaction.TransactionType == SIPTransactionTypesEnum.InviteClient || transaction.TransactionType == SIPTransactionTypesEnum.InviteServer)
+ if (transaction.TransactionType is SIPTransactionTypesEnum.InviteClient or SIPTransactionTypesEnum.InviteServer)
{
if (transaction.TransactionState == SIPTransactionStatesEnum.Confirmed)
{
@@ -706,8 +708,8 @@ private void RemoveExpiredTransactions()
// - Calling: it means no response of any kind (provisional or final) was received from the server in time.
// - Trying: it means all we got was a "100 Trying" response without any follow up progress indications or final response.
- if (transaction.TransactionState == SIPTransactionStatesEnum.Calling ||
- transaction.TransactionState == SIPTransactionStatesEnum.Trying)
+ if (transaction.TransactionState is SIPTransactionStatesEnum.Calling or
+ SIPTransactionStatesEnum.Trying)
{
transaction.Expire(now);
expiredTransactionIds.Add(transaction.TransactionId);
@@ -725,9 +727,9 @@ private void RemoveExpiredTransactions()
}
else if (now.Subtract(transaction.Created).TotalMilliseconds >= m_t6)
{
- if (transaction.TransactionState == SIPTransactionStatesEnum.Calling ||
- transaction.TransactionState == SIPTransactionStatesEnum.Trying ||
- transaction.TransactionState == SIPTransactionStatesEnum.Proceeding)
+ if (transaction.TransactionState is SIPTransactionStatesEnum.Calling or
+ SIPTransactionStatesEnum.Trying or
+ SIPTransactionStatesEnum.Proceeding)
{
//logger.LogWarning("Timed out transaction in SIPTransactionEngine, should have been timed out in the SIP Transport layer. " + transaction.TransactionRequest.Method + ".");
transaction.Expire(now);
diff --git a/src/SIPSorcery/core/SIPTransactions/UACInviteTransaction.cs b/src/SIPSorcery/core/SIPTransactions/UACInviteTransaction.cs
index 5547ba282..e331fa683 100644
--- a/src/SIPSorcery/core/SIPTransactions/UACInviteTransaction.cs
+++ b/src/SIPSorcery/core/SIPTransactions/UACInviteTransaction.cs
@@ -15,6 +15,8 @@
// BSD 3-Clause "New" or "Revised" License, see included LICENSE.md file.
//-----------------------------------------------------------------------------
+#nullable disable
+
using System;
using System.Net;
using System.Net.Sockets;
@@ -103,7 +105,7 @@ private async Task UACInviteTransaction_TransactionInformationRespo
{
try
{
- if (sipResponse.StatusCode > 100 && sipResponse.StatusCode <= 199)
+ if (sipResponse.StatusCode is > 100 and <= 199)
{
if (!_disablePrackSupport && sipResponse.Header.RSeq > 0)
{
@@ -145,7 +147,7 @@ private async Task UACInviteTransaction_TransactionFinalResponseRec
base.UpdateTransactionState(SIPTransactionStatesEnum.Confirmed);
// BranchId for 2xx responses needs to be a new one, non-2xx final responses use same one as original request.
- if (sipResponse.StatusCode >= 200 && sipResponse.StatusCode < 299)
+ if (sipResponse.StatusCode is >= 200 and < 299)
{
if (_sendOkAckManually == false)
{
diff --git a/src/SIPSorcery/core/SIPTransactions/UASInviteTransaction.cs b/src/SIPSorcery/core/SIPTransactions/UASInviteTransaction.cs
index 5371f5152..c32366ea7 100644
--- a/src/SIPSorcery/core/SIPTransactions/UASInviteTransaction.cs
+++ b/src/SIPSorcery/core/SIPTransactions/UASInviteTransaction.cs
@@ -15,6 +15,8 @@
// BSD 3-Clause "New" or "Revised" License, see included LICENSE.md file.
//-----------------------------------------------------------------------------
+#nullable disable
+
using System;
using System.Net.Sockets;
using System.Threading.Tasks;
@@ -123,7 +125,7 @@ private Task UASInviteTransaction_TransactionResponseReceived(SIPEn
/// A socket error with the result of the cancel.
public void CancelCall(SIPRequest sipCancelRequest = null)
{
- if (TransactionState == SIPTransactionStatesEnum.Calling || TransactionState == SIPTransactionStatesEnum.Trying || TransactionState == SIPTransactionStatesEnum.Proceeding)
+ if (TransactionState is SIPTransactionStatesEnum.Calling or SIPTransactionStatesEnum.Trying or SIPTransactionStatesEnum.Proceeding)
{
base.UpdateTransactionState(SIPTransactionStatesEnum.Cancelled);
UASInviteTransactionCancelled?.Invoke(this, sipCancelRequest);
diff --git a/src/SIPSorcery/core/SIPTransportConfig.cs b/src/SIPSorcery/core/SIPTransportConfig.cs
index e4f746b99..e7cc469f5 100644
--- a/src/SIPSorcery/core/SIPTransportConfig.cs
+++ b/src/SIPSorcery/core/SIPTransportConfig.cs
@@ -14,6 +14,8 @@
// BSD 3-Clause "New" or "Revised" License, see included LICENSE.md file.
//-----------------------------------------------------------------------------
+#nullable disable
+
using System;
using System.Collections.Generic;
using System.Net;
diff --git a/src/SIPSorcery/core/TWCCBitrateController.cs b/src/SIPSorcery/core/TWCCBitrateController.cs
index 19365a2c3..6ac50902f 100644
--- a/src/SIPSorcery/core/TWCCBitrateController.cs
+++ b/src/SIPSorcery/core/TWCCBitrateController.cs
@@ -13,6 +13,8 @@
* 2025-03-05 Initial creation.
*/
+#nullable disable
+
using System;
using SIPSorcery.Net;
using SIPSorceryMedia.Abstractions;
diff --git a/src/SIPSorcery/net/DtlsSrtp/DtlsSrtpTransport.cs b/src/SIPSorcery/net/DtlsSrtp/DtlsSrtpTransport.cs
index 0eb3515a4..d0fac8f74 100644
--- a/src/SIPSorcery/net/DtlsSrtp/DtlsSrtpTransport.cs
+++ b/src/SIPSorcery/net/DtlsSrtp/DtlsSrtpTransport.cs
@@ -19,159 +19,171 @@
using System;
using System.Collections.Concurrent;
+using System.Diagnostics;
using Org.BouncyCastle.Tls;
using SIPSorcery.Net.SharpSRTP.DTLS;
using SIPSorcery.Net.SharpSRTP.DTLSSRTP;
using SIPSorcery.Net.SharpSRTP.SRTP;
+using SIPSorcery.SIP.App;
-namespace SIPSorcery.Net
+namespace SIPSorcery.Net;
+
+public delegate void OnDataReadyEvent(byte[] data);
+public delegate void OnDtlsAlertEvent(TlsAlertLevelsEnum alertLevel, TlsAlertTypesEnum alertType, string alertDescription);
+
+public class DtlsSrtpTransport : DatagramTransport
{
- public delegate void OnDataReadyEvent(byte[] data);
- public delegate void OnDtlsAlertEvent(TlsAlertLevelsEnum alertLevel, TlsAlertTypesEnum alertType, string alertDescription);
+ public const int MAXIMUM_MTU = 1472; // 1500 - 20 (IP) - 8 (UDP)
+ public const int DTLS_RETRANSMISSION_CODE = -1;
- public class DtlsSrtpTransport : DatagramTransport
- {
- public const int MAXIMUM_MTU = 1472; // 1500 - 20 (IP) - 8 (UDP)
- public const int DTLS_RETRANSMISSION_CODE = -1;
+ private IDtlsSrtpPeer _connection;
- private IDtlsSrtpPeer _connection;
+ private ConcurrentQueue _data = new ConcurrentQueue();
+ private Certificate? _peerCertificate;
- private ConcurrentQueue _data = new ConcurrentQueue();
- private Certificate _peerCertificate;
+ public DatagramTransport? Transport { get; internal set; }
+ public bool IsClient { get { return _connection is DtlsSrtpClient; } }
+ public SrtpKeys? Keys { get; private set; }
- public DatagramTransport Transport { get; internal set; }
- public bool IsClient { get { return _connection is DtlsSrtpClient; } }
- public SrtpKeys Keys { get; private set; }
+ public SrtpSessionContext? Context { get; private set; }
- public SrtpSessionContext Context { get; private set; }
+ public int TimeoutMilliseconds { get { return _connection.TimeoutMilliseconds; } set { _connection.TimeoutMilliseconds = value; } }
- public int TimeoutMilliseconds { get { return _connection.TimeoutMilliseconds; } set { _connection.TimeoutMilliseconds = value; } }
+ public event OnDataReadyEvent? OnDataReady;
- public event OnDataReadyEvent OnDataReady;
+ public event OnDtlsAlertEvent? OnAlert;
- public event OnDtlsAlertEvent OnAlert;
+ public DtlsSrtpTransport(IDtlsSrtpPeer connection)
+ {
+ this._connection = connection;
+ this._connection.OnSessionStarted += DtlsSrtpTransport_OnSessionStarted;
+ this._connection.OnAlert += DtlsSrtpTransport_OnAlert;
+ }
- public DtlsSrtpTransport(IDtlsSrtpPeer connection)
- {
- this._connection = connection;
- this._connection.OnSessionStarted += DtlsSrtpTransport_OnSessionStarted;
- this._connection.OnAlert += DtlsSrtpTransport_OnAlert;
- }
+ private void DtlsSrtpTransport_OnSessionStarted(object? sender, DtlsSessionStartedEventArgs e)
+ {
+ this._peerCertificate = e.PeerCertificate;
+ this.Context = e.Context;
+ }
- private void DtlsSrtpTransport_OnSessionStarted(object sender, DtlsSessionStartedEventArgs e)
- {
- this._peerCertificate = e.PeerCertificate;
- this.Context = e.Context;
- }
+ private void DtlsSrtpTransport_OnAlert(object? sender, DtlsAlertEventArgs args)
+ {
+ OnAlert?.Invoke(args.Level, args.AlertType, args.Description);
+ }
- private void DtlsSrtpTransport_OnAlert(object sender, DtlsAlertEventArgs args)
- {
- OnAlert?.Invoke(args.Level, args.AlertType, args.Description);
- }
+ public bool DoHandshake(out string? handshakeError)
+ {
+ var transport = _connection.DoHandshake(out handshakeError, this, null);
+ Transport = transport;
+ return string.IsNullOrEmpty(handshakeError);
+ }
- public bool DoHandshake(out string handshakeError)
- {
- DtlsTransport transport = _connection.DoHandshake(out handshakeError, this, null);
- Transport = transport;
- return string.IsNullOrEmpty(handshakeError);
- }
+ public bool IsHandshakeComplete()
+ {
+ return Transport is not null;
+ }
- public bool IsHandshakeComplete()
- {
- return Transport != null;
- }
+ public int ProtectRTP(byte[] payload, int length, out int outputBufferLength)
+ {
+ Debug.Assert(Context is not null);
+ return Context.ProtectRtp(payload, length, out outputBufferLength);
+ }
- public int ProtectRTP(byte[] payload, int length, out int outputBufferLength)
- {
- return Context.ProtectRtp(payload, length, out outputBufferLength);
- }
+ public int UnprotectRTP(byte[] payload, int length, out int outputBufferLength)
+ {
+ Debug.Assert(Context is not null);
+ return Context.UnprotectRtp(payload, length, out outputBufferLength);
+ }
- public int UnprotectRTP(byte[] payload, int length, out int outputBufferLength)
- {
- return Context.UnprotectRtp(payload, length, out outputBufferLength);
- }
+ public int ProtectRTCP(byte[] payload, int length, out int outputBufferLength)
+ {
+ Debug.Assert(Context is not null);
+ return Context.ProtectRtcp(payload, length, out outputBufferLength);
+ }
- public int ProtectRTCP(byte[] payload, int length, out int outputBufferLength)
- {
- return Context.ProtectRtcp(payload, length, out outputBufferLength);
- }
+ public int UnprotectRTCP(byte[] payload, int length, out int outputBufferLength)
+ {
+ Debug.Assert(Context is not null);
+ return Context.UnprotectRtcp(payload, length, out outputBufferLength);
+ }
- public int UnprotectRTCP(byte[] payload, int length, out int outputBufferLength)
- {
- return Context.UnprotectRtcp(payload, length, out outputBufferLength);
- }
+ public Certificate? GetRemoteCertificate()
+ {
+ return _peerCertificate;
+ }
- public Certificate GetRemoteCertificate()
- {
- return _peerCertificate;
- }
+ public int GetReceiveLimit() => MAXIMUM_MTU;
- public int GetReceiveLimit() => MAXIMUM_MTU;
+ public int GetSendLimit() => MAXIMUM_MTU;
- public int GetSendLimit() => MAXIMUM_MTU;
+ // TODO: Optimize to avoid array copy.
+ public void WriteToRecvStream(byte[] buffer) // remoteEndPoint = "127.0.0.1:80"
+ {
+ _data.Enqueue(buffer);
+ }
- public void WriteToRecvStream(byte[] buffer)
+ public void Close()
+ {
+ var transport = Transport;
+ if (transport != null)
{
- _data.Enqueue(buffer);
+ Transport = null;
+ transport.Close();
}
+ }
- public void Close()
+ public int Receive(byte[] buf, int off, int len, int waitMillis)
+ {
+ var t = 0L;
+ while(true)
{
- var transport = Transport;
- if (transport != null)
+ if (_data.TryDequeue(out var data))
{
- Transport = null;
- transport.Close();
+ Buffer.BlockCopy(data, 0, buf, off, data.Length);
+ return data.Length;
}
- }
-
- public int Receive(byte[] buf, int off, int len, int waitMillis)
- {
- long t = 0;
- while(true)
+ else
{
- if (_data.TryDequeue(out var data))
- {
- Buffer.BlockCopy(data, 0, buf, off, data.Length);
- return data.Length;
- }
- else
+ System.Threading.Thread.Sleep(25);
+ t += 25;
+ if (t > waitMillis)
{
- System.Threading.Thread.Sleep(25);
- t += 25;
- if (t > waitMillis)
- {
- return -1;
- }
+ return -1;
}
}
}
+ }
- public void Send(byte[] buf, int off, int len)
+ public void Send(byte[] buf, int off, int len)
+ {
+ if (OnDataReady is not { } onDataReady)
{
- if (off != 0 || len < buf.Length)
- {
- buf = buf.AsSpan(off, len).ToArray();
- }
- OnDataReady?.Invoke(buf);
+ return;
}
-#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
- public int Receive(Span buffer, int waitMillis)
+ if (off != 0 || len < buf.Length)
{
- byte[] buff = buffer.ToArray();
- int len = Receive(buff, 0, buff.Length, waitMillis);
- if (len > 0)
- {
- buff.AsSpan(0, len).CopyTo(buffer);
- }
- return len;
+ buf = buf.AsSpan(off, len).ToArray();
}
- public void Send(ReadOnlySpan buffer)
+ onDataReady(buf);
+ }
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public int Receive(Span buffer, int waitMillis)
+ {
+ byte[] buff = buffer.ToArray();
+ int len = Receive(buff, 0, buff.Length, waitMillis);
+ if (len > 0)
{
- Send(buffer.ToArray(), 0, buffer.Length);
+ buff.AsSpan(0, len).CopyTo(buffer);
}
-#endif
+ return len;
}
+
+ public void Send(ReadOnlySpan buffer)
+ {
+ Send(buffer.ToArray(), 0, buffer.Length);
+ }
+#endif
}
diff --git a/src/SIPSorcery/net/DtlsSrtp/DtlsUtils.cs b/src/SIPSorcery/net/DtlsSrtp/DtlsUtils.cs
index e20cd6455..015d6518e 100644
--- a/src/SIPSorcery/net/DtlsSrtp/DtlsUtils.cs
+++ b/src/SIPSorcery/net/DtlsSrtp/DtlsUtils.cs
@@ -47,33 +47,32 @@
using Org.BouncyCastle.Tls.Crypto;
using SIPSorcery.Net.SharpSRTP.DTLS;
-namespace SIPSorcery.Net
+namespace SIPSorcery.Net;
+
+public class DtlsUtils
{
- public class DtlsUtils
+ public static (Certificate certificate, AsymmetricKeyParameter privateKey) CreateSelfSignedTlsCert(BcTlsCrypto crypto, bool useRsa = false)
{
- public static (Certificate certificate, AsymmetricKeyParameter privateKey) CreateSelfSignedTlsCert(BcTlsCrypto crypto, bool useRsa = false)
- {
- return DtlsCertificateUtils.GenerateCertificate("WebRTC", DateTime.UtcNow.AddDays(-1), DateTime.UtcNow.AddDays(30), useRsa);
- }
+ return DtlsCertificateUtils.GenerateCertificate("WebRTC", DateTime.UtcNow.AddDays(-1), DateTime.UtcNow.AddDays(30), useRsa);
+ }
- public static RTCDtlsFingerprint Fingerprint(string algorithm, TlsCertificate value)
- {
- return Fingerprint(new X509Certificate(value.GetEncoded()), algorithm);
- }
+ public static RTCDtlsFingerprint Fingerprint(string algorithm, TlsCertificate value)
+ {
+ return Fingerprint(new X509Certificate(value.GetEncoded()), algorithm);
+ }
- public static RTCDtlsFingerprint Fingerprint(Certificate certificate)
- {
- return Fingerprint(new X509Certificate(certificate.GetCertificateAt(0).GetEncoded()));
- }
+ public static RTCDtlsFingerprint Fingerprint(Certificate certificate)
+ {
+ return Fingerprint(new X509Certificate(certificate.GetCertificateAt(0).GetEncoded()));
+ }
- public static RTCDtlsFingerprint Fingerprint(X509Certificate x509Certificate, string algorithm = "sha-256")
- {
- return new RTCDtlsFingerprint { algorithm = algorithm, value = DtlsCertificateUtils.Fingerprint(x509Certificate.CertificateStructure, algorithm) };
- }
+ public static RTCDtlsFingerprint Fingerprint(X509Certificate x509Certificate, string algorithm = "sha-256")
+ {
+ return new RTCDtlsFingerprint { algorithm = algorithm, value = DtlsCertificateUtils.Fingerprint(x509Certificate.CertificateStructure, algorithm) };
+ }
- public static bool IsHashSupported(string algStr)
- {
- return DtlsCertificateUtils.IsHashSupported(algStr);
- }
+ public static bool IsHashSupported(string algStr)
+ {
+ return DtlsCertificateUtils.IsHashSupported(algStr);
}
}
diff --git a/src/SIPSorcery/net/DtlsSrtp/Lib/DTLS/DtlsCertificateUtils.cs b/src/SIPSorcery/net/DtlsSrtp/Lib/DTLS/DtlsCertificateUtils.cs
index a548b3db8..a0d5abcf5 100644
--- a/src/SIPSorcery/net/DtlsSrtp/Lib/DTLS/DtlsCertificateUtils.cs
+++ b/src/SIPSorcery/net/DtlsSrtp/Lib/DTLS/DtlsCertificateUtils.cs
@@ -19,23 +19,24 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Asn1.X9;
-using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Operators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Crypto.Prng;
-using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Security;
-using Org.BouncyCastle.Tls.Crypto.Impl.BC;
-using Org.BouncyCastle.Tls.Crypto;
using Org.BouncyCastle.Tls;
+using Org.BouncyCastle.Tls.Crypto;
+using Org.BouncyCastle.Tls.Crypto.Impl.BC;
using Org.BouncyCastle.Utilities.Encoders;
using Org.BouncyCastle.X509;
-using System.Collections.Generic;
-using System.Text;
-using System;
+using SIPSorcery.Sys;
namespace SIPSorcery.Net.SharpSRTP.DTLS
{
@@ -177,20 +178,25 @@ public static (Certificate certificate, AsymmetricKeyParameter key) GenerateECDS
public static string Fingerprint(X509CertificateStructure c, string algorithm = "SHA256")
{
- byte[] der = c.GetEncoded();
- byte[] hash = DigestUtilities.CalculateDigest(algorithm, der);
- byte[] hexBytes = Hex.Encode(hash);
- string hex = Encoding.ASCII.GetString(hexBytes).ToUpperInvariant();
-
- StringBuilder fp = new StringBuilder();
- int i = 0;
- fp.Append(hex.Substring(i, 2));
- while ((i += 2) < hex.Length)
+ var der = c.GetEncoded();
+ var hash = DigestUtilities.CalculateDigest(algorithm, der);
+
+ return string.Create(hash.Length + hash.Length / 2 - 1, hash, (span, value) =>
{
- fp.Append(':');
- fp.Append(hex.Substring(i, 2));
- }
- return fp.ToString();
+ var digits = "0123456789ABCDEF".AsSpan();
+ var p = 0;
+ for (var i = 0; p < span.Length && i < value.Length; i++)
+ {
+ if (i > 0)
+ {
+ span[p++] = ':';
+ }
+
+ var b = value[i];
+ span[p++] = char.ToUpperInvariant((char)(digits[b >> 4]));
+ span[p++] = char.ToUpperInvariant((char)(digits[b & 0x0F]));
+ }
+ });
}
public static bool IsHashSupported(string algStr)
@@ -200,7 +206,7 @@ public static bool IsHashSupported(string algStr)
throw new ArgumentNullException(nameof(algStr));
}
- IDigest digest = null;
+ IDigest? digest = null;
try
{
diff --git a/src/SIPSorcery/net/DtlsSrtp/Lib/DTLS/DtlsClient.cs b/src/SIPSorcery/net/DtlsSrtp/Lib/DTLS/DtlsClient.cs
index d12e887ad..94ce7caf0 100644
--- a/src/SIPSorcery/net/DtlsSrtp/Lib/DTLS/DtlsClient.cs
+++ b/src/SIPSorcery/net/DtlsSrtp/Lib/DTLS/DtlsClient.cs
@@ -19,6 +19,8 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
+using System;
+using System.Collections.Generic;
using Microsoft.Extensions.Logging;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto;
@@ -27,391 +29,378 @@
using Org.BouncyCastle.Tls.Crypto.Impl.BC;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.Encoders;
-using System;
-using System.Collections.Generic;
-namespace SIPSorcery.Net.SharpSRTP.DTLS
+namespace SIPSorcery.Net.SharpSRTP.DTLS;
+
+public class DtlsClient : DefaultTlsClient, IDtlsPeer
{
- public class DtlsClient : DefaultTlsClient, IDtlsPeer
+ private readonly object _syncRoot = new object();
+ private static readonly ILogger _logger = LogFactory.CreateLogger();
+
+ protected DatagramTransport? _clientDatagramTransport; // valid only for the current session
+
+ private TlsSession? _session;
+
+ public bool AutogenerateCertificate { get; set; } = true;
+
+ public int TimeoutMilliseconds { get; set; } = 20000;
+ public Certificate? Certificate { get; private set; }
+ public AsymmetricKeyParameter? CertificatePrivateKey { get; private set; }
+ public short CertificateSignatureAlgorithm { get; private set; }
+ public short CertificateHashAlgorithm { get; private set; }
+
+ public bool ForceUseExtendedMasterSecret { get; set; } = true;
+ public TlsServerCertificate? RemoteCertificate { get; private set; }
+ public Certificate? PeerCertificate { get { return RemoteCertificate?.Certificate; } }
+
+ public event EventHandler? OnHandshakeCompleted;
+ public event EventHandler? OnAlert;
+
+ public DtlsClient(
+ TlsSession? session = null,
+ Certificate? certificate = null,
+ AsymmetricKeyParameter? privateKey = null,
+ short certificateSignatureAlgorithm = SignatureAlgorithm.ecdsa,
+ short certificateHashAlgorithm = HashAlgorithm.sha256)
+ : this(
+ new BcTlsCrypto(),
+ session,
+ certificate,
+ privateKey,
+ certificateSignatureAlgorithm,
+ certificateHashAlgorithm)
+ { }
+
+ public DtlsClient(
+ TlsCrypto crypto,
+ TlsSession? session = null,
+ Certificate? certificate = null,
+ AsymmetricKeyParameter? privateKey = null,
+ short certificateSignatureAlgorithm = SignatureAlgorithm.ecdsa,
+ short certificateHashAlgorithm = HashAlgorithm.sha256) : base(crypto)
{
- private readonly object _syncRoot = new object();
- private static readonly ILogger _logger = LogFactory.CreateLogger();
- protected DatagramTransport _clientDatagramTransport = null;
- private TlsSession _session;
-
- public bool AutogenerateCertificate { get; set; } = true;
-
- public int TimeoutMilliseconds { get; set; } = 20000;
- public Certificate Certificate { get; private set; }
- public AsymmetricKeyParameter CertificatePrivateKey { get; private set; }
- public short CertificateSignatureAlgorithm { get; private set; }
- public short CertificateHashAlgorithm { get; private set; }
+ this._session = session;
+ SetCertificate(certificate, privateKey, certificateSignatureAlgorithm, certificateHashAlgorithm);
+ }
- public bool ForceUseExtendedMasterSecret { get; set; } = true;
- public TlsServerCertificate RemoteCertificate { get; private set; }
- public Certificate PeerCertificate { get { return RemoteCertificate?.Certificate; } }
+ public virtual void SetCertificate(Certificate? certificate, AsymmetricKeyParameter? privateKey, short signatureAlgorithm, short hashAlgorithm)
+ {
+ Certificate = certificate;
+ CertificatePrivateKey = privateKey;
+ CertificateSignatureAlgorithm = signatureAlgorithm;
+ CertificateHashAlgorithm = hashAlgorithm;
+ }
- public event EventHandler OnHandshakeCompleted;
- public event EventHandler OnAlert;
+ public virtual void AutogenerateClientCertificate(bool isRsa)
+ {
+ var cert = DtlsCertificateUtils.GenerateCertificate(GetCertificateCommonName(), DateTime.UtcNow.AddDays(-1), DateTime.UtcNow.AddDays(30), isRsa);
+ SetCertificate(cert.Certificate, cert.PrivateKey, isRsa ? SignatureAlgorithm.rsa : SignatureAlgorithm.ecdsa, HashAlgorithm.sha256);
+ }
- public DtlsClient(TlsSession session = null, Certificate certificate = null, AsymmetricKeyParameter privateKey = null, short certificateSignatureAlgorithm = SignatureAlgorithm.ecdsa, short certificateHashAlgorithm = HashAlgorithm.sha256)
- : this(new BcTlsCrypto(), session, certificate, privateKey, certificateSignatureAlgorithm, certificateHashAlgorithm)
- { }
+ protected virtual string GetCertificateCommonName()
+ {
+ return "DTLS";
+ }
- public DtlsClient(TlsCrypto crypto, TlsSession session = null, Certificate certificate = null, AsymmetricKeyParameter privateKey = null, short certificateSignatureAlgorithm = SignatureAlgorithm.ecdsa, short certificateHashAlgorithm = HashAlgorithm.sha256) : base(crypto)
- {
- this._session = session;
- SetCertificate(certificate, privateKey, certificateSignatureAlgorithm, certificateHashAlgorithm);
- }
+ public override bool RequiresExtendedMasterSecret()
+ {
+ return ForceUseExtendedMasterSecret;
+ }
- public virtual void SetCertificate(Certificate certificate, AsymmetricKeyParameter privateKey, short signatureAlgorithm, short hashAlgorithm)
- {
- Certificate = certificate;
- CertificatePrivateKey = privateKey;
- CertificateSignatureAlgorithm = signatureAlgorithm;
- CertificateHashAlgorithm = hashAlgorithm;
- }
+ protected override ProtocolVersion[] GetSupportedVersions()
+ {
+ //return ProtocolVersion.DTLSv13.DownTo(ProtocolVersion.DTLSv12);
+ return ProtocolVersion.DTLSv12.Only(); // ProtocolVersion.IsSupportedDtlsVersionClient currently does not support DTLS 1.3
+ }
- public virtual void AutogenerateClientCertificate(bool isRsa)
+ protected override int[] GetSupportedCipherSuites()
+ {
+ // TODO: review
+ if (CertificateSignatureAlgorithm == SignatureAlgorithm.rsa)
{
- var cert = DtlsCertificateUtils.GenerateCertificate(GetCertificateCommonName(), DateTime.UtcNow.AddDays(-1), DateTime.UtcNow.AddDays(30), isRsa);
- SetCertificate(cert.Certificate, cert.PrivateKey, isRsa ? SignatureAlgorithm.rsa : SignatureAlgorithm.ecdsa, HashAlgorithm.sha256);
+ return new int[]
+ {
+ // TLS 1.3 cpihers
+ //CipherSuite.TLS_AES_256_GCM_SHA384,
+ //CipherSuite.TLS_AES_128_GCM_SHA256,
+ //CipherSuite.TLS_CHACHA20_POLY1305_SHA256,
+
+ // TLS 1.2 ciphers:
+ CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+ CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
+ CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
+ CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
+ CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
+ };
}
-
- protected virtual string GetCertificateCommonName()
+ else if (CertificateSignatureAlgorithm == SignatureAlgorithm.ecdsa)
{
- return "DTLS";
+ // ECDSA certificates require matching cipher suites
+ return new int[]
+ {
+ // TLS 1.3 cpihers
+ //CipherSuite.TLS_AES_256_GCM_SHA384,
+ //CipherSuite.TLS_AES_128_GCM_SHA256,
+ //CipherSuite.TLS_CHACHA20_POLY1305_SHA256,
+
+ // TLS 1.2 ciphers:
+ CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
+ CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
+ CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
+ CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
+ CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
+ };
}
-
- public override bool RequiresExtendedMasterSecret()
+ else
{
- return ForceUseExtendedMasterSecret;
+ throw new NotSupportedException();
}
+ }
- protected override ProtocolVersion[] GetSupportedVersions()
+ public virtual DtlsTransport? DoHandshake(out string? handshakeError, DatagramTransport datagramTransport, DtlsRequest? request = null)
+ {
+ lock (_syncRoot)
{
- //return ProtocolVersion.DTLSv13.DownTo(ProtocolVersion.DTLSv12);
- return ProtocolVersion.DTLSv12.Only(); // ProtocolVersion.IsSupportedDtlsVersionClient currently does not support DTLS 1.3
- }
+ DtlsTransport? transport = null;
- protected override int[] GetSupportedCipherSuites()
- {
- // TODO: review
- if (CertificateSignatureAlgorithm == SignatureAlgorithm.rsa)
+ try
{
- return new int[]
- {
- // TLS 1.3 cpihers
- //CipherSuite.TLS_AES_256_GCM_SHA384,
- //CipherSuite.TLS_AES_128_GCM_SHA256,
- //CipherSuite.TLS_CHACHA20_POLY1305_SHA256,
-
- // TLS 1.2 ciphers:
- CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
- CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
- CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
- CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
- CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
- };
+ var clientProtocol = new DtlsClientProtocol();
+ _clientDatagramTransport = datagramTransport;
+ transport = clientProtocol.Connect(this, datagramTransport);
+ _clientDatagramTransport = null;
}
- else if (CertificateSignatureAlgorithm == SignatureAlgorithm.ecdsa)
+ catch (Exception ex)
{
- // ECDSA certificates require matching cipher suites
- return new int[]
- {
- // TLS 1.3 cpihers
- //CipherSuite.TLS_AES_256_GCM_SHA384,
- //CipherSuite.TLS_AES_128_GCM_SHA256,
- //CipherSuite.TLS_CHACHA20_POLY1305_SHA256,
-
- // TLS 1.2 ciphers:
- CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
- CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
- CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
- CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
- CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
- };
- }
- else
- {
- throw new NotSupportedException();
+ handshakeError = ex.Message;
+ return null;
}
- }
- public virtual DtlsTransport DoHandshake(out string handshakeError, DatagramTransport datagramTransport, DtlsRequest request = null)
- {
- lock (_syncRoot)
- {
- DtlsTransport transport = null;
+ handshakeError = null;
+ return transport;
+ }
+ }
- try
- {
- DtlsClientProtocol clientProtocol = new DtlsClientProtocol();
- _clientDatagramTransport = datagramTransport;
- transport = clientProtocol.Connect(this, datagramTransport);
- _clientDatagramTransport = null;
- }
- catch (Exception ex)
- {
- handshakeError = ex.Message;
- return null;
- }
+ public override TlsSession? GetSessionToResume()
+ {
+ return this._session;
+ }
- handshakeError = null;
- return transport;
- }
- }
+ public override int GetHandshakeTimeoutMillis() => TimeoutMilliseconds;
- public override TlsSession GetSessionToResume()
- {
- return this._session;
- }
+ public override void NotifyAlertRaised(short alertLevel, short alertDescription, string message, Exception cause)
+ {
+ _logger.LogDtlsClientAlertRaised(alertLevel, alertDescription, message, cause);
+ }
- public override int GetHandshakeTimeoutMillis() => TimeoutMilliseconds;
+ public override void NotifyAlertReceived(short level, short alertDescription)
+ {
+ _logger.LogDtlsClientAlertReceived(level, alertDescription);
- public override void NotifyAlertRaised(short alertLevel, short alertDescription, string message, Exception cause)
+ TlsAlertTypesEnum alertType = TlsAlertTypesEnum.Unassigned;
+ if (Enum.IsDefined(typeof(TlsAlertTypesEnum), (int)alertDescription))
{
- if (_logger.IsEnabled(LogLevel.Debug))
- {
- _logger.LogDebug("DTLS client raised alert: {AlertLevel}, {AlertDescription}.",
- AlertLevel.GetText(alertLevel), AlertDescription.GetText(alertDescription));
- }
- if (message != null)
- {
- _logger.LogDebug("> {Message}", message);
- }
- if (cause != null)
- {
- _logger.LogDebug("> {Cause}", cause);
- }
+ alertType = (TlsAlertTypesEnum)alertDescription;
}
- public override void NotifyAlertReceived(short level, short alertDescription)
+ TlsAlertLevelsEnum alertLevel = TlsAlertLevelsEnum.Warn;
+ if (Enum.IsDefined(typeof(TlsAlertLevelsEnum), (int)alertLevel))
{
- if (_logger.IsEnabled(LogLevel.Debug))
- {
- _logger.LogDebug("DTLS client received alert: {AlertLevel}, {AlertDescription}.",
- AlertLevel.GetText(level), AlertDescription.GetText(alertDescription));
- }
+ alertLevel = (TlsAlertLevelsEnum)level;
+ }
- TlsAlertTypesEnum alertType = TlsAlertTypesEnum.Unassigned;
- if (Enum.IsDefined(typeof(TlsAlertTypesEnum), (int)alertDescription))
- {
- alertType = (TlsAlertTypesEnum)alertDescription;
- }
+ OnAlert?.Invoke(this, new DtlsAlertEventArgs(alertLevel, alertType, AlertDescription.GetText(alertDescription)));
+ }
- TlsAlertLevelsEnum alertLevel = TlsAlertLevelsEnum.Warn;
- if (Enum.IsDefined(typeof(TlsAlertLevelsEnum), (int)alertLevel))
- {
- alertLevel = (TlsAlertLevelsEnum)level;
- }
+ public override void NotifyServerVersion(ProtocolVersion serverVersion)
+ {
+ base.NotifyServerVersion(serverVersion);
- OnAlert?.Invoke(this, new DtlsAlertEventArgs(alertLevel, alertType, AlertDescription.GetText(alertDescription)));
- }
+ _logger.LogDtlsClientNegotiated(serverVersion);
+ }
- public override void NotifyServerVersion(ProtocolVersion serverVersion)
- {
- base.NotifyServerVersion(serverVersion);
+ public override TlsAuthentication GetAuthentication()
+ {
+ return new DTlsAuthentication(m_context, this);
+ }
- _logger.LogDebug("DTLS client negotiated {ServerVersion}.", serverVersion);
- }
+ public override void NotifyHandshakeComplete()
+ {
+ base.NotifyHandshakeComplete();
- public override TlsAuthentication GetAuthentication()
+ ProtocolName protocolName = m_context.SecurityParameters.ApplicationProtocol;
+ if (protocolName != null)
{
- return new DTlsAuthentication(m_context, this);
+ _logger.LogDtlsClientAlpn(protocolName.GetUtf8Decoding());
}
- public override void NotifyHandshakeComplete()
+ TlsSession newSession = m_context.Session;
+ if (newSession != null)
{
- base.NotifyHandshakeComplete();
-
- ProtocolName protocolName = m_context.SecurityParameters.ApplicationProtocol;
- if (protocolName != null)
+ if (newSession.IsResumable)
{
- if (_logger.IsEnabled(LogLevel.Debug))
- {
- _logger.LogDebug("Client ALPN: {ApplicationProtocol}.", protocolName.GetUtf8Decoding());
- }
- }
+ byte[] newSessionID = newSession.SessionID;
+ string hex = ToHexString(newSessionID);
- TlsSession newSession = m_context.Session;
- if (newSession != null)
- {
- if (newSession.IsResumable)
+ if (_session != null && Arrays.AreEqual(_session.SessionID, newSessionID))
{
- byte[] newSessionID = newSession.SessionID;
- string hex = ToHexString(newSessionID);
-
- if (_session != null && Arrays.AreEqual(_session.SessionID, newSessionID))
- {
- _logger.LogDebug("Client resumed session: {SessionIdHex}.", hex);
- }
- else
- {
- _logger.LogDebug("Client established session: {SessionIdHex}.", hex);
- }
-
- this._session = newSession;
+ _logger.LogDtlsClientSessionResumed(hex);
}
-
- byte[] tlsServerEndPoint = m_context.ExportChannelBinding(ChannelBinding.tls_server_end_point);
- if (null != tlsServerEndPoint)
+ else
{
- if (_logger.IsEnabled(LogLevel.Debug))
- {
- _logger.LogDebug("Client 'tls-server-end-point': {TlsServerEndPoint}.", ToHexString(tlsServerEndPoint));
- }
+ _logger.LogDtlsClientSessionEstablished(hex);
}
- byte[] tlsUnique = m_context.ExportChannelBinding(ChannelBinding.tls_unique);
- if (_logger.IsEnabled(LogLevel.Debug))
- {
- _logger.LogDebug("Client 'tls-unique': {TlsUnique}.", ToHexString(tlsUnique));
- }
+ this._session = newSession;
}
- OnHandshakeCompleted?.Invoke(this, new DtlsHandshakeCompletedEventArgs(m_context.SecurityParameters));
- }
-
- public override IDictionary GetClientExtensions()
- {
- if (m_context.SecurityParameters.ClientRandom == null)
+ byte[] tlsServerEndPoint = m_context.ExportChannelBinding(ChannelBinding.tls_server_end_point);
+ if (null != tlsServerEndPoint)
{
- throw new TlsFatalAlert(AlertDescription.internal_error);
+ _logger.LogDtlsClientTlsServerEndPoint(ToHexString(tlsServerEndPoint));
}
- return base.GetClientExtensions();
+ byte[] tlsUnique = m_context.ExportChannelBinding(ChannelBinding.tls_unique);
+ _logger.LogDtlsClientTlsUnique(ToHexString(tlsUnique));
}
- public override void ProcessServerExtensions(IDictionary serverExtensions)
+ OnHandshakeCompleted?.Invoke(this, new DtlsHandshakeCompletedEventArgs(m_context.SecurityParameters));
+ }
+
+ public override IDictionary GetClientExtensions()
+ {
+ if (m_context.SecurityParameters.ClientRandom == null)
{
- if (m_context.SecurityParameters.ServerRandom == null)
- {
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ return base.GetClientExtensions();
+ }
- base.ProcessServerExtensions(serverExtensions);
+ public override void ProcessServerExtensions(IDictionary serverExtensions)
+ {
+ if (m_context.SecurityParameters.ServerRandom == null)
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
}
- protected virtual string ToHexString(byte[] data)
+ base.ProcessServerExtensions(serverExtensions);
+ }
+
+ protected virtual string ToHexString(byte[] data)
+ {
+ return data == null ? "(null)" : Hex.ToHexString(data);
+ }
+
+ internal class DTlsAuthentication : TlsAuthentication
+ {
+ private readonly TlsContext _context;
+ private readonly DtlsClient _client;
+
+ public DTlsAuthentication(TlsContext context, DtlsClient client)
{
- return data == null ? "(null)" : Hex.ToHexString(data);
+ this._client = client ?? throw new ArgumentNullException(nameof(client));
+ this._context = context;
}
- internal class DTlsAuthentication : TlsAuthentication
+ public void NotifyServerCertificate(TlsServerCertificate serverCertificate)
{
- private readonly TlsContext _context;
- private readonly DtlsClient _client;
+ TlsCertificate[] chain = serverCertificate.Certificate.GetCertificateList();
- public DTlsAuthentication(TlsContext context, DtlsClient client)
+ _logger.LogDtlsClientServerCertificateChainReceived(chain.Length);
+ for (int i = 0; i != chain.Length; i++)
{
- this._client = client ?? throw new ArgumentNullException(nameof(client));
- this._context = context;
+ var entry = X509CertificateStructure.GetInstance(chain[i].GetEncoded());
+ _logger.LogDtlsClientServerCertificateFingerprint(DtlsCertificateUtils.Fingerprint(entry), entry.Subject.ToString());
}
- public void NotifyServerCertificate(TlsServerCertificate serverCertificate)
- {
- TlsCertificate[] chain = serverCertificate.Certificate.GetCertificateList();
-
- _logger.LogDebug("DTLS client received server certificate chain of length {CertificateCount}.", chain.Length);
- for (int i = 0; i != chain.Length; i++)
- {
- X509CertificateStructure entry = X509CertificateStructure.GetInstance(chain[i].GetEncoded());
- if (_logger.IsEnabled(LogLevel.Debug))
- {
- _logger.LogDebug("DTLS client fingerprint:SHA-256 {Fingerprint} ({Subject}).",
- DtlsCertificateUtils.Fingerprint(entry), entry.Subject);
- }
- }
+ bool isEmpty = serverCertificate == null || serverCertificate.Certificate == null || serverCertificate.Certificate.IsEmpty;
- bool isEmpty = serverCertificate == null || serverCertificate.Certificate == null || serverCertificate.Certificate.IsEmpty;
+ if (isEmpty)
+ {
+ throw new TlsFatalAlert(AlertDescription.bad_certificate);
+ }
- if (isEmpty)
- {
- throw new TlsFatalAlert(AlertDescription.bad_certificate);
- }
+ TlsCertificate[] certPath = chain;
- TlsCertificate[] certPath = chain;
+ // store the certificate for further fingerprint validation
+ _client.RemoteCertificate = serverCertificate;
- // store the certificate for further fingerprint validation
- _client.RemoteCertificate = serverCertificate;
+ TlsUtilities.CheckPeerSigAlgs(_context, certPath);
+ }
- TlsUtilities.CheckPeerSigAlgs(_context, certPath);
+ public TlsCredentials? GetClientCredentials(CertificateRequest certificateRequest)
+ {
+ short[] certificateTypes = certificateRequest.CertificateTypes;
+ if (certificateTypes == null || (!Arrays.Contains(certificateTypes, ClientCertificateType.rsa_sign) && !Arrays.Contains(certificateTypes, ClientCertificateType.ecdsa_sign)))
+ {
+ return null;
}
- public TlsCredentials GetClientCredentials(CertificateRequest certificateRequest)
+ if (_client.Certificate == null || _client.CertificatePrivateKey == null)
{
- short[] certificateTypes = certificateRequest.CertificateTypes;
- if (certificateTypes == null || (!Arrays.Contains(certificateTypes, ClientCertificateType.rsa_sign) && !Arrays.Contains(certificateTypes, ClientCertificateType.ecdsa_sign)))
+ if (_client.AutogenerateCertificate)
{
- return null;
+ bool isRsa = IsServerCertificateRsa(_client.RemoteCertificate);
+ _client.AutogenerateClientCertificate(isRsa);
}
-
- if (_client.Certificate == null || _client.CertificatePrivateKey == null)
+ else
{
- if (_client.AutogenerateCertificate)
- {
- bool isRsa = IsServerCertificateRsa(_client.RemoteCertificate);
- _client.AutogenerateClientCertificate(isRsa);
- }
- else
- {
- // no client certificate
- return null;
- }
+ // no client certificate
+ return null;
}
+ }
- var clientSigAlgs = _context.SecurityParameters.ClientSigAlgs;
-
- SignatureAndHashAlgorithm signatureAndHashAlgorithm = null;
+ var clientSigAlgs = _context.SecurityParameters.ClientSigAlgs;
- foreach (SignatureAndHashAlgorithm alg in clientSigAlgs)
- {
- if (alg.Signature == _client.CertificateSignatureAlgorithm && alg.Hash == _client.CertificateHashAlgorithm)
- {
- signatureAndHashAlgorithm = alg;
- break;
- }
- }
+ SignatureAndHashAlgorithm? signatureAndHashAlgorithm = null;
- if (signatureAndHashAlgorithm == null)
+ foreach (SignatureAndHashAlgorithm alg in clientSigAlgs)
+ {
+ if (alg.Signature == _client.CertificateSignatureAlgorithm && alg.Hash == _client.CertificateHashAlgorithm)
{
- throw new InvalidOperationException("DTLS Client does not support the selected certificate algorithm!");
+ signatureAndHashAlgorithm = alg;
+ break;
}
-
- return new BcDefaultTlsCredentialedSigner(new TlsCryptoParameters(_context), (BcTlsCrypto)_context.Crypto, _client.CertificatePrivateKey, _client.Certificate, signatureAndHashAlgorithm);
}
- }
- public static bool IsServerCertificateRsa(TlsServerCertificate serverCertificate)
- {
- if (serverCertificate == null || serverCertificate.Certificate == null || serverCertificate.Certificate.IsEmpty)
+ if (signatureAndHashAlgorithm == null)
{
- throw new ArgumentNullException(nameof(serverCertificate));
+ throw new InvalidOperationException("DTLS Client does not support the selected certificate algorithm!");
}
- var certList = serverCertificate.Certificate.GetCertificateList();
- if (certList == null || certList.Length == 0)
- {
- throw new ArgumentException("Server certificate chain is empty.", nameof(serverCertificate));
- }
+ return new BcDefaultTlsCredentialedSigner(new TlsCryptoParameters(_context), (BcTlsCrypto)_context.Crypto, _client.CertificatePrivateKey, _client.Certificate, signatureAndHashAlgorithm);
+ }
+ }
- var firstCertificate = X509CertificateStructure.GetInstance(certList[0].GetEncoded());
- var algOid = firstCertificate.SubjectPublicKeyInfo.Algorithm.Algorithm;
+ public static bool IsServerCertificateRsa(TlsServerCertificate? serverCertificate)
+ {
+ if (serverCertificate == null || serverCertificate.Certificate == null || serverCertificate.Certificate.IsEmpty)
+ {
+ throw new ArgumentNullException(nameof(serverCertificate));
+ }
- if (algOid.Equals(Org.BouncyCastle.Asn1.Pkcs.PkcsObjectIdentifiers.RsaEncryption))
- {
- return true;
- }
+ var certList = serverCertificate.Certificate.GetCertificateList();
+ if (certList == null || certList.Length == 0)
+ {
+ throw new ArgumentException("Server certificate chain is empty.", nameof(serverCertificate));
+ }
- // Fallback: decode the public key and check its runtime type
- var pubKey = Org.BouncyCastle.Security.PublicKeyFactory.CreateKey(firstCertificate.SubjectPublicKeyInfo);
- if (pubKey is Org.BouncyCastle.Crypto.Parameters.RsaKeyParameters)
- {
- return true;
- }
+ var firstCertificate = X509CertificateStructure.GetInstance(certList[0].GetEncoded());
+ var algOid = firstCertificate.SubjectPublicKeyInfo.Algorithm.Algorithm;
- return false;
+ if (algOid.Equals(Org.BouncyCastle.Asn1.Pkcs.PkcsObjectIdentifiers.RsaEncryption))
+ {
+ return true;
}
+
+ // Fallback: decode the public key and check its runtime type
+ var pubKey = Org.BouncyCastle.Security.PublicKeyFactory.CreateKey(firstCertificate.SubjectPublicKeyInfo);
+ if (pubKey is Org.BouncyCastle.Crypto.Parameters.RsaKeyParameters)
+ {
+ return true;
+ }
+
+ return false;
}
}
diff --git a/src/SIPSorcery/net/DtlsSrtp/Lib/DTLS/DtlsServer.cs b/src/SIPSorcery/net/DtlsSrtp/Lib/DTLS/DtlsServer.cs
index f78871d8f..ad65bca3b 100644
--- a/src/SIPSorcery/net/DtlsSrtp/Lib/DTLS/DtlsServer.cs
+++ b/src/SIPSorcery/net/DtlsSrtp/Lib/DTLS/DtlsServer.cs
@@ -19,352 +19,338 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Text;
+using Microsoft.Extensions.Logging;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Tls;
using Org.BouncyCastle.Tls.Crypto;
using Org.BouncyCastle.Tls.Crypto.Impl.BC;
using Org.BouncyCastle.Utilities.Encoders;
-using Microsoft.Extensions.Logging;
-using System;
-using System.Collections.Generic;
+using SIPSorcery.Net;
+
+namespace SIPSorcery.Net.SharpSRTP.DTLS;
-namespace SIPSorcery.Net.SharpSRTP.DTLS
+public class DtlsServer : DefaultTlsServer, IDtlsPeer
{
- public class DtlsServer : DefaultTlsServer, IDtlsPeer
+ private readonly object _syncRoot = new object();
+ private static readonly ILogger _logger = LogFactory.CreateLogger();
+ protected DatagramTransport? _clientDatagramTransport; // valid only for the current session
+
+ public int TimeoutMilliseconds { get; set; } = 20000;
+
+ public Certificate? Certificate { get; private set; }
+ public AsymmetricKeyParameter? CertificatePrivateKey { get; private set; }
+ public short CertificateSignatureAlgorithm { get; private set; }
+ public short CertificateHashAlgorithm { get; private set; }
+
+ public bool ForceUseExtendedMasterSecret { get; set; } = true;
+ public event EventHandler? OnHandshakeCompleted;
+ public event EventHandler? OnAlert;
+
+ public DtlsServer(
+ Certificate? certificate = null,
+ AsymmetricKeyParameter? privateKey = null,
+ short certificateSignatureAlgorithm = SignatureAlgorithm.ecdsa,
+ short certificateHashAlgorithm = HashAlgorithm.sha256) :
+ this(
+ new BcTlsCrypto(),
+ certificate,
+ privateKey,
+ certificateSignatureAlgorithm,
+ certificateHashAlgorithm)
+ { }
+
+ public DtlsServer(
+ TlsCrypto crypto,
+ Certificate? certificate = null,
+ AsymmetricKeyParameter? privateKey = null,
+ short certificateSignatureAlgorithm = SignatureAlgorithm.ecdsa,
+ short certificateHashAlgorithm = HashAlgorithm.sha256) : base(crypto)
{
- private readonly object _syncRoot = new object();
- private static readonly ILogger logger = LogFactory.CreateLogger();
- protected DatagramTransport _clientDatagramTransport = null;
-
- public int TimeoutMilliseconds { get; set; } = 20000;
-
- public Certificate Certificate { get; private set; }
- public AsymmetricKeyParameter CertificatePrivateKey { get; private set; }
- public short CertificateSignatureAlgorithm { get; private set; }
- public short CertificateHashAlgorithm { get; private set; }
-
- public bool ForceUseExtendedMasterSecret { get; set; } = true;
- public event EventHandler OnHandshakeCompleted;
- public event EventHandler OnAlert;
-
- public DtlsServer(Certificate certificate = null, AsymmetricKeyParameter privateKey = null, short certificateSignatureAlgorithm = SignatureAlgorithm.ecdsa, short certificateHashAlgorithm = HashAlgorithm.sha256) :
- this(new BcTlsCrypto(), certificate, privateKey, certificateSignatureAlgorithm, certificateHashAlgorithm)
- { }
-
- public DtlsServer(TlsCrypto crypto, Certificate certificate = null, AsymmetricKeyParameter privateKey = null, short certificateSignatureAlgorithm = SignatureAlgorithm.ecdsa, short certificateHashAlgorithm = HashAlgorithm.sha256) : base(crypto)
+ if (certificate == null || privateKey == null)
{
- if (certificate == null || privateKey == null)
- {
- // generate default self-signed certificate - SRTP_AEAD_AES_256_GCM requires ECDsa
- AutogenerateClientCertificate(false);
- }
- else
- {
- SetCertificate(certificate, privateKey, certificateSignatureAlgorithm, certificateHashAlgorithm);
- }
+ // generate default self-signed certificate - SRTP_AEAD_AES_256_GCM requires ECDsa
+ AutogenerateClientCertificate(false);
}
-
- public virtual void SetCertificate(Certificate certificate, AsymmetricKeyParameter privateKey, short signatureAlgorithm, short hashAlgorithm)
+ else
{
- Certificate = certificate;
- CertificatePrivateKey = privateKey;
- CertificateSignatureAlgorithm = signatureAlgorithm;
- CertificateHashAlgorithm = hashAlgorithm;
+ SetCertificate(certificate, privateKey, certificateSignatureAlgorithm, certificateHashAlgorithm);
}
+ }
- public virtual void AutogenerateClientCertificate(bool isRsa)
- {
- var cert = DtlsCertificateUtils.GenerateCertificate(GetCertificateCommonName(), DateTime.UtcNow.AddDays(-1), DateTime.UtcNow.AddDays(30), isRsa);
- SetCertificate(cert.Certificate, cert.PrivateKey, isRsa ? SignatureAlgorithm.rsa : SignatureAlgorithm.ecdsa, HashAlgorithm.sha256);
- }
+ public virtual void SetCertificate(Certificate certificate, AsymmetricKeyParameter privateKey, short signatureAlgorithm, short hashAlgorithm)
+ {
+ Certificate = certificate;
+ CertificatePrivateKey = privateKey;
+ CertificateSignatureAlgorithm = signatureAlgorithm;
+ CertificateHashAlgorithm = hashAlgorithm;
+ }
- protected virtual string GetCertificateCommonName()
- {
- return "DTLS";
- }
+ public virtual void AutogenerateClientCertificate(bool isRsa)
+ {
+ var cert = DtlsCertificateUtils.GenerateCertificate(GetCertificateCommonName(), DateTime.UtcNow.AddDays(-1), DateTime.UtcNow.AddDays(30), isRsa);
+ SetCertificate(cert.Certificate, cert.PrivateKey, isRsa ? SignatureAlgorithm.rsa : SignatureAlgorithm.ecdsa, HashAlgorithm.sha256);
+ }
- public override bool RequiresExtendedMasterSecret()
- {
- return ForceUseExtendedMasterSecret;
- }
+ protected virtual string GetCertificateCommonName()
+ {
+ return "DTLS";
+ }
- protected override ProtocolVersion[] GetSupportedVersions()
- {
- //return ProtocolVersion.DTLSv13.DownTo(ProtocolVersion.DTLSv12);
- return ProtocolVersion.DTLSv12.Only(); // ProtocolVersion.IsSupportedDtlsVersionServer currently does not support DTLS 1.3
- }
+ public override bool RequiresExtendedMasterSecret()
+ {
+ return ForceUseExtendedMasterSecret;
+ }
- protected override int[] GetSupportedCipherSuites()
+ protected override ProtocolVersion[] GetSupportedVersions()
+ {
+ //return ProtocolVersion.DTLSv13.DownTo(ProtocolVersion.DTLSv12);
+ return ProtocolVersion.DTLSv12.Only(); // ProtocolVersion.IsSupportedDtlsVersionServer currently does not support DTLS 1.3
+ }
+
+ protected override int[] GetSupportedCipherSuites()
+ {
+ if (CertificateSignatureAlgorithm == SignatureAlgorithm.rsa)
{
- if (CertificateSignatureAlgorithm == SignatureAlgorithm.rsa)
+ return new int[]
{
- return new int[]
- {
- // TLS 1.2 ciphers:
- CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
- CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
- CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
- CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
- CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
- };
- }
- else if (CertificateSignatureAlgorithm == SignatureAlgorithm.ecdsa)
- {
- // ECDSA certificates require matching cipher suites
- return new int[]
- {
- // TLS 1.3 ciphers:
- //CipherSuite.TLS_AES_256_GCM_SHA384,
- //CipherSuite.TLS_AES_128_GCM_SHA256,
- //CipherSuite.TLS_CHACHA20_POLY1305_SHA256,
-
- // TLS 1.2 ciphers:
- CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
- CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
- CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
- CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
- CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
- };
- }
- else
- {
- throw new InvalidOperationException($"DTLS server certificate algorithm {CertificateSignatureAlgorithm} not supported!");
- }
+ // TLS 1.2 ciphers:
+ CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+ CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
+ CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
+ CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
+ CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
+ };
}
-
- public virtual DtlsTransport DoHandshake(out string handshakeError, DatagramTransport datagramTransport, DtlsRequest request = null)
+ else if (CertificateSignatureAlgorithm == SignatureAlgorithm.ecdsa)
{
- lock (_syncRoot)
+ // ECDSA certificates require matching cipher suites
+ return new int[]
{
- if (datagramTransport == null)
- {
- throw new ArgumentNullException(nameof(datagramTransport));
- }
-
- DtlsTransport transport = null;
-
- try
- {
- DtlsServerProtocol serverProtocol = new DtlsServerProtocol();
- _clientDatagramTransport = datagramTransport;
- transport = serverProtocol.Accept(this, datagramTransport, request);
- _clientDatagramTransport = null;
- }
- catch (Exception ex)
- {
- handshakeError = ex.Message;
- return null;
- }
-
- handshakeError = null;
- return transport;
- }
+ // TLS 1.3 ciphers:
+ //CipherSuite.TLS_AES_256_GCM_SHA384,
+ //CipherSuite.TLS_AES_128_GCM_SHA256,
+ //CipherSuite.TLS_CHACHA20_POLY1305_SHA256,
+
+ // TLS 1.2 ciphers:
+ CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
+ CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
+ CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
+ CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
+ CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
+ };
}
-
- public override void NotifyAlertRaised(short alertLevel, short alertDescription, string message, Exception cause)
+ else
{
- if (logger.IsEnabled(LogLevel.Debug))
- {
- logger.LogDebug("DTLS server raised alert: {AlertLevel}, {AlertDescription}.",
- AlertLevel.GetText(alertLevel), AlertDescription.GetText(alertDescription));
- }
-
- if (message != null)
- {
- logger.LogDebug("> {Message}", message);
- }
- if (cause != null)
- {
- logger.LogDebug("> {Cause}", cause);
- }
+ throw new InvalidOperationException($"DTLS server certificate algorithm {CertificateSignatureAlgorithm} not supported!");
}
+ }
- public override void NotifyAlertReceived(short level, short alertDescription)
+ public virtual DtlsTransport? DoHandshake(out string? handshakeError, DatagramTransport datagramTransport, DtlsRequest? request = null)
+ {
+ lock (_syncRoot)
{
- if (logger.IsEnabled(LogLevel.Debug))
+ if (datagramTransport == null)
{
- logger.LogDebug("DTLS server received alert: {AlertLevel}, {AlertDescription}.",
- AlertLevel.GetText(level), AlertDescription.GetText(alertDescription));
+ throw new ArgumentNullException(nameof(datagramTransport));
}
- TlsAlertTypesEnum alertType = TlsAlertTypesEnum.Unassigned;
- if (Enum.IsDefined(typeof(TlsAlertTypesEnum), (int)alertDescription))
+ DtlsTransport? transport = null;
+
+ try
{
- alertType = (TlsAlertTypesEnum)alertDescription;
+ DtlsServerProtocol serverProtocol = new DtlsServerProtocol();
+ _clientDatagramTransport = datagramTransport;
+ transport = serverProtocol.Accept(this, datagramTransport, request);
+ _clientDatagramTransport = null;
}
-
- TlsAlertLevelsEnum alertLevel = TlsAlertLevelsEnum.Warn;
- if (Enum.IsDefined(typeof(TlsAlertLevelsEnum), (int)alertLevel))
+ catch (Exception ex)
{
- alertLevel = (TlsAlertLevelsEnum)level;
+ handshakeError = ex.Message;
+ return null;
}
- OnAlert?.Invoke(this, new DtlsAlertEventArgs(alertLevel, alertType, AlertDescription.GetText(alertDescription)));
+ handshakeError = null;
+ return transport;
}
+ }
- public override ProtocolVersion GetServerVersion()
- {
- ProtocolVersion serverVersion = base.GetServerVersion();
- logger.LogDebug("DTLS server negotiated {ServerVersion}.", serverVersion);
- return serverVersion;
- }
+ public override void NotifyAlertRaised(short alertLevel, short alertDescription, string message, Exception cause)
+ {
+ _logger.LogDtlsServerAlertRaised(alertLevel, alertDescription, message, cause);
+ }
- public override int GetHandshakeTimeoutMillis()
+ public override void NotifyAlertReceived(short level, short alertDescription)
+ {
+ _logger.LogDtlsServerAlertReceived(level, alertDescription);
+
+ TlsAlertTypesEnum alertType = TlsAlertTypesEnum.Unassigned;
+ if (Enum.IsDefined(typeof(TlsAlertTypesEnum), (int)alertDescription))
{
- return TimeoutMilliseconds;
+ alertType = (TlsAlertTypesEnum)alertDescription;
}
- public override CertificateRequest GetCertificateRequest()
+ TlsAlertLevelsEnum alertLevel = TlsAlertLevelsEnum.Warn;
+ if (Enum.IsDefined(typeof(TlsAlertLevelsEnum), (int)alertLevel))
{
- short[] certificateTypes = new short[] { ClientCertificateType.ecdsa_sign, ClientCertificateType.rsa_sign };
-
- IList serverSigAlgs = null;
- if (TlsUtilities.IsSignatureAlgorithmsExtensionAllowed(m_context.ServerVersion))
- {
- serverSigAlgs = TlsUtilities.GetDefaultSupportedSignatureAlgorithms(m_context);
- }
-
- return new CertificateRequest(certificateTypes, serverSigAlgs, null);
+ alertLevel = (TlsAlertLevelsEnum)level;
}
- public override void NotifyClientCertificate(Certificate clientCertificate)
- {
- TlsCertificate[] chain = clientCertificate.GetCertificateList();
+ OnAlert?.Invoke(this, new DtlsAlertEventArgs(alertLevel, alertType, AlertDescription.GetText(alertDescription)));
+ }
+
+ public override ProtocolVersion GetServerVersion()
+ {
+ ProtocolVersion serverVersion = base.GetServerVersion();
+ _logger.LogDtlsServerNegotiated(serverVersion);
+ return serverVersion;
+ }
- logger.LogDebug("DTLS server received client certificate chain of length {CertificateCount}.", chain.Length);
+ public override int GetHandshakeTimeoutMillis()
+ {
+ return TimeoutMilliseconds;
+ }
- for (int i = 0; i != chain.Length; i++)
- {
- X509CertificateStructure entry = X509CertificateStructure.GetInstance(chain[i].GetEncoded());
- if (logger.IsEnabled(LogLevel.Debug))
- {
- logger.LogDebug("fingerprint:SHA-256 {Fingerprint} ({Subject}).",
- DtlsCertificateUtils.Fingerprint(entry), entry.Subject);
- }
- }
- }
+ public override CertificateRequest GetCertificateRequest()
+ {
+ short[] certificateTypes = new short[] { ClientCertificateType.ecdsa_sign, ClientCertificateType.rsa_sign };
- public override void NotifyHandshakeComplete()
+ IList? serverSigAlgs = null;
+ if (TlsUtilities.IsSignatureAlgorithmsExtensionAllowed(m_context.ServerVersion))
{
- base.NotifyHandshakeComplete();
+ serverSigAlgs = TlsUtilities.GetDefaultSupportedSignatureAlgorithms(m_context);
+ }
- ProtocolName protocolName = m_context.SecurityParameters.ApplicationProtocol;
- if (protocolName != null)
- {
- if (logger.IsEnabled(LogLevel.Debug))
- {
- logger.LogDebug("Server ALPN: {ApplicationProtocol}.", protocolName.GetUtf8Decoding());
- }
- }
+ return new CertificateRequest(certificateTypes, serverSigAlgs, null);
+ }
- byte[] tlsServerEndPoint = m_context.ExportChannelBinding(ChannelBinding.tls_server_end_point);
- if (logger.IsEnabled(LogLevel.Debug))
- {
- logger.LogDebug("Server 'tls-server-end-point': {TlsServerEndPoint}.", ToHexString(tlsServerEndPoint));
- }
+ public override void NotifyClientCertificate(Certificate clientCertificate)
+ {
+ TlsCertificate[] chain = clientCertificate.GetCertificateList();
- byte[] tlsUnique = m_context.ExportChannelBinding(ChannelBinding.tls_unique);
- if (logger.IsEnabled(LogLevel.Debug))
- {
- logger.LogDebug("Server 'tls-unique': {TlsUnique}.", ToHexString(tlsUnique));
- }
+ _logger.LogDtlsServerCertificateChainReceived(chain.Length);
- OnHandshakeCompleted?.Invoke(this, new DtlsHandshakeCompletedEventArgs(m_context.SecurityParameters));
+ for (int i = 0; i != chain.Length; i++)
+ {
+ X509CertificateStructure entry = X509CertificateStructure.GetInstance(chain[i].GetEncoded());
+ _logger.LogDtlsServerCertificateFingerprint(DtlsCertificateUtils.Fingerprint(entry), entry.Subject.ToString());
}
+ }
- public override void ProcessClientExtensions(IDictionary clientExtensions)
- {
- if (m_context.SecurityParameters.ClientRandom == null)
- {
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
+ public override void NotifyHandshakeComplete()
+ {
+ base.NotifyHandshakeComplete();
- base.ProcessClientExtensions(clientExtensions);
+ ProtocolName protocolName = m_context.SecurityParameters.ApplicationProtocol;
+ if (protocolName != null)
+ {
+ _logger.LogDtlsServerAlpn(protocolName.GetUtf8Decoding());
}
- public override IDictionary GetServerExtensions()
- {
- if (m_context.SecurityParameters.ServerRandom == null)
- {
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
+ byte[] tlsServerEndPoint = m_context.ExportChannelBinding(ChannelBinding.tls_server_end_point);
+ _logger.LogDtlsServerTlsServerEndPoint(ToHexString(tlsServerEndPoint));
- return base.GetServerExtensions();
- }
+ byte[] tlsUnique = m_context.ExportChannelBinding(ChannelBinding.tls_unique);
+ _logger.LogDtlsServerTlsUnique(ToHexString(tlsUnique));
- public override void GetServerExtensionsForConnection(IDictionary serverExtensions)
- {
- if (m_context.SecurityParameters.ServerRandom == null)
- {
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
+ OnHandshakeCompleted?.Invoke(this, new DtlsHandshakeCompletedEventArgs(m_context.SecurityParameters));
+ }
- base.GetServerExtensionsForConnection(serverExtensions);
+ public override void ProcessClientExtensions(IDictionary clientExtensions)
+ {
+ if (m_context.SecurityParameters.ClientRandom == null)
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
}
- protected virtual string ToHexString(byte[] data)
+ base.ProcessClientExtensions(clientExtensions);
+ }
+
+ public override IDictionary GetServerExtensions()
+ {
+ if (m_context.SecurityParameters.ServerRandom == null)
{
- return data == null ? "(null)" : Hex.ToHexString(data);
+ throw new TlsFatalAlert(AlertDescription.internal_error);
}
- public override int GetSelectedCipherSuite()
+ return base.GetServerExtensions();
+ }
+
+ public override void GetServerExtensionsForConnection(IDictionary serverExtensions)
+ {
+ if (m_context.SecurityParameters.ServerRandom == null)
{
- return base.GetSelectedCipherSuite();
+ throw new TlsFatalAlert(AlertDescription.internal_error);
}
- protected override TlsCredentialedSigner GetECDsaSignerCredentials()
- {
- IList clientSigAlgs = m_context.SecurityParameters.ClientSigAlgs;
- SignatureAndHashAlgorithm signatureAndHashAlgorithm = null;
+ base.GetServerExtensionsForConnection(serverExtensions);
+ }
- if (Certificate == null || CertificatePrivateKey == null)
- {
- throw new InvalidOperationException("DTLS server ECDsa certificate not set!");
- }
+ protected virtual string ToHexString(byte[] data)
+ {
+ return data == null ? "(null)" : Hex.ToHexString(data);
+ }
- foreach (SignatureAndHashAlgorithm alg in clientSigAlgs)
- {
- if (alg.Signature == CertificateSignatureAlgorithm && alg.Hash == CertificateHashAlgorithm)
- {
- signatureAndHashAlgorithm = alg;
- break;
- }
- }
+ public override int GetSelectedCipherSuite()
+ {
+ return base.GetSelectedCipherSuite();
+ }
- if (signatureAndHashAlgorithm == null)
- {
- throw new InvalidOperationException("DTLS Client does not support the selected certificate algorithm!");
- }
+ protected override TlsCredentialedSigner GetECDsaSignerCredentials()
+ {
+ IList clientSigAlgs = m_context.SecurityParameters.ClientSigAlgs;
+ SignatureAndHashAlgorithm? signatureAndHashAlgorithm = null;
- return new BcDefaultTlsCredentialedSigner(new TlsCryptoParameters(m_context), (BcTlsCrypto)m_context.Crypto, CertificatePrivateKey, Certificate, signatureAndHashAlgorithm);
+ if (Certificate == null || CertificatePrivateKey == null)
+ {
+ throw new InvalidOperationException("DTLS server ECDsa certificate not set!");
}
- protected override TlsCredentialedSigner GetRsaSignerCredentials()
+ foreach (SignatureAndHashAlgorithm alg in clientSigAlgs)
{
- IList clientSigAlgs = m_context.SecurityParameters.ClientSigAlgs;
- SignatureAndHashAlgorithm signatureAndHashAlgorithm = null;
-
- if (Certificate == null || CertificatePrivateKey == null)
+ if (alg.Signature == CertificateSignatureAlgorithm && alg.Hash == CertificateHashAlgorithm)
{
- throw new InvalidOperationException("DTLS server RSA certificate not set!");
+ signatureAndHashAlgorithm = alg;
+ break;
}
+ }
- foreach (SignatureAndHashAlgorithm alg in clientSigAlgs)
- {
- if (alg.Signature == CertificateSignatureAlgorithm && alg.Hash == CertificateHashAlgorithm)
- {
- signatureAndHashAlgorithm = alg;
- break;
- }
- }
+ if (signatureAndHashAlgorithm == null)
+ {
+ throw new InvalidOperationException("DTLS Client does not support the selected certificate algorithm!");
+ }
+
+ return new BcDefaultTlsCredentialedSigner(new TlsCryptoParameters(m_context), (BcTlsCrypto)m_context.Crypto, CertificatePrivateKey, Certificate, signatureAndHashAlgorithm);
+ }
- if (signatureAndHashAlgorithm == null)
+ protected override TlsCredentialedSigner GetRsaSignerCredentials()
+ {
+ IList clientSigAlgs = m_context.SecurityParameters.ClientSigAlgs;
+ SignatureAndHashAlgorithm? signatureAndHashAlgorithm = null;
+
+ if (Certificate == null || CertificatePrivateKey == null)
+ {
+ throw new InvalidOperationException("DTLS server RSA certificate not set!");
+ }
+
+ foreach (SignatureAndHashAlgorithm alg in clientSigAlgs)
+ {
+ if (alg.Signature == CertificateSignatureAlgorithm && alg.Hash == CertificateHashAlgorithm)
{
- throw new InvalidOperationException("DTLS Client does not support the selected certificate algorithm!");
+ signatureAndHashAlgorithm = alg;
+ break;
}
+ }
- return new BcDefaultTlsCredentialedSigner(new TlsCryptoParameters(m_context), (BcTlsCrypto)m_context.Crypto, CertificatePrivateKey, Certificate, signatureAndHashAlgorithm);
+ if (signatureAndHashAlgorithm == null)
+ {
+ throw new InvalidOperationException("DTLS Client does not support the selected certificate algorithm!");
}
+
+ return new BcDefaultTlsCredentialedSigner(new TlsCryptoParameters(m_context), (BcTlsCrypto)m_context.Crypto, CertificatePrivateKey, Certificate, signatureAndHashAlgorithm);
}
}
diff --git a/src/SIPSorcery/net/DtlsSrtp/Lib/DTLS/IDtlsPeer.cs b/src/SIPSorcery/net/DtlsSrtp/Lib/DTLS/IDtlsPeer.cs
index e97192788..cf0555663 100644
--- a/src/SIPSorcery/net/DtlsSrtp/Lib/DTLS/IDtlsPeer.cs
+++ b/src/SIPSorcery/net/DtlsSrtp/Lib/DTLS/IDtlsPeer.cs
@@ -23,106 +23,105 @@
using Org.BouncyCastle.Tls;
using System;
-namespace SIPSorcery.Net.SharpSRTP.DTLS
+namespace SIPSorcery.Net.SharpSRTP.DTLS;
+
+public enum TlsAlertLevelsEnum
{
- public enum TlsAlertLevelsEnum
- {
- Warn = 1,
- Fatal = 2
- }
+ Warn = 1,
+ Fatal = 2
+}
- // https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-6
- public enum TlsAlertTypesEnum
- {
- CloseNotify = 0,
- // 1-9 unassigned
- UnexpectedMessage = 10,
- // 11-19 unassigned
- BadRecordMac = 20,
- DecryptionFailedReserved = 21, // Used in TLS versions prior to 1.3.
- RecordOverflow = 22,
- // 23-29 unassigned
- DecompressionFailureReserved = 30, // Used in TLS versions prior to 1.3.
- // 31-39 unassigned
- HandshakeFailure = 40,
- NoCertificateReserved = 41, // Used in SSLv3 but not in TLS.
- BadCertificate = 42,
- UnsupportedCertificate = 43,
- CertificateRevoked = 44,
- CertificateExpired = 45,
- CertificateUnknown = 46,
- IllegalParameter = 47,
- UnknownCA = 48,
- AccessDenied = 49,
- DecodeError = 50,
- DecryptError = 51,
- TooManyCidsRequested = 52,
- // 53-59 unassigned
- ExportRestrictionReserved = 60, // Used in TLS 1.0 but not TLS 1.1 or later.
- ProtocolVersion = 70,
- InsufficientSecurity = 71,
- // 72-79 unassigned
- InternalEror = 80,
- // 81-85 unassigned
- InappropriateFallback = 86,
- // 87-89 unassigned
- UserCanceled = 90,
- // 91-99 unassigned
- NoRenegotiationReserved = 100, // Used in TLS versions prior to 1.3.
- // 101-108 unassigned
- MissingExtension = 109,
- UnsupportedExtension = 110,
- CertificateUnobtainableReserved = 111, // Used in TLS versions prior to 1.3.
- UnrecognizedName = 112,
- BadCertificateStatusResponse = 113,
- BadCertificateHashValueReserved = 114, // Used in TLS versions prior to 1.3.
- UnknownPskIdentity = 115,
- CertificateRequired = 116,
- GeneralError = 117,
- // 118-119 unassigned
- NoApplicationProtocol = 120,
- EchRequired = 121,
- // 122-255 unassigned
- Unassigned = 255
- }
+// https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-6
+public enum TlsAlertTypesEnum
+{
+ CloseNotify = 0,
+ // 1-9 unassigned
+ UnexpectedMessage = 10,
+ // 11-19 unassigned
+ BadRecordMac = 20,
+ DecryptionFailedReserved = 21, // Used in TLS versions prior to 1.3.
+ RecordOverflow = 22,
+ // 23-29 unassigned
+ DecompressionFailureReserved = 30, // Used in TLS versions prior to 1.3.
+ // 31-39 unassigned
+ HandshakeFailure = 40,
+ NoCertificateReserved = 41, // Used in SSLv3 but not in TLS.
+ BadCertificate = 42,
+ UnsupportedCertificate = 43,
+ CertificateRevoked = 44,
+ CertificateExpired = 45,
+ CertificateUnknown = 46,
+ IllegalParameter = 47,
+ UnknownCA = 48,
+ AccessDenied = 49,
+ DecodeError = 50,
+ DecryptError = 51,
+ TooManyCidsRequested = 52,
+ // 53-59 unassigned
+ ExportRestrictionReserved = 60, // Used in TLS 1.0 but not TLS 1.1 or later.
+ ProtocolVersion = 70,
+ InsufficientSecurity = 71,
+ // 72-79 unassigned
+ InternalEror = 80,
+ // 81-85 unassigned
+ InappropriateFallback = 86,
+ // 87-89 unassigned
+ UserCanceled = 90,
+ // 91-99 unassigned
+ NoRenegotiationReserved = 100, // Used in TLS versions prior to 1.3.
+ // 101-108 unassigned
+ MissingExtension = 109,
+ UnsupportedExtension = 110,
+ CertificateUnobtainableReserved = 111, // Used in TLS versions prior to 1.3.
+ UnrecognizedName = 112,
+ BadCertificateStatusResponse = 113,
+ BadCertificateHashValueReserved = 114, // Used in TLS versions prior to 1.3.
+ UnknownPskIdentity = 115,
+ CertificateRequired = 116,
+ GeneralError = 117,
+ // 118-119 unassigned
+ NoApplicationProtocol = 120,
+ EchRequired = 121,
+ // 122-255 unassigned
+ Unassigned = 255
+}
- public class DtlsAlertEventArgs : EventArgs
- {
- public TlsAlertLevelsEnum Level { get; }
- public TlsAlertTypesEnum AlertType { get; }
- public string Description { get; }
+public class DtlsAlertEventArgs : EventArgs
+{
+ public TlsAlertLevelsEnum Level { get; }
+ public TlsAlertTypesEnum AlertType { get; }
+ public string Description { get; }
- public DtlsAlertEventArgs(TlsAlertLevelsEnum level, TlsAlertTypesEnum type, string description)
- {
- this.Level = level;
- this.AlertType = type;
- this.Description = description;
- }
+ public DtlsAlertEventArgs(TlsAlertLevelsEnum level, TlsAlertTypesEnum type, string description)
+ {
+ this.Level = level;
+ this.AlertType = type;
+ this.Description = description;
}
+}
- public class DtlsHandshakeCompletedEventArgs : EventArgs
- {
- public SecurityParameters SecurityParameters { get; }
+public class DtlsHandshakeCompletedEventArgs : EventArgs
+{
+ public SecurityParameters SecurityParameters { get; }
- public DtlsHandshakeCompletedEventArgs(SecurityParameters securityParameters)
- {
- SecurityParameters = securityParameters;
- }
+ public DtlsHandshakeCompletedEventArgs(SecurityParameters securityParameters)
+ {
+ SecurityParameters = securityParameters;
}
+}
- public interface IDtlsPeer
- {
- event EventHandler OnAlert;
- event EventHandler OnHandshakeCompleted;
- int TimeoutMilliseconds { get; set; }
- bool ForceUseExtendedMasterSecret { get; set; }
+public interface IDtlsPeer
+{
+ event EventHandler? OnAlert;
+ event EventHandler? OnHandshakeCompleted;
+ int TimeoutMilliseconds { get; set; }
+ bool ForceUseExtendedMasterSecret { get; set; }
- Certificate Certificate { get; }
- AsymmetricKeyParameter CertificatePrivateKey { get; }
- short CertificateSignatureAlgorithm { get; }
- short CertificateHashAlgorithm { get; }
- void SetCertificate(Certificate certificate, AsymmetricKeyParameter privateKey, short signatureAlgorithm, short hashAlgorithm);
+ Certificate? Certificate { get; }
+ AsymmetricKeyParameter? CertificatePrivateKey { get; }
+ short CertificateSignatureAlgorithm { get; }
+ short CertificateHashAlgorithm { get; }
+ void SetCertificate(Certificate certificate, AsymmetricKeyParameter privateKey, short signatureAlgorithm, short hashAlgorithm);
- DtlsTransport DoHandshake(out string handshakeError, DatagramTransport datagramTransport, DtlsRequest request = null);
- }
+ DtlsTransport? DoHandshake(out string? handshakeError, DatagramTransport datagramTransport, DtlsRequest? request = null);
}
diff --git a/src/SIPSorcery/net/DtlsSrtp/Lib/DTLSSRTP/DtlsSrtpClient.cs b/src/SIPSorcery/net/DtlsSrtp/Lib/DTLSSRTP/DtlsSrtpClient.cs
index aa24b8e9c..a0c581868 100644
--- a/src/SIPSorcery/net/DtlsSrtp/Lib/DTLSSRTP/DtlsSrtpClient.cs
+++ b/src/SIPSorcery/net/DtlsSrtp/Lib/DTLSSRTP/DtlsSrtpClient.cs
@@ -27,135 +27,159 @@
using SIPSorcery.Net.SharpSRTP.SRTP;
using System;
using System.Collections.Generic;
+using System.Diagnostics;
-namespace SIPSorcery.Net.SharpSRTP.DTLSSRTP
+namespace SIPSorcery.Net.SharpSRTP.DTLSSRTP;
+
+public class DtlsSrtpClient : DtlsClient, IDtlsSrtpPeer
{
- public class DtlsSrtpClient : DtlsClient, IDtlsSrtpPeer
+ private UseSrtpData _srtpData;
+
+ public event EventHandler? OnSessionStarted;
+ public int MkiLength { get; private set; } = 0;
+
+ public DtlsSrtpClient(
+ Certificate? certificate = null,
+ AsymmetricKeyParameter? privateKey = null,
+ short certificateSignatureAlgorithm = SignatureAlgorithm.ecdsa,
+ short certificateHashAlgorithm = HashAlgorithm.sha256,
+ TlsSession? session = null) :
+ this(
+ new BcTlsCrypto(),
+ certificate,
+ privateKey,
+ certificateSignatureAlgorithm,
+ certificateHashAlgorithm,
+ session)
+ { }
+
+ public DtlsSrtpClient(
+ TlsCrypto crypto,
+ Certificate? certificate = null,
+ AsymmetricKeyParameter? privateKey = null,
+ short certificateSignatureAlgorithm = SignatureAlgorithm.ecdsa,
+ short certificateHashAlgorithm = HashAlgorithm.sha256,
+ TlsSession? session = null) :
+ base(
+ crypto,
+ session,
+ certificate,
+ privateKey,
+ certificateSignatureAlgorithm,
+ certificateHashAlgorithm)
{
- private UseSrtpData _srtpData;
-
- public event EventHandler OnSessionStarted;
- public int MkiLength { get; private set; } = 0;
-
- public DtlsSrtpClient(Certificate certificate = null, AsymmetricKeyParameter privateKey = null, short certificateSignatureAlgorithm = SignatureAlgorithm.ecdsa, short certificateHashAlgorithm = HashAlgorithm.sha256, TlsSession session = null) :
- this(new BcTlsCrypto(), certificate, privateKey, certificateSignatureAlgorithm, certificateHashAlgorithm, session)
- { }
+ int[] protectionProfiles = GetSupportedProtectionProfiles();
- public DtlsSrtpClient(TlsCrypto crypto, Certificate certificate = null, AsymmetricKeyParameter privateKey = null, short certificateSignatureAlgorithm = SignatureAlgorithm.ecdsa, short certificateHashAlgorithm = HashAlgorithm.sha256, TlsSession session = null) :
- base(crypto, session, certificate, privateKey, certificateSignatureAlgorithm, certificateHashAlgorithm)
- {
- int[] protectionProfiles = GetSupportedProtectionProfiles();
+ byte[] mki = DtlsSrtpProtocol.GenerateMki(MkiLength);
+ this._srtpData = new UseSrtpData(protectionProfiles, mki);
- byte[] mki = DtlsSrtpProtocol.GenerateMki(MkiLength);
- this._srtpData = new UseSrtpData(protectionProfiles, mki);
+ this.OnHandshakeCompleted += DtlsSrtpClient_OnHandshakeCompleted;
+ }
- this.OnHandshakeCompleted += DtlsSrtpClient_OnHandshakeCompleted;
- }
+ private void DtlsSrtpClient_OnHandshakeCompleted(object? sender, DtlsHandshakeCompletedEventArgs e)
+ {
+ SrtpSessionContext context = CreateSessionContext(e.SecurityParameters);
+ Certificate peerCertificate = e.SecurityParameters.PeerCertificate;
+ Debug.Assert(base._clientDatagramTransport is not null);
+ OnSessionStarted?.Invoke(this, new DtlsSessionStartedEventArgs(context, peerCertificate, base._clientDatagramTransport));
+ }
- private void DtlsSrtpClient_OnHandshakeCompleted(object sender, DtlsHandshakeCompletedEventArgs e)
+ public void SetMKI(byte[] mki)
+ {
+ if (mki == null)
{
- SrtpSessionContext context = CreateSessionContext(e.SecurityParameters);
- Certificate peerCertificate = e.SecurityParameters.PeerCertificate;
- OnSessionStarted?.Invoke(this, new DtlsSessionStartedEventArgs(context, peerCertificate, base._clientDatagramTransport));
+ MkiLength = 0;
+ mki = new byte[0];
}
-
- public void SetMKI(byte[] mki)
+ else
{
- if (mki == null)
- {
- MkiLength = 0;
- mki = new byte[0];
- }
- else
+ if (mki.Length > 255)
{
- if (mki.Length > 255)
- {
- throw new ArgumentOutOfRangeException(nameof(mki));
- }
-
- MkiLength = mki.Length;
+ throw new ArgumentOutOfRangeException(nameof(mki));
}
- this._srtpData = new UseSrtpData(_srtpData.ProtectionProfiles, mki);
- }
-
- protected virtual int[] GetSupportedProtectionProfiles()
- {
- return new int[]
- {
- ExtendedSrtpProtectionProfile.DOUBLE_AEAD_AES_256_GCM_AEAD_AES_256_GCM,
- ExtendedSrtpProtectionProfile.DOUBLE_AEAD_AES_128_GCM_AEAD_AES_128_GCM,
- ExtendedSrtpProtectionProfile.SRTP_AEAD_AES_256_GCM,
- ExtendedSrtpProtectionProfile.SRTP_AEAD_ARIA_256_GCM,
- ExtendedSrtpProtectionProfile.SRTP_AEAD_AES_128_GCM,
- ExtendedSrtpProtectionProfile.SRTP_AEAD_ARIA_128_GCM,
- ExtendedSrtpProtectionProfile.SRTP_ARIA_256_CTR_HMAC_SHA1_80,
- ExtendedSrtpProtectionProfile.SRTP_AES128_CM_HMAC_SHA1_80,
- ExtendedSrtpProtectionProfile.SRTP_ARIA_128_CTR_HMAC_SHA1_80,
- ExtendedSrtpProtectionProfile.SRTP_AES128_CM_HMAC_SHA1_32,
- ExtendedSrtpProtectionProfile.SRTP_ARIA_256_CTR_HMAC_SHA1_32,
- ExtendedSrtpProtectionProfile.SRTP_ARIA_128_CTR_HMAC_SHA1_32,
-
- // do not offer NULL profiles to make sure these do not get selected by accident
- //ExtendedSrtpProtectionProfile.SRTP_NULL_HMAC_SHA1_80,
- //ExtendedSrtpProtectionProfile.SRTP_NULL_HMAC_SHA1_32
- };
+ MkiLength = mki.Length;
}
- protected override string GetCertificateCommonName()
- {
- return "WebRTC";
- }
+ this._srtpData = new UseSrtpData(_srtpData.ProtectionProfiles, mki);
+ }
- public override void ProcessServerExtensions(IDictionary serverExtensions)
+ protected virtual int[] GetSupportedProtectionProfiles()
+ {
+ return new int[]
{
- base.ProcessServerExtensions(serverExtensions);
-
- // https://www.rfc-editor.org/rfc/rfc5764#section-4.1
- UseSrtpData serverSrtpExtension = TlsSrtpUtilities.GetUseSrtpExtension(serverExtensions);
+ ExtendedSrtpProtectionProfile.DOUBLE_AEAD_AES_256_GCM_AEAD_AES_256_GCM,
+ ExtendedSrtpProtectionProfile.DOUBLE_AEAD_AES_128_GCM_AEAD_AES_128_GCM,
+ ExtendedSrtpProtectionProfile.SRTP_AEAD_AES_256_GCM,
+ ExtendedSrtpProtectionProfile.SRTP_AEAD_ARIA_256_GCM,
+ ExtendedSrtpProtectionProfile.SRTP_AEAD_AES_128_GCM,
+ ExtendedSrtpProtectionProfile.SRTP_AEAD_ARIA_128_GCM,
+ ExtendedSrtpProtectionProfile.SRTP_ARIA_256_CTR_HMAC_SHA1_80,
+ ExtendedSrtpProtectionProfile.SRTP_AES128_CM_HMAC_SHA1_80,
+ ExtendedSrtpProtectionProfile.SRTP_ARIA_128_CTR_HMAC_SHA1_80,
+ ExtendedSrtpProtectionProfile.SRTP_AES128_CM_HMAC_SHA1_32,
+ ExtendedSrtpProtectionProfile.SRTP_ARIA_256_CTR_HMAC_SHA1_32,
+ ExtendedSrtpProtectionProfile.SRTP_ARIA_128_CTR_HMAC_SHA1_32,
+
+ // do not offer NULL profiles to make sure these do not get selected by accident
+ //ExtendedSrtpProtectionProfile.SRTP_NULL_HMAC_SHA1_80,
+ //ExtendedSrtpProtectionProfile.SRTP_NULL_HMAC_SHA1_32
+ };
+ }
- // verify that the server has selected exactly 1 profile
- int[] clientSupportedProfiles = GetSupportedProtectionProfiles();
- if (serverSrtpExtension.ProtectionProfiles.Length != 1)
- {
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
+ protected override string GetCertificateCommonName()
+ {
+ return "WebRTC";
+ }
- // verify that the server has selected a profile we support
- int selectedProfile = serverSrtpExtension.ProtectionProfiles[0];
- if (Array.IndexOf(clientSupportedProfiles, selectedProfile) < 0)
- {
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
+ public override void ProcessServerExtensions(IDictionary serverExtensions)
+ {
+ base.ProcessServerExtensions(serverExtensions);
- // verify the mki sent by the server matches our mki
- if (_srtpData.Mki != null && serverSrtpExtension.Mki != null && !_srtpData.Mki.AsSpan().SequenceEqual(serverSrtpExtension.Mki))
- {
- throw new TlsFatalAlert(AlertDescription.illegal_parameter);
- }
+ // https://www.rfc-editor.org/rfc/rfc5764#section-4.1
+ UseSrtpData serverSrtpExtension = TlsSrtpUtilities.GetUseSrtpExtension(serverExtensions);
- // store the server extension as it contains the selected profile
- _srtpData = serverSrtpExtension;
+ // verify that the server has selected exactly 1 profile
+ int[] clientSupportedProfiles = GetSupportedProtectionProfiles();
+ if (serverSrtpExtension.ProtectionProfiles.Length != 1)
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
}
- public override IDictionary GetClientExtensions()
+ // verify that the server has selected a profile we support
+ int selectedProfile = serverSrtpExtension.ProtectionProfiles[0];
+ if (Array.IndexOf(clientSupportedProfiles, selectedProfile) < 0)
{
- var extensions = base.GetClientExtensions();
- TlsSrtpUtilities.AddUseSrtpExtension(extensions, _srtpData);
- return extensions;
+ throw new TlsFatalAlert(AlertDescription.internal_error);
}
- public virtual SrtpSessionContext CreateSessionContext(SecurityParameters securityParameters)
+ // verify the mki sent by the server matches our mki
+ if (_srtpData.Mki != null && serverSrtpExtension.Mki != null && !_srtpData.Mki.AsSpan().SequenceEqual(serverSrtpExtension.Mki))
{
- // this should only be called from OnHandshakeCompleted so we should still have _srtpData from the connection
- if (m_context == null)
- {
- throw new InvalidOperationException();
- }
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
- int selectedProtectionProfile = _srtpData.ProtectionProfiles[0];
- DtlsSrtpKeys keys = DtlsSrtpProtocol.CreateMasterKeys(selectedProtectionProfile, _srtpData.Mki, securityParameters, ForceUseExtendedMasterSecret);
- return DtlsSrtpProtocol.CreateSrtpClientSessionContext(keys);
+ // store the server extension as it contains the selected profile
+ _srtpData = serverSrtpExtension;
+ }
+
+ public override IDictionary GetClientExtensions()
+ {
+ var extensions = base.GetClientExtensions();
+ TlsSrtpUtilities.AddUseSrtpExtension(extensions, _srtpData);
+ return extensions;
+ }
+
+ public virtual SrtpSessionContext CreateSessionContext(SecurityParameters securityParameters)
+ {
+ // this should only be called from OnHandshakeCompleted so we should still have _srtpData from the connection
+ if (m_context == null)
+ {
+ throw new InvalidOperationException();
}
+
+ int selectedProtectionProfile = _srtpData.ProtectionProfiles[0];
+ DtlsSrtpKeys keys = DtlsSrtpProtocol.CreateMasterKeys(selectedProtectionProfile, _srtpData.Mki, securityParameters, ForceUseExtendedMasterSecret);
+ return DtlsSrtpProtocol.CreateSrtpClientSessionContext(keys);
}
}
diff --git a/src/SIPSorcery/net/DtlsSrtp/Lib/DTLSSRTP/DtlsSrtpKeys.cs b/src/SIPSorcery/net/DtlsSrtp/Lib/DTLSSRTP/DtlsSrtpKeys.cs
index b029bf288..cf448b69d 100644
--- a/src/SIPSorcery/net/DtlsSrtp/Lib/DTLSSRTP/DtlsSrtpKeys.cs
+++ b/src/SIPSorcery/net/DtlsSrtp/Lib/DTLSSRTP/DtlsSrtpKeys.cs
@@ -22,44 +22,43 @@
using System;
using SIPSorcery.Net.SharpSRTP.SRTP;
-namespace SIPSorcery.Net.SharpSRTP.DTLSSRTP
-{
- public class DtlsSrtpKeys
- {
- public SrtpProtectionProfileConfiguration ProtectionProfile { get; }
- public ReadOnlyMemory Mki { get; }
+namespace SIPSorcery.Net.SharpSRTP.DTLSSRTP;
- public ReadOnlyMemory ClientWriteMasterKey { get; }
- public ReadOnlyMemory ClientWriteMasterSalt { get; }
- public ReadOnlyMemory ServerWriteMasterKey { get; }
- public ReadOnlyMemory ServerWriteMasterSalt { get; }
+public class DtlsSrtpKeys
+{
+ public SrtpProtectionProfileConfiguration ProtectionProfile { get; }
+ public ReadOnlyMemory Mki { get; }
- public DtlsSrtpKeys(
- SrtpProtectionProfileConfiguration protectionProfile,
- ReadOnlyMemory clientWriteMasterKey,
- ReadOnlyMemory clientWriteMasterSalt,
- ReadOnlyMemory serverWriteMasterKey,
- ReadOnlyMemory serverWriteMasterSalt,
- ReadOnlyMemory mki = default)
- {
- this.ProtectionProfile = protectionProfile ?? throw new ArgumentNullException(nameof(protectionProfile));
- this.Mki = mki;
+ public ReadOnlyMemory ClientWriteMasterKey { get; }
+ public ReadOnlyMemory ClientWriteMasterSalt { get; }
+ public ReadOnlyMemory ServerWriteMasterKey { get; }
+ public ReadOnlyMemory ServerWriteMasterSalt { get; }
- int cipherKeyLen = protectionProfile.CipherKeyLength >> 3;
- int cipherSaltLen = protectionProfile.CipherSaltLength >> 3;
+ public DtlsSrtpKeys(
+ SrtpProtectionProfileConfiguration protectionProfile,
+ ReadOnlyMemory clientWriteMasterKey,
+ ReadOnlyMemory clientWriteMasterSalt,
+ ReadOnlyMemory serverWriteMasterKey,
+ ReadOnlyMemory serverWriteMasterSalt,
+ ReadOnlyMemory mki = default)
+ {
+ this.ProtectionProfile = protectionProfile ?? throw new ArgumentNullException(nameof(protectionProfile));
+ this.Mki = mki;
- if (clientWriteMasterKey.Length != cipherKeyLen
- || clientWriteMasterSalt.Length != cipherSaltLen
- || serverWriteMasterKey.Length != cipherKeyLen
- || serverWriteMasterSalt.Length != cipherSaltLen)
- {
- throw new ArgumentException();
- }
+ int cipherKeyLen = protectionProfile.CipherKeyLength >> 3;
+ int cipherSaltLen = protectionProfile.CipherSaltLength >> 3;
- this.ClientWriteMasterKey = clientWriteMasterKey;
- this.ClientWriteMasterSalt = clientWriteMasterSalt;
- this.ServerWriteMasterKey = serverWriteMasterKey;
- this.ServerWriteMasterSalt = serverWriteMasterSalt;
+ if (clientWriteMasterKey.Length != cipherKeyLen
+ || clientWriteMasterSalt.Length != cipherSaltLen
+ || serverWriteMasterKey.Length != cipherKeyLen
+ || serverWriteMasterSalt.Length != cipherSaltLen)
+ {
+ throw new ArgumentException();
}
+
+ this.ClientWriteMasterKey = clientWriteMasterKey;
+ this.ClientWriteMasterSalt = clientWriteMasterSalt;
+ this.ServerWriteMasterKey = serverWriteMasterKey;
+ this.ServerWriteMasterSalt = serverWriteMasterSalt;
}
}
diff --git a/src/SIPSorcery/net/DtlsSrtp/Lib/DTLSSRTP/DtlsSrtpProtocol.cs b/src/SIPSorcery/net/DtlsSrtp/Lib/DTLSSRTP/DtlsSrtpProtocol.cs
index b7b0414fb..31ae88c2b 100644
--- a/src/SIPSorcery/net/DtlsSrtp/Lib/DTLSSRTP/DtlsSrtpProtocol.cs
+++ b/src/SIPSorcery/net/DtlsSrtp/Lib/DTLSSRTP/DtlsSrtpProtocol.cs
@@ -23,216 +23,215 @@
using SIPSorcery.Net.SharpSRTP.SRTP;
using System;
using System.Collections.Generic;
-using System.Linq;
-namespace SIPSorcery.Net.SharpSRTP.DTLSSRTP
+namespace SIPSorcery.Net.SharpSRTP.DTLSSRTP;
+
+///
+/// Currently registered DTLS-SRTP profiles:
+/// https://www.iana.org/assignments/srtp-protection/srtp-protection.xhtml#srtp-protection-1
+///
+public abstract class ExtendedSrtpProtectionProfile : SrtpProtectionProfile
+{
+ // TODO: Remove this once BouncyCastle adds the constants
+ public const int DRAFT_SRTP_AES256_CM_SHA1_80 = 0x0003;
+ public const int DRAFT_SRTP_AES256_CM_SHA1_32 = 0x0004;
+ public const int DOUBLE_AEAD_AES_128_GCM_AEAD_AES_128_GCM = 0x0009;
+ public const int DOUBLE_AEAD_AES_256_GCM_AEAD_AES_256_GCM = 0x000A;
+ public const int SRTP_ARIA_128_CTR_HMAC_SHA1_80 = 0x000B;
+ public const int SRTP_ARIA_128_CTR_HMAC_SHA1_32 = 0x000C;
+ public const int SRTP_ARIA_256_CTR_HMAC_SHA1_80 = 0x000D;
+ public const int SRTP_ARIA_256_CTR_HMAC_SHA1_32 = 0x000E;
+ public const int SRTP_AEAD_ARIA_128_GCM = 0x000F;
+ public const int SRTP_AEAD_ARIA_256_GCM = 0x0010;
+}
+
+public static class DtlsSrtpProtocol
{
- ///
- /// Currently registered DTLS-SRTP profiles: https://www.iana.org/assignments/srtp-protection/srtp-protection.xhtml#srtp-protection-1
- ///
- public abstract class ExtendedSrtpProtectionProfile : SrtpProtectionProfile
+ public static readonly Dictionary DtlsProtectionProfiles;
+
+ static DtlsSrtpProtocol()
{
- // TODO: Remove this once BouncyCastle adds the constants
- public const int DRAFT_SRTP_AES256_CM_SHA1_80 = 0x0003;
- public const int DRAFT_SRTP_AES256_CM_SHA1_32 = 0x0004;
- public const int DOUBLE_AEAD_AES_128_GCM_AEAD_AES_128_GCM = 0x0009;
- public const int DOUBLE_AEAD_AES_256_GCM_AEAD_AES_256_GCM = 0x000A;
- public const int SRTP_ARIA_128_CTR_HMAC_SHA1_80 = 0x000B;
- public const int SRTP_ARIA_128_CTR_HMAC_SHA1_32 = 0x000C;
- public const int SRTP_ARIA_256_CTR_HMAC_SHA1_80 = 0x000D;
- public const int SRTP_ARIA_256_CTR_HMAC_SHA1_32 = 0x000E;
- public const int SRTP_AEAD_ARIA_128_GCM = 0x000F;
- public const int SRTP_AEAD_ARIA_256_GCM = 0x0010;
+ // see https://www.iana.org/assignments/srtp-protection/srtp-protection.xhtml#srtp-protection-1
+ DtlsProtectionProfiles = new Dictionary()
+ {
+ // https://www.rfc-editor.org/rfc/rfc8723.txt
+ { ExtendedSrtpProtectionProfile.DOUBLE_AEAD_AES_256_GCM_AEAD_AES_256_GCM, new SrtpProtectionProfileConfiguration(SrtpCiphers.DOUBLE_AEAD_AES_256_GCM_AEAD_AES_256_GCM, 512, 192, int.MaxValue, SrtpAuth.NONE, 0, 256) },
+ { ExtendedSrtpProtectionProfile.DOUBLE_AEAD_AES_128_GCM_AEAD_AES_128_GCM, new SrtpProtectionProfileConfiguration(SrtpCiphers.DOUBLE_AEAD_AES_128_GCM_AEAD_AES_128_GCM, 256, 192, int.MaxValue, SrtpAuth.NONE, 0, 256) },
+
+ // https://datatracker.ietf.org/doc/html/rfc8269
+ { ExtendedSrtpProtectionProfile.SRTP_AEAD_ARIA_256_GCM, new SrtpProtectionProfileConfiguration(SrtpCiphers.AEAD_ARIA_256_GCM, 256, 96, int.MaxValue, SrtpAuth.NONE, 0, 128) },
+ { ExtendedSrtpProtectionProfile.SRTP_AEAD_ARIA_128_GCM, new SrtpProtectionProfileConfiguration(SrtpCiphers.AEAD_ARIA_128_GCM, 128, 96, int.MaxValue, SrtpAuth.NONE, 0, 128) },
+ { ExtendedSrtpProtectionProfile.SRTP_ARIA_256_CTR_HMAC_SHA1_80, new SrtpProtectionProfileConfiguration(SrtpCiphers.ARIA_256_CTR, 256, 112, int.MaxValue, SrtpAuth.HMAC_SHA1, 160, 80) },
+ { ExtendedSrtpProtectionProfile.SRTP_ARIA_256_CTR_HMAC_SHA1_32, new SrtpProtectionProfileConfiguration(SrtpCiphers.ARIA_256_CTR, 256, 112, int.MaxValue, SrtpAuth.HMAC_SHA1, 160, 32) },
+ { ExtendedSrtpProtectionProfile.SRTP_ARIA_128_CTR_HMAC_SHA1_80, new SrtpProtectionProfileConfiguration(SrtpCiphers.ARIA_128_CTR, 128, 112, int.MaxValue, SrtpAuth.HMAC_SHA1, 160, 80) },
+ { ExtendedSrtpProtectionProfile.SRTP_ARIA_128_CTR_HMAC_SHA1_32, new SrtpProtectionProfileConfiguration(SrtpCiphers.ARIA_128_CTR, 128, 112, int.MaxValue, SrtpAuth.HMAC_SHA1, 160, 32) },
+
+ // https://datatracker.ietf.org/doc/html/rfc7714
+ { ExtendedSrtpProtectionProfile.SRTP_AEAD_AES_256_GCM, new SrtpProtectionProfileConfiguration(SrtpCiphers.AEAD_AES_256_GCM, 256, 96, int.MaxValue, SrtpAuth.NONE, 0, 128) },
+ { ExtendedSrtpProtectionProfile.SRTP_AEAD_AES_128_GCM, new SrtpProtectionProfileConfiguration(SrtpCiphers.AEAD_AES_128_GCM, 128, 96, int.MaxValue, SrtpAuth.NONE, 0, 128) },
+
+ // AES256 CM is specified in RFC 6188, but not included in IANA DTLS-SRTP registry https://www.iana.org/assignments/srtp-protection/srtp-protection.xhtml#srtp-protection-1
+ // https://www.rfc-editor.org/rfc/rfc6188
+ // AES192 CM is not supported in DTLS-SRTP
+ // AES256 CM was removed in Draft 4 of RFC 5764
+ // https://author-tools.ietf.org/iddiff?url1=draft-ietf-avt-dtls-srtp-04&url2=draft-ietf-avt-dtls-srtp-03&difftype=--html
+ { ExtendedSrtpProtectionProfile.DRAFT_SRTP_AES256_CM_SHA1_80, new SrtpProtectionProfileConfiguration(SrtpCiphers.AES_256_CM, 256, 112, int.MaxValue, SrtpAuth.HMAC_SHA1, 160, 80) },
+ { ExtendedSrtpProtectionProfile.DRAFT_SRTP_AES256_CM_SHA1_32, new SrtpProtectionProfileConfiguration(SrtpCiphers.AES_256_CM, 256, 112, int.MaxValue, SrtpAuth.HMAC_SHA1, 160, 32) },
+
+ // https://datatracker.ietf.org/doc/html/rfc5764#section-9
+ { ExtendedSrtpProtectionProfile.SRTP_AES128_CM_HMAC_SHA1_80, new SrtpProtectionProfileConfiguration(SrtpCiphers.AES_128_CM, 128, 112, int.MaxValue, SrtpAuth.HMAC_SHA1, 160, 80) },
+ { ExtendedSrtpProtectionProfile.SRTP_AES128_CM_HMAC_SHA1_32, new SrtpProtectionProfileConfiguration(SrtpCiphers.AES_128_CM, 128, 112, int.MaxValue, SrtpAuth.HMAC_SHA1, 160, 32) },
+
+ // for NULL we still need the keys (K_a) for auth, so we use the same key lengths as AES128 CM in order to derive non-zero master keys
+ { ExtendedSrtpProtectionProfile.SRTP_NULL_HMAC_SHA1_80, new SrtpProtectionProfileConfiguration(SrtpCiphers.NULL, 128, 112, int.MaxValue, SrtpAuth.HMAC_SHA1, 160, 80) },
+ { ExtendedSrtpProtectionProfile.SRTP_NULL_HMAC_SHA1_32, new SrtpProtectionProfileConfiguration(SrtpCiphers.NULL, 128, 112, int.MaxValue, SrtpAuth.HMAC_SHA1, 160, 32) },
+ };
}
- public static class DtlsSrtpProtocol
+ public static DtlsSrtpKeys CreateMasterKeys(int protectionProfile, byte[] mki, SecurityParameters dtlsSecurityParameters, bool requireExtendedMasterSecret = true)
{
- public static readonly Dictionary DtlsProtectionProfiles;
-
- static DtlsSrtpProtocol()
+ // verify that we have extended master secret before computing the keys
+ if (!dtlsSecurityParameters.IsExtendedMasterSecret && requireExtendedMasterSecret)
{
- // see https://www.iana.org/assignments/srtp-protection/srtp-protection.xhtml#srtp-protection-1
- DtlsProtectionProfiles = new Dictionary()
- {
- // https://www.rfc-editor.org/rfc/rfc8723.txt
- { ExtendedSrtpProtectionProfile.DOUBLE_AEAD_AES_256_GCM_AEAD_AES_256_GCM, new SrtpProtectionProfileConfiguration(SrtpCiphers.DOUBLE_AEAD_AES_256_GCM_AEAD_AES_256_GCM, 512, 192, int.MaxValue, SrtpAuth.NONE, 0, 256) },
- { ExtendedSrtpProtectionProfile.DOUBLE_AEAD_AES_128_GCM_AEAD_AES_128_GCM, new SrtpProtectionProfileConfiguration(SrtpCiphers.DOUBLE_AEAD_AES_128_GCM_AEAD_AES_128_GCM, 256, 192, int.MaxValue, SrtpAuth.NONE, 0, 256) },
-
- // https://datatracker.ietf.org/doc/html/rfc8269
- { ExtendedSrtpProtectionProfile.SRTP_AEAD_ARIA_256_GCM, new SrtpProtectionProfileConfiguration(SrtpCiphers.AEAD_ARIA_256_GCM, 256, 96, int.MaxValue, SrtpAuth.NONE, 0, 128) },
- { ExtendedSrtpProtectionProfile.SRTP_AEAD_ARIA_128_GCM, new SrtpProtectionProfileConfiguration(SrtpCiphers.AEAD_ARIA_128_GCM, 128, 96, int.MaxValue, SrtpAuth.NONE, 0, 128) },
- { ExtendedSrtpProtectionProfile.SRTP_ARIA_256_CTR_HMAC_SHA1_80, new SrtpProtectionProfileConfiguration(SrtpCiphers.ARIA_256_CTR, 256, 112, int.MaxValue, SrtpAuth.HMAC_SHA1, 160, 80) },
- { ExtendedSrtpProtectionProfile.SRTP_ARIA_256_CTR_HMAC_SHA1_32, new SrtpProtectionProfileConfiguration(SrtpCiphers.ARIA_256_CTR, 256, 112, int.MaxValue, SrtpAuth.HMAC_SHA1, 160, 32) },
- { ExtendedSrtpProtectionProfile.SRTP_ARIA_128_CTR_HMAC_SHA1_80, new SrtpProtectionProfileConfiguration(SrtpCiphers.ARIA_128_CTR, 128, 112, int.MaxValue, SrtpAuth.HMAC_SHA1, 160, 80) },
- { ExtendedSrtpProtectionProfile.SRTP_ARIA_128_CTR_HMAC_SHA1_32, new SrtpProtectionProfileConfiguration(SrtpCiphers.ARIA_128_CTR, 128, 112, int.MaxValue, SrtpAuth.HMAC_SHA1, 160, 32) },
-
- // https://datatracker.ietf.org/doc/html/rfc7714
- { ExtendedSrtpProtectionProfile.SRTP_AEAD_AES_256_GCM, new SrtpProtectionProfileConfiguration(SrtpCiphers.AEAD_AES_256_GCM, 256, 96, int.MaxValue, SrtpAuth.NONE, 0, 128) },
- { ExtendedSrtpProtectionProfile.SRTP_AEAD_AES_128_GCM, new SrtpProtectionProfileConfiguration(SrtpCiphers.AEAD_AES_128_GCM, 128, 96, int.MaxValue, SrtpAuth.NONE, 0, 128) },
-
- // AES256 CM is specified in RFC 6188, but not included in IANA DTLS-SRTP registry https://www.iana.org/assignments/srtp-protection/srtp-protection.xhtml#srtp-protection-1
- // https://www.rfc-editor.org/rfc/rfc6188
- // AES192 CM is not supported in DTLS-SRTP
- // AES256 CM was removed in Draft 4 of RFC 5764
- // https://author-tools.ietf.org/iddiff?url1=draft-ietf-avt-dtls-srtp-04&url2=draft-ietf-avt-dtls-srtp-03&difftype=--html
- { ExtendedSrtpProtectionProfile.DRAFT_SRTP_AES256_CM_SHA1_80, new SrtpProtectionProfileConfiguration(SrtpCiphers.AES_256_CM, 256, 112, int.MaxValue, SrtpAuth.HMAC_SHA1, 160, 80) },
- { ExtendedSrtpProtectionProfile.DRAFT_SRTP_AES256_CM_SHA1_32, new SrtpProtectionProfileConfiguration(SrtpCiphers.AES_256_CM, 256, 112, int.MaxValue, SrtpAuth.HMAC_SHA1, 160, 32) },
-
- // https://datatracker.ietf.org/doc/html/rfc5764#section-9
- { ExtendedSrtpProtectionProfile.SRTP_AES128_CM_HMAC_SHA1_80, new SrtpProtectionProfileConfiguration(SrtpCiphers.AES_128_CM, 128, 112, int.MaxValue, SrtpAuth.HMAC_SHA1, 160, 80) },
- { ExtendedSrtpProtectionProfile.SRTP_AES128_CM_HMAC_SHA1_32, new SrtpProtectionProfileConfiguration(SrtpCiphers.AES_128_CM, 128, 112, int.MaxValue, SrtpAuth.HMAC_SHA1, 160, 32) },
-
- // for NULL we still need the keys (K_a) for auth, so we use the same key lengths as AES128 CM in order to derive non-zero master keys
- { ExtendedSrtpProtectionProfile.SRTP_NULL_HMAC_SHA1_80, new SrtpProtectionProfileConfiguration(SrtpCiphers.NULL, 128, 112, int.MaxValue, SrtpAuth.HMAC_SHA1, 160, 80) },
- { ExtendedSrtpProtectionProfile.SRTP_NULL_HMAC_SHA1_32, new SrtpProtectionProfileConfiguration(SrtpCiphers.NULL, 128, 112, int.MaxValue, SrtpAuth.HMAC_SHA1, 160, 32) },
- };
+ throw new InvalidOperationException();
}
- public static DtlsSrtpKeys CreateMasterKeys(int protectionProfile, byte[] mki, SecurityParameters dtlsSecurityParameters, bool requireExtendedMasterSecret = true)
+ // SRTP key derivation as described here https://datatracker.ietf.org/doc/html/rfc5764
+ var srtpSecurityParams = DtlsProtectionProfiles[protectionProfile];
+
+ // 2 * (SRTPSecurityParams.master_key_len + SRTPSecurityParams.master_salt_len) bytes of data
+ int sharedSecretLength = (2 * (srtpSecurityParams.CipherKeyLength + srtpSecurityParams.CipherSaltLength)) >> 3;
+
+ // EXTRACTOR-dtls_srtp https://datatracker.ietf.org/doc/html/rfc5705
+
+ // TODO: If context is provided, it computes:
+ /*
+ PRF(SecurityParameters.master_secret, label,
+ SecurityParameters.client_random +
+ SecurityParameters.server_random +
+ context_value_length + context_value
+ )[length]
+ */
+
+ // derive shared secret
+ /*
+ PRF(SecurityParameters.master_secret, label,
+ SecurityParameters.client_random +
+ SecurityParameters.server_random
+ )[length]
+ */
+ byte[] prfSeed = GC.AllocateUninitializedArray(dtlsSecurityParameters.ClientRandom.Length + dtlsSecurityParameters.ServerRandom.Length);
+ Buffer.BlockCopy(dtlsSecurityParameters.ClientRandom, 0, prfSeed, 0, dtlsSecurityParameters.ClientRandom.Length);
+ Buffer.BlockCopy(dtlsSecurityParameters.ServerRandom, 0, prfSeed, dtlsSecurityParameters.ClientRandom.Length, dtlsSecurityParameters.ServerRandom.Length);
+ byte[] sharedSecret = TlsUtilities.Prf(
+ dtlsSecurityParameters,
+ dtlsSecurityParameters.MasterSecret,
+ ExporterLabel.dtls_srtp, // The exporter label for this usage is "EXTRACTOR-dtls_srtp"
+ prfSeed,
+ sharedSecretLength
+ ).Extract();
+
+ return CreateMasterKeys(protectionProfile, mki, sharedSecret);
+ }
+
+ public static DtlsSrtpKeys CreateMasterKeys(int protectionProfile, byte[] mki, byte[] sharedSecret)
+ {
+ var srtpSecurityParams = DtlsProtectionProfiles[protectionProfile];
+
+ if (sharedSecret == null)
{
- // verify that we have extended master secret before computing the keys
- if (!dtlsSecurityParameters.IsExtendedMasterSecret && requireExtendedMasterSecret)
- {
- throw new InvalidOperationException();
- }
-
- // SRTP key derivation as described here https://datatracker.ietf.org/doc/html/rfc5764
- var srtpSecurityParams = DtlsProtectionProfiles[protectionProfile];
-
- // 2 * (SRTPSecurityParams.master_key_len + SRTPSecurityParams.master_salt_len) bytes of data
- int sharedSecretLength = (2 * (srtpSecurityParams.CipherKeyLength + srtpSecurityParams.CipherSaltLength)) >> 3;
-
- // EXTRACTOR-dtls_srtp https://datatracker.ietf.org/doc/html/rfc5705
-
- // TODO: If context is provided, it computes:
- /*
- PRF(SecurityParameters.master_secret, label,
- SecurityParameters.client_random +
- SecurityParameters.server_random +
- context_value_length + context_value
- )[length]
- */
-
- // derive shared secret
- /*
- PRF(SecurityParameters.master_secret, label,
- SecurityParameters.client_random +
- SecurityParameters.server_random
- )[length]
- */
- byte[] prfSeed = GC.AllocateUninitializedArray(dtlsSecurityParameters.ClientRandom.Length + dtlsSecurityParameters.ServerRandom.Length);
- Buffer.BlockCopy(dtlsSecurityParameters.ClientRandom, 0, prfSeed, 0, dtlsSecurityParameters.ClientRandom.Length);
- Buffer.BlockCopy(dtlsSecurityParameters.ServerRandom, 0, prfSeed, dtlsSecurityParameters.ClientRandom.Length, dtlsSecurityParameters.ServerRandom.Length);
- byte[] sharedSecret = TlsUtilities.Prf(
- dtlsSecurityParameters,
- dtlsSecurityParameters.MasterSecret,
- ExporterLabel.dtls_srtp, // The exporter label for this usage is "EXTRACTOR-dtls_srtp"
- prfSeed,
- sharedSecretLength
- ).Extract();
-
- return CreateMasterKeys(protectionProfile, mki, sharedSecret);
+ throw new ArgumentNullException(nameof(sharedSecret));
}
- public static DtlsSrtpKeys CreateMasterKeys(int protectionProfile, byte[] mki, byte[] sharedSecret)
+ int sharedSecretLength = (2 * (srtpSecurityParams.CipherKeyLength + srtpSecurityParams.CipherSaltLength)) >> 3;
+ if (sharedSecret.Length < sharedSecretLength)
{
- var srtpSecurityParams = DtlsProtectionProfiles[protectionProfile];
-
- if (sharedSecret == null)
- {
- throw new ArgumentNullException(nameof(sharedSecret));
- }
-
- int sharedSecretLength = (2 * (srtpSecurityParams.CipherKeyLength + srtpSecurityParams.CipherSaltLength)) >> 3;
- if (sharedSecret.Length < sharedSecretLength)
- {
- throw new ArgumentException("Invalid shared secret length.", nameof(sharedSecret));
- }
-
- var cipherKeyLen = srtpSecurityParams.CipherKeyLength >> 3;
- var cipherSaltLen = srtpSecurityParams.CipherSaltLength >> 3;
-
-
- ReadOnlyMemory clientWriteMasterKey, clientWriteMasterSalt, serverWriteMasterKey, serverWriteMasterSalt;
-
- if (srtpSecurityParams.Cipher >= SrtpCiphers.DOUBLE_AEAD_AES_128_GCM_AEAD_AES_128_GCM)
- {
- // we have to maintain separation of the inner and outer keys according to RFC8723
- // |
- int halfKeyLen = cipherKeyLen / 2;
- int halfSaltLen = cipherSaltLen / 2;
- int halfSecret = sharedSecretLength / 2;
-
- // ClientWriteMasterKey: inner + outer
- var clientKey = new byte[cipherKeyLen];
- Buffer.BlockCopy(sharedSecret, 0, clientKey, 0, halfKeyLen);
- Buffer.BlockCopy(sharedSecret, halfSecret, clientKey, halfKeyLen, halfKeyLen);
- clientWriteMasterKey = clientKey.AsMemory();
-
- // ServerWriteMasterKey: inner + outer
- var serverKey = new byte[cipherKeyLen];
- Buffer.BlockCopy(sharedSecret, halfKeyLen, serverKey, 0, halfKeyLen);
- Buffer.BlockCopy(sharedSecret, halfSecret + halfKeyLen, serverKey, halfKeyLen, halfKeyLen);
- serverWriteMasterKey = serverKey.AsMemory();
-
- // ClientWriteMasterSalt: inner + outer
- var clientSalt = new byte[cipherSaltLen];
- Buffer.BlockCopy(sharedSecret, 2 * halfKeyLen, clientSalt, 0, halfSaltLen);
- Buffer.BlockCopy(sharedSecret, halfSecret + 2 * halfKeyLen, clientSalt, halfSaltLen, halfSaltLen);
- clientWriteMasterSalt = clientSalt.AsMemory();
-
- // ServerWriteMasterSalt: inner + outer
- var serverSalt = new byte[cipherSaltLen];
- Buffer.BlockCopy(sharedSecret, 2 * halfKeyLen + halfSaltLen, serverSalt, 0, halfSaltLen);
- Buffer.BlockCopy(sharedSecret, halfSecret + 2 * halfKeyLen + halfSaltLen, serverSalt, halfSaltLen, halfSaltLen);
- serverWriteMasterSalt = serverSalt.AsMemory();
- }
- else
- {
- //
- int offset = 0;
- clientWriteMasterKey = sharedSecret.AsMemory(offset, cipherKeyLen);
- offset += cipherKeyLen;
- serverWriteMasterKey = sharedSecret.AsMemory(offset, cipherKeyLen);
- offset += cipherKeyLen;
- clientWriteMasterSalt = sharedSecret.AsMemory(offset, cipherSaltLen);
- offset += cipherSaltLen;
- serverWriteMasterSalt = sharedSecret.AsMemory(offset, cipherSaltLen);
- }
-
- var k = new DtlsSrtpKeys(
- srtpSecurityParams,
- clientWriteMasterKey,
- clientWriteMasterSalt,
- serverWriteMasterKey,
- serverWriteMasterSalt,
- mki == null ? default : mki.AsMemory());
- return k;
+ throw new ArgumentException("Invalid shared secret length.", nameof(sharedSecret));
}
- public static byte[] GenerateMki(int length)
+ var cipherKeyLen = srtpSecurityParams.CipherKeyLength >> 3;
+ var cipherSaltLen = srtpSecurityParams.CipherSaltLength >> 3;
+
+
+ ReadOnlyMemory clientWriteMasterKey, clientWriteMasterSalt, serverWriteMasterKey, serverWriteMasterSalt;
+
+ if (srtpSecurityParams.Cipher >= SrtpCiphers.DOUBLE_AEAD_AES_128_GCM_AEAD_AES_128_GCM)
{
- return SrtpProtocol.GenerateMki(length);
+ // we have to maintain separation of the inner and outer keys according to RFC8723
+ // |
+ int halfKeyLen = cipherKeyLen / 2;
+ int halfSaltLen = cipherSaltLen / 2;
+ int halfSecret = sharedSecretLength / 2;
+
+ // ClientWriteMasterKey: inner + outer
+ var clientKey = new byte[cipherKeyLen];
+ Buffer.BlockCopy(sharedSecret, 0, clientKey, 0, halfKeyLen);
+ Buffer.BlockCopy(sharedSecret, halfSecret, clientKey, halfKeyLen, halfKeyLen);
+ clientWriteMasterKey = clientKey.AsMemory();
+
+ // ServerWriteMasterKey: inner + outer
+ var serverKey = new byte[cipherKeyLen];
+ Buffer.BlockCopy(sharedSecret, halfKeyLen, serverKey, 0, halfKeyLen);
+ Buffer.BlockCopy(sharedSecret, halfSecret + halfKeyLen, serverKey, halfKeyLen, halfKeyLen);
+ serverWriteMasterKey = serverKey.AsMemory();
+
+ // ClientWriteMasterSalt: inner + outer
+ var clientSalt = new byte[cipherSaltLen];
+ Buffer.BlockCopy(sharedSecret, 2 * halfKeyLen, clientSalt, 0, halfSaltLen);
+ Buffer.BlockCopy(sharedSecret, halfSecret + 2 * halfKeyLen, clientSalt, halfSaltLen, halfSaltLen);
+ clientWriteMasterSalt = clientSalt.AsMemory();
+
+ // ServerWriteMasterSalt: inner + outer
+ var serverSalt = new byte[cipherSaltLen];
+ Buffer.BlockCopy(sharedSecret, 2 * halfKeyLen + halfSaltLen, serverSalt, 0, halfSaltLen);
+ Buffer.BlockCopy(sharedSecret, halfSecret + 2 * halfKeyLen + halfSaltLen, serverSalt, halfSaltLen, halfSaltLen);
+ serverWriteMasterSalt = serverSalt.AsMemory();
}
-
- public static SrtpSessionContext CreateSrtpServerSessionContext(DtlsSrtpKeys keys)
+ else
{
- var encodeRtpContext = new SrtpContext(SrtpContextType.RTP, keys.ProtectionProfile, keys.ServerWriteMasterKey, keys.ServerWriteMasterSalt, keys.Mki);
- var encodeRtcpContext = new SrtpContext(SrtpContextType.RTCP, keys.ProtectionProfile, keys.ServerWriteMasterKey, keys.ServerWriteMasterSalt, keys.Mki);
- var decodeRtpContext = new SrtpContext(SrtpContextType.RTP, keys.ProtectionProfile, keys.ClientWriteMasterKey, keys.ClientWriteMasterSalt, keys.Mki);
- var decodeRtcpContext = new SrtpContext(SrtpContextType.RTCP, keys.ProtectionProfile, keys.ClientWriteMasterKey, keys.ClientWriteMasterSalt, keys.Mki);
-
- return new SrtpSessionContext(encodeRtpContext, decodeRtpContext, encodeRtcpContext, decodeRtcpContext);
+ //
+ int offset = 0;
+ clientWriteMasterKey = sharedSecret.AsMemory(offset, cipherKeyLen);
+ offset += cipherKeyLen;
+ serverWriteMasterKey = sharedSecret.AsMemory(offset, cipherKeyLen);
+ offset += cipherKeyLen;
+ clientWriteMasterSalt = sharedSecret.AsMemory(offset, cipherSaltLen);
+ offset += cipherSaltLen;
+ serverWriteMasterSalt = sharedSecret.AsMemory(offset, cipherSaltLen);
}
- public static SrtpSessionContext CreateSrtpClientSessionContext(DtlsSrtpKeys keys)
- {
- var encodeRtpContext = new SrtpContext(SrtpContextType.RTP, keys.ProtectionProfile, keys.ClientWriteMasterKey, keys.ClientWriteMasterSalt, keys.Mki);
- var encodeRtcpContext = new SrtpContext(SrtpContextType.RTCP, keys.ProtectionProfile, keys.ClientWriteMasterKey, keys.ClientWriteMasterSalt, keys.Mki);
- var decodeRtpContext = new SrtpContext(SrtpContextType.RTP, keys.ProtectionProfile, keys.ServerWriteMasterKey, keys.ServerWriteMasterSalt, keys.Mki);
- var decodeRtcpContext = new SrtpContext(SrtpContextType.RTCP, keys.ProtectionProfile, keys.ServerWriteMasterKey, keys.ServerWriteMasterSalt, keys.Mki);
+ var k = new DtlsSrtpKeys(
+ srtpSecurityParams,
+ clientWriteMasterKey,
+ clientWriteMasterSalt,
+ serverWriteMasterKey,
+ serverWriteMasterSalt,
+ mki == null ? default : mki.AsMemory());
+ return k;
+ }
- return new SrtpSessionContext(encodeRtpContext, decodeRtpContext, encodeRtcpContext, decodeRtcpContext);
- }
+ public static byte[] GenerateMki(int length)
+ {
+ return SrtpProtocol.GenerateMki(length);
+ }
+
+ public static SrtpSessionContext CreateSrtpServerSessionContext(DtlsSrtpKeys keys)
+ {
+ var encodeRtpContext = new SrtpContext(SrtpContextType.RTP, keys.ProtectionProfile, keys.ServerWriteMasterKey, keys.ServerWriteMasterSalt, keys.Mki);
+ var encodeRtcpContext = new SrtpContext(SrtpContextType.RTCP, keys.ProtectionProfile, keys.ServerWriteMasterKey, keys.ServerWriteMasterSalt, keys.Mki);
+ var decodeRtpContext = new SrtpContext(SrtpContextType.RTP, keys.ProtectionProfile, keys.ClientWriteMasterKey, keys.ClientWriteMasterSalt, keys.Mki);
+ var decodeRtcpContext = new SrtpContext(SrtpContextType.RTCP, keys.ProtectionProfile, keys.ClientWriteMasterKey, keys.ClientWriteMasterSalt, keys.Mki);
+
+ return new SrtpSessionContext(encodeRtpContext, decodeRtpContext, encodeRtcpContext, decodeRtcpContext);
+ }
+
+ public static SrtpSessionContext CreateSrtpClientSessionContext(DtlsSrtpKeys keys)
+ {
+ var encodeRtpContext = new SrtpContext(SrtpContextType.RTP, keys.ProtectionProfile, keys.ClientWriteMasterKey, keys.ClientWriteMasterSalt, keys.Mki);
+ var encodeRtcpContext = new SrtpContext(SrtpContextType.RTCP, keys.ProtectionProfile, keys.ClientWriteMasterKey, keys.ClientWriteMasterSalt, keys.Mki);
+ var decodeRtpContext = new SrtpContext(SrtpContextType.RTP, keys.ProtectionProfile, keys.ServerWriteMasterKey, keys.ServerWriteMasterSalt, keys.Mki);
+ var decodeRtcpContext = new SrtpContext(SrtpContextType.RTCP, keys.ProtectionProfile, keys.ServerWriteMasterKey, keys.ServerWriteMasterSalt, keys.Mki);
+
+ return new SrtpSessionContext(encodeRtpContext, decodeRtpContext, encodeRtcpContext, decodeRtcpContext);
}
}
diff --git a/src/SIPSorcery/net/DtlsSrtp/Lib/DTLSSRTP/DtlsSrtpServer.cs b/src/SIPSorcery/net/DtlsSrtp/Lib/DTLSSRTP/DtlsSrtpServer.cs
index f3ea4bf98..090951342 100644
--- a/src/SIPSorcery/net/DtlsSrtp/Lib/DTLSSRTP/DtlsSrtpServer.cs
+++ b/src/SIPSorcery/net/DtlsSrtp/Lib/DTLSSRTP/DtlsSrtpServer.cs
@@ -27,116 +27,136 @@
using SIPSorcery.Net.SharpSRTP.SRTP;
using System;
using System.Collections.Generic;
+using System.Diagnostics;
-namespace SIPSorcery.Net.SharpSRTP.DTLSSRTP
+namespace SIPSorcery.Net.SharpSRTP.DTLSSRTP;
+
+// Useful link for troubleshooting WebRTC in Chrome/Edge: https://learn.microsoft.com/en-us/azure/communication-services/resources/troubleshooting/voice-video-calling/references/how-to-collect-browser-verbose-log
+public class DtlsSrtpServer : DtlsServer, IDtlsSrtpPeer
{
- // Useful link for troubleshooting WebRTC in Chrome/Edge: https://learn.microsoft.com/en-us/azure/communication-services/resources/troubleshooting/voice-video-calling/references/how-to-collect-browser-verbose-log
- public class DtlsSrtpServer : DtlsServer, IDtlsSrtpPeer
+ ///
+ /// Used in WebRTC to tell the server to not use MKI even if the client requested it.
+ ///
+ ///
+ /// RFC 8827 states: An SRTP Master Key Identifier (MKI) MUST NOT be used.
+ ///
+ public bool ForceDisableMKI { get; set; } = false;
+
+ private UseSrtpData? _srtpData;
+
+ public event EventHandler? OnSessionStarted;
+
+ public DtlsSrtpServer(
+ Certificate? certificate = null,
+ AsymmetricKeyParameter? privateKey = null,
+ short certificateSignatureAlgorithm = SignatureAlgorithm.ecdsa,
+ short certificateHashAlgorithm = HashAlgorithm.sha256)
+ : this(
+ new BcTlsCrypto(),
+ certificate,
+ privateKey,
+ certificateSignatureAlgorithm,
+ certificateHashAlgorithm)
+ { }
+
+ public DtlsSrtpServer(
+ TlsCrypto crypto,
+ Certificate? certificate = null,
+ AsymmetricKeyParameter? privateKey = null,
+ short certificateSignatureAlgorithm = SignatureAlgorithm.ecdsa,
+ short certificateHashAlgorithm = HashAlgorithm.sha256)
+ : base(
+ crypto,
+ certificate,
+ privateKey,
+ certificateSignatureAlgorithm,
+ certificateHashAlgorithm)
{
- ///
- /// Used in WebRTC to tell the server to not use MKI even if the client requested it.
- ///
- ///
- /// RFC 8827 states: An SRTP Master Key Identifier (MKI) MUST NOT be used.
- ///
- public bool ForceDisableMKI { get; set; } = false;
-
- private UseSrtpData _srtpData;
-
- public event EventHandler OnSessionStarted;
+ this.OnHandshakeCompleted += DtlsSrtpServer_OnHandshakeCompleted;
+ }
- public DtlsSrtpServer(Certificate certificate = null, AsymmetricKeyParameter privateKey = null, short certificateSignatureAlgorithm = SignatureAlgorithm.ecdsa, short certificateHashAlgorithm = HashAlgorithm.sha256)
- : this(new BcTlsCrypto(), certificate, privateKey, certificateSignatureAlgorithm, certificateHashAlgorithm)
- { }
+ private void DtlsSrtpServer_OnHandshakeCompleted(object? sender, DtlsHandshakeCompletedEventArgs e)
+ {
+ SrtpSessionContext context = CreateSessionContext(e.SecurityParameters);
+ Certificate peerCertificate = e.SecurityParameters.PeerCertificate;
+ OnSessionStarted?.Invoke(this, new DtlsSessionStartedEventArgs(context, peerCertificate, base._clientDatagramTransport));
+ }
- public DtlsSrtpServer(TlsCrypto crypto, Certificate certificate = null, AsymmetricKeyParameter privateKey = null, short certificateSignatureAlgorithm = SignatureAlgorithm.ecdsa, short certificateHashAlgorithm = HashAlgorithm.sha256)
- : base(crypto, certificate, privateKey, certificateSignatureAlgorithm, certificateHashAlgorithm)
+ protected virtual int[] GetSupportedProtectionProfiles()
+ {
+ return new int[]
{
- this.OnHandshakeCompleted += DtlsSrtpServer_OnHandshakeCompleted;
- }
+ ExtendedSrtpProtectionProfile.DOUBLE_AEAD_AES_256_GCM_AEAD_AES_256_GCM,
+ ExtendedSrtpProtectionProfile.DOUBLE_AEAD_AES_128_GCM_AEAD_AES_128_GCM,
+ ExtendedSrtpProtectionProfile.SRTP_AEAD_AES_256_GCM,
+ ExtendedSrtpProtectionProfile.SRTP_AEAD_ARIA_256_GCM,
+ ExtendedSrtpProtectionProfile.SRTP_AEAD_AES_128_GCM,
+ ExtendedSrtpProtectionProfile.SRTP_AEAD_ARIA_128_GCM,
+ ExtendedSrtpProtectionProfile.SRTP_ARIA_256_CTR_HMAC_SHA1_80,
+ ExtendedSrtpProtectionProfile.SRTP_AES128_CM_HMAC_SHA1_80,
+ ExtendedSrtpProtectionProfile.SRTP_ARIA_128_CTR_HMAC_SHA1_80,
+ ExtendedSrtpProtectionProfile.SRTP_ARIA_256_CTR_HMAC_SHA1_32,
+ ExtendedSrtpProtectionProfile.SRTP_AES128_CM_HMAC_SHA1_32,
+ ExtendedSrtpProtectionProfile.SRTP_ARIA_128_CTR_HMAC_SHA1_32,
+
+ // do not offer NULL profiles to make sure these do not get selected by accident
+ //ExtendedSrtpProtectionProfile.SRTP_NULL_HMAC_SHA1_80,
+ //ExtendedSrtpProtectionProfile.SRTP_NULL_HMAC_SHA1_32,
+ };
+ }
- private void DtlsSrtpServer_OnHandshakeCompleted(object sender, DtlsHandshakeCompletedEventArgs e)
- {
- SrtpSessionContext context = CreateSessionContext(e.SecurityParameters);
- Certificate peerCertificate = e.SecurityParameters.PeerCertificate;
- OnSessionStarted?.Invoke(this, new DtlsSessionStartedEventArgs(context, peerCertificate, base._clientDatagramTransport));
- }
+ protected override string GetCertificateCommonName()
+ {
+ return "WebRTC";
+ }
- protected virtual int[] GetSupportedProtectionProfiles()
- {
- return new int[]
- {
- ExtendedSrtpProtectionProfile.DOUBLE_AEAD_AES_256_GCM_AEAD_AES_256_GCM,
- ExtendedSrtpProtectionProfile.DOUBLE_AEAD_AES_128_GCM_AEAD_AES_128_GCM,
- ExtendedSrtpProtectionProfile.SRTP_AEAD_AES_256_GCM,
- ExtendedSrtpProtectionProfile.SRTP_AEAD_ARIA_256_GCM,
- ExtendedSrtpProtectionProfile.SRTP_AEAD_AES_128_GCM,
- ExtendedSrtpProtectionProfile.SRTP_AEAD_ARIA_128_GCM,
- ExtendedSrtpProtectionProfile.SRTP_ARIA_256_CTR_HMAC_SHA1_80,
- ExtendedSrtpProtectionProfile.SRTP_AES128_CM_HMAC_SHA1_80,
- ExtendedSrtpProtectionProfile.SRTP_ARIA_128_CTR_HMAC_SHA1_80,
- ExtendedSrtpProtectionProfile.SRTP_ARIA_256_CTR_HMAC_SHA1_32,
- ExtendedSrtpProtectionProfile.SRTP_AES128_CM_HMAC_SHA1_32,
- ExtendedSrtpProtectionProfile.SRTP_ARIA_128_CTR_HMAC_SHA1_32,
-
- // do not offer NULL profiles to make sure these do not get selected by accident
- //ExtendedSrtpProtectionProfile.SRTP_NULL_HMAC_SHA1_80,
- //ExtendedSrtpProtectionProfile.SRTP_NULL_HMAC_SHA1_32,
- };
- }
+ public override void ProcessClientExtensions(IDictionary clientExtensions)
+ {
+ base.ProcessClientExtensions(clientExtensions);
- protected override string GetCertificateCommonName()
- {
- return "WebRTC";
- }
+ UseSrtpData clientSrtpExtension = TlsSrtpUtilities.GetUseSrtpExtension(clientExtensions);
- public override void ProcessClientExtensions(IDictionary clientExtensions)
+ // Choose the highest priority profile supported by the server
+ int[] serverSupportedProfiles = GetSupportedProtectionProfiles();
+ bool found = false;
+ int selectedProfile = int.MinValue;
+ int minIndex = int.MaxValue;
+ for (int i = 0; i < clientSrtpExtension.ProtectionProfiles.Length; i++)
{
- base.ProcessClientExtensions(clientExtensions);
-
- UseSrtpData clientSrtpExtension = TlsSrtpUtilities.GetUseSrtpExtension(clientExtensions);
-
- // Choose the highest priority profile supported by the server
- int[] serverSupportedProfiles = GetSupportedProtectionProfiles();
- bool found = false;
- int selectedProfile = int.MinValue;
- int minIndex = int.MaxValue;
- for (int i = 0; i < clientSrtpExtension.ProtectionProfiles.Length; i++)
+ int val = clientSrtpExtension.ProtectionProfiles[i];
+ int idx = Array.IndexOf(serverSupportedProfiles, val);
+ if (idx >= 0 && idx < minIndex)
{
- int val = clientSrtpExtension.ProtectionProfiles[i];
- int idx = Array.IndexOf(serverSupportedProfiles, val);
- if (idx >= 0 && idx < minIndex)
- {
- minIndex = idx;
- selectedProfile = val;
- found = true;
- }
+ minIndex = idx;
+ selectedProfile = val;
+ found = true;
}
- if (!found)
- {
- throw new TlsFatalAlert(AlertDescription.internal_error);
- }
- _srtpData = new UseSrtpData(new int[] { selectedProfile }, ForceDisableMKI ? Array.Empty() : clientSrtpExtension.Mki); // Server must return only a single selected profile
}
-
- public override IDictionary GetServerExtensions()
+ if (!found)
{
- var extensions = base.GetServerExtensions();
- TlsSrtpUtilities.AddUseSrtpExtension(extensions, _srtpData);
- return extensions;
+ throw new TlsFatalAlert(AlertDescription.internal_error);
}
+ _srtpData = new UseSrtpData(new int[] { selectedProfile }, ForceDisableMKI ? Array.Empty() : clientSrtpExtension.Mki); // Server must return only a single selected profile
+ }
- public virtual SrtpSessionContext CreateSessionContext(SecurityParameters securityParameters)
- {
- // this should only be called from OnHandshakeCompleted so we should still have _srtpData from the connection
- if (m_context == null)
- {
- throw new InvalidOperationException();
- }
+ public override IDictionary GetServerExtensions()
+ {
+ var extensions = base.GetServerExtensions();
+ TlsSrtpUtilities.AddUseSrtpExtension(extensions, _srtpData);
+ return extensions;
+ }
- int selectedProtectionProfile = _srtpData.ProtectionProfiles[0];
- DtlsSrtpKeys keys = DtlsSrtpProtocol.CreateMasterKeys(_srtpData.ProtectionProfiles[0], _srtpData.Mki, securityParameters, ForceUseExtendedMasterSecret);
- return DtlsSrtpProtocol.CreateSrtpServerSessionContext(keys);
+ public virtual SrtpSessionContext CreateSessionContext(SecurityParameters securityParameters)
+ {
+ // this should only be called from OnHandshakeCompleted so we should still have _srtpData from the connection
+ if (m_context == null)
+ {
+ throw new InvalidOperationException();
}
+
+ Debug.Assert(_srtpData is not null);
+ int selectedProtectionProfile = _srtpData.ProtectionProfiles[0];
+ DtlsSrtpKeys keys = DtlsSrtpProtocol.CreateMasterKeys(_srtpData.ProtectionProfiles[0], _srtpData.Mki, securityParameters, ForceUseExtendedMasterSecret);
+ return DtlsSrtpProtocol.CreateSrtpServerSessionContext(keys);
}
}
diff --git a/src/SIPSorcery/net/DtlsSrtp/Lib/DTLSSRTP/IDtlsSrtpPeer.cs b/src/SIPSorcery/net/DtlsSrtp/Lib/DTLSSRTP/IDtlsSrtpPeer.cs
index b5cab6526..fd9b725ee 100644
--- a/src/SIPSorcery/net/DtlsSrtp/Lib/DTLSSRTP/IDtlsSrtpPeer.cs
+++ b/src/SIPSorcery/net/DtlsSrtp/Lib/DTLSSRTP/IDtlsSrtpPeer.cs
@@ -24,25 +24,24 @@
using SIPSorcery.Net.SharpSRTP.SRTP;
using System;
-namespace SIPSorcery.Net.SharpSRTP.DTLSSRTP
-{
- public class DtlsSessionStartedEventArgs : EventArgs
- {
- public SrtpSessionContext Context { get; private set; }
- public Certificate PeerCertificate { get; private set; }
- public DatagramTransport ClientDatagramTransport { get; private set; }
+namespace SIPSorcery.Net.SharpSRTP.DTLSSRTP;
- public DtlsSessionStartedEventArgs(SrtpSessionContext context, Certificate peerCertificate, DatagramTransport clientDatagramTransport)
- {
- this.Context = context ?? throw new ArgumentNullException(nameof(context));
- this.PeerCertificate = peerCertificate ?? throw new ArgumentNullException(nameof(peerCertificate));
- this.ClientDatagramTransport = clientDatagramTransport ?? throw new ArgumentNullException(nameof(clientDatagramTransport));
- }
- }
+public class DtlsSessionStartedEventArgs : EventArgs
+{
+ public SrtpSessionContext Context { get; private set; }
+ public Certificate PeerCertificate { get; private set; }
+ public DatagramTransport? ClientDatagramTransport { get; private set; }
- public interface IDtlsSrtpPeer : IDtlsPeer
+ public DtlsSessionStartedEventArgs(SrtpSessionContext context, Certificate peerCertificate, DatagramTransport? clientDatagramTransport)
{
- event EventHandler OnSessionStarted;
- SrtpSessionContext CreateSessionContext(SecurityParameters securityParameters);
+ this.Context = context ?? throw new ArgumentNullException(nameof(context));
+ this.PeerCertificate = peerCertificate ?? throw new ArgumentNullException(nameof(peerCertificate));
+ this.ClientDatagramTransport = clientDatagramTransport ?? throw new ArgumentNullException(nameof(clientDatagramTransport));
}
}
+
+public interface IDtlsSrtpPeer : IDtlsPeer
+{
+ event EventHandler? OnSessionStarted;
+ SrtpSessionContext CreateSessionContext(SecurityParameters securityParameters);
+}
diff --git a/src/SIPSorcery/net/DtlsSrtp/Lib/SRTP/Encryption/AEAD.cs b/src/SIPSorcery/net/DtlsSrtp/Lib/SRTP/Encryption/AEAD.cs
index efad8bbd9..6214cdc3b 100644
--- a/src/SIPSorcery/net/DtlsSrtp/Lib/SRTP/Encryption/AEAD.cs
+++ b/src/SIPSorcery/net/DtlsSrtp/Lib/SRTP/Encryption/AEAD.cs
@@ -23,6 +23,8 @@
using Org.BouncyCastle.Crypto.Parameters;
using System;
using System.Buffers.Binary;
+using SIPSorcery.Sys;
+
#if NET8_0_OR_GREATER
using ReadOnlyBytes = System.ReadOnlySpan;
using Bytes = System.Span;
diff --git a/src/SIPSorcery/net/DtlsSrtp/Lib/SRTP/Encryption/CTR.cs b/src/SIPSorcery/net/DtlsSrtp/Lib/SRTP/Encryption/CTR.cs
index d49baadb7..d760eeb39 100644
--- a/src/SIPSorcery/net/DtlsSrtp/Lib/SRTP/Encryption/CTR.cs
+++ b/src/SIPSorcery/net/DtlsSrtp/Lib/SRTP/Encryption/CTR.cs
@@ -20,6 +20,7 @@
// SOFTWARE.
using Org.BouncyCastle.Crypto;
+using SIPSorcery.Sys;
using System;
using System.Buffers;
using System.Buffers.Binary;
diff --git a/src/SIPSorcery/net/DtlsSrtp/Lib/SRTP/Encryption/F8.cs b/src/SIPSorcery/net/DtlsSrtp/Lib/SRTP/Encryption/F8.cs
index 2e48968c9..ccca8baca 100644
--- a/src/SIPSorcery/net/DtlsSrtp/Lib/SRTP/Encryption/F8.cs
+++ b/src/SIPSorcery/net/DtlsSrtp/Lib/SRTP/Encryption/F8.cs
@@ -21,6 +21,7 @@
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
+using SIPSorcery.Sys;
using System;
using System.Buffers;
using System.Buffers.Binary;
@@ -71,7 +72,7 @@ public static byte[] GenerateRtcpMessageKeyIV(IBlockCipher engine, byte[] k_e, b
#endif
GenerateRtcpIV(iv, rtcpPacket, index);
- byte[] iv2 = new byte[BLOCK_SIZE];
+ var iv2 = new byte[BLOCK_SIZE];
GenerateIV2(engine, k_e, k_s, iv, iv2);
@@ -108,14 +109,14 @@ private static void GenerateIV2(IBlockCipher engine, byte[] k_e, byte[] k_s, Rea
public static void Encrypt(IBlockCipher aes, ReadOnlySpan input, Span