Replace sound channel bitpacked structs with bitfields
Jeffrey Pfau jeffrey@endrift.com
Tue, 07 Oct 2014 00:36:07 -0700
2 files changed,
112 insertions(+),
120 deletions(-)
M
src/gba/gba-audio.c
→
src/gba/gba-audio.c
@@ -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 @@ audio->nextCh1 = 0;
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 @@ info->reg = GBADMARegisterSetDestControl(info->reg, DMA_FIXED);
} 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_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 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 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) {@@ -503,6 +480,25 @@ break;
} } 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) {
M
src/gba/gba-audio.h
→
src/gba/gba-audio.h
@@ -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 @@ int8_t sample;
}; 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 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;