fix(vm): patterns encoding was broken by the non-standard pattern lengths

This commit is contained in:
vsariola 2021-03-04 14:33:09 +02:00
parent c7448699b6
commit cc80fe7317

View File

@ -29,22 +29,26 @@ func fixPatternLength(patterns [][]byte, fixedLength int) [][]int {
// single linear array of notes. Note that variable length patterns are // single linear array of notes. Note that variable length patterns are
// concatenated as such; call fixPatternLength first if you want every pattern // concatenated as such; call fixPatternLength first if you want every pattern
// to be constant length. // to be constant length.
func flattenSequence(patterns [][]int, sequence []int) []int { func flattenSequence(patterns [][]int, sequence []int, songLength int, rowsPerPattern int, releaseFirst bool) []int {
sumLen := 0 sumLen := rowsPerPattern * songLength
for _, patIndex := range sequence {
if patIndex < 0 || patIndex >= len(patterns) {
continue
}
sumLen += len(patterns[patIndex])
}
notes := make([]int, sumLen) notes := make([]int, sumLen)
window := notes window := notes
for _, patIndex := range sequence { for i := 0; i < songLength; i++ {
if patIndex < 0 || patIndex >= len(patterns) { patIndex := -1
continue if i < len(sequence) {
patIndex = sequence[i]
} }
elementsCopied := copy(window, patterns[patIndex]) var k int
window = window[elementsCopied:] if patIndex >= 0 && patIndex < len(patterns) {
k = copy(window, patterns[patIndex])
}
for ; k < rowsPerPattern; k++ {
window[k] = 1 // pad with holds
}
if i == 0 && window[0] == 1 && releaseFirst {
window[0] = 0
}
window = window[rowsPerPattern:]
} }
return notes return notes
} }
@ -121,7 +125,7 @@ func addPatternsToTable(patterns [][]int, table [][]int) ([]int, [][]int) {
match = false match = false
break break
} }
if n != pat[i] { if (i < len(pat) && n != pat[i]) || n != 1 {
identical = false identical = false
} }
} }
@ -173,15 +177,14 @@ func bytesToInts(array []byte) []int {
} }
func ConstructPatterns(song *sointu.Song) ([][]byte, [][]byte, error) { func ConstructPatterns(song *sointu.Song) ([][]byte, [][]byte, error) {
patLength := song.Score.RowsPerPattern
sequences := make([][]byte, len(song.Score.Tracks)) sequences := make([][]byte, len(song.Score.Tracks))
var patterns [][]int var patterns [][]int
for i, t := range song.Score.Tracks { for i, t := range song.Score.Tracks {
fixed := fixPatternLength(t.Patterns, patLength) fixed := fixPatternLength(t.Patterns, song.Score.RowsPerPattern)
flat := flattenSequence(fixed, t.Order) flat := flattenSequence(fixed, t.Order, song.Score.Length, song.Score.RowsPerPattern, true)
dontCares := markDontCares(flat) dontCares := markDontCares(flat)
// TODO: we could give the user the possibility to use another length during encoding that during composing // TODO: we could give the user the possibility to use another length during encoding that during composing
chunks := splitSequence(dontCares, patLength) chunks := splitSequence(dontCares, song.Score.RowsPerPattern)
var sequence []int var sequence []int
sequence, patterns = addPatternsToTable(chunks, patterns) sequence, patterns = addPatternsToTable(chunks, patterns)
var err error var err error