mirror of https://github.com/mgba-emu/mgba.git
Replace sound channel bitpacked structs with bitfields
This commit is contained in:
parent
ad7f1ae939
commit
d2adc2449a
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue