diff --git a/go.mod b/go.mod index e788cff..9b52725 100755 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.18 require ( github.com/go-audio/wav v1.1.0 github.com/hajimehoshi/go-mp3 v0.3.3 - github.com/hajimehoshi/oto/v2 v2.1.0 + github.com/hajimehoshi/oto/v2 v2.2.0 github.com/jfreymuth/oggvorbis v1.0.3 ) @@ -13,5 +13,5 @@ require ( github.com/go-audio/audio v1.0.0 // indirect github.com/go-audio/riff v1.0.0 // indirect github.com/jfreymuth/vorbis v1.0.2 // indirect - golang.org/x/sys v0.0.0-20220408201424-a24fb2fb8a0f // indirect + golang.org/x/sys v0.0.0-20220712014510-0a85c31ab51e // indirect ) diff --git a/go.sum b/go.sum index 2f8fad4..d9b330d 100755 --- a/go.sum +++ b/go.sum @@ -9,6 +9,8 @@ github.com/hajimehoshi/go-mp3 v0.3.3/go.mod h1:qMJj/CSDxx6CGHiZeCgbiq2DSUkbK0Ubt github.com/hajimehoshi/oto v0.6.1/go.mod h1:0QXGEkbuJRohbJaxr7ZQSxnju7hEhseiPx2hrh6raOI= github.com/hajimehoshi/oto/v2 v2.1.0 h1:/h+UkbKzhD7xBHOQlWgKUplBPZ+J4DK3P2Y7g2UF1X4= github.com/hajimehoshi/oto/v2 v2.1.0/go.mod h1:9i0oYbpJ8BhVGkXDKdXKfFthX1JUNfXjeTp944W8TGM= +github.com/hajimehoshi/oto/v2 v2.2.0 h1:qhTriSacJ/2pdONRa90hjTvpEZH7xIP4W3itwYyE1Uk= +github.com/hajimehoshi/oto/v2 v2.2.0/go.mod h1:seWLbgHH7AyUMYKfKYT9pg7PhUu9/SisyJvNTT+ASQo= github.com/jfreymuth/oggvorbis v1.0.3 h1:MLNGGyhOMiVcvea9Dp5+gbs2SAwqwQbtrWnonYa0M0Y= github.com/jfreymuth/oggvorbis v1.0.3/go.mod h1:1U4pqWmghcoVsCJJ4fRBKv9peUJMBHixthRlBeD6uII= github.com/jfreymuth/vorbis v1.0.2 h1:m1xH6+ZI4thH927pgKD8JOH4eaGRm18rEE9/0WKjvNE= @@ -20,4 +22,6 @@ golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190429190828-d89cdac9e872/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220408201424-a24fb2fb8a0f h1:8w7RhxzTVgUzw/AH/9mUV5q0vMgy40SQRursCcfmkCw= golang.org/x/sys v0.0.0-20220408201424-a24fb2fb8a0f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220712014510-0a85c31ab51e h1:NHvCuwuS43lGnYhten69ZWqi2QOj/CiDNcKbVqwVoew= +golang.org/x/sys v0.0.0-20220712014510-0a85c31ab51e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= diff --git a/ogg_streamer.go b/ogg_streamer.go index 2b37e8a..cb0b290 100755 --- a/ogg_streamer.go +++ b/ogg_streamer.go @@ -3,7 +3,6 @@ package wavy import ( "io" "os" - "sync" "github.com/jfreymuth/oggvorbis" ) @@ -13,30 +12,19 @@ var _ io.ReadSeeker = &OggStreamer{} type OggStreamer struct { F *os.File Dec *oggvorbis.Reader - - //TODO: This is currently needed because of https://github.com/hajimehoshi/oto/issues/171 - //We should be able to delete once its resolved - mutex sync.Mutex } func (ws *OggStreamer) Read(outBuf []byte) (floatsRead int, err error) { - ws.mutex.Lock() - readerBuf := make([]float32, len(outBuf)/2) floatsRead, err = ws.Dec.Read(readerBuf) F32ToUnsignedPCM16(readerBuf[:floatsRead], outBuf) - ws.mutex.Unlock() - return floatsRead * 2, err } func (ws *OggStreamer) Seek(offset int64, whence int) (int64, error) { - ws.mutex.Lock() - defer ws.mutex.Unlock() - //This is because ogg expects position in samples not bytes offset /= BytesPerSample @@ -68,8 +56,7 @@ func (ws *OggStreamer) Size() int64 { func NewOggStreamer(f *os.File, dec *oggvorbis.Reader) *OggStreamer { return &OggStreamer{ - F: f, - Dec: dec, - mutex: sync.Mutex{}, + F: f, + Dec: dec, } } diff --git a/wav_streamer.go b/wav_streamer.go index 16288cd..22c82d0 100755 --- a/wav_streamer.go +++ b/wav_streamer.go @@ -3,7 +3,6 @@ package wavy import ( "io" "os" - "sync" "github.com/go-audio/wav" ) @@ -15,27 +14,18 @@ type WavStreamer struct { Dec *wav.Decoder Pos int64 PCMStart int64 - - //TODO: This is currently needed because of https://github.com/hajimehoshi/oto/issues/171 - //We should be able to delete once its resolved - mutex sync.Mutex } func (ws *WavStreamer) Read(outBuf []byte) (bytesRead int, err error) { - ws.mutex.Lock() bytesRead, err = ws.Dec.PCMChunk.Read(outBuf) ws.Pos += int64(bytesRead) - ws.mutex.Unlock() return bytesRead, err } func (ws *WavStreamer) Seek(offset int64, whence int) (int64, error) { - ws.mutex.Lock() - defer ws.mutex.Unlock() - //This will only seek the underlying file but not the actual decoder because it can't seek n, err := ws.Dec.Seek(offset, whence) if err != nil { @@ -89,6 +79,5 @@ func NewWavStreamer(f *os.File, wavDec *wav.Decoder) (*WavStreamer, error) { Dec: wavDec, Pos: currPos, PCMStart: currPos, - mutex: sync.Mutex{}, }, nil } diff --git a/wavy.go b/wavy.go index c4b66d3..e3bd5d7 100644 --- a/wavy.go +++ b/wavy.go @@ -25,8 +25,9 @@ type SoundInfo struct { } type Sound struct { - Player oto.Player - Info SoundInfo + Player oto.Player + PlayerSeeker io.Seeker + Info SoundInfo //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 @@ -234,13 +235,7 @@ func (s *Sound) IsPlaying() bool { func (s *Sound) SeekToPercent(percent float64) { percent = clamp01F64(percent) - s.Data.Seek(int64(float64(s.Info.Size)*percent), io.SeekStart) - - //NOTE: Due to https://github.com/hajimehoshi/oto/issues/171, it is safer to seek before reset so we don't seek while a read is happening. - //This can still happen though if for example sound was paused midway then seeked, as read would be getting called - if !s.IsPlaying() { - s.Player.Reset() - } + s.PlayerSeeker.Seek(int64(float64(s.Info.Size)*percent), io.SeekStart) } //SeekToTime moves the current position of the sound to the given duration. @@ -258,11 +253,7 @@ func (s *Sound) SeekToTime(t time.Duration) { byteCount = s.Info.Size } - s.Data.Seek(byteCount, io.SeekStart) - - if !s.IsPlaying() { - s.Player.Reset() - } + s.PlayerSeeker.Seek(byteCount, io.SeekStart) } func (s *Sound) IsClosed() bool { @@ -316,10 +307,11 @@ func CopyInMemSound(s *Sound) *Sound { p.SetVolume(s.Volume()) return &Sound{ - Player: p, - File: nil, - Data: sb, - Info: s.Info, + Player: p, + PlayerSeeker: p.(io.Seeker), + File: nil, + Data: sb, + Info: s.Info, } } @@ -344,10 +336,11 @@ func ClipInMemSoundPercent(s *Sound, fromPercent, toPercent float64) *Sound { p.SetVolume(s.Volume()) return &Sound{ - Player: p, - File: nil, - Data: sb, - Info: s.Info, + Player: p, + PlayerSeeker: p.(io.Seeker), + File: nil, + Data: sb, + Info: s.Info, } } @@ -401,6 +394,7 @@ func soundFromFile(f *os.File, s *Sound) error { s.Data = dec s.Player = Ctx.NewPlayer(dec) + s.PlayerSeeker = s.Player.(io.Seeker) s.Info.Size = dec.Length() } else if s.Info.Type == SoundType_WAV { @@ -411,6 +405,7 @@ func soundFromFile(f *os.File, s *Sound) error { s.Data = ws s.Player = Ctx.NewPlayer(ws) + s.PlayerSeeker = s.Player.(io.Seeker) s.Info.Size = ws.Size() } else if s.Info.Type == SoundType_OGG { @@ -423,6 +418,7 @@ func soundFromFile(f *os.File, s *Sound) error { s.Data = oggStreamer s.Player = Ctx.NewPlayer(oggStreamer) + s.PlayerSeeker = s.Player.(io.Seeker) s.Info.Size = oggStreamer.Size() } @@ -485,6 +481,7 @@ func decodeSoundFromReaderSeeker(r io.ReadSeeker, s *Sound) error { sb := &SoundBuffer{Data: finalBuf} s.Data = sb s.Player = Ctx.NewPlayer(sb) + s.PlayerSeeker = s.Player.(io.Seeker) s.Info.Size = int64(len(sb.Data)) } else if s.Info.Type == SoundType_WAV { @@ -502,6 +499,7 @@ func decodeSoundFromReaderSeeker(r io.ReadSeeker, s *Sound) error { sb := &SoundBuffer{Data: finalBuf} s.Data = sb s.Player = Ctx.NewPlayer(sb) + s.PlayerSeeker = s.Player.(io.Seeker) s.Info.Size = int64(len(sb.Data)) } else if s.Info.Type == SoundType_OGG { @@ -513,6 +511,7 @@ func decodeSoundFromReaderSeeker(r io.ReadSeeker, s *Sound) error { sb := &SoundBuffer{Data: F32ToUnsignedPCM16(soundData, nil)} s.Data = sb s.Player = Ctx.NewPlayer(sb) + s.PlayerSeeker = s.Player.(io.Seeker) s.Info.Size = int64(len(sb.Data)) }