forked from Apple-2-Tools/jace
Remove dead code
This commit is contained in:
parent
eb776d44af
commit
9118b83a43
@ -1,638 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2012 Brendan Robert (BLuRry) brendan.robert@gmail.com.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301 USA
|
||||
*/
|
||||
package jace.hardware.mockingboard;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import jace.hardware.CardMockingboard;
|
||||
|
||||
// Port of AY code from AppleWin -- not used buy kept for reference.
|
||||
|
||||
/***************************************************************************
|
||||
*
|
||||
* ay8910.c
|
||||
*
|
||||
*
|
||||
* Emulation of the AY-3-8910 / YM2149 sound chip.
|
||||
*
|
||||
* Based on various code snippets by Ville Hallik, Michael Cuddy,
|
||||
* Tatsuyuki Satoh, Fabrice Frances, Nicola Salmoria.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
//
|
||||
// From mame.txt (http://www.mame.net/readme.html)
|
||||
//
|
||||
// VI. Reuse of Source Code
|
||||
// --------------------------
|
||||
// This chapter might not apply to specific portions of MAME (e.g. CPU
|
||||
// emulators) which bear different copyright notices.
|
||||
// The source code cannot be used in a commercial product without the written
|
||||
// authorization of the authors. Use in non-commercial products is allowed, and
|
||||
// indeed encouraged. If you use portions of the MAME source code in your
|
||||
// program, however, you must make the full source code freely available as
|
||||
// well.
|
||||
// Usage of the _information_ contained in the source code is free for any use.
|
||||
// However, given the amount of time and energy it took to collect this
|
||||
// information, if you find new information we would appreciate if you made it
|
||||
// freely available as well.
|
||||
//
|
||||
|
||||
public class AY8910_old {
|
||||
static final int MAX_OUTPUT = 0x007fff;
|
||||
static final int MAX_AY8910 = 2;
|
||||
static final int CLOCK = 1789770;
|
||||
static final int SAMPLE_RATE = 44100;
|
||||
|
||||
// See AY8910_set_clock() for definition of STEP
|
||||
static final int STEP = 0x008000;
|
||||
static int num = 0, ym_num = 0;
|
||||
int SampleRate = 0;
|
||||
|
||||
/* register id's */
|
||||
public enum Reg {
|
||||
AFine(0, 255),
|
||||
ACoarse(1, 15),
|
||||
BFine(2, 255),
|
||||
BCoarse(3, 15),
|
||||
CFine(4, 255),
|
||||
CCoarse(5, 15),
|
||||
NoisePeriod(6, 31),
|
||||
Enable(7, 255),
|
||||
AVol(8, 31),
|
||||
BVol(9, 31),
|
||||
CVol(10, 31),
|
||||
EnvFine(11, 255),
|
||||
EnvCoarse(12, 255),
|
||||
EnvShape(13, 15),
|
||||
PortA(14, 255),
|
||||
PortB(15, 255);
|
||||
|
||||
public final int registerNumber;
|
||||
public final int max;
|
||||
Reg(int number, int maxValue) {
|
||||
registerNumber = number;
|
||||
max=maxValue;
|
||||
}
|
||||
static Reg get(int number) {
|
||||
for (Reg r:Reg.values())
|
||||
if (r.registerNumber == number) return r;
|
||||
return null;
|
||||
}
|
||||
static public Reg[] preferredOrder = new Reg[]{
|
||||
Enable,EnvShape,EnvCoarse,EnvFine,NoisePeriod,AVol,BVol,CVol,
|
||||
AFine,ACoarse,BFine,BCoarse,CFine,CCoarse};
|
||||
}
|
||||
|
||||
public AY8910_old() {
|
||||
chips = new ArrayList<PSG>();
|
||||
for (int i=0; i < MAX_AY8910; i++) {
|
||||
PSG chip = new PSG();
|
||||
chips.add(chip);
|
||||
}
|
||||
initAll(CLOCK, SAMPLE_RATE);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
private List<PSG> chips;
|
||||
|
||||
static int[] VolTable;
|
||||
static {
|
||||
buildMixerTable();
|
||||
}
|
||||
|
||||
private class PSG {
|
||||
int Channel;
|
||||
int register_latch;
|
||||
Map<Reg, Integer> registers;
|
||||
|
||||
int lastEnable;
|
||||
int UpdateStep;
|
||||
int PeriodA,PeriodB,PeriodC,PeriodN,PeriodE;
|
||||
int CountA,CountB,CountC,CountN,CountE;
|
||||
int VolA,VolB,VolC,VolE;
|
||||
int EnvelopeA,EnvelopeB,EnvelopeC;
|
||||
int OutputA,OutputB,OutputC,OutputN;
|
||||
int CountEnv;
|
||||
int Hold,Alternate,Attack,Holding;
|
||||
int RNG;
|
||||
|
||||
public PSG() {
|
||||
registers = new HashMap<Reg, Integer>();
|
||||
for (Reg r: Reg.values())
|
||||
setReg(r, 0);
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
register_latch = 0;
|
||||
RNG = 1;
|
||||
OutputA = 0;
|
||||
OutputB = 0;
|
||||
OutputC = 0;
|
||||
OutputN = 0x00ff;
|
||||
lastEnable = -1; /* force a write */
|
||||
for (Reg r: Reg.values())
|
||||
writeReg(r, 0);
|
||||
}
|
||||
|
||||
public void setClock(int clock) {
|
||||
/* the step clock for the tone and noise generators is the chip clock */
|
||||
/* divided by 8; for the envelope generator of the AY-3-8910, it is half */
|
||||
/* that much (clock/16), but the envelope of the YM2149 goes twice as */
|
||||
/* fast, therefore again clock/8. */
|
||||
/* Here we calculate the number of steps which happen during one sample */
|
||||
/* at the given sample rate. No. of events = sample rate / (clock/8). */
|
||||
/* STEP is a multiplier used to turn the fraction into a fixed point */
|
||||
/* number. */
|
||||
double clk = clock;
|
||||
double smprate = SampleRate;
|
||||
UpdateStep = (int) ((STEP * smprate * 8.0 + clk/2.0) / clk);
|
||||
}
|
||||
|
||||
public void setReg(Reg r, int value) {
|
||||
registers.put(r,value);
|
||||
}
|
||||
public int getReg(Reg r) {
|
||||
return registers.get(r);
|
||||
}
|
||||
|
||||
public void writeReg(Reg r, int value) {
|
||||
value &= r.max;
|
||||
setReg(r, value);
|
||||
int old;
|
||||
/* A note about the period of tones, noise and envelope: for speed reasons,*/
|
||||
/* we count down from the period to 0, but careful studies of the chip */
|
||||
/* output prove that it instead counts up from 0 until the counter becomes */
|
||||
/* greater or equal to the period. This is an important difference when the*/
|
||||
/* program is rapidly changing the period to modulate the sound. */
|
||||
/* To compensate for the difference, when the period is changed we adjust */
|
||||
/* our internal counter. */
|
||||
/* Also, note that period = 0 is the same as period = 1. This is mentioned */
|
||||
/* in the YM2203 data sheets. However, this does NOT apply to the Envelope */
|
||||
/* period. In that case, period = 0 is half as period = 1. */
|
||||
switch(r) {
|
||||
case ACoarse:
|
||||
case AFine:
|
||||
old = PeriodA;
|
||||
PeriodA = (getReg(Reg.AFine) + 256 * getReg(Reg.ACoarse)) * UpdateStep;
|
||||
if (PeriodA == 0) PeriodA = UpdateStep;
|
||||
CountA += PeriodA - old;
|
||||
if (CountA <= 0) CountA = 1;
|
||||
break;
|
||||
case BCoarse:
|
||||
case BFine:
|
||||
old = PeriodB;
|
||||
PeriodB = (getReg(Reg.BFine) + 256 * getReg(Reg.BCoarse)) * UpdateStep;
|
||||
if (PeriodB == 0) PeriodB = UpdateStep;
|
||||
CountB += PeriodB - old;
|
||||
if (CountB <= 0) CountB = 1;
|
||||
break;
|
||||
case CCoarse:
|
||||
case CFine:
|
||||
setReg(Reg.CCoarse, getReg(Reg.CCoarse) & 0x0f);
|
||||
old = PeriodC;
|
||||
PeriodA = (getReg(Reg.CFine) + 256 * getReg(Reg.CCoarse)) * UpdateStep;
|
||||
if (PeriodC == 0) PeriodC = UpdateStep;
|
||||
CountC += PeriodC - old;
|
||||
if (CountC <= 0) CountC = 1;
|
||||
break;
|
||||
case NoisePeriod:
|
||||
old = PeriodN;
|
||||
PeriodN = getReg(Reg.NoisePeriod) * UpdateStep;
|
||||
if (PeriodN == 0) PeriodN = UpdateStep;
|
||||
CountN += PeriodN - old;
|
||||
if (CountN <= 0) CountN = 1;
|
||||
break;
|
||||
case Enable:
|
||||
lastEnable = value;
|
||||
break;
|
||||
case AVol:
|
||||
EnvelopeA = value & 0x10;
|
||||
if (EnvelopeA > 0)
|
||||
VolA = VolE;
|
||||
else {
|
||||
if (value > 0)
|
||||
VolA = CardMockingboard.VolTable[value];
|
||||
else
|
||||
VolA = CardMockingboard.VolTable[0];
|
||||
}
|
||||
break;
|
||||
case BVol:
|
||||
EnvelopeB = value & 0x10;
|
||||
if (EnvelopeB > 0)
|
||||
VolB = VolE;
|
||||
else {
|
||||
if (value > 0)
|
||||
VolB = CardMockingboard.VolTable[value];
|
||||
else
|
||||
VolB = CardMockingboard.VolTable[0];
|
||||
}
|
||||
break;
|
||||
case CVol:
|
||||
EnvelopeC = value & 0x10;
|
||||
if (EnvelopeC > 0)
|
||||
VolC = VolE;
|
||||
else {
|
||||
if (value > 0)
|
||||
VolC = CardMockingboard.VolTable[value];
|
||||
else
|
||||
VolC = CardMockingboard.VolTable[0];
|
||||
}
|
||||
break;
|
||||
case EnvFine:
|
||||
case EnvCoarse:
|
||||
old = PeriodE;
|
||||
PeriodE = ((getReg(Reg.EnvFine) + 256 * getReg(Reg.EnvCoarse))) * UpdateStep;
|
||||
if (PeriodE == 0) PeriodE = UpdateStep / 2;
|
||||
CountE += PeriodE - old;
|
||||
if (CountE <= 0) CountE = 1;
|
||||
if (PeriodE <= 0) PeriodE = 1;
|
||||
break;
|
||||
case EnvShape:
|
||||
/* envelope shapes:
|
||||
C AtAlH
|
||||
0 0 x x \___
|
||||
0 1 x x /|__
|
||||
1 0 0 0 \\\\
|
||||
1 0 0 1 \___
|
||||
1 0 1 0 \/\/
|
||||
__
|
||||
1 0 1 1 \|
|
||||
1 1 0 0 ////
|
||||
___
|
||||
1 1 0 1 /
|
||||
1 1 1 0 /\/\
|
||||
1 1 1 1 /|__
|
||||
|
||||
The envelope counter on the AY-3-8910 has 16 steps. On the YM2149 it
|
||||
has twice the steps, happening twice as fast. Since the end result is
|
||||
just a smoother curve, we always use the YM2149 behaviour.
|
||||
*/
|
||||
Attack = (value & 0x04) != 0 ? 0x1f : 0x00;
|
||||
if ( (value & 0x08) == 0) {
|
||||
/* if Continue = 0, map the shape to the equivalent one which has Continue = 1 */
|
||||
Hold = 1;
|
||||
Alternate = Attack;
|
||||
} else {
|
||||
Hold = value & 0x01;
|
||||
Alternate = value & 0x02;
|
||||
}
|
||||
CountE = PeriodE;
|
||||
CountEnv = 0x1f;
|
||||
Holding = 0;
|
||||
VolE = CardMockingboard.VolTable[CountEnv ^ Attack];
|
||||
if (EnvelopeA != 0) VolA = VolE;
|
||||
if (EnvelopeB != 0) VolB = VolE;
|
||||
if (EnvelopeC != 0) VolC = VolE;
|
||||
break;
|
||||
case PortA:
|
||||
case PortB:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void update(int[][] buffer, int length) {
|
||||
int[] buf1, buf2, buf3;
|
||||
int outn;
|
||||
|
||||
buf1 = buffer[0];
|
||||
buf2 = buffer[1];
|
||||
buf3 = buffer[2];
|
||||
|
||||
|
||||
/* The 8910 has three outputs, each output is the mix of one of the three */
|
||||
/* tone generators and of the (single) noise generator. The two are mixed */
|
||||
/* BEFORE going into the DAC. The formula to mix each channel is: */
|
||||
/* (ToneOn | ToneDisable) & (NoiseOn | NoiseDisable). */
|
||||
/* Note that this means that if both tone and noise are disabled, the output */
|
||||
/* is 1, not 0, and can be modulated changing the volume. */
|
||||
|
||||
|
||||
/* If the channels are disabled, set their output to 1, and increase the */
|
||||
/* counter, if necessary, so they will not be inverted during this update. */
|
||||
/* Setting the output to 1 is necessary because a disabled channel is locked */
|
||||
/* into the ON state (see above); and it has no effect if the volume is 0. */
|
||||
/* If the volume is 0, increase the counter, but don't touch the output. */
|
||||
if ( (getReg(Reg.Enable) & 0x01) != 0) {
|
||||
if (CountA <= length*STEP) CountA += length*STEP;
|
||||
OutputA = 1;
|
||||
} else if (getReg(Reg.AVol) == 0) {
|
||||
/* note that I do count += length, NOT count = length + 1. You might think */
|
||||
/* it's the same since the volume is 0, but doing the latter could cause */
|
||||
/* interferencies when the program is rapidly modulating the volume. */
|
||||
if (CountA <= length*STEP) CountA += length*STEP;
|
||||
}
|
||||
|
||||
if ( (getReg(Reg.Enable) & 0x02) != 0) {
|
||||
if (CountB <= length*STEP) CountB += length*STEP;
|
||||
OutputB = 1;
|
||||
} else if (getReg(Reg.BVol) == 0) {
|
||||
if (CountB <= length*STEP) CountB += length*STEP;
|
||||
}
|
||||
|
||||
if ( (getReg(Reg.Enable) & 0x04) != 0) {
|
||||
if (CountC <= length*STEP) CountC += length*STEP;
|
||||
OutputC = 1;
|
||||
} else if (getReg(Reg.CVol) == 0) {
|
||||
if (CountC <= length*STEP) CountC += length*STEP;
|
||||
}
|
||||
|
||||
/* for the noise channel we must not touch OutputN - it's also not necessary */
|
||||
/* since we use outn. */
|
||||
if ((getReg(Reg.Enable) & 0x38) == 0x38) /* all off */
|
||||
if (CountN <= length*STEP) CountN += length*STEP;
|
||||
|
||||
outn = (OutputN | getReg(Reg.Enable));
|
||||
int index = 0;
|
||||
//System.out.println("Length:"+length);
|
||||
/* buffering loop */
|
||||
while (length != 0) {
|
||||
int vola,volb,volc;
|
||||
int left;
|
||||
|
||||
/* vola, volb and volc keep track of how long each square wave stays */
|
||||
/* in the 1 position during the sample period. */
|
||||
vola = volb = volc = 0;
|
||||
//System.out.println("STEP:"+STEP);
|
||||
|
||||
left = STEP;
|
||||
do {
|
||||
int nextevent;
|
||||
|
||||
if (CountN < left) nextevent = CountN;
|
||||
else nextevent = left;
|
||||
|
||||
if ( (outn & 0x08) != 0) {
|
||||
if (OutputA != 0) vola += CountA;
|
||||
CountA -= nextevent;
|
||||
/* PeriodA is the half period of the square wave. Here, in each */
|
||||
/* loop I add PeriodA twice, so that at the end of the loop the */
|
||||
/* square wave is in the same status (0 or 1) it was at the start. */
|
||||
/* vola is also incremented by PeriodA, since the wave has been 1 */
|
||||
/* exactly half of the time, regardless of the initial position. */
|
||||
/* If we exit the loop in the middle, OutputA has to be inverted */
|
||||
/* and vola incremented only if the exit status of the square */
|
||||
/* wave is 1. */
|
||||
while (CountA <= 0 && PeriodA > 0) {
|
||||
CountA += PeriodA;
|
||||
if (CountA > 0) {
|
||||
OutputA ^= 1;
|
||||
if (OutputA != 0) vola += PeriodA;
|
||||
break;
|
||||
}
|
||||
CountA += PeriodA;
|
||||
vola += PeriodA;
|
||||
}
|
||||
if (OutputA != 0) vola -= CountA;
|
||||
} else {
|
||||
CountA -= nextevent;
|
||||
while (CountA <= 0 && PeriodA > 0) {
|
||||
CountA += PeriodA;
|
||||
if (CountA > 0) {
|
||||
OutputA ^= 1;
|
||||
break;
|
||||
}
|
||||
CountA += PeriodA;
|
||||
}
|
||||
}
|
||||
|
||||
if ((outn & 0x10) != 0) {
|
||||
if (OutputB != 0) volb += CountB;
|
||||
CountB -= nextevent;
|
||||
while (CountB <= 0 && PeriodB > 0) {
|
||||
CountB += PeriodB;
|
||||
if (CountB > 0) {
|
||||
OutputB ^= 1;
|
||||
if (OutputB != 0) volb += PeriodB;
|
||||
break;
|
||||
}
|
||||
CountB += PeriodB;
|
||||
volb += PeriodB;
|
||||
}
|
||||
if (OutputB != 0) volb -= CountB;
|
||||
} else {
|
||||
CountB -= nextevent;
|
||||
while (CountB <= 0 && PeriodB > 0) {
|
||||
CountB += PeriodB;
|
||||
if (CountB > 0) {
|
||||
OutputB ^= 1;
|
||||
break;
|
||||
}
|
||||
CountB += PeriodB;
|
||||
}
|
||||
}
|
||||
|
||||
if ( (outn & 0x20) != 0) {
|
||||
if (OutputC != 0) volc += CountC;
|
||||
CountC -= nextevent;
|
||||
while (CountC <= 0 && PeriodC > 0) {
|
||||
CountC += PeriodC;
|
||||
if (CountC > 0) {
|
||||
OutputC ^= 1;
|
||||
if (OutputC != 0) volc += PeriodC;
|
||||
break;
|
||||
}
|
||||
CountC += PeriodC;
|
||||
volc += PeriodC;
|
||||
}
|
||||
if (OutputC != 0) volc -= CountC;
|
||||
} else {
|
||||
CountC -= nextevent;
|
||||
while (CountC <= 0 && PeriodC > 0) {
|
||||
CountC += PeriodC;
|
||||
if (CountC > 0) {
|
||||
OutputC ^= 1;
|
||||
break;
|
||||
}
|
||||
CountC += PeriodC;
|
||||
}
|
||||
}
|
||||
|
||||
CountN -= nextevent;
|
||||
if (CountN <= 0 && PeriodN > 0) {
|
||||
/* Is noise output going to change? */
|
||||
/* (bit0^bit1)? */
|
||||
if (((RNG + 1) & 2) != 0) {
|
||||
OutputN ^= 0x0FF;
|
||||
outn = (OutputN | getReg(Reg.Enable));
|
||||
}
|
||||
|
||||
/* The Random Number Generator of the 8910 is a 17-bit shift */
|
||||
/* register. The input to the shift register is bit0 XOR bit3 */
|
||||
/* (bit0 is the output). This was verified on AY-3-8910 and YM2149 chips. */
|
||||
|
||||
/* The following is a fast way to compute bit17 = bit0^bit3. */
|
||||
/* Instead of doing all the logic operations, we only check */
|
||||
/* bit0, relying on the fact that after three shifts of the */
|
||||
/* register, what now is bit3 will become bit0, and will */
|
||||
/* invert, if necessary, bit14, which previously was bit17. */
|
||||
if ((RNG & 1) != 0) RNG ^= 0x0024000; /* This version is called the "Galois configuration". */
|
||||
RNG >>= 1;
|
||||
CountN += PeriodN;
|
||||
}
|
||||
|
||||
left -= nextevent;
|
||||
} while (left > 0);
|
||||
// System.out.println("End left loop");
|
||||
|
||||
/* update envelope */
|
||||
if (Holding == 0) {
|
||||
CountE -= STEP;
|
||||
if (CountE <= 0) {
|
||||
do {
|
||||
CountEnv--;
|
||||
CountE += PeriodE;
|
||||
} while (CountE <= 0);
|
||||
|
||||
/* check envelope current position */
|
||||
if (CountEnv < 0) {
|
||||
if (Hold != 0) {
|
||||
if (Alternate != 0)
|
||||
Attack ^= 0x1f;
|
||||
Holding = 1;
|
||||
CountEnv = 0;
|
||||
} else {
|
||||
/* if CountEnv has looped an odd number of times (usually 1), */
|
||||
/* invert the output. */
|
||||
if ( (Alternate != 0) && ((CountEnv & 0x20) != 0))
|
||||
Attack ^= 0x1f;
|
||||
CountEnv &= 0x1f;
|
||||
}
|
||||
}
|
||||
|
||||
VolE = VolTable[CountEnv ^ Attack];
|
||||
/* reload volume */
|
||||
if (EnvelopeA != 0) VolA = VolE;
|
||||
if (EnvelopeB != 0) VolB = VolE;
|
||||
if (EnvelopeC != 0) VolC = VolE;
|
||||
}
|
||||
}
|
||||
|
||||
// Output PCM wave [-32768...32767] instead of MAME's voltage level [0...32767]
|
||||
// - This allows for better s/w mixing
|
||||
buf1[index] = (vola * VolA) / STEP;
|
||||
buf2[index] = (volb * VolB) / STEP;
|
||||
buf3[index] = (volc * VolC) / STEP;
|
||||
/*
|
||||
if(VolA != 0) {
|
||||
if (vola != 0) buf1[index] = (vola * VolA) / STEP;
|
||||
else buf1[index] = -VolA;
|
||||
} else {
|
||||
buf1[index] = 0;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
if(VolB != 0) {
|
||||
if (volb != 0) buf2[index] = (volb * VolB) / STEP;
|
||||
else buf2[index] = -VolB;
|
||||
} else
|
||||
buf2[index] = 0;
|
||||
|
||||
//
|
||||
|
||||
if(VolC != 0) {
|
||||
if (volc != 0) buf3[index] = (volc * VolC) / STEP;
|
||||
else buf3[index] = -VolC;
|
||||
} else
|
||||
buf3[index] = 0;
|
||||
*/
|
||||
index++;
|
||||
length--;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public void writeReg(int chipNumber, int register, int value) {
|
||||
Reg r = Reg.get(register);
|
||||
writeReg(chipNumber, r, value);
|
||||
}
|
||||
|
||||
public void writeReg(int chipNumber, Reg register, int value) {
|
||||
chips.get(chipNumber).writeReg(register, value);
|
||||
}
|
||||
|
||||
// /length/ is the number of samples we require
|
||||
// NB. This should be called at twice the 6522 IRQ rate or (eg) 60Hz if no IRQ.
|
||||
public void update(int chipNumber,int[][] buffer,int length) {
|
||||
chips.get(chipNumber).update(buffer, length);
|
||||
}
|
||||
|
||||
int[][] buffers;
|
||||
int bufferLength = -1;
|
||||
public int[][] getBuffers(int length) {
|
||||
if (buffers == null || bufferLength != length) {
|
||||
buffers = new int[3][length];
|
||||
bufferLength = length;
|
||||
}
|
||||
return buffers;
|
||||
}
|
||||
|
||||
public void playSound(int size, int[] left, int[] right) {
|
||||
int[][] buffers = getBuffers(left.length);
|
||||
update(0, buffers, size);
|
||||
mixDown(left, buffers, size);
|
||||
update(1, buffers, size);
|
||||
mixDown(right, buffers, size);
|
||||
}
|
||||
|
||||
public void mixDown(int[] out, int[][] in, int size) {
|
||||
for (int i=0; i < size; i++) {
|
||||
int sample = (in[0][i] + in[1][i] + in[2][i]) / 3;
|
||||
out[i] = sample;
|
||||
}
|
||||
}
|
||||
|
||||
public void setClock(int chipNumber,int clock) {
|
||||
chips.get(chipNumber).setClock(clock);
|
||||
}
|
||||
|
||||
public void reset(int chipNumber) {
|
||||
chips.get(chipNumber).reset();
|
||||
}
|
||||
|
||||
public void initAll(int nClock, int nSampleRate) {
|
||||
SampleRate = nSampleRate;
|
||||
for (PSG p:chips) {
|
||||
p.setClock(nClock);
|
||||
p.reset();
|
||||
}
|
||||
}
|
||||
|
||||
public void initClock(int nClock) {
|
||||
for (PSG p:chips) p.setClock(nClock);
|
||||
}
|
||||
|
||||
static void buildMixerTable() {
|
||||
VolTable = new int[32];
|
||||
int SampleRate;
|
||||
|
||||
/* calculate the volume->voltage conversion table */
|
||||
/* The AY-3-8910 has 16 levels, in a logarithmic scale (3dB per step) */
|
||||
/* The YM2149 still has 16 levels for the tone generators, but 32 for */
|
||||
/* the envelope generator (1.5dB per step). */
|
||||
double out = MAX_OUTPUT;
|
||||
for (int i = 31;i > 0;i--) {
|
||||
VolTable[i] = (int) (out + 0.5); /* round to nearest */ // [TC: unsigned int cast]
|
||||
out /= 1.188502227; /* = 10 ^ (1.5/20) = 1.5dB */
|
||||
}
|
||||
VolTable[0] = 0;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user