Went through the sound generation with a fine-tooth comb and made it sound a lot better!

This commit is contained in:
Brendan Robert 2015-09-06 00:47:58 -05:00
parent 11b26305f8
commit 45f56756e4
4 changed files with 113 additions and 108 deletions

View File

@ -33,6 +33,7 @@ import jace.hardware.mockingboard.R6522;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
@ -184,6 +185,7 @@ public class CardMockingboard extends Card implements Runnable {
} }
if (isRunning() && !pause) { if (isRunning() && !pause) {
// buildMixerTable();
timerSync.lock(); timerSync.lock();
try { try {
ticksSinceLastPlayback++; ticksSinceLastPlayback++;
@ -246,13 +248,13 @@ public class CardMockingboard extends Card implements Runnable {
out = out * 2.0 / 3.0 / numChips; out = out * 2.0 / 3.0 / numChips;
double delta = 1.15; double delta = 1.15;
for (int i = 15; i > 0; i--) { for (int i = 15; i > 0; i--) {
VolTable[i] = (int) Math.round(out); /* round to nearest */ // [TC: unsigned int cast] VolTable[i] = (int) (out / Math.pow(Math.sqrt(2),(15-i)));
// out /= 1.188502227; /* = 10 ^ (1.5/20) = 1.5dB */ // out /= 1.188502227; /* = 10 ^ (1.5/20) = 1.5dB */
// out /= 1.15; /* = 10 ^ (3/20) = 3dB */ // out /= 1.15; /* = 10 ^ (3/20) = 3dB */
// delta += 0.0225;
delta += 0.0225; // out /= delta; // As per applewin's source, the levels don't scale as documented.
out /= delta; // As per applewin's source, the levels don't scale as documented.
} }
VolTable[0] = 0; VolTable[0] = 0;
} }
Thread playbackThread = null; Thread playbackThread = null;
@ -321,10 +323,12 @@ public class CardMockingboard extends Card implements Runnable {
ticksSinceLastPlayback = 0; ticksSinceLastPlayback = 0;
int zeroSamples = 0; int zeroSamples = 0;
setRun(true); setRun(true);
LockSupport.parkNanos(5000);
while (isRunning()) { while (isRunning()) {
while (!computer.isRunning()) { while (isRunning() && !computer.isRunning()) {
Thread.sleep(500); Thread.currentThread().yield();
} }
if (isRunning()) {
computer.getMotherboard().requestSpeed(this); computer.getMotherboard().requestSpeed(this);
playSound(leftBuffer, rightBuffer); playSound(leftBuffer, rightBuffer);
int p = 0; int p = 0;
@ -384,11 +388,10 @@ public class CardMockingboard extends Card implements Runnable {
timerSync.unlock(); timerSync.unlock();
} }
} }
}
} catch (LineUnavailableException ex) { } catch (LineUnavailableException ex) {
Logger.getLogger(CardMockingboard.class Logger.getLogger(CardMockingboard.class
.getName()).log(Level.SEVERE, null, ex); .getName()).log(Level.SEVERE, null, ex);
} catch (InterruptedException ex) {
Logger.getLogger(CardMockingboard.class.getName()).log(Level.SEVERE, null, ex);
} finally { } finally {
computer.getMotherboard().cancelSpeedRequest(this); computer.getMotherboard().cancelSpeedRequest(this);
System.out.println("Mockingboard playback stopped"); System.out.println("Mockingboard playback stopped");

View File

@ -32,6 +32,11 @@ public class EnvelopeGenerator extends TimedGenerator {
int direction; int direction;
int amplitude; int amplitude;
boolean start1high = false;
boolean start2high = false;
boolean oneShot = false;
boolean oddEven = false;
public EnvelopeGenerator(int _clock, int _sampleRate) { public EnvelopeGenerator(int _clock, int _sampleRate) {
super(_clock, _sampleRate); super(_clock, _sampleRate);
} }
@ -50,57 +55,56 @@ public class EnvelopeGenerator extends TimedGenerator {
} }
} }
int effectiveAmplitude = 0;
public void step() { public void step() {
int stateChanges = updateCounter(); int stateChanges = updateCounter();
int total = 0;
for (int i = 0; i < stateChanges; i++) { for (int i = 0; i < stateChanges; i++) {
if (amplitude == 0 && direction == -1) {
if (!cont) {
direction = 0;
} else if (hold) {
direction = 0;
if (alt) {
amplitude = 15;
}
} else if (alt) {
direction = 1;
} else {
amplitude = 15;
}
}
if (amplitude == 15 && direction == 1) {
if (!cont) {
direction = 0;
amplitude = 0;
} else if (hold) {
direction = 0;
if (alt) {
amplitude = 0;
}
} else if (alt) {
direction = -1;
} else {
amplitude = 0;
}
}
amplitude += direction; amplitude += direction;
if (amplitude > 15 || amplitude < 0) {
setPhase(oddEven ? start1high : start2high);
oddEven = !oddEven;
if (hold) {
direction = 0;
}
}
total += amplitude;
}
if (stateChanges == 0) {
effectiveAmplitude = amplitude;
} else {
effectiveAmplitude = Math.min(15, total / stateChanges);
} }
} }
public void setShape(int shape) { public void setShape(int shape) {
oddEven = false;
counter = 0; counter = 0;
cont = (shape & 8) != 0; cont = (shape & 8) != 0;
attk = (shape & 4) != 0; attk = (shape & 4) != 0;
alt = (shape & 2) != 0; alt = (shape & 2) != 0;
hold = (shape & 1) != 0; hold = ((shape ^ 8) & 9) != 0;
if (attk) {
amplitude = 0; start1high = !attk;
direction = 1; start2high = cont && ! (attk ^ alt ^ hold);
} else {
setPhase(start1high);
}
public void setPhase(boolean isHigh) {
if (isHigh) {
amplitude = 15; amplitude = 15;
direction = -1; direction = -1;
} else {
amplitude = 0;
direction = 1;
} }
} }
public int getEffectiveAmplitude() {
return effectiveAmplitude;
}
public int getAmplitude() { public int getAmplitude() {
return amplitude; return amplitude;
} }

View File

@ -30,7 +30,7 @@ public class NoiseGenerator extends TimedGenerator {
} }
@Override @Override
public int stepsPerCycle() { public int stepsPerCycle() {
return 8; return 4;
} }
public void step() { public void step() {
int stateChanges = updateCounter(); int stateChanges = updateCounter();
@ -39,11 +39,14 @@ public class NoiseGenerator extends TimedGenerator {
} }
public static final int BIT17 = 0x010000; public static final int BIT17 = 0x010000;
public void updateRng() { public void updateRng() {
// noise = (noise >> 1) ^ ((noise & 1) ? 0x14000 : 0); rng = ((rng & 1) != 0 ? rng ^ 0x24000 : rng) >> 1;
int newBit17 = (rng & 0x04) > 0 == (rng & 0x01) > 0 ? BIT17 : 0; if ((rng & 1) == 1) {
rng = newBit17 + (rng >> 1); state = !state;
} }
}
boolean state = false;
public boolean isOn() { public boolean isOn() {
return ((rng & 1) == 1); return state;
} }
} }

View File

@ -58,16 +58,11 @@ public class SoundGenerator extends TimedGenerator {
public int step(NoiseGenerator noiseGen, EnvelopeGenerator envGen) { public int step(NoiseGenerator noiseGen, EnvelopeGenerator envGen) {
int stateChanges = updateCounter(); int stateChanges = updateCounter();
if (((stateChanges & 1) == 1)) inverted = !inverted; if (((stateChanges & 1) == 1)) inverted = !inverted;
if (amplitude == 0 && !useEnvGen) return 0; double amp = stateChanges == 0 ? 1 : 1.0 / Math.max(stateChanges-1, 1);
if (!active && !noiseActive) return 0; int vol = useEnvGen ? envGen.getEffectiveAmplitude() : amplitude;
boolean invert; boolean on = noiseActive && noiseGen.isOn() || (active && inverted);
int vol = useEnvGen ? envGen.getAmplitude() : amplitude; // return invert ? -CardMockingboard.VolTable[vol] : CardMockingboard.VolTable[vol];
if (active) { return on ? (int) (CardMockingboard.VolTable[vol] * amp) : 0;
invert = noiseActive && noiseGen.isOn() ? false : inverted;
} else {
invert = noiseActive && !noiseGen.isOn();
}
return invert ? -CardMockingboard.VolTable[vol] : CardMockingboard.VolTable[vol];
} }
@Override @Override