Skip to content

Commit

Permalink
fixed samplerate mismatch and bgm delay issue
Browse files Browse the repository at this point in the history
  • Loading branch information
ichirin2501 committed Jan 13, 2024
1 parent 49da8e9 commit c499149
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 51 deletions.
79 changes: 44 additions & 35 deletions cmd/rgnes/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,51 +64,57 @@ type Player struct {
channel chan float32
}

func newPlayer() *Player {
a := Player{}
a.channel = make(chan float32, 44100)
return &a
}

func (a *Player) Start() error {
func newPlayer() (*Player, error) {
host, err := portaudio.DefaultHostApi()
if err != nil {
return err
return nil, err
}
parameters := portaudio.HighLatencyParameters(nil, host.DefaultOutputDevice)
stream, err := portaudio.OpenStream(parameters, a.Callback)
if err != nil {
return err

p := Player{
sampleRate: parameters.SampleRate,
outputChannels: parameters.Output.Channels,
// If this channel size is too large (e.g. 44100), the BGM will be delayed. Make the size not too big
channel: make(chan float32, 3000),
}
if err := stream.Start(); err != nil {
return err

cbFunc := func(out []float32) {
var output float32
for i := range out {
if i%p.outputChannels == 0 {
select {
case sample := <-p.channel:
output = sample
default:
output = 0
}
}
out[i] = output
}
}
a.stream = stream
a.sampleRate = parameters.SampleRate
a.outputChannels = parameters.Output.Channels
return nil
stream, err := portaudio.OpenStream(parameters, cbFunc)
if err != nil {
return nil, err
}

p.stream = stream
return &p, nil
}

func (a *Player) Stop() error {
return a.stream.Close()
func (p *Player) Start() error {
return p.stream.Start()
}

func (a *Player) Callback(out []float32) {
var output float32
for i := range out {
if i%a.outputChannels == 0 {
select {
case sample := <-a.channel:
output = sample
default:
output = 0
}
}
out[i] = output
}
func (p *Player) Stop() error {
return p.stream.Close()
}
func (a *Player) Sample(v float32) {
a.channel <- v

func (p *Player) Sample(v float32) {
p.channel <- v
}

func (p *Player) SampleRate() float64 {
return p.sampleRate
}

func realMain() error {
Expand Down Expand Up @@ -149,7 +155,10 @@ func realMain() error {

portaudio.Initialize()
defer portaudio.Terminate()
player := newPlayer()
player, nil := newPlayer()
if err != nil {
return err
}
if err := player.Start(); err != nil {
return err
}
Expand Down
20 changes: 5 additions & 15 deletions nes/apu.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,13 @@ func init() {

type Player interface {
Sample(float32)
SampleRate() float64
}

type APUOption func(*APU)

type APU struct {
cpu *interrupter
player Player
sampleRate int
sampleRate float64
sampleTiming int
clock int
pulse1 *pulse
Expand All @@ -53,11 +52,11 @@ type APU struct {
writeDelayFrameCounter byte
}

func NewAPU(cpu *interrupter, p Player, opts ...APUOption) *APU {
func NewAPU(cpu *interrupter, p Player) *APU {
apu := &APU{
player: p,
cpu: cpu,
sampleRate: 44100,
sampleRate: p.SampleRate(),

clock: -1,
pulse1: newPulse(1),
Expand All @@ -69,19 +68,10 @@ func NewAPU(cpu *interrupter, p Player, opts ...APUOption) *APU {
frameStep: -1,
newFrameCounterVal: -1,
}
for _, opt := range opts {
opt(apu)
}
apu.sampleTiming = 1789773 / apu.sampleRate
apu.sampleTiming = int(1789773 / apu.sampleRate)
return apu
}

func WithSampleRate(sampleRate int) APUOption {
return func(apu *APU) {
apu.sampleRate = sampleRate
}
}

func (apu *APU) PowerUp() {
// todo
apu.writeStatus(0)
Expand Down
3 changes: 2 additions & 1 deletion tests/cpu_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ func (f *fakeRenderer) Refresh() {}

type fakePlayer struct{}

func (f *fakePlayer) Sample(v float32) {}
func (f *fakePlayer) Sample(v float32) {}
func (f *fakePlayer) SampleRate() float64 { return 44100 }

func Test_CPU_OUT_6000(t *testing.T) {
t.Parallel()
Expand Down

0 comments on commit c499149

Please sign in to comment.