转载自: http://blog.csdn.net/chidaidl/article/details/4809671
The Mean Opinion Score (MOS) test is a well acccepted standard which is defined in the ITU-T Rec.P.800. The value of MOS test is generated by letting large number of listeners to evaluate the quality of the test sentences. The test scores are averaged to a mean score which range from 1 to 5, 1 being the worst and 5 being the best.
The E-model which is defined by ITU-T Rec.G.107 is a computational model converting all parameters that affect a voice call into a single rating value R.
A VB source code was provided in G.107 for calculating R value. But considering not everybody knows VB, I would like to share some java code I used before.
- public class VoIPCalculator {
- /**
- * This function returns R value calculated by using the passed in parameters
- * See detail of each parameter in ITU-T G.107
- * @param T
- * @param Ppl
- * @param SLR
- * @param RLR
- * @param Ds
- * @param STMR
- * @param Dr
- * @param TELR
- * @param WEPL
- * @param Ie
- * @param BPL
- * @param BurstR
- * @param A
- * @param Nc
- * @param Ps
- * @param Pr
- * @param qdu
- * @param Nfor
- * @return
- */
- private static double calRValue(double T, double Ppl, double SLR,
- double RLR, double Ds, double STMR, double Dr, double TELR,
- double WEPL, double Ie, double BPL, double BurstR, double A,
- double Nc, double Ps, double Pr, double qdu, double Nfor) {
- double LSTR = STMR + Dr,
- Tr = 2*T,
- Ta = T;
- double Nfo = Nfor + RLR;
- double OLR = SLR+RLR;
- double Pre = Pr + 10*Math.log10(1+Math.pow(10,
- ((double)(10-LSTR))/(double)10));
- double Nor = RLR - 121 +Pre
- + 0.008*Math.pow((Pre-35),2);
- double Nos = Ps - SLR -Ds
- - 100 +0.004*Math.pow((Ps-OLR -Ds - 14),2);
- double No = 10*Math.log10((Math.pow(10, (double)Nc/(double)10))
- +Math.pow(10, (double)Nos/(double)10)
- +Math.pow(10, (double)Nor/(double)10)
- +Math.pow(10, (double)Nfo/(double)10));
- double Ro = 15 - 1.5*(SLR+No);
- double Q = 37 - 15*(Math.log10(qdu));
- double G = 1.07+0.258*Q+0.0602*Math.pow(Q, 2);
- double Z = (double)46/(double)30-G/(double)40;
- double Y = (double)(Ro-100)/(double)15+46/8.4-G/9;
- double Iq = 15*Math.log10(1+Math.pow(10, Y)
- +Math.pow(10, Z));
- double STMRo = -10*Math.log10(Math.pow(10, -STMR/(double)10)
- + Math.exp(-T/(double)4)*Math.pow(10, -TELR/10));
- double Ist = 12*Math.pow((1+Math.pow((STMRo-13)/(double)6, 8)),
- 1/(double)8)
- -28*Math.pow((1+Math.pow((STMRo+1)/19.4, 35)),
- 1/(double)35)
- -13*Math.pow((1+Math.pow((STMRo-3)/33, 13)),
- 1/(double)13)
- +29;
- double Xolr = OLR+0.2*(64+No-RLR);
- double Iolr = 20* (Math.pow((1+Math.pow((Xolr/8),(double)8)),
- ((double)1/(double)8))-Xolr/(double)8);
- double Is = Iolr + Ist + Iq;
- double TERV = TELR - 40*Math.log10((1+T/10)/(1+T/150)
- +6*Math.exp(-0.3*Math.pow(T,2)));
- double Idd = 0;
- if (Ta>100)
- {
- double X = Math.log10(Ta/(double)100)/Math.log10(2);
- Idd = 25 * (Math.pow((1+Math.pow(X, 6)),
- 1/(double)6)-3*Math.pow((1+Math.pow(X/(double)3, 6)),
- 1/(double)6)+2);
- }
- if (STMR<9)
- TERV = TERV + 0.5*Ist;
- double Rle = 10.5 * (WEPL+7)*Math.pow(Tr+1, -0.25);
- double Idle = (Ro-Rle)/(double)2
- + Math.sqrt(Math.pow(Ro-Rle, 2)/4+169);
- double Roe = -1.5*(No-RLR);
- double Re = 80+2.5*(TERV-14);
- double Idte = ((Roe-Re)/2
- + Math.sqrt(Math.pow(Roe-Re, 2)/(double)4+100) -1)*(1-Math.exp(-T));
- if (STMR > 20)
- Idte = Math.sqrt(Math.pow(Idte,2)+Math.pow(Ist,2));
- double Id = Idte + Idle + Idd;
- double Ieef = Ie+(95-Ie)*(Ppl/((Ppl/BurstR)+BPL));
- double R = Ro - Is - Id - Ieef +A;
- return R;
- }
- /**
- * Using default values recommended by ITU-T in G.107
- * @param T mean one-way delay
- * @param Ppl packet-loss probability
- * @return
- */
- public static double calRValue(double T, double Ppl)
- {
- double SLR = 8,
- RLR = 2,
- Ds = 3,
- STMR = 15,
- Dr = 3,
- TELR = 65,
- WEPL = 110,
- Ie = 0,
- BPL = 1,
- BurstR = 1,
- A = 0,
- Nc = -70,
- Ps = 35,
- Pr = 35,
- qdu = 1,
- Nfor = -64;
- return calRValue(T, Ppl, SLR, RLR, Ds, STMR, Dr, TELR, WEPL, Ie, BPL,
- BurstR, A, Nc, Ps, Pr, qdu, Nfor);
- }
- /**
- * This function calculates MOS value from R value
- * @param R
- * @return
- */
- public static double calMOSValue(double R)
- {
- double mos = 0;
- if (R<0)
- mos =1;
- else if (R>100)
- mos = 4.5;
- else
- mos = 1 + 0.035*R +R*(R-60)*(100-R)*7*Math.pow(10, -6);
- return mos;
- }
- public static void main(String... Args)
- {
- //assume mean one way dealy is 150ms, Packet-loss Probability is 0.01
- double T=150;
- double Ppl=0.01;
- double R = calRValue(T,Ppl);
- double MOSValue = calMOSValue(R);
- System.out.println("when one way delay is "+T+" and Packet-loss Probability is "+Ppl
- +", R vlaue is "+R+", MOS value is "+MOSValue);
- }
- }