Replace sound channel bitpacked structs with bitfields

This commit is contained in:
Jeffrey Pfau 2014-10-07 00:36:07 -07:00
parent ad7f1ae939
commit d2adc2449a
2 changed files with 112 additions and 120 deletions

View File

@ -10,6 +10,7 @@ const unsigned GBA_AUDIO_SAMPLES = 2048;
const unsigned GBA_AUDIO_FIFO_SIZE = 8 * sizeof(int32_t);
#define SWEEP_CYCLES (GBA_ARM7TDMI_FREQUENCY / 128)
static bool _writeEnvelope(struct GBAAudioEnvelope* envelope, uint16_t value);
static int32_t _updateSquareChannel(struct GBAAudioSquareControl* envelope, int duty);
static void _updateEnvelope(struct GBAAudioEnvelope* envelope);
static bool _updateSweep(struct GBAAudioChannel1* ch);
@ -33,21 +34,10 @@ void GBAAudioReset(struct GBAAudio* audio) {
audio->nextCh2 = 0;
audio->nextCh3 = 0;
audio->nextCh4 = 0;
audio->ch1.sweep.time = 0;
audio->ch1.envelope.nextStep = INT_MAX;
audio->ch1.control.nextStep = 0;
audio->ch1.control.endTime = 0;
audio->ch1.nextSweep = INT_MAX;
audio->ch1.sample = 0;
audio->ch2.envelope.nextStep = INT_MAX;
audio->ch2.control.nextStep = 0;
audio->ch2.control.endTime = 0;
audio->ch2.sample = 0;
audio->ch3.bank.packed = 0;
audio->ch3.control.endTime = 0;
audio->ch3.sample = 0;
audio->ch4.sample = 0;
audio->ch4.envelope.nextStep = INT_MAX;
audio->ch1 = (struct GBAAudioChannel1) { .envelope = { .nextStep = INT_MAX }, .nextSweep = INT_MAX };
audio->ch2 = (struct GBAAudioChannel2) { .envelope = { .nextStep = INT_MAX } };
audio->ch3 = (struct GBAAudioChannel3) { .bank = { .bank = 0 } };
audio->ch4 = (struct GBAAudioChannel4) { .envelope = { .nextStep = INT_MAX } };
audio->chA.dmaSource = 0;
audio->chB.dmaSource = 0;
audio->eventDiff = 0;
@ -257,7 +247,9 @@ void GBAAudioScheduleFifoDma(struct GBAAudio* audio, int number, struct GBADMA*
}
void GBAAudioWriteSOUND1CNT_LO(struct GBAAudio* audio, uint16_t value) {
audio->ch1.sweep.packed = value;
audio->ch1.sweep.shift = GBAAudioRegisterSquareSweepGetShift(value);
audio->ch1.sweep.direction = GBAAudioRegisterSquareSweepGetDirection(value);
audio->ch1.sweep.time = GBAAudioRegisterSquareSweepGetTime(value);
if (audio->ch1.sweep.time) {
audio->ch1.nextSweep = audio->ch1.sweep.time * SWEEP_CYCLES;
} else {
@ -266,23 +258,16 @@ void GBAAudioWriteSOUND1CNT_LO(struct GBAAudio* audio, uint16_t value) {
}
void GBAAudioWriteSOUND1CNT_HI(struct GBAAudio* audio, uint16_t value) {
audio->ch1.envelope.packed = value;
audio->ch1.envelope.dead = 0;
if (audio->ch1.envelope.stepTime) {
audio->ch1.envelope.nextStep = 0;
} else {
audio->ch1.envelope.nextStep = INT_MAX;
if (audio->ch1.envelope.initialVolume == 0) {
audio->ch1.envelope.dead = 1;
audio->ch1.sample = 0;
}
if (!_writeEnvelope(&audio->ch1.envelope, value)) {
audio->ch1.sample = 0;
}
}
void GBAAudioWriteSOUND1CNT_X(struct GBAAudio* audio, uint16_t value) {
audio->ch1.control.packed = value;
audio->ch1.control.frequency = GBAAudioRegisterControlGetFrequency(value);
audio->ch1.control.stop = GBAAudioRegisterControlGetStop(value);
audio->ch1.control.endTime = (GBA_ARM7TDMI_FREQUENCY * (64 - audio->ch1.envelope.length)) >> 8;
if (audio->ch1.control.restart) {
if (GBAAudioRegisterControlIsRestart(value)) {
if (audio->ch1.sweep.time) {
audio->ch1.nextSweep = audio->ch1.sweep.time * SWEEP_CYCLES;
} else {
@ -307,23 +292,16 @@ void GBAAudioWriteSOUND1CNT_X(struct GBAAudio* audio, uint16_t value) {
}
void GBAAudioWriteSOUND2CNT_LO(struct GBAAudio* audio, uint16_t value) {
audio->ch2.envelope.packed = value;
audio->ch2.envelope.dead = 0;
if (audio->ch2.envelope.stepTime) {
audio->ch2.envelope.nextStep = 0;
} else {
audio->ch2.envelope.nextStep = INT_MAX;
if (audio->ch2.envelope.initialVolume == 0) {
audio->ch2.envelope.dead = 1;
audio->ch2.sample = 0;
}
if (!_writeEnvelope(&audio->ch2.envelope, value)) {
audio->ch2.sample = 0;
}
}
void GBAAudioWriteSOUND2CNT_HI(struct GBAAudio* audio, uint16_t value) {
audio->ch2.control.packed = value;
audio->ch1.control.endTime = (GBA_ARM7TDMI_FREQUENCY * (64 - audio->ch2.envelope.length)) >> 8;
if (audio->ch2.control.restart) {
audio->ch2.control.frequency = GBAAudioRegisterControlGetFrequency(value);
audio->ch2.control.stop = GBAAudioRegisterControlGetStop(value);
audio->ch2.control.endTime = (GBA_ARM7TDMI_FREQUENCY * (64 - audio->ch2.envelope.length)) >> 8;
if (GBAAudioRegisterControlIsRestart(value)) {
audio->playingCh2 = 1;
audio->ch2.envelope.currentVolume = audio->ch2.envelope.initialVolume;
if (audio->ch2.envelope.stepTime) {
@ -336,42 +314,41 @@ void GBAAudioWriteSOUND2CNT_HI(struct GBAAudio* audio, uint16_t value) {
}
void GBAAudioWriteSOUND3CNT_LO(struct GBAAudio* audio, uint16_t value) {
audio->ch3.bank.packed = value;
audio->ch3.bank.size = GBAAudioRegisterBankGetSize(value);
audio->ch3.bank.bank = GBAAudioRegisterBankGetBank(value);
audio->ch3.bank.enable = GBAAudioRegisterBankGetEnable(value);
if (audio->ch3.control.endTime >= 0) {
audio->playingCh3 = audio->ch3.bank.enable;
}
}
void GBAAudioWriteSOUND3CNT_HI(struct GBAAudio* audio, uint16_t value) {
audio->ch3.wave.packed = value;
audio->ch3.wave.length = GBAAudioRegisterBankWaveGetLength(value);
audio->ch3.wave.volume = GBAAudioRegisterBankWaveGetVolume(value);
}
void GBAAudioWriteSOUND3CNT_X(struct GBAAudio* audio, uint16_t value) {
audio->ch3.control.packed = value;
audio->ch3.control.rate = GBAAudioRegisterControlGetRate(value);
audio->ch3.control.stop = GBAAudioRegisterControlGetStop(value);
audio->ch3.control.endTime = (GBA_ARM7TDMI_FREQUENCY * (256 - audio->ch3.wave.length)) >> 8;
if (audio->ch3.control.restart) {
if (GBAAudioRegisterControlIsRestart(value)) {
audio->playingCh3 = audio->ch3.bank.enable;
}
}
void GBAAudioWriteSOUND4CNT_LO(struct GBAAudio* audio, uint16_t value) {
audio->ch4.envelope.packed = value;
audio->ch4.envelope.dead = 0;
if (audio->ch4.envelope.stepTime) {
audio->ch4.envelope.nextStep = 0;
} else {
audio->ch4.envelope.nextStep = INT_MAX;
if (audio->ch4.envelope.initialVolume == 0) {
audio->ch4.envelope.dead = 1;
audio->ch4.sample = 0;
}
if (!_writeEnvelope(&audio->ch4.envelope, value)) {
audio->ch4.sample = 0;
}
}
void GBAAudioWriteSOUND4CNT_HI(struct GBAAudio* audio, uint16_t value) {
audio->ch4.control.packed = value;
audio->ch4.control.ratio = GBAAudioRegisterCh4ControlGetRatio(value);
audio->ch4.control.frequency = GBAAudioRegisterCh4ControlGetFrequency(value);
audio->ch4.control.power = GBAAudioRegisterCh4ControlGetPower(value);
audio->ch4.control.stop = GBAAudioRegisterCh4ControlGetStop(value);
audio->ch4.control.endTime = (GBA_ARM7TDMI_FREQUENCY * (64 - audio->ch4.envelope.length)) >> 8;
if (audio->ch4.control.restart) {
if (GBAAudioRegisterCh4ControlIsRestart(value)) {
audio->playingCh4 = 1;
audio->ch4.envelope.currentVolume = audio->ch4.envelope.initialVolume;
if (audio->ch4.envelope.stepTime) {
@ -505,6 +482,25 @@ unsigned GBAAudioResampleNN(struct GBAAudio* audio, float ratio, float* drift, s
return totalRead;
}
bool _writeEnvelope(struct GBAAudioEnvelope* envelope, uint16_t value) {
envelope->length = GBAAudioRegisterEnvelopeGetLength(value);
envelope->duty = GBAAudioRegisterEnvelopeGetDuty(value);
envelope->stepTime = GBAAudioRegisterEnvelopeGetStepTime(value);
envelope->direction = GBAAudioRegisterEnvelopeGetDirection(value);
envelope->initialVolume = GBAAudioRegisterEnvelopeGetInitialVolume(value);
envelope->dead = 0;
if (envelope->stepTime) {
envelope->nextStep = 0;
} else {
envelope->nextStep = INT_MAX;
if (envelope->initialVolume == 0) {
envelope->dead = 1;
return false;
}
}
return true;
}
static int32_t _updateSquareChannel(struct GBAAudioSquareControl* control, int duty) {
control->hi = !control->hi;
int period = 16 * (2048 - control->frequency);

View File

@ -9,46 +9,64 @@ struct GBADMA;
extern const unsigned GBA_AUDIO_SAMPLES;
DECL_BITFIELD(GBAAudioRegisterEnvelope, uint16_t);
DECL_BITS(GBAAudioRegisterEnvelope, Length, 0, 6);
DECL_BITS(GBAAudioRegisterEnvelope, Duty, 6, 2);
DECL_BITS(GBAAudioRegisterEnvelope, StepTime, 8, 3);
DECL_BIT(GBAAudioRegisterEnvelope, Direction, 11);
DECL_BITS(GBAAudioRegisterEnvelope, InitialVolume, 12, 4);
DECL_BITFIELD(GBAAudioRegisterControl, uint16_t);
DECL_BITS(GBAAudioRegisterControl, Rate, 0, 11);
DECL_BITS(GBAAudioRegisterControl, Frequency, 0, 11);
DECL_BIT(GBAAudioRegisterControl, Stop, 14);
DECL_BIT(GBAAudioRegisterControl, Restart, 15);
DECL_BITFIELD(GBAAudioRegisterSquareSweep, uint16_t);
DECL_BITS(GBAAudioRegisterSquareSweep, Shift, 0, 3);
DECL_BIT(GBAAudioRegisterSquareSweep, Direction, 3);
DECL_BITS(GBAAudioRegisterSquareSweep, Time, 4, 3);
DECL_BITFIELD(GBAAudioRegisterBank, uint16_t);
DECL_BIT(GBAAudioRegisterBank, Size, 5);
DECL_BIT(GBAAudioRegisterBank, Bank, 6);
DECL_BIT(GBAAudioRegisterBank, Enable, 7);
DECL_BITFIELD(GBAAudioRegisterBankWave, uint16_t);
DECL_BITS(GBAAudioRegisterBankWave, Length, 0, 8);
DECL_BITS(GBAAudioRegisterBankWave, Volume, 13, 3);
DECL_BITFIELD(GBAAudioRegisterCh4Control, uint16_t);
DECL_BITS(GBAAudioRegisterCh4Control, Ratio, 0, 3);
DECL_BIT(GBAAudioRegisterCh4Control, Power, 3);
DECL_BITS(GBAAudioRegisterCh4Control, Frequency, 4, 4);
DECL_BIT(GBAAudioRegisterCh4Control, Stop, 14);
DECL_BIT(GBAAudioRegisterCh4Control, Restart, 15);
struct GBAAudioEnvelope {
union {
struct {
unsigned length : 6;
unsigned duty : 2;
unsigned stepTime : 3;
unsigned direction : 1;
unsigned initialVolume : 4;
};
uint16_t packed;
};
uint8_t length;
uint8_t duty;
uint8_t stepTime;
uint8_t initialVolume;
bool direction;
int currentVolume;
int dead;
int32_t nextStep;
};
struct GBAAudioSquareControl {
union {
struct {
unsigned frequency : 11;
unsigned : 3;
unsigned stop : 1;
unsigned restart : 1;
};
uint16_t packed;
};
uint16_t frequency;
bool stop;
int hi;
int32_t nextStep;
int32_t endTime;
};
struct GBAAudioChannel1 {
union GBAAudioSquareSweep {
struct {
unsigned shift : 3;
unsigned direction : 1;
unsigned time : 3;
unsigned : 9;
};
uint16_t packed;
struct GBAAudioSquareSweep {
uint8_t shift;
uint8_t time;
bool direction;
} sweep;
int32_t nextSweep;
@ -64,36 +82,20 @@ struct GBAAudioChannel2 {
};
struct GBAAudioChannel3 {
union {
struct {
unsigned : 5;
unsigned size : 1;
unsigned bank : 1;
unsigned enable : 1;
unsigned : 7;
};
uint16_t packed;
struct {
bool size;
bool bank;
bool enable;
} bank;
union {
struct {
unsigned length : 8;
unsigned : 5;
unsigned volume : 3;
};
uint16_t packed;
struct {
uint8_t length;
uint8_t volume;
} wave;
struct {
union {
struct {
unsigned rate : 11;
unsigned : 3;
unsigned stop : 1;
unsigned restart : 1;
};
uint16_t packed;
};
uint16_t rate;
bool stop;
int32_t endTime;
} control;
@ -103,18 +105,12 @@ struct GBAAudioChannel3 {
struct GBAAudioChannel4 {
struct GBAAudioEnvelope envelope;
struct {
union {
struct {
unsigned ratio : 3;
unsigned power : 1;
unsigned frequency : 4;
unsigned : 6;
unsigned stop : 1;
unsigned restart : 1;
};
uint16_t packed;
};
uint8_t ratio;
uint8_t frequency;
bool power;
bool stop;
int32_t endTime;
} control;