mirror of
https://github.com/JetSetIlly/Gopher2600.git
synced 2024-06-02 20:18:20 -04:00
readded Supercharger WAV loading using go-audio/wav package
This commit is contained in:
parent
7e57bbe46c
commit
d47bbe01c3
|
@ -204,6 +204,7 @@ The following projects are used in the `Gopher2600` project:
|
|||
* https://github.com/go-gl/gl
|
||||
* https://github.com/hajimehoshi/go-mp3
|
||||
* https://github.com/pkg/term
|
||||
* https://github.com/go-audio/wav
|
||||
|
||||
* FontAwesome
|
||||
* https://fontawesome.com/
|
||||
|
|
6
go.mod
6
go.mod
|
@ -11,3 +11,9 @@ require (
|
|||
golang.org/x/image v0.0.0-20220413100746-70e8d0d3baa9
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a
|
||||
)
|
||||
|
||||
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
|
||||
)
|
||||
|
|
6
go.sum
6
go.sum
|
@ -1,4 +1,10 @@
|
|||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
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/go-gl/gl v0.0.0-20211210172815-726fda9656d6 h1:zDw5v7qm4yH7N8C8uWd+8Ii9rROdgWxQuGoJ9WDXxfk=
|
||||
github.com/go-gl/gl v0.0.0-20211210172815-726fda9656d6/go.mod h1:9YTyiznxEY1fVinfM7RvRcjRHbw2xLBJ3AAGIT0I4Nw=
|
||||
github.com/hajimehoshi/go-mp3 v0.3.3 h1:cWnfRdpye2m9ElSoVqneYRcpt/l3ijttgjMeQh+r+FE=
|
||||
|
|
|
@ -93,7 +93,11 @@ func newSoundLoad(cart *Supercharger, loader cartridgeloader.Loader) (tape, erro
|
|||
// get PCM data from data loaded from file
|
||||
tap.pcm, err = getPCM(loader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("soundload: %v", err)
|
||||
}
|
||||
|
||||
if len(tap.pcm.data) == 0 {
|
||||
return nil, fmt.Errorf("soundload: no PCM data in file")
|
||||
}
|
||||
|
||||
// the length of time of each sample in microseconds
|
||||
|
|
|
@ -21,17 +21,15 @@ import (
|
|||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
// "github.com/go-audio/audio"
|
||||
// "github.com/go-audio/wav".
|
||||
"github.com/go-audio/wav"
|
||||
|
||||
"github.com/hajimehoshi/go-mp3"
|
||||
"github.com/jetsetilly/gopher2600/cartridgeloader"
|
||||
"github.com/jetsetilly/gopher2600/curated"
|
||||
"github.com/jetsetilly/gopher2600/logger"
|
||||
)
|
||||
|
||||
type pcmData struct {
|
||||
totalTime float64
|
||||
totalTime float64 // in seconds
|
||||
sampleRate float64
|
||||
|
||||
// data is mono data (taken from the left channel in the case of stero
|
||||
|
@ -46,32 +44,55 @@ func getPCM(cl cartridgeloader.Loader) (pcmData, error) {
|
|||
|
||||
switch strings.ToLower(filepath.Ext(cl.Filename)) {
|
||||
case ".wav":
|
||||
return pcmData{}, curated.Errorf("wav files not currently supported (%s)", cl.Filename)
|
||||
dec := wav.NewDecoder(cl.StreamedData)
|
||||
if dec == nil {
|
||||
return p, fmt.Errorf("wav: error decoding")
|
||||
}
|
||||
|
||||
if !dec.IsValidFile() {
|
||||
return p, fmt.Errorf("wav: not a valid wav file")
|
||||
}
|
||||
|
||||
logger.Log(soundloadLogTag, "loading from wav file")
|
||||
|
||||
// load all data at once
|
||||
buf, err := dec.FullPCMBuffer()
|
||||
if err != nil {
|
||||
return p, fmt.Errorf("soundload: wav: %v", err)
|
||||
}
|
||||
floatBuf := buf.AsFloat32Buffer()
|
||||
|
||||
// copy first channel only of data stream
|
||||
p.data = make([]float32, 0, len(floatBuf.Data)/int(dec.NumChans))
|
||||
for i := 0; i < len(floatBuf.Data); i += int(dec.NumChans) {
|
||||
p.data = append(p.data, floatBuf.Data[i])
|
||||
}
|
||||
|
||||
// sample rate
|
||||
p.sampleRate = float64(dec.SampleRate)
|
||||
|
||||
// total time of recording in seconds
|
||||
dur, err := dec.Duration()
|
||||
if err != nil {
|
||||
return p, fmt.Errorf("wav: %v", err)
|
||||
}
|
||||
p.totalTime = dur.Seconds()
|
||||
|
||||
case ".mp3":
|
||||
dec, err := mp3.NewDecoder(cl.StreamedData)
|
||||
if err != nil {
|
||||
return p, fmt.Errorf("soundload: mp3: %v", err)
|
||||
return p, fmt.Errorf("mp3: %v", err)
|
||||
}
|
||||
|
||||
logger.Log(soundloadLogTag, "loading from mp3 file")
|
||||
|
||||
// according to the go-mp3 docs:
|
||||
//
|
||||
// "The stream is always formatted as 16bit (little endian) 2 channels even if
|
||||
// the source is single channel MP3. Thus, a sample always consists of 4
|
||||
// bytes.".
|
||||
p.sampleRate = float64(dec.SampleRate())
|
||||
|
||||
logger.Log(soundloadLogTag, "using left channel only")
|
||||
|
||||
err = nil
|
||||
chunk := make([]byte, 4096)
|
||||
for err != io.EOF {
|
||||
var chunkLen int
|
||||
chunkLen, err = dec.Read(chunk)
|
||||
if err != nil && err != io.EOF {
|
||||
return p, fmt.Errorf("soundload: mp3: %v", err)
|
||||
return p, fmt.Errorf("mp3: %v", err)
|
||||
}
|
||||
|
||||
// index increment of 4 because:
|
||||
|
@ -92,9 +113,17 @@ func getPCM(cl cartridgeloader.Loader) (pcmData, error) {
|
|||
p.data = append(p.data, float32(f))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
p.totalTime = float64(len(p.data)) / p.sampleRate
|
||||
// according to the go-mp3 docs:
|
||||
//
|
||||
// "The stream is always formatted as 16bit (little endian) 2 channels even if
|
||||
// the source is single channel MP3. Thus, a sample always consists of 4
|
||||
// bytes.".
|
||||
p.sampleRate = float64(dec.SampleRate())
|
||||
|
||||
// total time of recording in seconds
|
||||
p.totalTime = float64(len(p.data)) / p.sampleRate
|
||||
}
|
||||
|
||||
logger.Logf(soundloadLogTag, "sample rate: %0.2fHz", p.sampleRate)
|
||||
logger.Logf(soundloadLogTag, "total time: %.02fs", p.totalTime)
|
||||
|
|
Loading…
Reference in a new issue