Looping sounds+get volume+pause all+resume all

This commit is contained in:
bloeys
2022-06-25 23:56:05 +04:00
parent 60913cdfa1
commit a9eccbcb91
2 changed files with 95 additions and 10 deletions

100
wavy.go
View File

@ -25,6 +25,7 @@ type SoundInfo struct {
type Sound struct { type Sound struct {
Player oto.Player Player oto.Player
Info SoundInfo
//File is the file descriptor of the sound file being streamed. //File is the file descriptor of the sound file being streamed.
//This is only set if sound is streamed, and is kept to ensure GC doesn't hit it //This is only set if sound is streamed, and is kept to ensure GC doesn't hit it
@ -34,7 +35,7 @@ type Sound struct {
//Becomes nil after close //Becomes nil after close
Data io.ReadSeeker Data io.ReadSeeker
Info SoundInfo IsLooping bool
} }
//Those values are set after Init //Those values are set after Init
@ -75,22 +76,89 @@ func Init(sr SampleRate, chanCount SoundChannelCount, bitDepth SoundBitDepth) er
return nil return nil
} }
//PlayAsync plays the sound in the background and returns //Wait blocks until sound finishes playing. If the sound is not playing Wait returns immediately.
//In the worst case (Wait sleeping then sound immediately paused), Wait will block ~4% of the total play time.
//In most other cases Wait should be accurate to ~1ms
func (s *Sound) Wait() {
if !s.IsPlaying() {
return
}
//We wait the remaining time in 25 chunks so that if the sound was paused since wait was called we don't keep blocking
sleepTime := s.RemainingTime() / 25
for s.Player.IsPlaying() {
time.Sleep(sleepTime)
}
//If there is anything left it should be tiny so we check frequently
for s.Player.IsPlaying() {
time.Sleep(time.Millisecond)
}
}
//PlayAsync plays the sound in the background and returns.
func (s *Sound) PlayAsync() { func (s *Sound) PlayAsync() {
s.Player.Play() s.Player.Play()
} }
//PlaySync plays the sound (if its not already playing) and waits for it to finish before returning. //PlaySync calls PlayAsync() followed by Wait()
func (s *Sound) PlaySync() { func (s *Sound) PlaySync() {
s.PlayAsync()
if !s.Player.IsPlaying() { s.Wait()
s.Player.Play()
} }
time.Sleep(s.RemainingTime()) //LoopAsync plays the sound 'timesToPlay' times.
for s.Player.IsPlaying() || s.Player.UnplayedBufferSize() > 0 { //If timesToPlay<0 then it is played indefinitely until paused
time.Sleep(time.Millisecond) //If timesToPlay==0 then the sound is not played.
//If a sound is already playing then it will be paused then resumed in a looping manner
func (s *Sound) LoopAsync(timesToPlay int) {
if timesToPlay == 0 {
return
} }
if s.IsPlaying() {
s.Pause()
s.Wait()
}
s.PlayAsync()
s.IsLooping = true
go func() {
if timesToPlay < 0 {
for {
s.Wait()
//Check is here because we don't want to seek back if we got paused
if !s.IsLooping {
break
}
s.SeekToPercent(0)
s.PlayAsync()
}
} else {
for timesToPlay > 0 {
timesToPlay--
s.Wait()
//Check is here because we don't want to seek back if we got paused
if !s.IsLooping {
break
}
s.SeekToPercent(0)
s.PlayAsync()
}
}
}()
} }
//TotalTime returns the time taken to play the entire sound. //TotalTime returns the time taken to play the entire sound.
@ -124,7 +192,13 @@ func (s *Sound) SetVolume(newVol float64) {
s.Player.SetVolume(newVol) s.Player.SetVolume(newVol)
} }
//Volume returns the current volume
func (s *Sound) Volume() float64 {
return s.Player.Volume()
}
func (s *Sound) Pause() { func (s *Sound) Pause() {
s.IsLooping = false
s.Player.Pause() s.Player.Pause()
} }
@ -221,6 +295,14 @@ func CopyInMemSound(s *Sound) *Sound {
} }
} }
func PauseAllSounds() {
Ctx.Suspend()
}
func ResumeAllSounds() {
Ctx.Resume()
}
//NewSoundStreaming plays sound by streaming from a file, so no need to load the entire file into memory. //NewSoundStreaming plays sound by streaming from a file, so no need to load the entire file into memory.
//Good for large sound files //Good for large sound files
func NewSoundStreaming(fpath string) (s *Sound, err error) { func NewSoundStreaming(fpath string) (s *Sound, err error) {

View File

@ -87,8 +87,11 @@ func TestSound(t *testing.T) {
s2 := wavy.CopyInMemSound(s) s2 := wavy.CopyInMemSound(s)
s2.SetVolume(0.25) s2.SetVolume(0.25)
s.PlaySync() //Already finished, should not play //Already finished, should not play
s2.PlaySync() //Should play from beginning s.PlaySync()
//Should play from beginning
s2.PlaySync()
//Test seek and play //Test seek and play
s2.SeekToPercent(0.2) s2.SeekToPercent(0.2)