/* * Copyright (C) 2010 mbelib Author * GPG Key ID: 0xEA5EFE2C (9E7A 5527 9CDC EBF7 BF1B D772 4F98 E863 EA5E FE2C) * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include #include #include #include "mbelib.h" #include "ambe3600x2400_const.h" void mbe_dumpAmbe2400Data (char *ambe_d) { int i; char *ambe; ambe = ambe_d; for (i = 0; i < 49; i++) { printf ("%i", *ambe); ambe++; } printf (" "); } void mbe_dumpAmbe3600x2400Frame (char ambe_fr[4][24]) { int j; // c0 printf ("ambe_fr c0: "); for (j = 23; j >= 0; j--) { printf ("%i", ambe_fr[0][j]); } printf (" "); // c1 printf ("ambe_fr c1: "); for (j = 22; j >= 0; j--) { printf ("%i", ambe_fr[1][j]); } printf (" "); // c2 printf ("ambe_fr c2: "); for (j = 10; j >= 0; j--) { printf ("%i", ambe_fr[2][j]); } printf (" "); // c3 printf ("ambe_fr c3: "); for (j = 13; j >= 0; j--) { printf ("%i", ambe_fr[3][j]); } printf (" "); } int mbe_eccAmbe3600x2400C0 (char ambe_fr[4][24]) { int j, errs; char in[23], out[23]; for (j = 0; j < 23; j++) { in[j] = ambe_fr[0][j + 1]; } errs = mbe_golay2312 (in, out); // ambe_fr[0][0] should be the C0 golay24 parity bit. // TODO: actually test that here... for (j = 0; j < 23; j++) { ambe_fr[0][j + 1] = out[j]; } return (errs); } int mbe_eccAmbe3600x2400Data (char ambe_fr[4][24], char *ambe_d) { int j, errs; char *ambe, gin[24], gout[24]; ambe = ambe_d; // just copy C0 for (j = 23; j > 11; j--) { *ambe = ambe_fr[0][j]; ambe++; } // ecc and copy C1 for (j = 0; j < 23; j++) { gin[j] = ambe_fr[1][j]; } errs = mbe_golay2312 (gin, gout); for (j = 22; j > 10; j--) { *ambe = gout[j]; ambe++; } // just copy C2 for (j = 10; j >= 0; j--) { *ambe = ambe_fr[2][j]; ambe++; } // just copy C3 for (j = 13; j >= 0; j--) { *ambe = ambe_fr[3][j]; ambe++; } return (errs); } int mbe_decodeAmbe2400Parms (char *ambe_d, mbe_parms * cur_mp, mbe_parms * prev_mp) { int ji, i, j, k, l, L, m, am, ak; int intkl[57]; int b0, b1, b2, b3, b4, b5, b6, b7, b8; float f0, Cik[5][18], flokl[57], deltal[57]; float Sum42, Sum43, Tl[57], Gm[9], Ri[9], sum, c1, c2; int silence; int Ji[5], jl; float deltaGamma, BigGamma; float unvc, rconst; silence = 0; #ifdef AMBE_DEBUG printf ("\n"); #endif // copy repeat from prev_mp cur_mp->repeat = prev_mp->repeat; // check if frame is tone or other; this matches section 7.2 on the P25 Half rate vocoder annex doc b0 = 0; b0 |= ambe_d[0]<<6; b0 |= ambe_d[1]<<5; b0 |= ambe_d[2]<<4; b0 |= ambe_d[3]<<3; b0 |= ambe_d[4]<<2; b0 |= ambe_d[5]<<1; b0 |= ambe_d[48]; if ((b0&0x7E) == 0x7E) // frame is tone { // find tone index // Cx# 0000000000001111111111112222222222233333333333333 // // IDX 0000000000111111111122222222223333333333444444444 // idx 0123456789012345678901234567890123456789012345678 // exm 1111110101001110100000001000000000000000001100000 : t=0111100 // ex2 1111110110101110100000000000000000000000000000000 : t=1100010 // ex3 1111110010101110110000001000000000000000000110000 : t=0000110 // tt1 1111110010011110100000001000000000000000000101000 : t=0000101 // tt3 1111110010011110000000001000000000000000000101000 // ton HHHHHHDEF410======......P.................32==... // vol 765430 21 //DEF indexes the following tables for tone bits 5-7 int t7tab[8] = {1,0,0,0,0,1,1,1}; int t6tab[8] = {0,0,0,1,1,1,1,0}; int t5tab[8] = {0,0,1,0,1,1,0,1}; // V V V V V G G G V = verified, G = guessed (and unused by all normal tone indices) b1 = 0; b1 |= t7tab[((ambe_d[6]<<2)|(ambe_d[7]<<1)|ambe_d[8])]<<7; //t7 128 b1 |= t6tab[((ambe_d[6]<<2)|(ambe_d[7]<<1)|ambe_d[8])]<<6; //t6 64 b1 |= t5tab[((ambe_d[6]<<2)|(ambe_d[7]<<1)|ambe_d[8])]<<5; //t5 32 b1 |= ambe_d[9]<<4; //t4 16 e verified b1 |= ambe_d[42]<<3; //t3 8 d verified b1 |= ambe_d[43]<<2; //t2 4 c verified b1 |= ambe_d[10]<<1; //t1 2 b verified b1 |= ambe_d[11]; //t0 1 a verified b2 = 0; b2 |= ambe_d[12]<<7; //v7 128 h verified b2 |= ambe_d[13]<<6; //v6 64 g verified b2 |= ambe_d[14]<<5; //v5 32 f verified b2 |= ambe_d[15]<<4; //v4 16 e guess based on data b2 |= ambe_d[16]<<3; //v3 8 d guess based on data b2 |= ambe_d[44]<<2; //v2 4 c guess based on data b2 |= ambe_d[45]<<1; //v1 2 b guess based on data b2 |= ambe_d[17]; //v0 1 a guess based on data // the order of the last 3 bits may really be 17,44,45 not 44,45,17 as above fprintf(stderr,"Tone volume: %d; ", b2); if (b1 < 5) { fprintf(stderr, "index: %d, was <5, invalid!\n", b1); silence = 1; } else if ((b1 >= 5) && (b1 <= 122)) { fprintf(stderr, "index: %d, Single tone hz: %f\n", b1, (float)b1*31.25); } else if ((b1 > 122) && (b1 < 128)) { fprintf(stderr, "index: %d, was >122 and <128, invalid!\n", b1); silence = 1; } else if ((b1 >= 128) && (b1 <= 163)) { fprintf(stderr, "index: %d, Dual tone\n", b1); // note: dual tone index is different on ambe(dstar) and ambe2+ } else { fprintf(stderr, "index: %d, was >163, invalid!\n", b1); silence = 1; } if(silence == 1) { #ifdef AMBE_DEBUG printf ("Silence Frame\n"); #endif cur_mp->w0 = ((float) 2 * M_PI) / (float) 32; f0 = (float) 1 / (float) 32; L = 14; cur_mp->L = 14; for (l = 1; l <= L; l++) { cur_mp->Vl[l] = 0; } } #ifdef AMBE_DEBUG printf ("Tone Frame\n"); #endif return (3); } //fprintf(stderr,"Voice Frame, Pitch = %f\n", powf(2, ((float)b0+195.626)/-46.368)*8000); // was 45.368 //fprintf(stderr,"Voice Frame, rawPitch = %02d, Pitch = %f\n", b0, powf(2, ((-1*(float)(17661/((int)1<<12))) - (2.1336e-2 * ((float)b0+0.5))))*8000); //fprintf(stderr,"Voice Frame, Pitch = %f, ", powf(2, (-4.311767578125 - (2.1336e-2 * ((float)b0+0.5))))*8000); // decode fundamental frequency w0 from b0 is already done if (silence == 0) { // w0 from specification document //f0 = AmbeW0table[b0]; //cur_mp->w0 = f0 * (float) 2 *M_PI; // w0 from patent filings //f0 = powf (2, ((float) b0 + (float) 195.626) / -(float) 46.368); // was 45.368 // w0 guess f0 = powf(2, (-4.311767578125 - (2.1336e-2 * ((float)b0+0.5)))); cur_mp->w0 = f0 * (float) 2 *M_PI; } unvc = (float) 0.2046 / sqrtf (cur_mp->w0); //unvc = (float) 1; //unvc = (float) 0.2046 / sqrtf (f0); // decode L L = 0; if (silence == 0) { // L from specification document // lookup L in tabl3 L = AmbePlusLtable[b0]; // L formula from patent filings //L=(int)((float)0.4627 / f0); cur_mp->L = L; } // decode V/UV parameters // load b1 from ambe_d //TODO: use correct table (i.e. 0x0000 0x0005 0x0050 0x0055 etc) b1 = 0; b1 |= ambe_d[38]<<3; b1 |= ambe_d[39]<<2; b1 |= ambe_d[40]<<1; b1 |= ambe_d[41]; //fprintf(stderr,"V/UV = %d, ", b1); for (l = 1; l <= L; l++) { // jl from specification document jl = (int) ((float) l * (float) 16.0 * f0); // jl from patent filings? //jl = (int)(((float)l * (float)16.0 * f0) + 0.25); if (silence == 0) { cur_mp->Vl[l] = AmbePlusVuv[b1][jl]; } #ifdef AMBE_DEBUG printf ("jl[%i]:%i Vl[%i]:%i\n", l, jl, l, cur_mp->Vl[l]); #endif } #ifdef AMBE_DEBUG printf ("\nb0:%i w0:%f L:%i b1:%i\n", b0, cur_mp->w0, L, b1); #endif // decode gain vector // load b2 from ambe_d b2 = 0; b2 |= ambe_d[6]<<5; b2 |= ambe_d[7]<<4; b2 |= ambe_d[8]<<3; b2 |= ambe_d[9]<<2; b2 |= ambe_d[42]<<1; b2 |= ambe_d[43]; //fprintf(stderr,"Gain = %d,\n", b2); deltaGamma = AmbePlusDg[b2]; cur_mp->gamma = deltaGamma + ((float) 0.5 * prev_mp->gamma); #ifdef AMBE_DEBUG printf ("b2: %i, deltaGamma: %f gamma: %f gamma-1: %f\n", b2, deltaGamma, cur_mp->gamma, prev_mp->gamma); #endif // decode PRBA vectors Gm[1] = 0; // load b3 from ambe_d b3 = 0; b3 |= ambe_d[10]<<8; b3 |= ambe_d[11]<<7; b3 |= ambe_d[12]<<6; b3 |= ambe_d[13]<<5; b3 |= ambe_d[14]<<4; b3 |= ambe_d[15]<<3; b3 |= ambe_d[16]<<2; b3 |= ambe_d[44]<<1; b3 |= ambe_d[45]; Gm[2] = AmbePlusPRBA24[b3][0]; Gm[3] = AmbePlusPRBA24[b3][1]; Gm[4] = AmbePlusPRBA24[b3][2]; // load b4 from ambe_d b4 = 0; b4 |= ambe_d[17]<<6; b4 |= ambe_d[18]<<5; b4 |= ambe_d[19]<<4; b4 |= ambe_d[20]<<3; b4 |= ambe_d[21]<<2; b4 |= ambe_d[46]<<1; b4 |= ambe_d[47]; Gm[5] = AmbePlusPRBA58[b4][0]; Gm[6] = AmbePlusPRBA58[b4][1]; Gm[7] = AmbePlusPRBA58[b4][2]; Gm[8] = AmbePlusPRBA58[b4][3]; #ifdef AMBE_DEBUG printf ("b3: %i Gm[2]: %f Gm[3]: %f Gm[4]: %f b4: %i Gm[5]: %f Gm[6]: %f Gm[7]: %f Gm[8]: %f\n", b3, Gm[2], Gm[3], Gm[4], b4, Gm[5], Gm[6], Gm[7], Gm[8]); #endif // compute Ri for (i = 1; i <= 8; i++) { sum = 0; for (m = 1; m <= 8; m++) { if (m == 1) { am = 1; } else { am = 2; } sum = sum + ((float) am * Gm[m] * cosf ((M_PI * (float) (m - 1) * ((float) i - (float) 0.5)) / (float) 8)); } Ri[i] = sum; #ifdef AMBE_DEBUG printf ("R%i: %f ", i, Ri[i]); #endif } #ifdef AMBE_DEBUG printf ("\n"); #endif // generate first to elements of each Ci,k block from PRBA vector rconst = ((float) 1 / ((float) 2 * M_SQRT2)); Cik[1][1] = (float) 0.5 *(Ri[1] + Ri[2]); Cik[1][2] = rconst * (Ri[1] - Ri[2]); Cik[2][1] = (float) 0.5 *(Ri[3] + Ri[4]); Cik[2][2] = rconst * (Ri[3] - Ri[4]); Cik[3][1] = (float) 0.5 *(Ri[5] + Ri[6]); Cik[3][2] = rconst * (Ri[5] - Ri[6]); Cik[4][1] = (float) 0.5 *(Ri[7] + Ri[8]); Cik[4][2] = rconst * (Ri[7] - Ri[8]); // decode HOC // load b5 from ambe_d b5 = 0; b5 |= ambe_d[22]<<3; b5 |= ambe_d[23]<<2; b5 |= ambe_d[25]<<1; b5 |= ambe_d[26]; // load b6 from ambe_d b6 = 0; b6 |= ambe_d[27]<<3; b6 |= ambe_d[28]<<2; b6 |= ambe_d[29]<<1; b6 |= ambe_d[30]; // load b7 from ambe_d b7 = 0; b7 |= ambe_d[31]<<3; b7 |= ambe_d[32]<<2; b7 |= ambe_d[33]<<1; b7 |= ambe_d[34]; // load b8 from ambe_d b8 = 0; b8 |= ambe_d[35]<<3; b8 |= ambe_d[36]<<2; b8 |= ambe_d[37]<<1; //b8 |= 0; // least significant bit of hoc3 unused here, and according to the patent is forced to 0 when not used // lookup Ji Ji[1] = AmbePlusLmprbl[L][0]; Ji[2] = AmbePlusLmprbl[L][1]; Ji[3] = AmbePlusLmprbl[L][2]; Ji[4] = AmbePlusLmprbl[L][3]; #ifdef AMBE_DEBUG printf ("Ji[1]: %i Ji[2]: %i Ji[3]: %i Ji[4]: %i\n", Ji[1], Ji[2], Ji[3], Ji[4]); printf ("b5: %i b6: %i b7: %i b8: %i\n", b5, b6, b7, b8); #endif // Load Ci,k with the values from the HOC tables // there appear to be a couple typos in eq. 37 so we will just do what makes sense // (3 <= k <= Ji and k<=6) for (k = 3; k <= Ji[1]; k++) { if (k > 6) { Cik[1][k] = 0; } else { Cik[1][k] = AmbePlusHOCb5[b5][k - 3]; #ifdef AMBE_DEBUG printf ("C1,%i: %f ", k, Cik[1][k]); #endif } } for (k = 3; k <= Ji[2]; k++) { if (k > 6) { Cik[2][k] = 0; } else { Cik[2][k] = AmbePlusHOCb6[b6][k - 3]; #ifdef AMBE_DEBUG printf ("C2,%i: %f ", k, Cik[2][k]); #endif } } for (k = 3; k <= Ji[3]; k++) { if (k > 6) { Cik[3][k] = 0; } else { Cik[3][k] = AmbePlusHOCb7[b7][k - 3]; #ifdef AMBE_DEBUG printf ("C3,%i: %f ", k, Cik[3][k]); #endif } } for (k = 3; k <= Ji[4]; k++) { if (k > 6) { Cik[4][k] = 0; } else { Cik[4][k] = AmbePlusHOCb8[b8][k - 3]; #ifdef AMBE_DEBUG printf ("C4,%i: %f ", k, Cik[4][k]); #endif } } #ifdef AMBE_DEBUG printf ("\n"); #endif // inverse DCT each Ci,k to give ci,j (Tl) l = 1; for (i = 1; i <= 4; i++) { ji = Ji[i]; for (j = 1; j <= ji; j++) { sum = 0; for (k = 1; k <= ji; k++) { if (k == 1) { ak = 1; } else { ak = 2; } #ifdef AMBE_DEBUG printf ("j: %i Cik[%i][%i]: %f ", j, i, k, Cik[i][k]); #endif sum = sum + ((float) ak * Cik[i][k] * cosf ((M_PI * (float) (k - 1) * ((float) j - (float) 0.5)) / (float) ji)); } Tl[l] = sum; #ifdef AMBE_DEBUG printf ("Tl[%i]: %f\n", l, Tl[l]); #endif l++; } } // determine log2Ml by applying ci,j to previous log2Ml // fix for when L > L(-1) if (cur_mp->L > prev_mp->L) { for (l = (prev_mp->L) + 1; l <= cur_mp->L; l++) { prev_mp->Ml[l] = prev_mp->Ml[prev_mp->L]; prev_mp->log2Ml[l] = prev_mp->log2Ml[prev_mp->L]; } } prev_mp->log2Ml[0] = prev_mp->log2Ml[1]; prev_mp->Ml[0] = prev_mp->Ml[1]; // Part 1 Sum43 = 0; for (l = 1; l <= cur_mp->L; l++) { // eq. 40 flokl[l] = ((float) prev_mp->L / (float) cur_mp->L) * (float) l; intkl[l] = (int) (flokl[l]); #ifdef AMBE_DEBUG printf ("flok%i: %f, intk%i: %i ", l, flokl[l], l, intkl[l]); #endif // eq. 41 deltal[l] = flokl[l] - (float) intkl[l]; #ifdef AMBE_DEBUG printf ("delta%i: %f ", l, deltal[l]); #endif // eq 43 Sum43 = Sum43 + ((((float) 1 - deltal[l]) * prev_mp->log2Ml[intkl[l]]) + (deltal[l] * prev_mp->log2Ml[intkl[l] + 1])); } Sum43 = (((float) 0.65 / (float) cur_mp->L) * Sum43); #ifdef AMBE_DEBUG printf ("\n"); printf ("Sum43: %f\n", Sum43); #endif // Part 2 Sum42 = 0; for (l = 1; l <= cur_mp->L; l++) { Sum42 += Tl[l]; } Sum42 = Sum42 / (float) cur_mp->L; BigGamma = cur_mp->gamma - ((float) 0.5 * (log ((float) cur_mp->L) / log ((float) 2))) - Sum42; //BigGamma=cur_mp->gamma - ((float)0.5 * log((float)cur_mp->L)) - Sum42; // Part 3 for (l = 1; l <= cur_mp->L; l++) { c1 = ((float) 0.65 * ((float) 1 - deltal[l]) * prev_mp->log2Ml[intkl[l]]); c2 = ((float) 0.65 * deltal[l] * prev_mp->log2Ml[intkl[l] + 1]); cur_mp->log2Ml[l] = Tl[l] + c1 + c2 - Sum43 + BigGamma; // inverse log to generate spectral amplitudes if (cur_mp->Vl[l] == 1) { cur_mp->Ml[l] = exp ((float) 0.693 * cur_mp->log2Ml[l]); } else { cur_mp->Ml[l] = unvc * exp ((float) 0.693 * cur_mp->log2Ml[l]); } #ifdef AMBE_DEBUG printf ("flokl[%i]: %f, intkl[%i]: %i ", l, flokl[l], l, intkl[l]); printf ("deltal[%i]: %f ", l, deltal[l]); printf ("prev_mp->log2Ml[%i]: %f\n", l, prev_mp->log2Ml[intkl[l]]); printf ("BigGamma: %f c1: %f c2: %f Sum43: %f Tl[%i]: %f log2Ml[%i]: %f Ml[%i]: %f\n", BigGamma, c1, c2, Sum43, l, Tl[l], l, cur_mp->log2Ml[l], l, cur_mp->Ml[l]); #endif } return (0); } void mbe_demodulateAmbe3600x2400Data (char ambe_fr[4][24]) { int i, j, k; unsigned short pr[115]; unsigned short foo = 0; // create pseudo-random modulator for (i = 23; i >= 12; i--) { foo <<= 1; foo |= ambe_fr[0][i]; } pr[0] = (16 * foo); for (i = 1; i < 24; i++) { pr[i] = (173 * pr[i - 1]) + 13849 - (65536 * (((173 * pr[i - 1]) + 13849) / 65536)); } for (i = 1; i < 24; i++) { pr[i] = pr[i] / 32768; } // demodulate ambe_fr with pr k = 1; for (j = 22; j >= 0; j--) { ambe_fr[1][j] = ((ambe_fr[1][j]) ^ pr[k]); k++; } } void mbe_processAmbe2400Dataf (float *aout_buf, int *errs2, char *err_str, char ambe_d[49], mbe_parms * cur_mp, mbe_parms * prev_mp, mbe_parms * prev_mp_enhanced, int uvquality) { int i, bad; for (i = 0; i < *errs2; i++) { *err_str = '='; err_str++; } bad = mbe_decodeAmbe2400Parms (ambe_d, cur_mp, prev_mp); if (bad == 2) { // Erasure frame *err_str = 'E'; err_str++; cur_mp->repeat = 0; } else if (bad == 3) { // Tone Frame *err_str = 'T'; err_str++; cur_mp->repeat = 0; } else if (*errs2 > 3) { mbe_useLastMbeParms (cur_mp, prev_mp); cur_mp->repeat++; *err_str = 'R'; err_str++; } else { cur_mp->repeat = 0; } if (bad == 0) { if (cur_mp->repeat <= 3) { mbe_moveMbeParms (cur_mp, prev_mp); mbe_spectralAmpEnhance (cur_mp); mbe_synthesizeSpeechf (aout_buf, cur_mp, prev_mp_enhanced, uvquality); mbe_moveMbeParms (cur_mp, prev_mp_enhanced); } else { *err_str = 'M'; err_str++; mbe_synthesizeSilencef (aout_buf); mbe_initMbeParms (cur_mp, prev_mp, prev_mp_enhanced); } } else { mbe_synthesizeSilencef (aout_buf); mbe_initMbeParms (cur_mp, prev_mp, prev_mp_enhanced); } *err_str = 0; } void mbe_processAmbe2400Data (short *aout_buf, int *errs2, char *err_str, char ambe_d[49], mbe_parms * cur_mp, mbe_parms * prev_mp, mbe_parms * prev_mp_enhanced, int uvquality) { float float_buf[160]; mbe_processAmbe2400Dataf (float_buf, errs2, err_str, ambe_d, cur_mp, prev_mp, prev_mp_enhanced, uvquality); mbe_floattoshort (float_buf, aout_buf); } void mbe_processAmbe3600x2400Framef (float *aout_buf, int *errs2, char *err_str, char ambe_fr[4][24], char ambe_d[49], mbe_parms * cur_mp, mbe_parms * prev_mp, mbe_parms * prev_mp_enhanced, int uvquality) { int errs = 0; *errs2 = 0; errs = mbe_eccAmbe3600x2400C0 (ambe_fr); mbe_demodulateAmbe3600x2400Data (ambe_fr); *errs2 = errs; *errs2 += mbe_eccAmbe3600x2400Data (ambe_fr, ambe_d); mbe_processAmbe2400Dataf (aout_buf, errs2, err_str, ambe_d, cur_mp, prev_mp, prev_mp_enhanced, uvquality); } void mbe_processAmbe3600x2400Frame (short *aout_buf, int *errs2, char *err_str, char ambe_fr[4][24], char ambe_d[49], mbe_parms * cur_mp, mbe_parms * prev_mp, mbe_parms * prev_mp_enhanced, int uvquality) { float float_buf[160]; mbe_processAmbe3600x2400Framef (float_buf, errs2, err_str, ambe_fr, ambe_d, cur_mp, prev_mp, prev_mp_enhanced, uvquality); mbe_floattoshort (float_buf, aout_buf); }