mirror of
https://github.com/bloeys/wavy.git
synced 2025-12-29 09:28:19 +00:00
Wav file loading
This commit is contained in:
7
go.mod
7
go.mod
@ -7,4 +7,9 @@ require (
|
|||||||
github.com/hajimehoshi/oto/v2 v2.1.0
|
github.com/hajimehoshi/oto/v2 v2.1.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require golang.org/x/sys v0.0.0-20220408201424-a24fb2fb8a0f // indirect
|
require (
|
||||||
|
github.com/go-audio/audio v1.0.0 // indirect
|
||||||
|
github.com/go-audio/riff v1.0.0 // indirect
|
||||||
|
github.com/go-audio/wav v1.1.0 // indirect
|
||||||
|
golang.org/x/sys v0.0.0-20220408201424-a24fb2fb8a0f // indirect
|
||||||
|
)
|
||||||
|
|||||||
6
go.sum
6
go.sum
@ -1,3 +1,9 @@
|
|||||||
|
github.com/go-audio/audio v1.0.0 h1:zS9vebldgbQqktK4H0lUqWrG8P0NxCJVqcj7ZpNnwd4=
|
||||||
|
github.com/go-audio/audio v1.0.0/go.mod h1:6uAu0+H2lHkwdGsAY+j2wHPNPpPoeg5AaEFh9FlA+Zs=
|
||||||
|
github.com/go-audio/riff v1.0.0 h1:d8iCGbDvox9BfLagY94fBynxSPHO80LmZCaOsmKxokA=
|
||||||
|
github.com/go-audio/riff v1.0.0/go.mod h1:l3cQwc85y79NQFCRB7TiPoNiaijp6q8Z0Uv38rVG498=
|
||||||
|
github.com/go-audio/wav v1.1.0 h1:jQgLtbqBzY7G+BM8fXF7AHUk1uHUviWS4X39d5rsL2g=
|
||||||
|
github.com/go-audio/wav v1.1.0/go.mod h1:mpe9qfwbScEbkd8uybLuIpTgHyrISw/OTuvjUW2iGtE=
|
||||||
github.com/hajimehoshi/go-mp3 v0.3.3 h1:cWnfRdpye2m9ElSoVqneYRcpt/l3ijttgjMeQh+r+FE=
|
github.com/hajimehoshi/go-mp3 v0.3.3 h1:cWnfRdpye2m9ElSoVqneYRcpt/l3ijttgjMeQh+r+FE=
|
||||||
github.com/hajimehoshi/go-mp3 v0.3.3/go.mod h1:qMJj/CSDxx6CGHiZeCgbiq2DSUkbK0UbtXShQcnfyMM=
|
github.com/hajimehoshi/go-mp3 v0.3.3/go.mod h1:qMJj/CSDxx6CGHiZeCgbiq2DSUkbK0UbtXShQcnfyMM=
|
||||||
github.com/hajimehoshi/oto v0.6.1/go.mod h1:0QXGEkbuJRohbJaxr7ZQSxnju7hEhseiPx2hrh6raOI=
|
github.com/hajimehoshi/oto v0.6.1/go.mod h1:0QXGEkbuJRohbJaxr7ZQSxnju7hEhseiPx2hrh6raOI=
|
||||||
|
|||||||
@ -5,6 +5,7 @@ type SoundType int
|
|||||||
const (
|
const (
|
||||||
SoundType_Unknown SoundType = iota
|
SoundType_Unknown SoundType = iota
|
||||||
SoundType_MP3
|
SoundType_MP3
|
||||||
|
SoundType_WAV
|
||||||
)
|
)
|
||||||
|
|
||||||
type SampleRate int
|
type SampleRate int
|
||||||
|
|||||||
BIN
test_audio_files/camera.wav
Executable file
BIN
test_audio_files/camera.wav
Executable file
Binary file not shown.
11
test_audio_files/license.txt
Executable file
11
test_audio_files/license.txt
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
|
||||||
|
"Free Sounds Library"
|
||||||
|
|
||||||
|
|
||||||
|
Free Sound Effects Site.
|
||||||
|
|
||||||
|
|
||||||
|
Licence: License: Attribution 4.0 International (CC BY 4.0). You are allowed to use sound effects free of charge and royalty free in your multimedia projects for commercial or non-commercial purposes.
|
||||||
|
|
||||||
|
|
||||||
|
http://www.freesoundslibrary.com
|
||||||
87
wavy.go
87
wavy.go
@ -7,9 +7,9 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/go-audio/wav"
|
||||||
"github.com/hajimehoshi/go-mp3"
|
"github.com/hajimehoshi/go-mp3"
|
||||||
"github.com/hajimehoshi/oto/v2"
|
"github.com/hajimehoshi/oto/v2"
|
||||||
)
|
)
|
||||||
@ -52,7 +52,7 @@ var (
|
|||||||
|
|
||||||
//Pre-defined errors
|
//Pre-defined errors
|
||||||
var (
|
var (
|
||||||
ErrunknownSoundType = errors.New("unknown sound type. Sound file extension must be one of: .mp3")
|
errUnknownSoundType = errors.New("unknown sound type. Sound file extension must be one of: .mp3")
|
||||||
)
|
)
|
||||||
|
|
||||||
//Init prepares the default audio device and does any required setup.
|
//Init prepares the default audio device and does any required setup.
|
||||||
@ -354,14 +354,9 @@ func ResumeAllSounds() {
|
|||||||
//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) {
|
||||||
|
|
||||||
//Error checking filetype
|
soundType := GetSoundFileType(fpath)
|
||||||
soundType := SoundType_Unknown
|
|
||||||
if strings.HasSuffix(fpath, ".mp3") {
|
|
||||||
soundType = SoundType_MP3
|
|
||||||
}
|
|
||||||
|
|
||||||
if soundType == SoundType_Unknown {
|
if soundType == SoundType_Unknown {
|
||||||
return nil, ErrunknownSoundType
|
return nil, errUnknownSoundType
|
||||||
}
|
}
|
||||||
|
|
||||||
//We read file but don't close so the player can stream the file any time later
|
//We read file but don't close so the player can stream the file any time later
|
||||||
@ -378,17 +373,9 @@ func NewSoundStreaming(fpath string) (s *Sound, err error) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
//Load file depending on type
|
err = soundFromReaderSeeker(file, s)
|
||||||
if soundType == SoundType_MP3 {
|
if err != nil {
|
||||||
|
return nil, getLoadingErr(fpath, err)
|
||||||
dec, err := mp3.NewDecoder(file)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
s.Info.Size = dec.Length()
|
|
||||||
s.Player = Ctx.NewPlayer(dec)
|
|
||||||
s.Data = dec
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return s, nil
|
return s, nil
|
||||||
@ -397,19 +384,14 @@ func NewSoundStreaming(fpath string) (s *Sound, err error) {
|
|||||||
//NewSoundMem loads the entire sound file into memory
|
//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
|
soundType := GetSoundFileType(fpath)
|
||||||
soundType := SoundType_Unknown
|
|
||||||
if strings.HasSuffix(fpath, ".mp3") {
|
|
||||||
soundType = SoundType_MP3
|
|
||||||
}
|
|
||||||
|
|
||||||
if soundType == SoundType_Unknown {
|
if soundType == SoundType_Unknown {
|
||||||
return nil, ErrunknownSoundType
|
return nil, getLoadingErr(fpath, errUnknownSoundType)
|
||||||
}
|
}
|
||||||
|
|
||||||
fileBytes, err := os.ReadFile(fpath)
|
fileBytes, err := os.ReadFile(fpath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, getLoadingErr(fpath, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
bytesReader := bytes.NewReader(fileBytes)
|
bytesReader := bytes.NewReader(fileBytes)
|
||||||
@ -420,34 +402,69 @@ func NewSoundMem(fpath string) (s *Sound, err error) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
//Load file depending on type
|
err = soundFromReaderSeeker(bytesReader, s)
|
||||||
if soundType == SoundType_MP3 {
|
if err != nil {
|
||||||
|
return nil, getLoadingErr(fpath, err)
|
||||||
|
}
|
||||||
|
|
||||||
dec, err := mp3.NewDecoder(bytesReader)
|
return s, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getLoadingErr(fpath string, err error) error {
|
||||||
|
return fmt.Errorf("failed to load '%s' with err '%s'", fpath, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
func soundFromReaderSeeker(r io.ReadSeeker, s *Sound) error {
|
||||||
|
|
||||||
|
if s.Info.Type == SoundType_MP3 {
|
||||||
|
|
||||||
|
dec, err := mp3.NewDecoder(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
finalBuf, err := ReadAllFromReader(dec, 0, uint64(dec.Length()))
|
finalBuf, err := ReadAllFromReader(dec, 0, uint64(dec.Length()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
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.Info.Size = int64(len(sb.Data))
|
s.Info.Size = int64(len(sb.Data))
|
||||||
|
return nil
|
||||||
|
|
||||||
|
} else if s.Info.Type == SoundType_WAV {
|
||||||
|
|
||||||
|
wavDec := wav.NewDecoder(r)
|
||||||
|
err := wavDec.FwdToPCM()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
finalBuf, err := ReadAllFromReader(wavDec.PCMChunk, 0, uint64(wavDec.PCMSize))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
sb := &SoundBuffer{Data: finalBuf}
|
||||||
|
s.Data = sb
|
||||||
|
s.Player = Ctx.NewPlayer(sb)
|
||||||
|
s.Info.Size = int64(len(sb.Data))
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return s, nil
|
panic("invalid sound type")
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetSoundFileType(fpath string) SoundType {
|
func GetSoundFileType(fpath string) SoundType {
|
||||||
|
|
||||||
ext := path.Ext(fpath)
|
ext := path.Ext(fpath)
|
||||||
switch ext {
|
switch ext {
|
||||||
case "mp3":
|
case ".mp3":
|
||||||
return SoundType_MP3
|
return SoundType_MP3
|
||||||
|
case ".wav", ".wave":
|
||||||
|
return SoundType_WAV
|
||||||
default:
|
default:
|
||||||
return SoundType_Unknown
|
return SoundType_Unknown
|
||||||
}
|
}
|
||||||
|
|||||||
17
wavy_test.go
17
wavy_test.go
@ -9,16 +9,16 @@ import (
|
|||||||
|
|
||||||
func TestSound(t *testing.T) {
|
func TestSound(t *testing.T) {
|
||||||
|
|
||||||
fatihaFilepath := "./test_audio_files/Fatiha.mp3"
|
|
||||||
tadaFilepath := "./test_audio_files/tada.mp3"
|
|
||||||
const fatihaLenMS = 55484
|
|
||||||
|
|
||||||
err := wavy.Init(wavy.SampleRate_44100, wavy.SoundChannelCount_2, wavy.SoundBitDepth_2)
|
err := wavy.Init(wavy.SampleRate_44100, wavy.SoundChannelCount_2, wavy.SoundBitDepth_2)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Failed to init wavy. Err: %s\n", err)
|
t.Errorf("Failed to init wavy. Err: %s\n", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const fatihaFilepath = "./test_audio_files/Fatiha.mp3"
|
||||||
|
const tadaFilepath = "./test_audio_files/tada.mp3"
|
||||||
|
const fatihaLenMS = 55484
|
||||||
|
|
||||||
//Streaming
|
//Streaming
|
||||||
s, err := wavy.NewSoundStreaming(fatihaFilepath)
|
s, err := wavy.NewSoundStreaming(fatihaFilepath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -103,6 +103,15 @@ func TestSound(t *testing.T) {
|
|||||||
s3 := wavy.ClipInMemSoundPercent(s2, 0, 0.25)
|
s3 := wavy.ClipInMemSoundPercent(s2, 0, 0.25)
|
||||||
s3.LoopAsync(3)
|
s3.LoopAsync(3)
|
||||||
s3.WaitLoop()
|
s3.WaitLoop()
|
||||||
|
|
||||||
|
//Wav
|
||||||
|
const wavFPath = "./test_audio_files/camera.wav"
|
||||||
|
s, err = wavy.NewSoundMem(wavFPath)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Failed to load memory sound with path '%s'. Err: %s\n", wavFPath, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s.PlaySync()
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestByteCountFromPlayTime(t *testing.T) {
|
func TestByteCountFromPlayTime(t *testing.T) {
|
||||||
|
|||||||
Reference in New Issue
Block a user