mirror of
https://github.com/vsariola/sointu.git
synced 2025-07-18 13:04:25 -04:00
refactor(compiler): remove EncodedSong and pass patterns & sequences separately
This commit is contained in:
@ -86,7 +86,7 @@ func (com *Compiler) Song(song *sointu.Song) (map[string]string, error) {
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf(`could not encode patch: %v`, err)
|
||||
}
|
||||
encodedSong, err := EncodeSong(song)
|
||||
patterns, sequences, err := ConstructPatterns(song)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf(`could not encode song: %v`, err)
|
||||
}
|
||||
@ -104,9 +104,12 @@ func (com *Compiler) Song(song *sointu.Song) (map[string]string, error) {
|
||||
X86Macros
|
||||
SongMacros
|
||||
*EncodedPatch
|
||||
EncodedSong *EncodedSong
|
||||
Hold int
|
||||
}{compilerMacros, featureSetMacros, x86Macros, songMacros, encodedPatch, encodedSong, 1}
|
||||
Patterns [][]byte
|
||||
Sequences [][]byte
|
||||
PatternLength int
|
||||
SequenceLength int
|
||||
Hold int
|
||||
}{compilerMacros, featureSetMacros, x86Macros, songMacros, encodedPatch, patterns, sequences, len(patterns[0]), len(sequences[0]), 1}
|
||||
populatedTemplate, extension, err = com.compile(templateName, &data)
|
||||
} else if com.Arch == "wasm" {
|
||||
wasmMacros := *NewWasmMacros()
|
||||
@ -116,9 +119,12 @@ func (com *Compiler) Song(song *sointu.Song) (map[string]string, error) {
|
||||
WasmMacros
|
||||
SongMacros
|
||||
*EncodedPatch
|
||||
EncodedSong *EncodedSong
|
||||
Hold int
|
||||
}{compilerMacros, featureSetMacros, wasmMacros, songMacros, encodedPatch, encodedSong, 1}
|
||||
Patterns [][]byte
|
||||
Sequences [][]byte
|
||||
PatternLength int
|
||||
SequenceLength int
|
||||
Hold int
|
||||
}{compilerMacros, featureSetMacros, wasmMacros, songMacros, encodedPatch, patterns, sequences, len(patterns[0]), len(sequences[0]), 1}
|
||||
populatedTemplate, extension, err = com.compile(templateName, &data)
|
||||
}
|
||||
if err != nil {
|
||||
|
@ -1,78 +0,0 @@
|
||||
package compiler_test
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/vsariola/sointu"
|
||||
"github.com/vsariola/sointu/compiler"
|
||||
)
|
||||
|
||||
func TestPatternReusing(t *testing.T) {
|
||||
song := sointu.Song{
|
||||
Tracks: []sointu.Track{{
|
||||
Patterns: [][]byte{{64, 1, 1, 1, 0, 0, 0, 0}, {72, 0, 0, 0, 0, 0, 0, 0}},
|
||||
Sequence: []byte{0, 1},
|
||||
}, {
|
||||
Patterns: [][]byte{{64, 1, 1, 1, 0, 0, 0, 0}, {84, 0, 0, 0, 0, 0, 0, 0}},
|
||||
Sequence: []byte{0, 1},
|
||||
}},
|
||||
}
|
||||
encodedSong, err := compiler.EncodeSong(&song)
|
||||
if err != nil {
|
||||
t.Fatalf("song encoding error: %v", err)
|
||||
}
|
||||
expected := compiler.EncodedSong{
|
||||
Sequences: [][]byte{{0, 1}, {0, 2}},
|
||||
Patterns: [][]byte{{64, 1, 1, 1, 0, 0, 0, 0}, {72, 0, 0, 0, 0, 0, 0, 0}, {84, 0, 0, 0, 0, 0, 0, 0}},
|
||||
}
|
||||
if !reflect.DeepEqual(*encodedSong, expected) {
|
||||
t.Fatalf("got different EncodedSong than expected. got: %v expected: %v", *encodedSong, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnnecessaryHolds(t *testing.T) {
|
||||
song := sointu.Song{
|
||||
Tracks: []sointu.Track{{
|
||||
Patterns: [][]byte{{64, 1, 1, 1, 0, 1, 0, 0}, {72, 0, 1, 0, 1, 0, 0, 0}},
|
||||
Sequence: []byte{0, 1},
|
||||
}, {
|
||||
Patterns: [][]byte{{64, 1, 1, 1, 0, 0, 1, 0}, {84, 0, 0, 0, 1, 1, 0, 0}},
|
||||
Sequence: []byte{0, 1},
|
||||
}},
|
||||
}
|
||||
encodedSong, err := compiler.EncodeSong(&song)
|
||||
if err != nil {
|
||||
t.Fatalf("song encoding error: %v", err)
|
||||
}
|
||||
expected := compiler.EncodedSong{
|
||||
Sequences: [][]byte{{0, 1}, {0, 2}},
|
||||
Patterns: [][]byte{{64, 1, 1, 1, 0, 0, 0, 0}, {72, 0, 0, 0, 0, 0, 0, 0}, {84, 0, 0, 0, 0, 0, 0, 0}},
|
||||
}
|
||||
if !reflect.DeepEqual(*encodedSong, expected) {
|
||||
t.Fatalf("got different EncodedSong than expected. got: %v expected: %v", *encodedSong, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDontCares(t *testing.T) {
|
||||
song := sointu.Song{
|
||||
Tracks: []sointu.Track{{
|
||||
Patterns: [][]byte{{64, 1, 1, 1, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0}},
|
||||
Sequence: []byte{0, 1},
|
||||
}, {
|
||||
Patterns: [][]byte{{64, 1, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 0, 0, 0, 0, 0}},
|
||||
Sequence: []byte{0, 1},
|
||||
}},
|
||||
}
|
||||
encodedSong, err := compiler.EncodeSong(&song)
|
||||
if err != nil {
|
||||
t.Fatalf("song encoding error: %v", err)
|
||||
}
|
||||
expected := compiler.EncodedSong{
|
||||
Sequences: [][]byte{{0, 1}, {2, 1}},
|
||||
Patterns: [][]byte{{64, 1, 1, 1, 0, 0, 0, 0}, {1, 1, 1, 0, 0, 0, 0, 0}, {64, 1, 1, 1, 1, 1, 1, 1}},
|
||||
}
|
||||
if !reflect.DeepEqual(*encodedSong, expected) {
|
||||
t.Fatalf("got different EncodedSong than expected. got: %v expected: %v", *encodedSong, expected)
|
||||
}
|
||||
}
|
@ -7,14 +7,6 @@ import (
|
||||
"github.com/vsariola/sointu"
|
||||
)
|
||||
|
||||
// EncodedSong has a single global pattern table and all track sequences are
|
||||
// indices to this table. This is in contrast with sointu. Song, which has one
|
||||
// pattern table per track.
|
||||
type EncodedSong struct {
|
||||
Patterns [][]byte
|
||||
Sequences [][]byte
|
||||
}
|
||||
|
||||
// fixPatternLength makes sure that every pattern is the same length. During
|
||||
// composing. Patterns shorter than the given length are padded with 1 / "hold";
|
||||
// patterns longer than the given length are cropped.
|
||||
@ -174,19 +166,7 @@ func bytesToInts(array []byte) []int {
|
||||
return ret
|
||||
}
|
||||
|
||||
func (e *EncodedSong) PatternLength() int {
|
||||
return len(e.Patterns[0])
|
||||
}
|
||||
|
||||
func (e *EncodedSong) SequenceLength() int {
|
||||
return len(e.Sequences[0])
|
||||
}
|
||||
|
||||
func (e *EncodedSong) TotalRows() int {
|
||||
return e.SequenceLength() * e.PatternLength()
|
||||
}
|
||||
|
||||
func EncodeSong(song *sointu.Song) (*EncodedSong, error) {
|
||||
func ConstructPatterns(song *sointu.Song) ([][]byte, [][]byte, error) {
|
||||
patLength := song.PatternRows()
|
||||
sequences := make([][]byte, len(song.Tracks))
|
||||
var patterns [][]int
|
||||
@ -201,7 +181,7 @@ func EncodeSong(song *sointu.Song) (*EncodedSong, error) {
|
||||
var err error
|
||||
sequences[i], err = intsToBytes(sequence)
|
||||
if err != nil {
|
||||
return nil, errors.New("the constructed pattern table would result in > 256 unique patterns; only 256 unique patterns are supported")
|
||||
return nil, nil, errors.New("the constructed pattern table would result in > 256 unique patterns; only 256 unique patterns are supported")
|
||||
}
|
||||
}
|
||||
bytePatterns := make([][]byte, len(patterns))
|
||||
@ -210,8 +190,8 @@ func EncodeSong(song *sointu.Song) (*EncodedSong, error) {
|
||||
replaceInts(pat, -1, 0) // replace don't cares with releases
|
||||
bytePatterns[i], err = intsToBytes(pat)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid note in pattern, notes should be 0 .. 255: %v", err)
|
||||
return nil, nil, fmt.Errorf("invalid note in pattern, notes should be 0 .. 255: %v", err)
|
||||
}
|
||||
}
|
||||
return &EncodedSong{Patterns: bytePatterns, Sequences: sequences}, nil
|
||||
return bytePatterns, sequences, nil
|
||||
}
|
81
compiler/patterns_test.go
Normal file
81
compiler/patterns_test.go
Normal file
@ -0,0 +1,81 @@
|
||||
package compiler_test
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/vsariola/sointu"
|
||||
"github.com/vsariola/sointu/compiler"
|
||||
)
|
||||
|
||||
func TestPatternReusing(t *testing.T) {
|
||||
song := sointu.Song{
|
||||
Tracks: []sointu.Track{{
|
||||
Patterns: [][]byte{{64, 1, 1, 1, 0, 0, 0, 0}, {72, 0, 0, 0, 0, 0, 0, 0}},
|
||||
Sequence: []byte{0, 1},
|
||||
}, {
|
||||
Patterns: [][]byte{{64, 1, 1, 1, 0, 0, 0, 0}, {84, 0, 0, 0, 0, 0, 0, 0}},
|
||||
Sequence: []byte{0, 1},
|
||||
}},
|
||||
}
|
||||
patterns, sequences, err := compiler.ConstructPatterns(&song)
|
||||
if err != nil {
|
||||
t.Fatalf("erorr constructing patterns: %v", err)
|
||||
}
|
||||
expectedSequences := [][]byte{{0, 1}, {0, 2}}
|
||||
expectedPatterns := [][]byte{{64, 1, 1, 1, 0, 0, 0, 0}, {72, 0, 0, 0, 0, 0, 0, 0}, {84, 0, 0, 0, 0, 0, 0, 0}}
|
||||
if !reflect.DeepEqual(patterns, expectedPatterns) {
|
||||
t.Fatalf("got different patterns than expected. got: %v expected: %v", patterns, expectedPatterns)
|
||||
}
|
||||
if !reflect.DeepEqual(sequences, expectedSequences) {
|
||||
t.Fatalf("got different patterns than expected. got: %v expected: %v", patterns, expectedPatterns)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnnecessaryHolds(t *testing.T) {
|
||||
song := sointu.Song{
|
||||
Tracks: []sointu.Track{{
|
||||
Patterns: [][]byte{{64, 1, 1, 1, 0, 1, 0, 0}, {72, 0, 1, 0, 1, 0, 0, 0}},
|
||||
Sequence: []byte{0, 1},
|
||||
}, {
|
||||
Patterns: [][]byte{{64, 1, 1, 1, 0, 0, 1, 0}, {84, 0, 0, 0, 1, 1, 0, 0}},
|
||||
Sequence: []byte{0, 1},
|
||||
}},
|
||||
}
|
||||
patterns, sequences, err := compiler.ConstructPatterns(&song)
|
||||
if err != nil {
|
||||
t.Fatalf("erorr constructing patterns: %v", err)
|
||||
}
|
||||
expectedSequences := [][]byte{{0, 1}, {0, 2}}
|
||||
expectedPatterns := [][]byte{{64, 1, 1, 1, 0, 0, 0, 0}, {72, 0, 0, 0, 0, 0, 0, 0}, {84, 0, 0, 0, 0, 0, 0, 0}}
|
||||
if !reflect.DeepEqual(patterns, expectedPatterns) {
|
||||
t.Fatalf("got different patterns than expected. got: %v expected: %v", patterns, expectedPatterns)
|
||||
}
|
||||
if !reflect.DeepEqual(sequences, expectedSequences) {
|
||||
t.Fatalf("got different patterns than expected. got: %v expected: %v", patterns, expectedPatterns)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDontCares(t *testing.T) {
|
||||
song := sointu.Song{
|
||||
Tracks: []sointu.Track{{
|
||||
Patterns: [][]byte{{64, 1, 1, 1, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0}},
|
||||
Sequence: []byte{0, 1},
|
||||
}, {
|
||||
Patterns: [][]byte{{64, 1, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 0, 0, 0, 0, 0}},
|
||||
Sequence: []byte{0, 1},
|
||||
}},
|
||||
}
|
||||
patterns, sequences, err := compiler.ConstructPatterns(&song)
|
||||
if err != nil {
|
||||
t.Fatalf("erorr constructing patterns: %v", err)
|
||||
}
|
||||
expectedSequences := [][]byte{{0, 1}, {2, 1}}
|
||||
expectedPatterns := [][]byte{{64, 1, 1, 1, 0, 0, 0, 0}, {1, 1, 1, 0, 0, 0, 0, 0}, {64, 1, 1, 1, 1, 1, 1, 1}}
|
||||
if !reflect.DeepEqual(patterns, expectedPatterns) {
|
||||
t.Fatalf("got different patterns than expected. got: %v expected: %v", patterns, expectedPatterns)
|
||||
}
|
||||
if !reflect.DeepEqual(sequences, expectedSequences) {
|
||||
t.Fatalf("got different patterns than expected. got: %v expected: %v", patterns, expectedPatterns)
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user