aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/util.cpp6
-rw-r--r--common/util.h8
-rw-r--r--sound/fmopl.cpp43
3 files changed, 37 insertions, 20 deletions
diff --git a/common/util.cpp b/common/util.cpp
index 82a910f9a8..1f48a6ddd9 100644
--- a/common/util.cpp
+++ b/common/util.cpp
@@ -196,6 +196,12 @@ uint RandomSource::getRandomNumber(uint max) {
return _randSeed % (max + 1);
}
+uint RandomSource::getRandomBit(void) {
+ _randSeed = 0xDEADBF03 * (_randSeed + 1);
+ _randSeed = (_randSeed >> 13) | (_randSeed << 19);
+ return _randSeed & 1;
+}
+
uint RandomSource::getRandomNumberRng(uint min, uint max) {
return getRandomNumber(max - min) + min;
}
diff --git a/common/util.h b/common/util.h
index e7a71ff42c..dd205f159c 100644
--- a/common/util.h
+++ b/common/util.h
@@ -83,7 +83,7 @@ bool matchString(const char *str, const char *pat);
class StringTokenizer {
public:
/**
- * Creates a StringTokenizer.
+ * Creates a StringTokenizer.
* @param str The string to be tokenized.
* @param delimiters String containing all the delimiter characters (i.e. the characters to be ignored).
* @note Uses space, horizontal tab, carriage return, newline, form feed and vertical tab as delimiters by default.
@@ -132,6 +132,12 @@ public:
*/
uint getRandomNumber(uint max);
/**
+ * Generates a random unsigned integer in the interval [0, 1].
+ * Identical to getRandomNumber(1), but faster, hopefully.
+ * @return a random number in the interval [0, max].
+ */
+ uint getRandomBit(void);
+ /**
* Generates a random unsigned integer in the interval [min, max].
* @param min the lower bound
* @param max the upper bound
diff --git a/sound/fmopl.cpp b/sound/fmopl.cpp
index 8e96e62b64..4e4048353a 100644
--- a/sound/fmopl.cpp
+++ b/sound/fmopl.cpp
@@ -86,7 +86,8 @@ int EG_AED;
#define AMS_ENT 512
#define AMS_SHIFT (32-9)
-#define VIB_RATE 256
+#define VIB_RATE_SHIFT 8
+#define VIB_RATE (1<<VIB_RATE_SHIFT)
/* -------------------- local defines , macros --------------------- */
@@ -402,7 +403,7 @@ inline void CALC_FCSLOT(OPL_CH *CH, OPL_SLOT *SLOT) {
/* set multi,am,vib,EG-TYP,KSR,mul */
inline void set_mul(FM_OPL *OPL, int slot, int v) {
- OPL_CH *CH = &OPL->P_CH[slot / 2];
+ OPL_CH *CH = &OPL->P_CH[slot>>1];
OPL_SLOT *SLOT = &CH->SLOT[slot & 1];
SLOT->mul = MUL_TABLE[v & 0x0f];
@@ -415,7 +416,7 @@ inline void set_mul(FM_OPL *OPL, int slot, int v) {
/* set ksl & tl */
inline void set_ksl_tl(FM_OPL *OPL, int slot, int v) {
- OPL_CH *CH = &OPL->P_CH[slot / 2];
+ OPL_CH *CH = &OPL->P_CH[slot>>1];
OPL_SLOT *SLOT = &CH->SLOT[slot & 1];
int ksl = v >> 6; /* 0 / 1.5 / 3 / 6 db/OCT */
@@ -429,7 +430,7 @@ inline void set_ksl_tl(FM_OPL *OPL, int slot, int v) {
/* set attack rate & decay rate */
inline void set_ar_dr(FM_OPL *OPL, int slot, int v) {
- OPL_CH *CH = &OPL->P_CH[slot / 2];
+ OPL_CH *CH = &OPL->P_CH[slot>>1];
OPL_SLOT *SLOT = &CH->SLOT[slot & 1];
int ar = v >> 4;
int dr = v & 0x0f;
@@ -447,7 +448,7 @@ inline void set_ar_dr(FM_OPL *OPL, int slot, int v) {
/* set sustain level & release rate */
inline void set_sl_rr(FM_OPL *OPL, int slot, int v) {
- OPL_CH *CH = &OPL->P_CH[slot / 2];
+ OPL_CH *CH = &OPL->P_CH[slot>>1];
OPL_SLOT *SLOT = &CH->SLOT[slot & 1];
int sl = v >> 4;
int rr = v & 0x0f;
@@ -476,10 +477,10 @@ inline void OPL_CALC_CH(OPL_CH *CH) {
if(env_out < (uint)(EG_ENT - 1)) {
/* PG */
if(SLOT->vib)
- SLOT->Cnt += (SLOT->Incr * vib / VIB_RATE);
+ SLOT->Cnt += (SLOT->Incr * vib) >> VIB_RATE_SHIFT;
else
SLOT->Cnt += SLOT->Incr;
- /* connectoion */
+ /* connection */
if(CH->FB) {
int feedback1 = (CH->op1_out[0] + CH->op1_out[1]) >> CH->FB;
CH->op1_out[1] = CH->op1_out[0];
@@ -497,10 +498,10 @@ inline void OPL_CALC_CH(OPL_CH *CH) {
if(env_out < (uint)(EG_ENT - 1)) {
/* PG */
if(SLOT->vib)
- SLOT->Cnt += (SLOT->Incr * vib / VIB_RATE);
+ SLOT->Cnt += (SLOT->Incr * vib) >> VIB_RATE_SHIFT;
else
SLOT->Cnt += SLOT->Incr;
- /* connectoion */
+ /* connection */
outd[0] += OP_OUT(SLOT, env_out, feedback2);
}
}
@@ -509,7 +510,11 @@ inline void OPL_CALC_CH(OPL_CH *CH) {
#define WHITE_NOISE_db 6.0
inline void OPL_CALC_RH(FM_OPL *OPL, OPL_CH *CH) {
uint env_tam, env_sd, env_top, env_hh;
- int whitenoise = int(OPL->rnd.getRandomNumber(1) * (WHITE_NOISE_db / EG_STEP));
+ // This code used to do int(OPL->rnd.getRandomBit() * (WHITE_NOISE_db / EG_STEP)),
+ // but EG_STEP = 96.0/EG_ENT, and WHITE_NOISE_db=6.0. So, that's equivalent to
+ // int(OPL->rnd.getRandomBit() * EG_ENT/16). We know that EG_ENT is 4096, or 1024,
+ // or 128, so we can safely avoid any FP ops.
+ int whitenoise = OPL->rnd.getRandomBit() * (EG_ENT>>4);
int tone8;
@@ -524,10 +529,10 @@ inline void OPL_CALC_RH(FM_OPL *OPL, OPL_CH *CH) {
if(env_out < EG_ENT-1) {
/* PG */
if(SLOT->vib)
- SLOT->Cnt += (SLOT->Incr * vib / VIB_RATE);
+ SLOT->Cnt += (SLOT->Incr * vib) >> VIB_RATE_SHIFT;
else
SLOT->Cnt += SLOT->Incr;
- /* connectoion */
+ /* connection */
if(CH[6].FB) {
int feedback1 = (CH[6].op1_out[0] + CH[6].op1_out[1]) >> CH[6].FB;
CH[6].op1_out[1] = CH[6].op1_out[0];
@@ -547,10 +552,10 @@ inline void OPL_CALC_RH(FM_OPL *OPL, OPL_CH *CH) {
if(env_out < EG_ENT-1) {
/* PG */
if(SLOT->vib)
- SLOT->Cnt += (SLOT->Incr * vib / VIB_RATE);
+ SLOT->Cnt += (SLOT->Incr * vib) >> VIB_RATE_SHIFT;
else
SLOT->Cnt += SLOT->Incr;
- /* connectoion */
+ /* connection */
outd[0] += OP_OUT(SLOT, env_out, feedback2) * 2;
}
@@ -565,19 +570,19 @@ inline void OPL_CALC_RH(FM_OPL *OPL, OPL_CH *CH) {
/* PG */
if(SLOT7_1->vib)
- SLOT7_1->Cnt += (2 * SLOT7_1->Incr * vib / VIB_RATE);
+ SLOT7_1->Cnt += (SLOT7_1->Incr * vib) >> (VIB_RATE_SHIFT-1);
else
SLOT7_1->Cnt += 2 * SLOT7_1->Incr;
if(SLOT7_2->vib)
- SLOT7_2->Cnt += ((CH[7].fc * 8) * vib / VIB_RATE);
+ SLOT7_2->Cnt += (CH[7].fc * vib) >> (VIB_RATE_SHIFT-3);
else
SLOT7_2->Cnt += (CH[7].fc * 8);
if(SLOT8_1->vib)
- SLOT8_1->Cnt += (SLOT8_1->Incr * vib / VIB_RATE);
+ SLOT8_1->Cnt += (SLOT8_1->Incr * vib) >> VIB_RATE_SHIFT;
else
SLOT8_1->Cnt += SLOT8_1->Incr;
if(SLOT8_2->vib)
- SLOT8_2->Cnt += ((CH[8].fc * 48) * vib / VIB_RATE);
+ SLOT8_2->Cnt += ((CH[8].fc * 3) * vib) >> (VIB_RATE_SHIFT-4);
else
SLOT8_2->Cnt += (CH[8].fc * 48);
@@ -938,7 +943,7 @@ void OPLWriteReg(FM_OPL *OPL, int r, int v) {
slot = slot_array[r & 0x1f];
if(slot == -1)
return;
- CH = &OPL->P_CH[slot / 2];
+ CH = &OPL->P_CH[slot>>1];
if(OPL->wavesel) {
CH->SLOT[slot&1].wavetable = &SIN_TABLE[(v & 0x03) * SIN_ENT];
}