mirror of
https://github.com/badvision/jace.git
synced 2024-11-24 15:30:51 +00:00
Went through the sound generation with a fine-tooth comb and made it sound a lot better!
This commit is contained in:
parent
11b26305f8
commit
45f56756e4
@ -33,6 +33,7 @@ import jace.hardware.mockingboard.R6522;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.Condition;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.LockSupport;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
@ -184,6 +185,7 @@ public class CardMockingboard extends Card implements Runnable {
|
||||
}
|
||||
|
||||
if (isRunning() && !pause) {
|
||||
// buildMixerTable();
|
||||
timerSync.lock();
|
||||
try {
|
||||
ticksSinceLastPlayback++;
|
||||
@ -246,13 +248,13 @@ public class CardMockingboard extends Card implements Runnable {
|
||||
out = out * 2.0 / 3.0 / numChips;
|
||||
double delta = 1.15;
|
||||
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.15; /* = 10 ^ (3/20) = 3dB */
|
||||
|
||||
delta += 0.0225;
|
||||
out /= delta; // As per applewin's source, the levels don't scale as documented.
|
||||
// delta += 0.0225;
|
||||
// out /= delta; // As per applewin's source, the levels don't scale as documented.
|
||||
}
|
||||
|
||||
VolTable[0] = 0;
|
||||
}
|
||||
Thread playbackThread = null;
|
||||
@ -321,74 +323,75 @@ public class CardMockingboard extends Card implements Runnable {
|
||||
ticksSinceLastPlayback = 0;
|
||||
int zeroSamples = 0;
|
||||
setRun(true);
|
||||
LockSupport.parkNanos(5000);
|
||||
while (isRunning()) {
|
||||
while (!computer.isRunning()) {
|
||||
Thread.sleep(500);
|
||||
while (isRunning() && !computer.isRunning()) {
|
||||
Thread.currentThread().yield();
|
||||
}
|
||||
computer.getMotherboard().requestSpeed(this);
|
||||
playSound(leftBuffer, rightBuffer);
|
||||
int p = 0;
|
||||
for (int idx = 0; idx < BUFFER_LENGTH; idx++) {
|
||||
int sampleL = leftBuffer[idx];
|
||||
int sampleR = rightBuffer[idx];
|
||||
// Convert left + right samples into buffer format
|
||||
if (sampleL == 0 && sampleR == 0) {
|
||||
zeroSamples++;
|
||||
} else {
|
||||
if (isRunning()) {
|
||||
computer.getMotherboard().requestSpeed(this);
|
||||
playSound(leftBuffer, rightBuffer);
|
||||
int p = 0;
|
||||
for (int idx = 0; idx < BUFFER_LENGTH; idx++) {
|
||||
int sampleL = leftBuffer[idx];
|
||||
int sampleR = rightBuffer[idx];
|
||||
// Convert left + right samples into buffer format
|
||||
if (sampleL == 0 && sampleR == 0) {
|
||||
zeroSamples++;
|
||||
} else {
|
||||
zeroSamples = 0;
|
||||
}
|
||||
for (int shift = SoundMixer.BITS - 8, index = 0; shift >= 0; shift -= 8, index++) {
|
||||
buffer[p + index] = (byte) (sampleR >> shift);
|
||||
buffer[p + index + bytesPerSample] = (byte) (sampleL >> shift);
|
||||
}
|
||||
p += frameSize;
|
||||
}
|
||||
try {
|
||||
timerSync.lock();
|
||||
ticksSinceLastPlayback -= ticksBeteenPlayback;
|
||||
} finally {
|
||||
timerSync.unlock();
|
||||
}
|
||||
out.write(buffer, 0, buffer.length);
|
||||
if (zeroSamples >= MAX_IDLE_SAMPLES) {
|
||||
zeroSamples = 0;
|
||||
}
|
||||
for (int shift = SoundMixer.BITS - 8, index = 0; shift >= 0; shift -= 8, index++) {
|
||||
buffer[p + index] = (byte) (sampleR >> shift);
|
||||
buffer[p + index + bytesPerSample] = (byte) (sampleL >> shift);
|
||||
}
|
||||
p += frameSize;
|
||||
}
|
||||
try {
|
||||
timerSync.lock();
|
||||
ticksSinceLastPlayback -= ticksBeteenPlayback;
|
||||
} finally {
|
||||
timerSync.unlock();
|
||||
}
|
||||
out.write(buffer, 0, buffer.length);
|
||||
if (zeroSamples >= MAX_IDLE_SAMPLES) {
|
||||
zeroSamples = 0;
|
||||
pause = true;
|
||||
computer.getMotherboard().cancelSpeedRequest(this);
|
||||
while (pause && isRunning()) {
|
||||
try {
|
||||
Thread.sleep(50);
|
||||
timerSync.lock();
|
||||
playbackFinished.signalAll();
|
||||
} catch (InterruptedException ex) {
|
||||
return;
|
||||
} catch (IllegalMonitorStateException ex) {
|
||||
// Do nothing
|
||||
} finally {
|
||||
pause = true;
|
||||
computer.getMotherboard().cancelSpeedRequest(this);
|
||||
while (pause && isRunning()) {
|
||||
try {
|
||||
timerSync.unlock();
|
||||
Thread.sleep(50);
|
||||
timerSync.lock();
|
||||
playbackFinished.signalAll();
|
||||
} catch (InterruptedException ex) {
|
||||
return;
|
||||
} catch (IllegalMonitorStateException ex) {
|
||||
// Do nothing -- this is probably caused by a suspension event
|
||||
// Do nothing
|
||||
} finally {
|
||||
try {
|
||||
timerSync.unlock();
|
||||
} catch (IllegalMonitorStateException ex) {
|
||||
// Do nothing -- this is probably caused by a suspension event
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
timerSync.lock();
|
||||
playbackFinished.signalAll();
|
||||
while (isRunning() && ticksSinceLastPlayback < ticksBeteenPlayback) {
|
||||
cpuCountReached.await();
|
||||
try {
|
||||
timerSync.lock();
|
||||
playbackFinished.signalAll();
|
||||
while (isRunning() && ticksSinceLastPlayback < ticksBeteenPlayback) {
|
||||
cpuCountReached.await();
|
||||
}
|
||||
} catch (InterruptedException ex) {
|
||||
// Do nothing, probably killing playback thread on purpose
|
||||
} finally {
|
||||
timerSync.unlock();
|
||||
}
|
||||
} catch (InterruptedException ex) {
|
||||
// Do nothing, probably killing playback thread on purpose
|
||||
} finally {
|
||||
timerSync.unlock();
|
||||
}
|
||||
}
|
||||
} catch (LineUnavailableException ex) {
|
||||
Logger.getLogger(CardMockingboard.class
|
||||
.getName()).log(Level.SEVERE, null, ex);
|
||||
} catch (InterruptedException ex) {
|
||||
Logger.getLogger(CardMockingboard.class.getName()).log(Level.SEVERE, null, ex);
|
||||
} finally {
|
||||
computer.getMotherboard().cancelSpeedRequest(this);
|
||||
System.out.println("Mockingboard playback stopped");
|
||||
|
@ -32,6 +32,11 @@ public class EnvelopeGenerator extends TimedGenerator {
|
||||
int direction;
|
||||
int amplitude;
|
||||
|
||||
boolean start1high = false;
|
||||
boolean start2high = false;
|
||||
boolean oneShot = false;
|
||||
boolean oddEven = false;
|
||||
|
||||
public EnvelopeGenerator(int _clock, int _sampleRate) {
|
||||
super(_clock, _sampleRate);
|
||||
}
|
||||
@ -50,55 +55,54 @@ public class EnvelopeGenerator extends TimedGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
int effectiveAmplitude = 0;
|
||||
public void step() {
|
||||
int stateChanges = updateCounter();
|
||||
int total = 0;
|
||||
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;
|
||||
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) {
|
||||
oddEven = false;
|
||||
counter = 0;
|
||||
cont = (shape & 8) != 0;
|
||||
attk = (shape & 4) != 0;
|
||||
alt = (shape & 2) != 0;
|
||||
hold = (shape & 1) != 0;
|
||||
if (attk) {
|
||||
hold = ((shape ^ 8) & 9) != 0;
|
||||
|
||||
start1high = !attk;
|
||||
start2high = cont && ! (attk ^ alt ^ hold);
|
||||
|
||||
setPhase(start1high);
|
||||
}
|
||||
|
||||
public void setPhase(boolean isHigh) {
|
||||
if (isHigh) {
|
||||
amplitude = 15;
|
||||
direction = -1;
|
||||
} else {
|
||||
amplitude = 0;
|
||||
direction = 1;
|
||||
} else {
|
||||
amplitude = 15;
|
||||
direction = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int getEffectiveAmplitude() {
|
||||
return effectiveAmplitude;
|
||||
}
|
||||
|
||||
public int getAmplitude() {
|
||||
|
@ -30,7 +30,7 @@ public class NoiseGenerator extends TimedGenerator {
|
||||
}
|
||||
@Override
|
||||
public int stepsPerCycle() {
|
||||
return 8;
|
||||
return 4;
|
||||
}
|
||||
public void step() {
|
||||
int stateChanges = updateCounter();
|
||||
@ -39,11 +39,14 @@ public class NoiseGenerator extends TimedGenerator {
|
||||
}
|
||||
public static final int BIT17 = 0x010000;
|
||||
public void updateRng() {
|
||||
// noise = (noise >> 1) ^ ((noise & 1) ? 0x14000 : 0);
|
||||
int newBit17 = (rng & 0x04) > 0 == (rng & 0x01) > 0 ? BIT17 : 0;
|
||||
rng = newBit17 + (rng >> 1);
|
||||
rng = ((rng & 1) != 0 ? rng ^ 0x24000 : rng) >> 1;
|
||||
if ((rng & 1) == 1) {
|
||||
state = !state;
|
||||
}
|
||||
}
|
||||
|
||||
boolean state = false;
|
||||
public boolean isOn() {
|
||||
return ((rng & 1) == 1);
|
||||
return state;
|
||||
}
|
||||
}
|
@ -58,16 +58,11 @@ public class SoundGenerator extends TimedGenerator {
|
||||
public int step(NoiseGenerator noiseGen, EnvelopeGenerator envGen) {
|
||||
int stateChanges = updateCounter();
|
||||
if (((stateChanges & 1) == 1)) inverted = !inverted;
|
||||
if (amplitude == 0 && !useEnvGen) return 0;
|
||||
if (!active && !noiseActive) return 0;
|
||||
boolean invert;
|
||||
int vol = useEnvGen ? envGen.getAmplitude() : amplitude;
|
||||
if (active) {
|
||||
invert = noiseActive && noiseGen.isOn() ? false : inverted;
|
||||
} else {
|
||||
invert = noiseActive && !noiseGen.isOn();
|
||||
}
|
||||
return invert ? -CardMockingboard.VolTable[vol] : CardMockingboard.VolTable[vol];
|
||||
double amp = stateChanges == 0 ? 1 : 1.0 / Math.max(stateChanges-1, 1);
|
||||
int vol = useEnvGen ? envGen.getEffectiveAmplitude() : amplitude;
|
||||
boolean on = noiseActive && noiseGen.isOn() || (active && inverted);
|
||||
// return invert ? -CardMockingboard.VolTable[vol] : CardMockingboard.VolTable[vol];
|
||||
return on ? (int) (CardMockingboard.VolTable[vol] * amp) : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
Loading…
Reference in New Issue
Block a user