/* 0F 0F /r B7 */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::PMULHRW_PqQq(bxInstruction_c *i) { BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2, result; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->rm()); } else { BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), RMAddr(i)); } Bit32s product1 = Bit32s(MMXSW0(op1)) * Bit32s(MMXSW0(op2)) + 0x8000; Bit32s product2 = Bit32s(MMXSW1(op1)) * Bit32s(MMXSW1(op2)) + 0x8000; Bit32s product3 = Bit32s(MMXSW2(op1)) * Bit32s(MMXSW2(op2)) + 0x8000; Bit32s product4 = Bit32s(MMXSW3(op1)) * Bit32s(MMXSW3(op2)) + 0x8000; MMXUW0(result) = Bit16u(product1 >> 16); MMXUW1(result) = Bit16u(product2 >> 16); MMXUW2(result) = Bit16u(product3 >> 16); MMXUW3(result) = Bit16u(product4 >> 16); /* now write result back to destination */ BX_WRITE_MMX_REG(i->nnn(), result); }
void Tables::initMT32ConstantTables(Synth *synth) { int lf; synth->printDebug("Initialising Pitch Tables"); for (lf = -108; lf <= 108; lf++) { tvfKeyfollowMult[lf + 108] = (int)(256 * powf(2.0f, (float)(lf / 24.0f))); //synth->printDebug("KT %d = %d", f, keytable[f+108]); } for (int res = 0; res < 31; res++) { resonanceFactor[res] = powf((float)res / 30.0f, 5.0f) + 1.0f; } int period = 65536; for (int ang = 0; ang < period; ang++) { int halfang = (period / 2); int angval = ang % halfang; float tval = (((float)angval / (float)halfang) - 0.5f) * 2; if (ang >= halfang) tval = -tval; sintable[ang] = (Bit16s)(tval * 50.0f) + 50; } int velt, dep; float tempdep; for (velt = 0; velt < 128; velt++) { for (dep = 0; dep < 5; dep++) { if (dep > 0) { float ff = (float)(exp(3.5f * tvcatconst[dep] * (59.0f - (float)velt)) * tvcatmult[dep]); tempdep = 256.0f * ff; envTimeVelfollowMult[dep][velt] = (int)tempdep; //if ((velt % 16) == 0) { // synth->printDebug("Key %d, depth %d, factor %d", velt, dep, (int)tempdep); //} } else envTimeVelfollowMult[dep][velt] = 256; } for (dep = -7; dep < 8; dep++) { float fldep = (float)abs(dep) / 7.0f; fldep = powf(fldep,2.5f); if (dep < 0) fldep = fldep * -1.0f; pwVelfollowAdd[dep+7][velt] = Bit32s((fldep * (float)velt * 100) / 128.0); } } for (dep = 0; dep <= 100; dep++) { for (velt = 0; velt < 128; velt++) { float fdep = (float)dep * 0.000347013f; // Another MT-32 constant float fv = ((float)velt - 64.0f)/7.26f; float flogdep = powf(10, fdep * fv); float fbase; if (velt > 64) synth->tables.tvfVelfollowMult[velt][dep] = (int)(flogdep * 256.0); else { //lff = 1 - (pow(((128.0 - (float)lf) / 64.0),.25) * ((float)velt / 96)); fbase = 1 - (powf(((float)dep / 100.0f),.25f) * ((float)(64-velt) / 96.0f)); synth->tables.tvfVelfollowMult[velt][dep] = (int)(fbase * 256.0); } //synth->printDebug("Filvel dep %d velt %d = %x", dep, velt, filveltable[velt][dep]); } } for (lf = 0; lf < 128; lf++) { float veloFract = lf / 127.0f; for (int velsens = 0; velsens <= 100; velsens++) { float sensFract = (velsens - 50) / 50.0f; if (velsens < 50) { tvaVelfollowMult[lf][velsens] = FIXEDPOINT_MAKE(1.0f / powf(2.0f, veloFract * -sensFract * 127.0f / 20.0f), 8); } else { tvaVelfollowMult[lf][velsens] = FIXEDPOINT_MAKE(1.0f / powf(2.0f, (1.0f - veloFract) * sensFract * 127.0f / 20.0f), 8); } } } for (lf = 0; lf <= 100; lf++) { // Converts the 0-100 range used by the MT-32 to volume multiplier volumeMult[lf] = FIXEDPOINT_MAKE(powf((float)lf / 100.0f, FLOAT_LN), 7); } for (lf = 0; lf <= 100; lf++) { float mv = lf / 100.0f; float pt = mv - 0.5f; if (pt < 0) pt = 0; // Original (CC version) //pwFactor[lf] = (int)(pt * 210.04f) + 128; // Approximation from sample comparison pwFactor[lf] = (int)(pt * 179.0f) + 128; } for (unsigned int i = 0; i < MAX_SAMPLE_OUTPUT; i++) { int myRand; myRand = rand(); //myRand = ((myRand - 16383) * 7168) >> 16; // This one is slower but works with all values of RAND_MAX myRand = (int)((myRand - RAND_MAX / 2) / (float)RAND_MAX * (7168 / 2)); //FIXME:KG: Original ultimately set the lowest two bits to 0, for no obvious reason noiseBuf[i] = (Bit16s)myRand; } float tdist; float padjtable[51]; for (lf = 0; lf <= 50; lf++) { if (lf == 0) padjtable[lf] = 7; else if (lf == 1) padjtable[lf] = 6; else if (lf == 2) padjtable[lf] = 5; else if (lf == 3) padjtable[lf] = 4; else if (lf == 4) padjtable[lf] = 4 - (0.333333f); else if (lf == 5) padjtable[lf] = 4 - (0.333333f * 2); else if (lf == 6) padjtable[lf] = 3; else if ((lf > 6) && (lf <= 12)) { tdist = (lf-6.0f) / 6.0f; padjtable[lf] = 3.0f - tdist; } else if ((lf > 12) && (lf <= 25)) { tdist = (lf - 12.0f) / 13.0f; padjtable[lf] = 2.0f - tdist; } else { tdist = (lf - 25.0f) / 25.0f; padjtable[lf] = 1.0f - tdist; } //synth->printDebug("lf %d = padj %f", lf, padjtable[lf]); } float lfp, depf, finalval, tlf; int depat, pval, depti; for (lf = 0; lf <= 10; lf++) { // I believe the depth is cubed or something for (depat = 0; depat <= 100; depat++) { if (lf > 0) { depti = abs(depat - 50); tlf = (float)lf - padjtable[depti]; if (tlf < 0) tlf = 0; lfp = (float)exp(0.713619942f * tlf) / 407.4945111f; if (depat < 50) finalval = 4096.0f * powf(2, -lfp); else finalval = 4096.0f * powf(2, lfp); pval = (int)finalval; pitchEnvVal[lf][depat] = pval; //synth->printDebug("lf %d depat %d pval %d tlf %f lfp %f", lf,depat,pval, tlf, lfp); } else { pitchEnvVal[lf][depat] = 4096; //synth->printDebug("lf %d depat %d pval 4096", lf, depat); } } } for (lf = 0; lf <= 100; lf++) { // It's linear - verified on MT-32 - one of the few things linear lfp = ((float)lf * 0.1904f) / 310.55f; for (depat = 0; depat <= 100; depat++) { depf = ((float)depat - 50.0f) / 50.0f; //finalval = pow(2, lfp * depf * .5); finalval = 4096.0f + (4096.0f * lfp * depf); pval = (int)finalval; lfoShift[lf][depat] = pval; //synth->printDebug("lf %d depat %d pval %x", lf,depat,pval); } } for (lf = 0; lf <= 12; lf++) { for (int distval = 0; distval < 128; distval++) { float amplog, dval; if (lf == 0) { amplog = 0; dval = 1; tvaBiasMult[lf][distval] = 256; } else { /* amplog = powf(1.431817011f, (float)lf) / FLOAT_PI; dval = ((128.0f - (float)distval) / 128.0f); amplog = exp(amplog); dval = powf(amplog, dval) / amplog; tvaBiasMult[lf][distval] = (int)(dval * 256.0); */ // Lets assume for a second it's linear // Distance of full volume reduction amplog = (float)(12.0f / (float)lf) * 24.0f; if (distval > amplog) { tvaBiasMult[lf][distval] = 0; } else { dval = (amplog - (float)distval) / amplog; tvaBiasMult[lf][distval] = (int)(dval * 256.0f); } } //synth->printDebug("Ampbias lf %d distval %d = %f (%x) %f", lf, distval, dval, tvaBiasMult[lf][distval],amplog); } } for (lf = 0; lf <= 14; lf++) { for (int distval = 0; distval < 128; distval++) { float filval = fabsf((float)((lf - 7) * 12) / 7.0f); float amplog, dval; if (lf == 7) { amplog = 0; dval = 1; tvfBiasMult[lf][distval] = 256; } else { //amplog = pow(1.431817011, filval) / FLOAT_PI; amplog = powf(1.531817011f, filval) / FLOAT_PI; dval = (128.0f - (float)distval) / 128.0f; amplog = (float)exp(amplog); dval = powf(amplog,dval)/amplog; if (lf < 8) { tvfBiasMult[lf][distval] = (int)(dval * 256.0f); } else { dval = powf(dval, 0.3333333f); if (dval < 0.01f) dval = 0.01f; dval = 1 / dval; tvfBiasMult[lf][distval] = (int)(dval * 256.0f); } } //synth->printDebug("Fbias lf %d distval %d = %f (%x) %f", lf, distval, dval, tvfBiasMult[lf][distval],amplog); } } }