diff --git a/go.mod b/go.mod index f5d8c34..c2f9ac9 100755 --- a/go.mod +++ b/go.mod @@ -7,4 +7,9 @@ require ( 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 +) diff --git a/go.sum b/go.sum index f8e07e5..ec8ba10 100755 --- a/go.sum +++ b/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/go.mod h1:qMJj/CSDxx6CGHiZeCgbiq2DSUkbK0UbtXShQcnfyMM= github.com/hajimehoshi/oto v0.6.1/go.mod h1:0QXGEkbuJRohbJaxr7ZQSxnju7hEhseiPx2hrh6raOI= diff --git a/sound_enums.go b/sound_enums.go index b21251d..ed407c5 100755 --- a/sound_enums.go +++ b/sound_enums.go @@ -5,6 +5,7 @@ type SoundType int const ( SoundType_Unknown SoundType = iota SoundType_MP3 + SoundType_WAV ) type SampleRate int diff --git a/test_audio_files/camera.wav b/test_audio_files/camera.wav new file mode 100755 index 0000000..2b8bc26 Binary files /dev/null and b/test_audio_files/camera.wav differ diff --git a/test_audio_files/license.txt b/test_audio_files/license.txt new file mode 100755 index 0000000..2c43e82 --- /dev/null +++ b/test_audio_files/license.txt @@ -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 \ No newline at end of file diff --git a/wavy.go b/wavy.go index d124f0c..ec67dfe 100644 --- a/wavy.go +++ b/wavy.go @@ -7,9 +7,9 @@ import ( "io" "os" "path" - "strings" "time" + "github.com/go-audio/wav" "github.com/hajimehoshi/go-mp3" "github.com/hajimehoshi/oto/v2" ) @@ -52,7 +52,7 @@ var ( //Pre-defined errors 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. @@ -354,14 +354,9 @@ func ResumeAllSounds() { //Good for large sound files func NewSoundStreaming(fpath string) (s *Sound, err error) { - //Error checking filetype - soundType := SoundType_Unknown - if strings.HasSuffix(fpath, ".mp3") { - soundType = SoundType_MP3 - } - + soundType := GetSoundFileType(fpath) 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 @@ -378,17 +373,9 @@ func NewSoundStreaming(fpath string) (s *Sound, err error) { }, } - //Load file depending on type - if soundType == SoundType_MP3 { - - dec, err := mp3.NewDecoder(file) - if err != nil { - return nil, err - } - - s.Info.Size = dec.Length() - s.Player = Ctx.NewPlayer(dec) - s.Data = dec + err = soundFromReaderSeeker(file, s) + if err != nil { + return nil, getLoadingErr(fpath, err) } return s, nil @@ -397,19 +384,14 @@ func NewSoundStreaming(fpath string) (s *Sound, err error) { //NewSoundMem loads the entire sound file into memory func NewSoundMem(fpath string) (s *Sound, err error) { - //Error checking filetype - soundType := SoundType_Unknown - if strings.HasSuffix(fpath, ".mp3") { - soundType = SoundType_MP3 - } - + soundType := GetSoundFileType(fpath) if soundType == SoundType_Unknown { - return nil, ErrunknownSoundType + return nil, getLoadingErr(fpath, errUnknownSoundType) } fileBytes, err := os.ReadFile(fpath) if err != nil { - return nil, err + return nil, getLoadingErr(fpath, err) } bytesReader := bytes.NewReader(fileBytes) @@ -420,34 +402,69 @@ func NewSoundMem(fpath string) (s *Sound, err error) { }, } - //Load file depending on type - if soundType == SoundType_MP3 { + err = soundFromReaderSeeker(bytesReader, s) + 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 { - return nil, err + return err } finalBuf, err := ReadAllFromReader(dec, 0, uint64(dec.Length())) if err != nil { - return nil, err + return err } sb := &SoundBuffer{Data: finalBuf} s.Data = sb s.Player = Ctx.NewPlayer(sb) 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 { ext := path.Ext(fpath) switch ext { - case "mp3": + case ".mp3": return SoundType_MP3 + case ".wav", ".wave": + return SoundType_WAV default: return SoundType_Unknown } diff --git a/wavy_test.go b/wavy_test.go index 1333d5e..fb43839 100755 --- a/wavy_test.go +++ b/wavy_test.go @@ -9,16 +9,16 @@ import ( 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) if err != nil { t.Errorf("Failed to init wavy. Err: %s\n", err) return } + const fatihaFilepath = "./test_audio_files/Fatiha.mp3" + const tadaFilepath = "./test_audio_files/tada.mp3" + const fatihaLenMS = 55484 + //Streaming s, err := wavy.NewSoundStreaming(fatihaFilepath) if err != nil { @@ -103,6 +103,15 @@ func TestSound(t *testing.T) { s3 := wavy.ClipInMemSoundPercent(s2, 0, 0.25) s3.LoopAsync(3) 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) {