mirror of
https://github.com/vsariola/sointu.git
synced 2025-05-28 03:10:24 -04:00
feat(sointu-cli): Support importing/exporting in YAML
This commit is contained in:
parent
fa163b3884
commit
2106ebde56
1
go.mod
1
go.mod
@ -5,4 +5,5 @@ go 1.15
|
||||
require (
|
||||
gioui.org v0.0.0-20201106195654-dbc0796d0207
|
||||
github.com/hajimehoshi/oto v0.6.6
|
||||
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776
|
||||
)
|
||||
|
3
go.sum
3
go.sum
@ -30,3 +30,6 @@ golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/tools v0.0.0-20190927191325-030b2cf1153e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
@ -11,6 +11,8 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
|
||||
"github.com/vsariola/sointu/go4k"
|
||||
"github.com/vsariola/sointu/go4k/audio/oto"
|
||||
"github.com/vsariola/sointu/go4k/bridge"
|
||||
@ -23,6 +25,7 @@ func main() {
|
||||
play := flag.Bool("p", false, "Play the input songs.")
|
||||
asmOut := flag.Bool("a", false, "Output the song as .asm file, to standard output unless otherwise specified.")
|
||||
jsonOut := flag.Bool("j", false, "Output the song as .json file, to standard output unless otherwise specified.")
|
||||
yamlOut := flag.Bool("y", false, "Output the song as .yml file, to standard output unless otherwise specified.")
|
||||
headerOut := flag.Bool("c", false, "Output .h C header file, to standard output unless otherwise specified.")
|
||||
exactLength := flag.Bool("e", false, "When outputting the C header file, calculate the exact length of song by rendering it once. Only useful when using SPEED opcodes.")
|
||||
rawOut := flag.Bool("r", false, "Output the rendered song as .raw stereo float32 buffer, to standard output unless otherwise specified.")
|
||||
@ -34,7 +37,7 @@ func main() {
|
||||
flag.Usage()
|
||||
os.Exit(0)
|
||||
}
|
||||
if !*asmOut && !*jsonOut && !*rawOut && !*headerOut && !*play {
|
||||
if !*asmOut && !*jsonOut && !*rawOut && !*headerOut && !*play && !*yamlOut {
|
||||
*play = true // if the user gives nothing to output, then the default behaviour is just to play the file
|
||||
}
|
||||
needsRendering := *play || *exactLength || *rawOut
|
||||
@ -78,12 +81,14 @@ func main() {
|
||||
return fmt.Errorf("Could not read file %v: %v", filename, err)
|
||||
}
|
||||
var song go4k.Song
|
||||
if err := json.Unmarshal(inputBytes, &song); err != nil {
|
||||
song2, err2 := go4k.ParseAsm(string(inputBytes))
|
||||
if err2 != nil {
|
||||
return fmt.Errorf("The song could not be parsed as .json (%v) nor .asm (%v)", err, err2)
|
||||
if errJSON := json.Unmarshal(inputBytes, &song); errJSON != nil {
|
||||
if errYaml := yaml.Unmarshal(inputBytes, &song); errYaml != nil {
|
||||
song2, errAsm := go4k.ParseAsm(string(inputBytes))
|
||||
if errAsm != nil {
|
||||
return fmt.Errorf("The song could not be parsed as .json (%v), .yml (%v) nor .asm (%v)", errJSON, errYaml, errAsm)
|
||||
}
|
||||
song = *song2
|
||||
}
|
||||
song = *song2
|
||||
}
|
||||
var buffer []float32
|
||||
if needsRendering {
|
||||
@ -141,6 +146,15 @@ func main() {
|
||||
return fmt.Errorf("Error outputting JSON file: %v", err)
|
||||
}
|
||||
}
|
||||
if *yamlOut {
|
||||
yamlSong, err := yaml.Marshal(song)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Could not marshal the song as yaml file: %v", err)
|
||||
}
|
||||
if err := output(".yml", yamlSong); err != nil {
|
||||
return fmt.Errorf("Error outputting yaml file: %v", err)
|
||||
}
|
||||
}
|
||||
if *rawOut {
|
||||
buf := new(bytes.Buffer)
|
||||
err := binary.Write(buf, binary.LittleEndian, buffer)
|
||||
@ -168,7 +182,14 @@ func main() {
|
||||
retval = 1
|
||||
continue
|
||||
}
|
||||
ymlfiles, err := filepath.Glob(filepath.Join(param, "*.yml"))
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Could not glob the path %v for yml files: %v\n", param, err)
|
||||
retval = 1
|
||||
continue
|
||||
}
|
||||
files := append(asmfiles, jsonfiles...)
|
||||
files = append(files, ymlfiles...)
|
||||
for _, file := range files {
|
||||
err := process(file)
|
||||
if err != nil {
|
||||
|
@ -8,7 +8,7 @@ import (
|
||||
// Unit is e.g. a filter, oscillator, envelope and its parameters
|
||||
type Unit struct {
|
||||
Type string
|
||||
Parameters map[string]int
|
||||
Parameters map[string]int `yaml:",flow"`
|
||||
}
|
||||
|
||||
const (
|
||||
@ -34,7 +34,7 @@ type SampleOffset struct {
|
||||
// Patch is simply a list of instruments used in a song
|
||||
type Patch struct {
|
||||
Instruments []Instrument
|
||||
DelayTimes []int
|
||||
DelayTimes []int `yaml:",flow"`
|
||||
SampleOffsets []SampleOffset
|
||||
}
|
||||
|
||||
@ -62,7 +62,7 @@ func (patch Patch) InstrumentForVoice(voice int) (int, error) {
|
||||
|
||||
type Track struct {
|
||||
NumVoices int
|
||||
Sequence []byte
|
||||
Sequence []byte `yaml:",flow"`
|
||||
}
|
||||
|
||||
type Synth interface {
|
||||
|
@ -7,11 +7,11 @@ import (
|
||||
|
||||
type Song struct {
|
||||
BPM int
|
||||
Patterns [][]byte
|
||||
Tracks []Track
|
||||
Patch Patch
|
||||
Output16Bit bool
|
||||
Hold byte
|
||||
Patterns [][]byte `yaml:",flow"`
|
||||
Tracks []Track
|
||||
Patch Patch
|
||||
}
|
||||
|
||||
func (s *Song) PatternRows() int {
|
||||
|
@ -8,7 +8,7 @@ import (
|
||||
"github.com/vsariola/sointu/go4k"
|
||||
)
|
||||
|
||||
const expectedMarshaled = `{"BPM":100,"Patterns":["QABEACAAAABLAE4AAAAAAA=="],"Tracks":[{"NumVoices":1,"Sequence":"AA=="}],"Patch":{"Instruments":[{"NumVoices":1,"Units":[{"Type":"envelope","Parameters":{"attack":32,"decay":32,"gain":128,"release":64,"stereo":0,"sustain":64}},{"Type":"oscillator","Parameters":{"color":96,"detune":64,"flags":64,"gain":128,"phase":0,"shape":64,"stereo":0,"transpose":64}},{"Type":"mulp","Parameters":{"stereo":0}},{"Type":"envelope","Parameters":{"attack":32,"decay":32,"gain":128,"release":64,"stereo":0,"sustain":64}},{"Type":"oscillator","Parameters":{"color":64,"detune":64,"flags":64,"gain":128,"phase":64,"shape":96,"stereo":0,"transpose":72}},{"Type":"mulp","Parameters":{"stereo":0}},{"Type":"out","Parameters":{"gain":128,"stereo":1}}]}],"DelayTimes":[],"SampleOffsets":[]},"Output16Bit":false,"Hold":1}`
|
||||
const expectedMarshaled = `{"BPM":100,"Output16Bit":false,"Hold":1,"Patterns":["QABEACAAAABLAE4AAAAAAA=="],"Tracks":[{"NumVoices":1,"Sequence":"AA=="}],"Patch":{"Instruments":[{"NumVoices":1,"Units":[{"Type":"envelope","Parameters":{"attack":32,"decay":32,"gain":128,"release":64,"stereo":0,"sustain":64}},{"Type":"oscillator","Parameters":{"color":96,"detune":64,"flags":64,"gain":128,"phase":0,"shape":64,"stereo":0,"transpose":64}},{"Type":"mulp","Parameters":{"stereo":0}},{"Type":"envelope","Parameters":{"attack":32,"decay":32,"gain":128,"release":64,"stereo":0,"sustain":64}},{"Type":"oscillator","Parameters":{"color":64,"detune":64,"flags":64,"gain":128,"phase":64,"shape":96,"stereo":0,"transpose":72}},{"Type":"mulp","Parameters":{"stereo":0}},{"Type":"out","Parameters":{"gain":128,"stereo":1}}]}],"DelayTimes":[],"SampleOffsets":[]}}`
|
||||
|
||||
var testSong = go4k.Song{
|
||||
BPM: 100,
|
||||
|
@ -37,7 +37,7 @@ func TestPlayer(t *testing.T) {
|
||||
SampleOffsets: []go4k.SampleOffset{}}
|
||||
patterns := [][]byte{{64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0}}
|
||||
tracks := []go4k.Track{go4k.Track{1, []byte{0}}}
|
||||
song := go4k.Song{100, patterns, tracks, patch, false, 1}
|
||||
song := go4k.Song{BPM: 100, Patterns: patterns, Tracks: tracks, Patch: patch, Output16Bit: false, Hold: 1}
|
||||
synth, err := bridge.Synth(patch)
|
||||
if err != nil {
|
||||
t.Fatalf("Compiling patch failed: %v", err)
|
||||
|
Loading…
Reference in New Issue
Block a user