Skip to content

Commit

Permalink
fix
Browse files Browse the repository at this point in the history
  • Loading branch information
akatsuki105 committed Apr 10, 2021
1 parent 76a5e7a commit ed0f085
Show file tree
Hide file tree
Showing 3 changed files with 163 additions and 2 deletions.
143 changes: 141 additions & 2 deletions pkg/gba/apu.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
package gba

import (
"mettaur/pkg/ram"
"mettaur/pkg/util"
)

const (
SND_FREQUENCY = 32768
SAMPLE_TIME float64 = 1.0 / 32768
)

const (
CH_LEN = 1 << 14
)

const (
PSG_MAX = 0x7f
PSG_MIN = -0x80
Expand All @@ -13,6 +27,131 @@ const (
var dutyLookUp = [4]float64{0.125, 0.25, 0.5, 0.75}
var dutyLookUpi = [4]float64{0.875, 0.75, 0.5, 0.25}

func (g *GBA) squareSample(ch int) {
// cntx := g._getRAM()
type SoundChan struct {
phase bool
lfsr uint16
samples float64
lengthTime float64
sweepTime float64
envTime float64
}

func (g *GBA) squareSample(ch int) int8 {
cntx := g._getRAM(ram.SOUNDCNT_X)
if !util.Bit(cntx, ch) {
return 0
}
if !(ch == 0 || ch == 1) {
return 0
}

toneAddr := uint32(ram.SOUND1CNT_H)
if ch == 1 {
toneAddr = ram.SOUND2CNT_L
}

freqHz := g._getRAM(ram.SOUND1CNT_X) & 0b0111_1111_1111
if ch == 1 {
freqHz = g._getRAM(ram.SOUND2CNT_H) & 0b0111_1111_1111
}
frequency := 131072 / float64(2048-freqHz)

// Full length of the generated wave (if enabled) in seconds
soundLen := g._getRAM(toneAddr) & 0b0011_1111
length := float64(64-soundLen) / 256

// Envelope volume change interval in seconds
envStep := g._getRAM(toneAddr) >> 8 & 0b111
envelopeInterval := float64(envStep) / 64

cycleSamples := SND_FREQUENCY / frequency // Numbers of samples that a single cycle (wave phase change 1 -> 0) takes at output sample rate

// Length reached check (if so, just disable the channel and return silence)
if (ch == 0 && util.Bit(g._getRAM(ram.SOUND1CNT_X), 14)) || (ch == 1 && util.Bit(g._getRAM(ram.SOUND2CNT_H), 14)) {
g.apu[ch].lengthTime += SAMPLE_TIME
if g.apu[ch].lengthTime >= length {
g.disableSoundChan(ch)
return 0
}
}

// Frequency sweep (Square 1 channel only)
sweepTime := (g._getRAM(ram.SOUND1CNT_L) >> 4) & 0b111
sweepInterval := 0.0078 * float64(sweepTime+1) // Frquency sweep change interval in seconds
if ch == 0 {
g.apu[0].sweepTime += SAMPLE_TIME
if g.apu[0].sweepTime >= sweepInterval {
g.apu[0].sweepTime -= sweepInterval
sweepShift := byte(g._getRAM(ram.SOUND1CNT_L) & 0b111)
if sweepShift > 0 {
disp := uint32(freqHz >> sweepShift)
if !util.Bit(g._getRAM(ram.SOUND1CNT_L), 3) {
freqHz += disp
} else {
freqHz -= disp
}

if freqHz < 0x7ff {
// update frequency
ctrl := uint16(g._getRAM(ram.SOUND1CNT_X))
ctrl = (ctrl & ^uint16(0x7ff)) | uint16(freqHz)
g._setRAM16(ram.SOUND1CNT_X, ctrl)
} else {
g.disableSoundChan(0)
}
}
}
}

envelope := uint16((g._getRAM(toneAddr) >> 12) & 0xf)
if envStep > 0 {
g.apu[ch].envTime += SAMPLE_TIME
if g.apu[ch].envTime >= envelopeInterval {
g.apu[ch].envTime -= envelopeInterval

tone := uint16(g._getRAM(toneAddr))
if util.Bit(tone, 11) {
if envelope < 0xf {
envelope++
}
} else {
if envelope > 0 {
envelope--
}
}

tone = (tone & ^uint16(0xf000)) | (envelope << 12)
g._setRAM16(toneAddr, tone)
}
}

// Phase change (when the wave goes from Low to High or High to Low, the Square Wave pattern)
duty := (g._getRAM(toneAddr) >> 6) & 0b111
g.apu[ch].samples++
if g.apu[ch].phase {
// 1 -> 0
phaseChange := cycleSamples * dutyLookUp[duty]
if g.apu[ch].samples > phaseChange {
g.apu[ch].samples -= phaseChange
g.apu[ch].phase = false
}
} else {
// 0 -> 1
phaseChange := cycleSamples * dutyLookUpi[duty]
if g.apu[ch].samples > phaseChange {
g.apu[ch].samples -= phaseChange
g.apu[ch].phase = true
}
}

if g.apu[ch].phase {
return int8((float64(envelope) / 15) * PSG_MAX)
}
return int8((float64(envelope) / 15) * PSG_MIN)
}

func (g *GBA) disableSoundChan(ch int) {
cntx := byte(g._getRAM(ram.SOUNDCNT_X))
cntx = cntx & ^(1 << ch)
g._setRAM8(ram.SOUNDCNT_X, cntx)
}
1 change: 1 addition & 0 deletions pkg/gba/gba.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ type GBA struct {
dma [4]*DMA
joypad joypad.Joypad
DoSav bool
apu [4]*SoundChan
}

type Pipe struct {
Expand Down
21 changes: 21 additions & 0 deletions pkg/ram/io.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,27 @@ const (
BLDY = base + 0x54
)

// Sound IO
const (
SOUND1CNT_L = base + 0x60
SOUND1CNT_H = base + 0x62
SOUND1CNT_X = base + 0x64
SOUND2CNT_L = base + 0x68
SOUND2CNT_H = base + 0x6c
SOUND3CNT_L = base + 0x70
SOUND3CNT_H = base + 0x72
SOUND3CNT_X = base + 0x74
SOUND4CNT_L = base + 0x78
SOUND4CNT_H = base + 0x7c
SOUNDCNT_L = base + 0x80
SOUNDCNT_H = base + 0x82
SOUNDCNT_X = base + 0x84
SOUNDBIAS = base + 0x88
WAVE_RAM = base + 0x90
FIFO_A = base + 0xa0
FIFO_B = base + 0xa4
)

// DMA Transfer
const (
DMA0SAD = base + 0xb0
Expand Down

0 comments on commit ed0f085

Please sign in to comment.