Use oto v2.2.0+use oto seeker+remove mutexes

This commit is contained in:
bloeys
2022-07-22 17:44:49 +04:00
parent 0021d0a7dc
commit 3d3cdf1e32
5 changed files with 29 additions and 50 deletions

4
go.mod
View File

@ -5,7 +5,7 @@ go 1.18
require ( require (
github.com/go-audio/wav v1.1.0 github.com/go-audio/wav v1.1.0
github.com/hajimehoshi/go-mp3 v0.3.3 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 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/audio v1.0.0 // indirect
github.com/go-audio/riff v1.0.0 // indirect github.com/go-audio/riff v1.0.0 // indirect
github.com/jfreymuth/vorbis v1.0.2 // 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
) )

4
go.sum
View File

@ -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 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 h1:/h+UkbKzhD7xBHOQlWgKUplBPZ+J4DK3P2Y7g2UF1X4=
github.com/hajimehoshi/oto/v2 v2.1.0/go.mod h1:9i0oYbpJ8BhVGkXDKdXKfFthX1JUNfXjeTp944W8TGM= 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 h1:MLNGGyhOMiVcvea9Dp5+gbs2SAwqwQbtrWnonYa0M0Y=
github.com/jfreymuth/oggvorbis v1.0.3/go.mod h1:1U4pqWmghcoVsCJJ4fRBKv9peUJMBHixthRlBeD6uII= github.com/jfreymuth/oggvorbis v1.0.3/go.mod h1:1U4pqWmghcoVsCJJ4fRBKv9peUJMBHixthRlBeD6uII=
github.com/jfreymuth/vorbis v1.0.2 h1:m1xH6+ZI4thH927pgKD8JOH4eaGRm18rEE9/0WKjvNE= 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-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 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-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= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=

View File

@ -3,7 +3,6 @@ package wavy
import ( import (
"io" "io"
"os" "os"
"sync"
"github.com/jfreymuth/oggvorbis" "github.com/jfreymuth/oggvorbis"
) )
@ -13,30 +12,19 @@ var _ io.ReadSeeker = &OggStreamer{}
type OggStreamer struct { type OggStreamer struct {
F *os.File F *os.File
Dec *oggvorbis.Reader 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) { func (ws *OggStreamer) Read(outBuf []byte) (floatsRead int, err error) {
ws.mutex.Lock()
readerBuf := make([]float32, len(outBuf)/2) readerBuf := make([]float32, len(outBuf)/2)
floatsRead, err = ws.Dec.Read(readerBuf) floatsRead, err = ws.Dec.Read(readerBuf)
F32ToUnsignedPCM16(readerBuf[:floatsRead], outBuf) F32ToUnsignedPCM16(readerBuf[:floatsRead], outBuf)
ws.mutex.Unlock()
return floatsRead * 2, err return floatsRead * 2, err
} }
func (ws *OggStreamer) Seek(offset int64, whence int) (int64, error) { 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 //This is because ogg expects position in samples not bytes
offset /= BytesPerSample offset /= BytesPerSample
@ -70,6 +58,5 @@ func NewOggStreamer(f *os.File, dec *oggvorbis.Reader) *OggStreamer {
return &OggStreamer{ return &OggStreamer{
F: f, F: f,
Dec: dec, Dec: dec,
mutex: sync.Mutex{},
} }
} }

View File

@ -3,7 +3,6 @@ package wavy
import ( import (
"io" "io"
"os" "os"
"sync"
"github.com/go-audio/wav" "github.com/go-audio/wav"
) )
@ -15,27 +14,18 @@ type WavStreamer struct {
Dec *wav.Decoder Dec *wav.Decoder
Pos int64 Pos int64
PCMStart 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) { func (ws *WavStreamer) Read(outBuf []byte) (bytesRead int, err error) {
ws.mutex.Lock()
bytesRead, err = ws.Dec.PCMChunk.Read(outBuf) bytesRead, err = ws.Dec.PCMChunk.Read(outBuf)
ws.Pos += int64(bytesRead) ws.Pos += int64(bytesRead)
ws.mutex.Unlock()
return bytesRead, err return bytesRead, err
} }
func (ws *WavStreamer) Seek(offset int64, whence int) (int64, error) { 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 //This will only seek the underlying file but not the actual decoder because it can't seek
n, err := ws.Dec.Seek(offset, whence) n, err := ws.Dec.Seek(offset, whence)
if err != nil { if err != nil {
@ -89,6 +79,5 @@ func NewWavStreamer(f *os.File, wavDec *wav.Decoder) (*WavStreamer, error) {
Dec: wavDec, Dec: wavDec,
Pos: currPos, Pos: currPos,
PCMStart: currPos, PCMStart: currPos,
mutex: sync.Mutex{},
}, nil }, nil
} }

23
wavy.go
View File

@ -26,6 +26,7 @@ type SoundInfo struct {
type Sound struct { type Sound struct {
Player oto.Player Player oto.Player
PlayerSeeker io.Seeker
Info SoundInfo Info SoundInfo
//File is the file descriptor of the sound file being streamed. //File is the file descriptor of the sound file being streamed.
@ -234,13 +235,7 @@ func (s *Sound) IsPlaying() bool {
func (s *Sound) SeekToPercent(percent float64) { func (s *Sound) SeekToPercent(percent float64) {
percent = clamp01F64(percent) percent = clamp01F64(percent)
s.Data.Seek(int64(float64(s.Info.Size)*percent), io.SeekStart) s.PlayerSeeker.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()
}
} }
//SeekToTime moves the current position of the sound to the given duration. //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 byteCount = s.Info.Size
} }
s.Data.Seek(byteCount, io.SeekStart) s.PlayerSeeker.Seek(byteCount, io.SeekStart)
if !s.IsPlaying() {
s.Player.Reset()
}
} }
func (s *Sound) IsClosed() bool { func (s *Sound) IsClosed() bool {
@ -317,6 +308,7 @@ func CopyInMemSound(s *Sound) *Sound {
return &Sound{ return &Sound{
Player: p, Player: p,
PlayerSeeker: p.(io.Seeker),
File: nil, File: nil,
Data: sb, Data: sb,
Info: s.Info, Info: s.Info,
@ -345,6 +337,7 @@ func ClipInMemSoundPercent(s *Sound, fromPercent, toPercent float64) *Sound {
return &Sound{ return &Sound{
Player: p, Player: p,
PlayerSeeker: p.(io.Seeker),
File: nil, File: nil,
Data: sb, Data: sb,
Info: s.Info, Info: s.Info,
@ -401,6 +394,7 @@ func soundFromFile(f *os.File, s *Sound) error {
s.Data = dec s.Data = dec
s.Player = Ctx.NewPlayer(dec) s.Player = Ctx.NewPlayer(dec)
s.PlayerSeeker = s.Player.(io.Seeker)
s.Info.Size = dec.Length() s.Info.Size = dec.Length()
} else if s.Info.Type == SoundType_WAV { } else if s.Info.Type == SoundType_WAV {
@ -411,6 +405,7 @@ func soundFromFile(f *os.File, s *Sound) error {
s.Data = ws s.Data = ws
s.Player = Ctx.NewPlayer(ws) s.Player = Ctx.NewPlayer(ws)
s.PlayerSeeker = s.Player.(io.Seeker)
s.Info.Size = ws.Size() s.Info.Size = ws.Size()
} else if s.Info.Type == SoundType_OGG { } else if s.Info.Type == SoundType_OGG {
@ -423,6 +418,7 @@ func soundFromFile(f *os.File, s *Sound) error {
s.Data = oggStreamer s.Data = oggStreamer
s.Player = Ctx.NewPlayer(oggStreamer) s.Player = Ctx.NewPlayer(oggStreamer)
s.PlayerSeeker = s.Player.(io.Seeker)
s.Info.Size = oggStreamer.Size() s.Info.Size = oggStreamer.Size()
} }
@ -485,6 +481,7 @@ func decodeSoundFromReaderSeeker(r io.ReadSeeker, s *Sound) error {
sb := &SoundBuffer{Data: finalBuf} sb := &SoundBuffer{Data: finalBuf}
s.Data = sb s.Data = sb
s.Player = Ctx.NewPlayer(sb) s.Player = Ctx.NewPlayer(sb)
s.PlayerSeeker = s.Player.(io.Seeker)
s.Info.Size = int64(len(sb.Data)) s.Info.Size = int64(len(sb.Data))
} else if s.Info.Type == SoundType_WAV { } else if s.Info.Type == SoundType_WAV {
@ -502,6 +499,7 @@ func decodeSoundFromReaderSeeker(r io.ReadSeeker, s *Sound) error {
sb := &SoundBuffer{Data: finalBuf} sb := &SoundBuffer{Data: finalBuf}
s.Data = sb s.Data = sb
s.Player = Ctx.NewPlayer(sb) s.Player = Ctx.NewPlayer(sb)
s.PlayerSeeker = s.Player.(io.Seeker)
s.Info.Size = int64(len(sb.Data)) s.Info.Size = int64(len(sb.Data))
} else if s.Info.Type == SoundType_OGG { } 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)} sb := &SoundBuffer{Data: F32ToUnsignedPCM16(soundData, nil)}
s.Data = sb s.Data = sb
s.Player = Ctx.NewPlayer(sb) s.Player = Ctx.NewPlayer(sb)
s.PlayerSeeker = s.Player.(io.Seeker)
s.Info.Size = int64(len(sb.Data)) s.Info.Size = int64(len(sb.Data))
} }