Many sounds from one data buffer+volume control

This commit is contained in:
bloeys
2022-06-25 20:44:03 +04:00
parent cdc8d47353
commit ca4db3a12b
3 changed files with 45 additions and 13 deletions

View File

@ -58,12 +58,12 @@ func (sb *SoundBuffer) Seek(offset int64, whence int) (int64, error) {
return sb.Pos, nil return sb.Pos, nil
} }
//Clone returns a new SoundBuffer that uses the same `Data` but with an independent ReadSeeker. //Copy returns a new SoundBuffer that uses the same `Data` but with an independent ReadSeeker.
//This allows you to have many readers all reading from different positions of the same buffer. //This allows you to have many readers all reading from different positions of the same buffer.
// //
//The new buffer will have its starting position set to io.SeekStart (`Pos=0`) //The new buffer will have its starting position set to io.SeekStart (`Pos=0`)
func (sb *SoundBuffer) Clone() SoundBuffer { func (sb *SoundBuffer) Copy() *SoundBuffer {
return SoundBuffer{ return &SoundBuffer{
Data: sb.Data, Data: sb.Data,
Pos: 0, Pos: 0,
} }

43
wavy.go
View File

@ -26,9 +26,9 @@ type SoundInfo struct {
type Sound struct { type Sound struct {
Player oto.Player Player oto.Player
//FileDesc 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
FileDesc *os.File File *os.File
//Data is an io.ReadSeeker over an open file or over a buffer containing the uncompressed sound file. //Data is an io.ReadSeeker over an open file or over a buffer containing the uncompressed sound file.
//Becomes nil after close //Becomes nil after close
@ -110,6 +110,17 @@ func (s *Sound) RemainingTime() time.Duration {
return time.Duration(lenInMS) * time.Millisecond return time.Duration(lenInMS) * time.Millisecond
} }
//SetVolume must be between 0 and 1 (both inclusive). Other values will panic.
//The default volume is 1.
func (s *Sound) SetVolume(newVol float64) {
if newVol < 0 || newVol > 1 {
panic("sound volume can not be less than zero or bigger than one")
}
s.Player.SetVolume(newVol)
}
func (s *Sound) IsClosed() bool { func (s *Sound) IsClosed() bool {
return s.Data == nil return s.Data == nil
} }
@ -123,8 +134,8 @@ func (s *Sound) Close() error {
} }
var fdErr error = nil var fdErr error = nil
if s.FileDesc != nil { if s.File != nil {
fdErr = s.FileDesc.Close() fdErr = s.File.Close()
} }
s.Data = nil s.Data = nil
@ -145,7 +156,27 @@ func (s *Sound) Close() error {
return fdErr return fdErr
} }
//CopyInMemSound returns a new sound object that has identitcal info but uses the same underlying data.
//Since the sound data is not copied this function is very fast.
//
//The returned sound can be used independently of the original one (e.g. use it to play the same gunshot sound many times).
func CopyInMemSound(s *Sound) *Sound {
if s.Info.Mode == SoundMode_Streaming {
panic("streaming sounds can not be copied. Please use NewSoundStreaming instead")
}
d := s.Data.(*SoundBuffer).Copy()
return &Sound{
Player: Ctx.NewPlayer(d),
File: nil,
Data: d,
Info: s.Info,
}
}
//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
func NewSoundStreaming(fpath string) (s *Sound, err error) { func NewSoundStreaming(fpath string) (s *Sound, err error) {
//Error checking filetype //Error checking filetype
@ -165,7 +196,7 @@ func NewSoundStreaming(fpath string) (s *Sound, err error) {
} }
s = &Sound{ s = &Sound{
FileDesc: file, File: file,
Info: SoundInfo{ Info: SoundInfo{
Type: soundType, Type: soundType,
Mode: SoundMode_Streaming, Mode: SoundMode_Streaming,
@ -188,7 +219,7 @@ func NewSoundStreaming(fpath string) (s *Sound, err error) {
return s, nil return s, nil
} }
//NewSoundMem loads the entire sound file into memory and plays from that //NewSoundMem loads the entire sound file into memory
func NewSoundMem(fpath string) (s *Sound, err error) { func NewSoundMem(fpath string) (s *Sound, err error) {
//Error checking filetype //Error checking filetype

View File

@ -1,7 +1,6 @@
package wavy_test package wavy_test
import ( import (
"io"
"testing" "testing"
"time" "time"
@ -85,7 +84,9 @@ func TestSound(t *testing.T) {
s.PlaySync() s.PlaySync()
//Test repeat playing //Test repeat playing
s.Player.Reset() s2 := wavy.CopyInMemSound(s)
s.Data.Seek(0, io.SeekStart) s2.SetVolume(0.25)
s.PlaySync()
s.PlaySync() //Already finished, should not play
s2.PlaySync() //Should play from beginning
} }