mirror of
https://github.com/bloeys/wavy.git
synced 2025-12-29 09:28:19 +00:00
Use oto v2.2.0+use oto seeker+remove mutexes
This commit is contained in:
4
go.mod
4
go.mod
@ -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
4
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 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=
|
||||||
|
|||||||
@ -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
|
||||||
|
|
||||||
@ -68,8 +56,7 @@ func (ws *OggStreamer) Size() int64 {
|
|||||||
|
|
||||||
func NewOggStreamer(f *os.File, dec *oggvorbis.Reader) *OggStreamer {
|
func NewOggStreamer(f *os.File, dec *oggvorbis.Reader) *OggStreamer {
|
||||||
return &OggStreamer{
|
return &OggStreamer{
|
||||||
F: f,
|
F: f,
|
||||||
Dec: dec,
|
Dec: dec,
|
||||||
mutex: sync.Mutex{},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
43
wavy.go
43
wavy.go
@ -25,8 +25,9 @@ type SoundInfo struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Sound struct {
|
type Sound struct {
|
||||||
Player oto.Player
|
Player oto.Player
|
||||||
Info SoundInfo
|
PlayerSeeker io.Seeker
|
||||||
|
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
|
||||||
@ -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 {
|
||||||
@ -316,10 +307,11 @@ func CopyInMemSound(s *Sound) *Sound {
|
|||||||
p.SetVolume(s.Volume())
|
p.SetVolume(s.Volume())
|
||||||
|
|
||||||
return &Sound{
|
return &Sound{
|
||||||
Player: p,
|
Player: p,
|
||||||
File: nil,
|
PlayerSeeker: p.(io.Seeker),
|
||||||
Data: sb,
|
File: nil,
|
||||||
Info: s.Info,
|
Data: sb,
|
||||||
|
Info: s.Info,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -344,10 +336,11 @@ func ClipInMemSoundPercent(s *Sound, fromPercent, toPercent float64) *Sound {
|
|||||||
p.SetVolume(s.Volume())
|
p.SetVolume(s.Volume())
|
||||||
|
|
||||||
return &Sound{
|
return &Sound{
|
||||||
Player: p,
|
Player: p,
|
||||||
File: nil,
|
PlayerSeeker: p.(io.Seeker),
|
||||||
Data: sb,
|
File: nil,
|
||||||
Info: s.Info,
|
Data: sb,
|
||||||
|
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))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user