refactor(compiler): remove EncodedSong and pass patterns & sequences separately

This commit is contained in:
vsariola
2021-01-05 19:25:46 +02:00
parent 69f236dbd3
commit 1187c2a200
6 changed files with 118 additions and 129 deletions

View File

@ -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 {

View File

@ -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)
}
}

View File

@ -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
View 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)
}
}