beep icon indicating copy to clipboard operation
beep copied to clipboard

Setting Streamer to nil not stopping sound

Open assemblaj opened this issue 2 years ago • 0 comments

Hello, I'm from the IKEMEN-Go project. On our save-state branch, we are having an issue where setting the ctrl.Streamer instance to nil isn't stopping sound. Setting ctrl.Paused = true stops the sound, though. Any suggestions as to what could be wrong and how to pin down this issue? Here is the code in our library:

Our custom streamer for handling Panning and Volume

type SoundEffect struct {
	streamer beep.Streamer
	volume   float32
	ls, p    float32
	x        *float32
}

// sys is our global Game object 
func (s *SoundEffect) Stream(samples [][2]float64) (n int, ok bool) {
	lv, rv := s.volume, s.volume
	if sys.stereoEffects && (s.x != nil || s.p != 0) {
		var r float32
		if s.x != nil { // pan
			r = ((sys.xmax - s.ls**s.x) - s.p) / (sys.xmax - sys.xmin)
		} else { // abspan
			r = ((sys.xmax-sys.xmin)/2 - s.p) / (sys.xmax - sys.xmin)
		}
		sc := sys.panningRange / 100
		of := (100 - sys.panningRange) / 200
		lv = s.volume * 2 * (r*sc + of)
		rv = s.volume * 2 * ((1-r)*sc + of)
		if lv > 512 {
			lv = 512
		} else if lv < 0 {
			lv = 0
		}
		if rv > 512 {
			rv = 512
		} else if rv < 0 {
			rv = 0
		}
	}

	n, ok = s.streamer.Stream(samples)
	for i := range samples[:n] {
		samples[i][0] *= float64(lv / 256)
		samples[i][1] *= float64(rv / 256)
	}
	return n, ok
}

func (s *SoundEffect) Err() error {
	return s.streamer.Err()
}

How we play sound

func (s *SoundChannel) Play(sound *Sound, loop bool, freqmul float32) {
	if sound == nil {
		return
	}
	s.sound = sound
	s.streamer = s.sound.GetStreamer()
	loopCount := int(1)
	if loop {
		loopCount = -1
	}
	looper := beep.Loop(loopCount, s.streamer)
	s.sfx = &SoundEffect{streamer: looper, volume: 256}
	srcRate := s.sound.format.SampleRate
	dstRate := beep.SampleRate(audioFrequency / freqmul)
	resampler := beep.Resample(audioResampleQuality, srcRate, dstRate, s.sfx)
	s.ctrl = &beep.Ctrl{Streamer: resampler}
	sys.soundMixer.Add(s.ctrl)
}

How we are stopping sound

func (s *SoundChannel) Stop() {
	if s.ctrl != nil {
		speaker.Lock()
		s.ctrl.Streamer = nil
		speaker.Unlock()
	}
	s.sound = nil
}

assemblaj avatar Aug 26 '22 18:08 assemblaj