blob: 16a8843642063d45fa95ccfb658505dbc65376b0 [file] [log] [blame] [raw]
#ifndef _SID_H
#define _SID_H
#include "sound.h"
#define SOUND_FREQ_PAL_C64 985248
enum {
SID6581 = 0,
SID8580,
SID8580DB,
SID6581R1
};
// SID class
class SIDsound : public SoundSource
{
public:
SIDsound(unsigned int model, unsigned int chnlDisableMask);
virtual ~SIDsound();
virtual void reset();
virtual void setReplayFreq() {
calcEnvelopeTable();
};
void setModel(unsigned int model);
void setFrequency(unsigned int sid_frequency);
void setSampleRate(unsigned int sampleRate_);
void calcEnvelopeTable();
unsigned char read(unsigned int adr);
void write(unsigned int adr, unsigned char byte);
virtual void calcSamples(short *buf, unsigned int count);
void enableDisableChannel(unsigned int ch, bool enabled) {
voice[ch].disabled = !enabled;
}
void calcSamplesLQ(short *buf, long count);
private:
// SIDsound waveforms
enum {
WAVE_NONE, WAVE_TRI, WAVE_SAW, WAVE_TRISAW, WAVE_PULSE,
WAVE_TRIPULSE, WAVE_SAWPULSE, WAVE_TRISAWPULSE, WAVE_NOISE
};
// Envelope Genarator states
enum {
EG_FROZEN, EG_ATTACK, EG_DECAY, EG_RELEASE
};
// Filter types
enum {
FILTER_NONE, FILTER_LP, FILTER_BP, FILTER_LPBP, FILTER_HP, FILTER_NOTCH, FILTER_HPBP, FILTER_ALL
};
// Class for SID voices
class SIDVoice {
public:
int wave; // the selected waveform
int egState; // state of the EG
SIDVoice *modulatedBy; // the voice that modulates this one
SIDVoice *modulatesThis;// the voice that is modulated by this one
unsigned int accu; // accumulator of the waveform generator, 8.16 fixed
unsigned int accPrev; // previous accu value (for ring modulation)
unsigned int add; // added to the accumulator for each sample
unsigned int shiftReg; // shift register for noise waveform
unsigned short freq; // voice frequency
unsigned short pw; // pulse-width value
unsigned int envAttackAdd;
unsigned int envDecaySub;
unsigned int envSustainLevel;
unsigned int envReleaseSub;
unsigned int envCurrLevel;
unsigned int envCounter;
unsigned int envExpCounter;
unsigned int envCounterCompare;
unsigned int gate; // EG gate flag
unsigned int ring; // ring modulation flag
unsigned int test; // test flag
unsigned int filter; // voice filtered flag
unsigned int muted; // voice muted flag (only for 3rd voice)
bool disabled; // voice disabled
// This bit is set for the modulating voice,
// not for the modulated one (compared to the real one)
unsigned int sync; // sync modulation flag
};
int volume; // SID Master volume
unsigned int sidBaseFreq; // SID base frequency
unsigned int sidCyclesPerSampleInt;
unsigned int clockDeltaRemainder;
int dcMixer; // different for 6581 and 8580 (constant level output for digi)
int dcVoice;
int dcWave;
int dcDigiBlaster;
int extIn;
//
unsigned int clock();
// Wave generator functions
inline static int waveTriangle(SIDVoice &v);
inline static int waveSaw(SIDVoice &v);
inline static int wavePulse(SIDVoice &v);
inline static int waveTriSaw(SIDVoice &v);
inline static int waveTriPulse(SIDVoice &v);
inline static int waveSawPulse(SIDVoice &v);
inline static int waveTriSawPulse(SIDVoice &v);
inline static int waveNoise(SIDVoice &v);
inline static int getWaveSample(SIDVoice &v);
inline void updateShiftReg(SIDVoice &v);
// Envelope
inline int doEnvelopeGenerator(unsigned int cycles, SIDVoice &v);
static const unsigned int RateCountPeriod[16]; // Factors for A/D/S/R Timing
static const unsigned char envGenDRdivisors[256]; // For exponential approximation of D/R
static unsigned int masterVolume;
// voice array for the 3 channels
SIDVoice voice[3];
// filter stuff
unsigned char filterType; // filter type
unsigned int filterCutoff; // SID filter frequency
unsigned char filterResonance; // filter resonance (0..15)
double cutOffFreq[2048]; // filter cutoff frequency register
int resonanceCoeffDiv1024; // filter resonance * 1024
int w0; // filter cutoff freq
void setResonance();
void setFilterCutoff();
int filterOutput(unsigned int cycles, int Vi);
int Vhp; // highpass
int Vbp; // bandpass
int Vlp; // lowpass
//
unsigned char lastByteWritten;// Last value written to the SID
int model_;
bool enableDigiBlaster;
unsigned int sampleRate;
};
/*
Wave outputs
*/
inline int SIDsound::waveTriangle(SIDVoice &v)
{
unsigned int msb = (v.ring ? v.accu ^ v.modulatedBy->accu : v.accu)
& 0x8000000;
// triangle wave 15 bit only
return ((msb ? ~v.accu : v.accu) >> 15) & 0xFFF;
}
inline int SIDsound::waveSaw(SIDVoice &v)
{
return v.accu >> 16;
}
inline int SIDsound::wavePulse(SIDVoice &v)
{
// square wave starts high
return (v.test | ((v.accu >> 16) >= v.pw ? 0xFFF : 0x000));
}
inline int SIDsound::waveTriSaw(SIDVoice &v)
{
unsigned int sm = (waveTriangle(v)) & (waveSaw(v));
return (sm>>1) & (sm<<1);
}
inline int SIDsound::waveTriPulse(SIDVoice &v)
{
unsigned int sm = (waveTriangle(v)) & (wavePulse(v));
return (sm>>1) & (sm<<1);
}
inline int SIDsound::waveSawPulse(SIDVoice &v)
{
return (waveSaw(v)) & (wavePulse(v));
}
inline int SIDsound::waveTriSawPulse(SIDVoice &v)
{
unsigned int sm = (waveTriangle(v)) & (waveSaw(v)) & (wavePulse(v));
return (sm>>1) & (sm<<1);
}
#endif