示例#1
0
/* 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);
}
示例#2
0
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);
		}
	}
}