mirror of
https://github.com/vsariola/sointu.git
synced 2025-07-18 13:04:25 -04:00
feat(sointu, tracker,...): restructure domain & tracker models
send targets are now by ID and Song has "Score" part, which is the notes for it. also, moved the model part separate of the actual gioui dependend stuff. sorry to my future self about the code bomb; ended up too far and did not find an easy way to rewrite the history to make the steps smaller, so in the end, just squashed everything.
This commit is contained in:
11
audio.go
Normal file
11
audio.go
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package sointu
|
||||||
|
|
||||||
|
type AudioSink interface {
|
||||||
|
WriteAudio(buffer []float32) error
|
||||||
|
Close() error
|
||||||
|
}
|
||||||
|
|
||||||
|
type AudioContext interface {
|
||||||
|
Output() AudioSink
|
||||||
|
Close() error
|
||||||
|
}
|
@ -23,7 +23,7 @@ func (s BridgeService) Compile(patch sointu.Patch) (sointu.Synth, error) {
|
|||||||
|
|
||||||
func Synth(patch sointu.Patch) (*C.Synth, error) {
|
func Synth(patch sointu.Patch) (*C.Synth, error) {
|
||||||
s := new(C.Synth)
|
s := new(C.Synth)
|
||||||
comPatch, err := compiler.Encode(&patch, compiler.AllFeatures{})
|
comPatch, err := compiler.Encode(patch, compiler.AllFeatures{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error compiling patch: %v", err)
|
return nil, fmt.Errorf("error compiling patch: %v", err)
|
||||||
}
|
}
|
||||||
@ -102,7 +102,7 @@ func (s *C.Synth) Release(voice int) {
|
|||||||
|
|
||||||
// Update
|
// Update
|
||||||
func (s *C.Synth) Update(patch sointu.Patch) error {
|
func (s *C.Synth) Update(patch sointu.Patch) error {
|
||||||
comPatch, err := compiler.Encode(&patch, compiler.AllFeatures{})
|
comPatch, err := compiler.Encode(patch, compiler.AllFeatures{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error compiling patch: %v", err)
|
return fmt.Errorf("error compiling patch: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -29,8 +29,7 @@ const su_max_samples = SAMPLES_PER_ROW * TOTAL_ROWS
|
|||||||
// const bufsize = su_max_samples * 2
|
// const bufsize = su_max_samples * 2
|
||||||
|
|
||||||
func TestOscillatSine(t *testing.T) {
|
func TestOscillatSine(t *testing.T) {
|
||||||
patch := sointu.Patch{
|
patch := sointu.Patch{sointu.Instrument{NumVoices: 1, Units: []sointu.Unit{
|
||||||
Instruments: []sointu.Instrument{sointu.Instrument{NumVoices: 1, Units: []sointu.Unit{
|
|
||||||
sointu.Unit{Type: "envelope", Parameters: map[string]int{"stereo": 0, "attack": 32, "decay": 32, "sustain": 64, "release": 64, "gain": 128}},
|
sointu.Unit{Type: "envelope", Parameters: map[string]int{"stereo": 0, "attack": 32, "decay": 32, "sustain": 64, "release": 64, "gain": 128}},
|
||||||
sointu.Unit{Type: "oscillator", Parameters: map[string]int{"stereo": 0, "transpose": 64, "detune": 64, "phase": 0, "color": 96, "shape": 64, "gain": 128, "type": sointu.Sine, "lfo": 0, "unison": 0}},
|
sointu.Unit{Type: "oscillator", Parameters: map[string]int{"stereo": 0, "transpose": 64, "detune": 64, "phase": 0, "color": 96, "shape": 64, "gain": 128, "type": sointu.Sine, "lfo": 0, "unison": 0}},
|
||||||
sointu.Unit{Type: "mulp", Parameters: map[string]int{"stereo": 0}},
|
sointu.Unit{Type: "mulp", Parameters: map[string]int{"stereo": 0}},
|
||||||
@ -38,9 +37,9 @@ func TestOscillatSine(t *testing.T) {
|
|||||||
sointu.Unit{Type: "oscillator", Parameters: map[string]int{"stereo": 0, "transpose": 72, "detune": 64, "phase": 64, "color": 64, "shape": 96, "gain": 128, "type": sointu.Sine, "lfo": 0, "unison": 0}},
|
sointu.Unit{Type: "oscillator", Parameters: map[string]int{"stereo": 0, "transpose": 72, "detune": 64, "phase": 64, "color": 64, "shape": 96, "gain": 128, "type": sointu.Sine, "lfo": 0, "unison": 0}},
|
||||||
sointu.Unit{Type: "mulp", Parameters: map[string]int{"stereo": 0}},
|
sointu.Unit{Type: "mulp", Parameters: map[string]int{"stereo": 0}},
|
||||||
sointu.Unit{Type: "out", Parameters: map[string]int{"stereo": 1, "gain": 128}},
|
sointu.Unit{Type: "out", Parameters: map[string]int{"stereo": 1, "gain": 128}},
|
||||||
}}}}
|
}}}
|
||||||
tracks := []sointu.Track{{NumVoices: 1, Sequence: []byte{0}, Patterns: [][]byte{{64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0}}}}
|
tracks := []sointu.Track{{NumVoices: 1, Order: []int{0}, Patterns: [][]byte{{64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0}}}}
|
||||||
song := sointu.Song{BPM: 100, RowsPerPattern: 16, RowsPerBeat: 4, Tracks: tracks, Patch: patch}
|
song := sointu.Song{BPM: 100, RowsPerBeat: 4, Score: sointu.Score{RowsPerPattern: 16, Length: 1, Tracks: tracks}, Patch: patch}
|
||||||
synth, err := bridge.Synth(patch)
|
synth, err := bridge.Synth(patch)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Compiling patch failed: %v", err)
|
t.Fatalf("Compiling patch failed: %v", err)
|
||||||
@ -53,13 +52,11 @@ func TestOscillatSine(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestRenderSamples(t *testing.T) {
|
func TestRenderSamples(t *testing.T) {
|
||||||
patch := sointu.Patch{
|
patch := sointu.Patch{sointu.Instrument{NumVoices: 1, Units: []sointu.Unit{
|
||||||
Instruments: []sointu.Instrument{
|
|
||||||
sointu.Instrument{NumVoices: 1, Units: []sointu.Unit{
|
|
||||||
sointu.Unit{Type: "envelope", Parameters: map[string]int{"stereo": 0, "attack": 64, "decay": 64, "sustain": 64, "release": 80, "gain": 128}},
|
sointu.Unit{Type: "envelope", Parameters: map[string]int{"stereo": 0, "attack": 64, "decay": 64, "sustain": 64, "release": 80, "gain": 128}},
|
||||||
sointu.Unit{Type: "envelope", Parameters: map[string]int{"stereo": 0, "attack": 95, "decay": 64, "sustain": 64, "release": 80, "gain": 128}},
|
sointu.Unit{Type: "envelope", Parameters: map[string]int{"stereo": 0, "attack": 95, "decay": 64, "sustain": 64, "release": 80, "gain": 128}},
|
||||||
sointu.Unit{Type: "out", Parameters: map[string]int{"stereo": 1, "gain": 128}},
|
sointu.Unit{Type: "out", Parameters: map[string]int{"stereo": 1, "gain": 128}},
|
||||||
}}}}
|
}}}
|
||||||
|
|
||||||
synth, err := bridge.Synth(patch)
|
synth, err := bridge.Synth(patch)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -107,7 +104,7 @@ func TestAllRegressionTests(t *testing.T) {
|
|||||||
t.Fatalf("Compiling patch failed: %v", err)
|
t.Fatalf("Compiling patch failed: %v", err)
|
||||||
}
|
}
|
||||||
buffer, err := sointu.Play(synth, song)
|
buffer, err := sointu.Play(synth, song)
|
||||||
buffer = buffer[:song.TotalRows()*song.SamplesPerRow()*2] // extend to the nominal length always.
|
buffer = buffer[:song.Score.LengthInRows()*song.SamplesPerRow()*2] // extend to the nominal length always.
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Play failed: %v", err)
|
t.Fatalf("Play failed: %v", err)
|
||||||
}
|
}
|
||||||
@ -138,11 +135,9 @@ func TestAllRegressionTests(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestStackUnderflow(t *testing.T) {
|
func TestStackUnderflow(t *testing.T) {
|
||||||
patch := sointu.Patch{
|
patch := sointu.Patch{sointu.Instrument{NumVoices: 1, Units: []sointu.Unit{
|
||||||
Instruments: []sointu.Instrument{
|
|
||||||
sointu.Instrument{NumVoices: 1, Units: []sointu.Unit{
|
|
||||||
sointu.Unit{Type: "pop", Parameters: map[string]int{}},
|
sointu.Unit{Type: "pop", Parameters: map[string]int{}},
|
||||||
}}}}
|
}}}
|
||||||
synth, err := bridge.Synth(patch)
|
synth, err := bridge.Synth(patch)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("bridge compile error: %v", err)
|
t.Fatalf("bridge compile error: %v", err)
|
||||||
@ -156,10 +151,9 @@ func TestStackUnderflow(t *testing.T) {
|
|||||||
|
|
||||||
func TestStackBalancing(t *testing.T) {
|
func TestStackBalancing(t *testing.T) {
|
||||||
patch := sointu.Patch{
|
patch := sointu.Patch{
|
||||||
Instruments: []sointu.Instrument{
|
|
||||||
sointu.Instrument{NumVoices: 1, Units: []sointu.Unit{
|
sointu.Instrument{NumVoices: 1, Units: []sointu.Unit{
|
||||||
sointu.Unit{Type: "push", Parameters: map[string]int{}},
|
sointu.Unit{Type: "push", Parameters: map[string]int{}},
|
||||||
}}}}
|
}}}
|
||||||
synth, err := bridge.Synth(patch)
|
synth, err := bridge.Synth(patch)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("bridge compile error: %v", err)
|
t.Fatalf("bridge compile error: %v", err)
|
||||||
@ -173,7 +167,6 @@ func TestStackBalancing(t *testing.T) {
|
|||||||
|
|
||||||
func TestStackOverflow(t *testing.T) {
|
func TestStackOverflow(t *testing.T) {
|
||||||
patch := sointu.Patch{
|
patch := sointu.Patch{
|
||||||
Instruments: []sointu.Instrument{
|
|
||||||
sointu.Instrument{NumVoices: 1, Units: []sointu.Unit{
|
sointu.Instrument{NumVoices: 1, Units: []sointu.Unit{
|
||||||
sointu.Unit{Type: "loadval", Parameters: map[string]int{"value": 128}},
|
sointu.Unit{Type: "loadval", Parameters: map[string]int{"value": 128}},
|
||||||
sointu.Unit{Type: "loadval", Parameters: map[string]int{"value": 128}},
|
sointu.Unit{Type: "loadval", Parameters: map[string]int{"value": 128}},
|
||||||
@ -193,7 +186,7 @@ func TestStackOverflow(t *testing.T) {
|
|||||||
sointu.Unit{Type: "pop", Parameters: map[string]int{}},
|
sointu.Unit{Type: "pop", Parameters: map[string]int{}},
|
||||||
sointu.Unit{Type: "pop", Parameters: map[string]int{}},
|
sointu.Unit{Type: "pop", Parameters: map[string]int{}},
|
||||||
sointu.Unit{Type: "pop", Parameters: map[string]int{}},
|
sointu.Unit{Type: "pop", Parameters: map[string]int{}},
|
||||||
}}}}
|
}}}
|
||||||
synth, err := bridge.Synth(patch)
|
synth, err := bridge.Synth(patch)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("bridge compile error: %v", err)
|
t.Fatalf("bridge compile error: %v", err)
|
||||||
@ -206,13 +199,11 @@ func TestStackOverflow(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestDivideByZero(t *testing.T) {
|
func TestDivideByZero(t *testing.T) {
|
||||||
patch := sointu.Patch{
|
patch := sointu.Patch{sointu.Instrument{NumVoices: 1, Units: []sointu.Unit{
|
||||||
Instruments: []sointu.Instrument{
|
|
||||||
sointu.Instrument{NumVoices: 1, Units: []sointu.Unit{
|
|
||||||
sointu.Unit{Type: "loadval", Parameters: map[string]int{"value": 128}},
|
sointu.Unit{Type: "loadval", Parameters: map[string]int{"value": 128}},
|
||||||
sointu.Unit{Type: "invgain", Parameters: map[string]int{"invgain": 0}},
|
sointu.Unit{Type: "invgain", Parameters: map[string]int{"invgain": 0}},
|
||||||
sointu.Unit{Type: "pop", Parameters: map[string]int{}},
|
sointu.Unit{Type: "pop", Parameters: map[string]int{}},
|
||||||
}}}}
|
}}}
|
||||||
synth, err := bridge.Synth(patch)
|
synth, err := bridge.Synth(patch)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("bridge compile error: %v", err)
|
t.Fatalf("bridge compile error: %v", err)
|
||||||
|
@ -122,6 +122,9 @@ func main() {
|
|||||||
if song.RowsPerBeat == 0 {
|
if song.RowsPerBeat == 0 {
|
||||||
song.RowsPerBeat = 4
|
song.RowsPerBeat = 4
|
||||||
}
|
}
|
||||||
|
if song.Score.Length == 0 {
|
||||||
|
song.Score.Length = len(song.Score.Tracks[0].Patterns)
|
||||||
|
}
|
||||||
var compiledPlayer map[string]string
|
var compiledPlayer map[string]string
|
||||||
if compile {
|
if compile {
|
||||||
var err error
|
var err error
|
||||||
|
@ -125,7 +125,7 @@ func main() {
|
|||||||
fmt.Fprintln(outputFile, "// Code generated by go generate; DO NOT EDIT.")
|
fmt.Fprintln(outputFile, "// Code generated by go generate; DO NOT EDIT.")
|
||||||
fmt.Fprintln(outputFile, "package tracker")
|
fmt.Fprintln(outputFile, "package tracker")
|
||||||
fmt.Fprintln(outputFile, "")
|
fmt.Fprintln(outputFile, "")
|
||||||
fmt.Fprintln(outputFile, "var gmDlsEntries = []GmDlsEntry{")
|
fmt.Fprintln(outputFile, "var GmDlsEntries = []GmDlsEntry{")
|
||||||
readChunk(0, inputFile, &gmDlsVisitor{outputFile: outputFile})
|
readChunk(0, inputFile, &gmDlsVisitor{outputFile: outputFile})
|
||||||
fmt.Fprintln(outputFile, "}")
|
fmt.Fprintln(outputFile, "}")
|
||||||
}
|
}
|
||||||
|
@ -4,11 +4,9 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"gioui.org/app"
|
|
||||||
"gioui.org/unit"
|
|
||||||
"github.com/vsariola/sointu/bridge"
|
"github.com/vsariola/sointu/bridge"
|
||||||
"github.com/vsariola/sointu/oto"
|
"github.com/vsariola/sointu/oto"
|
||||||
"github.com/vsariola/sointu/tracker"
|
"github.com/vsariola/sointu/tracker/gioui"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@ -19,18 +17,5 @@ func main() {
|
|||||||
}
|
}
|
||||||
defer audioContext.Close()
|
defer audioContext.Close()
|
||||||
synthService := bridge.BridgeService{}
|
synthService := bridge.BridgeService{}
|
||||||
go func() {
|
gioui.Main(audioContext, synthService)
|
||||||
w := app.NewWindow(
|
|
||||||
app.Size(unit.Dp(800), unit.Dp(600)),
|
|
||||||
app.Title("Sointu Tracker"),
|
|
||||||
)
|
|
||||||
t := tracker.New(audioContext, synthService)
|
|
||||||
defer t.Close()
|
|
||||||
if err := t.Run(w); err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
os.Exit(0)
|
|
||||||
}()
|
|
||||||
app.Main()
|
|
||||||
}
|
}
|
||||||
|
@ -82,7 +82,7 @@ func (com *Compiler) Song(song *sointu.Song) (map[string]string, error) {
|
|||||||
}
|
}
|
||||||
features := NecessaryFeaturesFor(song.Patch)
|
features := NecessaryFeaturesFor(song.Patch)
|
||||||
retmap := map[string]string{}
|
retmap := map[string]string{}
|
||||||
encodedPatch, err := Encode(&song.Patch, features)
|
encodedPatch, err := Encode(song.Patch, features)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf(`could not encode patch: %v`, err)
|
return nil, fmt.Errorf(`could not encode patch: %v`, err)
|
||||||
}
|
}
|
||||||
|
@ -22,16 +22,22 @@ type SampleOffset struct {
|
|||||||
LoopLength uint16
|
LoopLength uint16
|
||||||
}
|
}
|
||||||
|
|
||||||
func Encode(patch *sointu.Patch, featureSet FeatureSet) (*EncodedPatch, error) {
|
func Encode(patch sointu.Patch, featureSet FeatureSet) (*EncodedPatch, error) {
|
||||||
var c EncodedPatch
|
var c EncodedPatch
|
||||||
sampleOffsetMap := map[SampleOffset]int{}
|
sampleOffsetMap := map[SampleOffset]int{}
|
||||||
for instrIndex, instr := range patch.Instruments {
|
globalAddrs := map[int]uint16{}
|
||||||
|
globalFixups := map[int]([]int){}
|
||||||
|
voiceNo := 0
|
||||||
|
for instrIndex, instr := range patch {
|
||||||
if len(instr.Units) > 63 {
|
if len(instr.Units) > 63 {
|
||||||
return nil, errors.New("An instrument can have a maximum of 63 units")
|
return nil, errors.New("An instrument can have a maximum of 63 units")
|
||||||
}
|
}
|
||||||
if instr.NumVoices < 1 {
|
if instr.NumVoices < 1 {
|
||||||
return nil, errors.New("Each instrument must have at least 1 voice")
|
return nil, errors.New("Each instrument must have at least 1 voice")
|
||||||
}
|
}
|
||||||
|
localAddrs := map[int]uint16{}
|
||||||
|
localFixups := map[int]([]int){}
|
||||||
|
localUnitNo := 0
|
||||||
for _, unit := range instr.Units {
|
for _, unit := range instr.Units {
|
||||||
if unit.Type == "" { // empty units are just ignored & skipped
|
if unit.Type == "" { // empty units are just ignored & skipped
|
||||||
continue
|
continue
|
||||||
@ -113,44 +119,62 @@ func Encode(patch *sointu.Patch, featureSet FeatureSet) (*EncodedPatch, error) {
|
|||||||
}
|
}
|
||||||
values = append(values, byte(flags))
|
values = append(values, byte(flags))
|
||||||
} else if unit.Type == "send" {
|
} else if unit.Type == "send" {
|
||||||
|
targetID := unit.Parameters["target"]
|
||||||
|
targetInstrIndex, _, err := patch.FindSendTarget(targetID)
|
||||||
targetVoice := unit.Parameters["voice"]
|
targetVoice := unit.Parameters["voice"]
|
||||||
var targetInstrument int
|
var addr uint16 = uint16(unit.Parameters["port"]) & 7
|
||||||
if targetVoice == 0 {
|
|
||||||
targetInstrument = instrIndex
|
|
||||||
} else {
|
|
||||||
var err error
|
|
||||||
targetInstrument, err = patch.InstrumentForVoice(targetVoice - 1)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("send targeted a voice %v, which out of the range of instruments", targetVoice-1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
origTarget := unit.Parameters["unit"]
|
|
||||||
targetUnit := origTarget
|
|
||||||
for k := 0; k < origTarget; k++ {
|
|
||||||
units := patch.Instruments[targetInstrument].Units
|
|
||||||
if k >= len(units) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if units[k].Type == "" {
|
|
||||||
targetUnit--
|
|
||||||
}
|
|
||||||
}
|
|
||||||
address := ((targetUnit + 1) << 4) + unit.Parameters["port"] // each unit is 16 dwords, 8 workspace followed by 8 ports. +1 is for skipping the note/release/inputs
|
|
||||||
if unit.Parameters["voice"] > 0 {
|
|
||||||
address += 0x8000 + 16 + (unit.Parameters["voice"]-1)*1024 // global send, +16 is for skipping the out/aux ports
|
|
||||||
}
|
|
||||||
if unit.Parameters["sendpop"] == 1 {
|
if unit.Parameters["sendpop"] == 1 {
|
||||||
address += 0x8
|
addr += 0x8
|
||||||
}
|
}
|
||||||
values = append(values, byte(address&255), byte(address>>8))
|
|
||||||
|
if err == nil {
|
||||||
|
// local send is only possible if targetVoice is "auto" (0) and
|
||||||
|
// the targeted unit is in the same instrument as send
|
||||||
|
if targetInstrIndex == instrIndex && targetVoice == 0 {
|
||||||
|
if v, ok := localAddrs[targetID]; ok {
|
||||||
|
addr += v
|
||||||
|
} else {
|
||||||
|
localFixups[targetID] = append(localFixups[targetID], len(c.Values)+len(values))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
addr += 0x8000
|
||||||
|
if targetVoice > 0 { // "auto" (0) means for global send that it targets voice 0 of that instrument
|
||||||
|
addr += uint16((targetVoice - 1) * 0x400)
|
||||||
|
}
|
||||||
|
if v, ok := globalAddrs[targetID]; ok {
|
||||||
|
addr += v
|
||||||
|
} else {
|
||||||
|
globalFixups[targetID] = append(globalFixups[targetID], len(c.Values)+len(values))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// if no target will be found, the send will trash some of
|
||||||
|
// the last values of the last port of the last voice, which
|
||||||
|
// is unlikely to cause issues. We still honor the POP bit.
|
||||||
|
addr &= 0x8
|
||||||
|
addr |= 0xFFF7
|
||||||
|
}
|
||||||
|
values = append(values, byte(addr&255), byte(addr>>8))
|
||||||
} else if unit.Type == "delay" {
|
} else if unit.Type == "delay" {
|
||||||
countTrack := (unit.Parameters["count"] << 1) - 1 + unit.Parameters["notetracking"] // 1 means no note tracking and 1 delay, 2 means notetracking with 1 delay, 3 means no note tracking and 2 delays etc.
|
countTrack := (unit.Parameters["count"] << 1) - 1 + unit.Parameters["notetracking"] // 1 means no note tracking and 1 delay, 2 means notetracking with 1 delay, 3 means no note tracking and 2 delays etc.
|
||||||
values = append(values, byte(unit.Parameters["delay"]), byte(countTrack))
|
values = append(values, byte(unit.Parameters["delay"]), byte(countTrack))
|
||||||
}
|
}
|
||||||
c.Commands = append(c.Commands, byte(opcode+unit.Parameters["stereo"]))
|
c.Commands = append(c.Commands, byte(opcode+unit.Parameters["stereo"]))
|
||||||
c.Values = append(c.Values, values...)
|
c.Values = append(c.Values, values...)
|
||||||
|
if unit.ID != 0 {
|
||||||
|
localAddr := uint16((localUnitNo + 1) << 4)
|
||||||
|
fixUp(c.Values, localFixups[unit.ID], localAddr)
|
||||||
|
localFixups[unit.ID] = nil
|
||||||
|
localAddrs[unit.ID] = localAddr
|
||||||
|
globalAddr := localAddr + 16 + uint16(voiceNo)*1024
|
||||||
|
fixUp(c.Values, globalFixups[unit.ID], globalAddr)
|
||||||
|
globalFixups[unit.ID] = nil
|
||||||
|
globalAddrs[unit.ID] = globalAddr
|
||||||
|
}
|
||||||
|
localUnitNo++ // a command in command stream means the wrkspace addr gets also increased
|
||||||
}
|
}
|
||||||
c.Commands = append(c.Commands, byte(0)) // advance
|
c.Commands = append(c.Commands, byte(0)) // advance
|
||||||
|
voiceNo += instr.NumVoices
|
||||||
c.NumVoices += uint32(instr.NumVoices)
|
c.NumVoices += uint32(instr.NumVoices)
|
||||||
for k := 0; k < instr.NumVoices-1; k++ {
|
for k := 0; k < instr.NumVoices-1; k++ {
|
||||||
c.PolyphonyBitmask = (c.PolyphonyBitmask << 1) + 1
|
c.PolyphonyBitmask = (c.PolyphonyBitmask << 1) + 1
|
||||||
@ -163,3 +187,12 @@ func Encode(patch *sointu.Patch, featureSet FeatureSet) (*EncodedPatch, error) {
|
|||||||
|
|
||||||
return &c, nil
|
return &c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func fixUp(values []byte, positions []int, delta uint16) {
|
||||||
|
for _, pos := range positions {
|
||||||
|
orig := (uint16(values[pos+1]) << 8) + uint16(values[pos])
|
||||||
|
new := orig + delta
|
||||||
|
values[pos] = byte(new & 255)
|
||||||
|
values[pos+1] = byte(new >> 8)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -17,6 +17,7 @@ type FeatureSet interface {
|
|||||||
SupportsParamValueOtherThan(unitType string, paramName string, value int) bool
|
SupportsParamValueOtherThan(unitType string, paramName string, value int) bool
|
||||||
SupportsModulation(unitType string, paramName string) bool
|
SupportsModulation(unitType string, paramName string) bool
|
||||||
SupportsPolyphony() bool
|
SupportsPolyphony() bool
|
||||||
|
SupportsGlobalSend() bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type Instruction struct {
|
type Instruction struct {
|
||||||
@ -58,6 +59,10 @@ func (_ AllFeatures) SupportsPolyphony() bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (_ AllFeatures) SupportsGlobalSend() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func (_ AllFeatures) Opcode(unitType string) (int, bool) {
|
func (_ AllFeatures) Opcode(unitType string) (int, bool) {
|
||||||
code, ok := allOpcodes[unitType]
|
code, ok := allOpcodes[unitType]
|
||||||
return code, ok
|
return code, ok
|
||||||
@ -114,12 +119,13 @@ type NecessaryFeatures struct {
|
|||||||
instructions []string
|
instructions []string
|
||||||
supportsParamValue map[paramKey](map[int]bool)
|
supportsParamValue map[paramKey](map[int]bool)
|
||||||
supportsModulation map[paramKey]bool
|
supportsModulation map[paramKey]bool
|
||||||
|
globalSend bool
|
||||||
polyphony bool
|
polyphony bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NecessaryFeaturesFor(patch sointu.Patch) NecessaryFeatures {
|
func NecessaryFeaturesFor(patch sointu.Patch) NecessaryFeatures {
|
||||||
features := NecessaryFeatures{opcodes: map[string]int{}, supportsParamValue: map[paramKey](map[int]bool){}, supportsModulation: map[paramKey]bool{}}
|
features := NecessaryFeatures{opcodes: map[string]int{}, supportsParamValue: map[paramKey](map[int]bool){}, supportsModulation: map[paramKey]bool{}}
|
||||||
for instrNo, instrument := range patch.Instruments {
|
for instrIndex, instrument := range patch {
|
||||||
for _, unit := range instrument.Units {
|
for _, unit := range instrument.Units {
|
||||||
if _, ok := features.opcodes[unit.Type]; !ok {
|
if _, ok := features.opcodes[unit.Type]; !ok {
|
||||||
features.instructions = append(features.instructions, unit.Type)
|
features.instructions = append(features.instructions, unit.Type)
|
||||||
@ -133,27 +139,20 @@ func NecessaryFeaturesFor(patch sointu.Patch) NecessaryFeatures {
|
|||||||
features.supportsParamValue[key][v] = true
|
features.supportsParamValue[key][v] = true
|
||||||
}
|
}
|
||||||
if unit.Type == "send" {
|
if unit.Type == "send" {
|
||||||
targetInstrument := instrNo
|
targetInstrIndex, targetUnitIndex, err := patch.FindSendTarget(unit.Parameters["target"])
|
||||||
if unit.Parameters["voice"] > 0 {
|
|
||||||
v, err := patch.InstrumentForVoice(unit.Parameters["voice"] - 1)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
targetInstrument = v
|
targetUnit := patch[targetInstrIndex].Units[targetUnitIndex]
|
||||||
}
|
portList := sointu.Ports[targetUnit.Type]
|
||||||
if unit.Parameters["unit"] < 0 || unit.Parameters["unit"] >= len(patch.Instruments[targetInstrument].Units) {
|
portIndex := unit.Parameters["port"]
|
||||||
continue // send is modulating outside the range of the target instrument; probably a bug in patch, but at least it's not modulating the uniType we're after
|
if portIndex < 0 || portIndex >= len(portList) {
|
||||||
}
|
continue
|
||||||
targetUnit := patch.Instruments[targetInstrument].Units[unit.Parameters["unit"]]
|
|
||||||
modulatedPortNo := 0
|
|
||||||
for _, v := range sointu.UnitTypes[targetUnit.Type] {
|
|
||||||
if v.CanModulate {
|
|
||||||
if modulatedPortNo == unit.Parameters["port"] {
|
|
||||||
features.supportsModulation[paramKey{targetUnit.Type, v.Name}] = true
|
|
||||||
}
|
|
||||||
modulatedPortNo++
|
|
||||||
}
|
}
|
||||||
|
if targetInstrIndex != instrIndex || unit.Parameters["voice"] > 0 {
|
||||||
|
features.globalSend = true
|
||||||
}
|
}
|
||||||
|
features.supportsModulation[paramKey{targetUnit.Type, portList[portIndex]}] = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if instrument.NumVoices > 1 {
|
if instrument.NumVoices > 1 {
|
||||||
@ -204,3 +203,7 @@ func (n NecessaryFeatures) InputNumber(unitType string, paramName string) int {
|
|||||||
func (_ NecessaryFeatures) TransformCount(unitType string) int {
|
func (_ NecessaryFeatures) TransformCount(unitType string) int {
|
||||||
return allTransformCounts[unitType]
|
return allTransformCounts[unitType]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (n NecessaryFeatures) SupportsGlobalSend() bool {
|
||||||
|
return n.globalSend
|
||||||
|
}
|
||||||
|
@ -32,11 +32,17 @@ func fixPatternLength(patterns [][]byte, fixedLength int) [][]int {
|
|||||||
func flattenSequence(patterns [][]int, sequence []int) []int {
|
func flattenSequence(patterns [][]int, sequence []int) []int {
|
||||||
sumLen := 0
|
sumLen := 0
|
||||||
for _, patIndex := range sequence {
|
for _, patIndex := range sequence {
|
||||||
|
if patIndex < 0 || patIndex >= len(patterns) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
sumLen += len(patterns[patIndex])
|
sumLen += len(patterns[patIndex])
|
||||||
}
|
}
|
||||||
notes := make([]int, sumLen)
|
notes := make([]int, sumLen)
|
||||||
window := notes
|
window := notes
|
||||||
for _, patIndex := range sequence {
|
for _, patIndex := range sequence {
|
||||||
|
if patIndex < 0 || patIndex >= len(patterns) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
elementsCopied := copy(window, patterns[patIndex])
|
elementsCopied := copy(window, patterns[patIndex])
|
||||||
window = window[elementsCopied:]
|
window = window[elementsCopied:]
|
||||||
}
|
}
|
||||||
@ -167,12 +173,12 @@ func bytesToInts(array []byte) []int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ConstructPatterns(song *sointu.Song) ([][]byte, [][]byte, error) {
|
func ConstructPatterns(song *sointu.Song) ([][]byte, [][]byte, error) {
|
||||||
patLength := song.RowsPerPattern
|
patLength := song.Score.RowsPerPattern
|
||||||
sequences := make([][]byte, len(song.Tracks))
|
sequences := make([][]byte, len(song.Score.Tracks))
|
||||||
var patterns [][]int
|
var patterns [][]int
|
||||||
for i, t := range song.Tracks {
|
for i, t := range song.Score.Tracks {
|
||||||
fixed := fixPatternLength(t.Patterns, patLength)
|
fixed := fixPatternLength(t.Patterns, patLength)
|
||||||
flat := flattenSequence(fixed, bytesToInts(t.Sequence))
|
flat := flattenSequence(fixed, t.Order)
|
||||||
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, patLength)
|
||||||
|
@ -10,14 +10,16 @@ import (
|
|||||||
|
|
||||||
func TestPatternReusing(t *testing.T) {
|
func TestPatternReusing(t *testing.T) {
|
||||||
song := sointu.Song{
|
song := sointu.Song{
|
||||||
|
Score: sointu.Score{
|
||||||
RowsPerPattern: 8,
|
RowsPerPattern: 8,
|
||||||
Tracks: []sointu.Track{{
|
Tracks: []sointu.Track{{
|
||||||
Patterns: [][]byte{{64, 1, 1, 1, 0, 0, 0, 0}, {72, 0, 0, 0, 0, 0, 0, 0}},
|
Patterns: [][]byte{{64, 1, 1, 1, 0, 0, 0, 0}, {72, 0, 0, 0, 0, 0, 0, 0}},
|
||||||
Sequence: []byte{0, 1},
|
Order: []int{0, 1},
|
||||||
}, {
|
}, {
|
||||||
Patterns: [][]byte{{64, 1, 1, 1, 0, 0, 0, 0}, {84, 0, 0, 0, 0, 0, 0, 0}},
|
Patterns: [][]byte{{64, 1, 1, 1, 0, 0, 0, 0}, {84, 0, 0, 0, 0, 0, 0, 0}},
|
||||||
Sequence: []byte{0, 1},
|
Order: []int{0, 1},
|
||||||
}},
|
}},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
patterns, sequences, err := compiler.ConstructPatterns(&song)
|
patterns, sequences, err := compiler.ConstructPatterns(&song)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -35,14 +37,15 @@ func TestPatternReusing(t *testing.T) {
|
|||||||
|
|
||||||
func TestUnnecessaryHolds(t *testing.T) {
|
func TestUnnecessaryHolds(t *testing.T) {
|
||||||
song := sointu.Song{
|
song := sointu.Song{
|
||||||
|
Score: sointu.Score{
|
||||||
RowsPerPattern: 8,
|
RowsPerPattern: 8,
|
||||||
Tracks: []sointu.Track{{
|
Tracks: []sointu.Track{{
|
||||||
Patterns: [][]byte{{64, 1, 1, 1, 0, 1, 0, 0}, {72, 0, 1, 0, 1, 0, 0, 0}},
|
Patterns: [][]byte{{64, 1, 1, 1, 0, 1, 0, 0}, {72, 0, 1, 0, 1, 0, 0, 0}},
|
||||||
Sequence: []byte{0, 1},
|
Order: []int{0, 1},
|
||||||
}, {
|
}, {
|
||||||
Patterns: [][]byte{{64, 1, 1, 1, 0, 0, 1, 0}, {84, 0, 0, 0, 1, 1, 0, 0}},
|
Patterns: [][]byte{{64, 1, 1, 1, 0, 0, 1, 0}, {84, 0, 0, 0, 1, 1, 0, 0}},
|
||||||
Sequence: []byte{0, 1},
|
Order: []int{0, 1},
|
||||||
}},
|
}}},
|
||||||
}
|
}
|
||||||
patterns, sequences, err := compiler.ConstructPatterns(&song)
|
patterns, sequences, err := compiler.ConstructPatterns(&song)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -60,14 +63,17 @@ func TestUnnecessaryHolds(t *testing.T) {
|
|||||||
|
|
||||||
func TestDontCares(t *testing.T) {
|
func TestDontCares(t *testing.T) {
|
||||||
song := sointu.Song{
|
song := sointu.Song{
|
||||||
|
Score: sointu.Score{
|
||||||
|
Length: 2,
|
||||||
RowsPerPattern: 8,
|
RowsPerPattern: 8,
|
||||||
Tracks: []sointu.Track{{
|
Tracks: []sointu.Track{{
|
||||||
Patterns: [][]byte{{64, 1, 1, 1, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0}},
|
Patterns: [][]byte{{64, 1, 1, 1, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0}},
|
||||||
Sequence: []byte{0, 1},
|
Order: []int{0, 1},
|
||||||
}, {
|
}, {
|
||||||
Patterns: [][]byte{{64, 1, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 0, 0, 0, 0, 0}},
|
Patterns: [][]byte{{64, 1, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 0, 0, 0, 0, 0}},
|
||||||
Sequence: []byte{0, 1},
|
Order: []int{0, 1},
|
||||||
}},
|
}},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
patterns, sequences, err := compiler.ConstructPatterns(&song)
|
patterns, sequences, err := compiler.ConstructPatterns(&song)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -13,10 +13,10 @@ type SongMacros struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewSongMacros(s *sointu.Song) *SongMacros {
|
func NewSongMacros(s *sointu.Song) *SongMacros {
|
||||||
maxSamples := s.SamplesPerRow() * s.TotalRows()
|
maxSamples := s.SamplesPerRow() * s.Score.LengthInRows()
|
||||||
p := SongMacros{Song: s, MaxSamples: maxSamples}
|
p := SongMacros{Song: s, MaxSamples: maxSamples}
|
||||||
trackVoiceNumber := 0
|
trackVoiceNumber := 0
|
||||||
for _, t := range s.Tracks {
|
for _, t := range s.Score.Tracks {
|
||||||
for b := 0; b < t.NumVoices-1; b++ {
|
for b := 0; b < t.NumVoices-1; b++ {
|
||||||
p.VoiceTrackBitmask += 1 << trackVoiceNumber
|
p.VoiceTrackBitmask += 1 << trackVoiceNumber
|
||||||
trackVoiceNumber++
|
trackVoiceNumber++
|
||||||
@ -28,7 +28,7 @@ func NewSongMacros(s *sointu.Song) *SongMacros {
|
|||||||
|
|
||||||
func (p *SongMacros) NumDelayLines() string {
|
func (p *SongMacros) NumDelayLines() string {
|
||||||
total := 0
|
total := 0
|
||||||
for _, instr := range p.Song.Patch.Instruments {
|
for _, instr := range p.Song.Patch {
|
||||||
for _, unit := range instr.Units {
|
for _, unit := range instr.Units {
|
||||||
if unit.Type == "delay" {
|
if unit.Type == "delay" {
|
||||||
total += unit.Parameters["count"] * (1 + unit.Parameters["stereo"])
|
total += unit.Parameters["count"] * (1 + unit.Parameters["stereo"])
|
||||||
|
16
instrument.go
Normal file
16
instrument.go
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package sointu
|
||||||
|
|
||||||
|
// Instrument includes a list of units consisting of the instrument, and the number of polyphonic voices for this instrument
|
||||||
|
type Instrument struct {
|
||||||
|
Name string `yaml:",omitempty"`
|
||||||
|
NumVoices int
|
||||||
|
Units []Unit
|
||||||
|
}
|
||||||
|
|
||||||
|
func (instr *Instrument) Copy() Instrument {
|
||||||
|
units := make([]Unit, len(instr.Units))
|
||||||
|
for i, u := range instr.Units {
|
||||||
|
units[i] = u.Copy()
|
||||||
|
}
|
||||||
|
return Instrument{Name: instr.Name, NumVoices: instr.NumVoices, Units: units}
|
||||||
|
}
|
150
patch.go
Normal file
150
patch.go
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
package sointu
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Patch is simply a list of instruments used in a song
|
||||||
|
type Patch []Instrument
|
||||||
|
|
||||||
|
func (p Patch) Copy() Patch {
|
||||||
|
instruments := make([]Instrument, len(p))
|
||||||
|
for i, instr := range p {
|
||||||
|
instruments[i] = instr.Copy()
|
||||||
|
}
|
||||||
|
return instruments
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p Patch) NumVoices() int {
|
||||||
|
ret := 0
|
||||||
|
for _, i := range p {
|
||||||
|
ret += i.NumVoices
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p Patch) FirstVoiceForInstrument(instrIndex int) int {
|
||||||
|
ret := 0
|
||||||
|
for _, t := range p[:instrIndex] {
|
||||||
|
ret += t.NumVoices
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p Patch) InstrumentForVoice(voice int) (int, error) {
|
||||||
|
if voice < 0 {
|
||||||
|
return 0, errors.New("voice cannot be negative")
|
||||||
|
}
|
||||||
|
for i, instr := range p {
|
||||||
|
if voice < instr.NumVoices {
|
||||||
|
return i, nil
|
||||||
|
}
|
||||||
|
voice -= instr.NumVoices
|
||||||
|
}
|
||||||
|
return 0, errors.New("voice number is beyond the total voices of an instrument")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p Patch) FindSendTarget(id int) (int, int, error) {
|
||||||
|
if id == 0 {
|
||||||
|
return 0, 0, errors.New("send targets unit id 0")
|
||||||
|
}
|
||||||
|
for i, instr := range p {
|
||||||
|
for u, unit := range instr.Units {
|
||||||
|
if unit.ID == id {
|
||||||
|
return i, u, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0, 0, fmt.Errorf("send targets an unit with id %v, could not find a unit with such an ID in the patch", id)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p Patch) ParamHintString(instrIndex, unitIndex int, param string) string {
|
||||||
|
if instrIndex < 0 || instrIndex >= len(p) {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
instr := p[instrIndex]
|
||||||
|
if unitIndex < 0 || unitIndex >= len(instr.Units) {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
unit := instr.Units[unitIndex]
|
||||||
|
value := unit.Parameters[param]
|
||||||
|
switch unit.Type {
|
||||||
|
case "envelope":
|
||||||
|
switch param {
|
||||||
|
case "attack":
|
||||||
|
return engineeringTime(math.Pow(2, 24*float64(value)/128) / 44100)
|
||||||
|
case "decay":
|
||||||
|
return engineeringTime(math.Pow(2, 24*float64(value)/128) / 44100 * (1 - float64(unit.Parameters["sustain"])/128))
|
||||||
|
case "release":
|
||||||
|
return engineeringTime(math.Pow(2, 24*float64(value)/128) / 44100 * float64(unit.Parameters["sustain"]) / 128)
|
||||||
|
}
|
||||||
|
case "oscillator":
|
||||||
|
switch param {
|
||||||
|
case "type":
|
||||||
|
switch value {
|
||||||
|
case Sine:
|
||||||
|
return "Sine"
|
||||||
|
case Trisaw:
|
||||||
|
return "Trisaw"
|
||||||
|
case Pulse:
|
||||||
|
return "Pulse"
|
||||||
|
case Gate:
|
||||||
|
return "Gate"
|
||||||
|
case Sample:
|
||||||
|
return "Sample"
|
||||||
|
default:
|
||||||
|
return "Unknown"
|
||||||
|
}
|
||||||
|
case "transpose":
|
||||||
|
relvalue := value - 64
|
||||||
|
octaves := relvalue / 12
|
||||||
|
semitones := relvalue % 12
|
||||||
|
if octaves != 0 {
|
||||||
|
return fmt.Sprintf("%v oct, %v st", octaves, semitones)
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%v st", semitones)
|
||||||
|
case "detune":
|
||||||
|
return fmt.Sprintf("%v st", float32(value-64)/64.0)
|
||||||
|
}
|
||||||
|
case "compressor":
|
||||||
|
switch param {
|
||||||
|
case "attack":
|
||||||
|
fallthrough
|
||||||
|
case "release":
|
||||||
|
alpha := math.Pow(2, -24*float64(value)/128) // alpha is the "smoothing factor" of first order low pass iir
|
||||||
|
sec := -1 / (44100 * math.Log(1-alpha)) // from smoothing factor to time constant, https://en.wikipedia.org/wiki/Exponential_smoothing
|
||||||
|
return engineeringTime(sec)
|
||||||
|
case "ratio":
|
||||||
|
return fmt.Sprintf("1 : %.3f", 1-float64(value)/128)
|
||||||
|
}
|
||||||
|
case "send":
|
||||||
|
switch param {
|
||||||
|
case "voice":
|
||||||
|
if value == 0 {
|
||||||
|
return "auto"
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%v", value)
|
||||||
|
case "target":
|
||||||
|
instrIndex, unitIndex, err := p.FindSendTarget(unit.Parameters["target"])
|
||||||
|
if err != nil {
|
||||||
|
return "invalid target"
|
||||||
|
}
|
||||||
|
instr := p[instrIndex]
|
||||||
|
unit := instr.Units[unitIndex]
|
||||||
|
return fmt.Sprintf("%v / %v%v", instr.Name, unit.Type, unitIndex)
|
||||||
|
case "port":
|
||||||
|
instrIndex, unitIndex, err := p.FindSendTarget(unit.Parameters["target"])
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Sprintf("%v ???", value)
|
||||||
|
}
|
||||||
|
portList := Ports[p[instrIndex].Units[unitIndex].Type]
|
||||||
|
if value < 0 || value >= len(portList) {
|
||||||
|
return fmt.Sprintf("%v ???", value)
|
||||||
|
}
|
||||||
|
return fmt.Sprintf(portList[value])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
35
score.go
Normal file
35
score.go
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
package sointu
|
||||||
|
|
||||||
|
type Score struct {
|
||||||
|
Tracks []Track
|
||||||
|
RowsPerPattern int
|
||||||
|
Length int // length of the song, in number of patterns
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l Score) Copy() Score {
|
||||||
|
tracks := make([]Track, len(l.Tracks))
|
||||||
|
for i, t := range l.Tracks {
|
||||||
|
tracks[i] = t.Copy()
|
||||||
|
}
|
||||||
|
return Score{Tracks: tracks, RowsPerPattern: l.RowsPerPattern, Length: l.Length}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l Score) NumVoices() int {
|
||||||
|
ret := 0
|
||||||
|
for _, t := range l.Tracks {
|
||||||
|
ret += t.NumVoices
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l Score) FirstVoiceForTrack(track int) int {
|
||||||
|
ret := 0
|
||||||
|
for _, t := range l.Tracks[:track] {
|
||||||
|
ret += t.NumVoices
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l Score) LengthInRows() int {
|
||||||
|
return l.RowsPerPattern * l.Length
|
||||||
|
}
|
587
sointu.go
587
sointu.go
@ -1,587 +0,0 @@
|
|||||||
package sointu
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"math"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Unit is e.g. a filter, oscillator, envelope and its parameters
|
|
||||||
type Unit struct {
|
|
||||||
Type string
|
|
||||||
Parameters map[string]int `yaml:",flow"`
|
|
||||||
VarArgs []int `yaml:",flow,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *Unit) Copy() Unit {
|
|
||||||
parameters := make(map[string]int)
|
|
||||||
for k, v := range u.Parameters {
|
|
||||||
parameters[k] = v
|
|
||||||
}
|
|
||||||
varArgs := make([]int, len(u.VarArgs))
|
|
||||||
copy(varArgs, u.VarArgs)
|
|
||||||
return Unit{Type: u.Type, Parameters: parameters, VarArgs: varArgs}
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
Sine = iota
|
|
||||||
Trisaw = iota
|
|
||||||
Pulse = iota
|
|
||||||
Gate = iota
|
|
||||||
Sample = iota
|
|
||||||
)
|
|
||||||
|
|
||||||
// Instrument includes a list of units consisting of the instrument, and the number of polyphonic voices for this instrument
|
|
||||||
type Instrument struct {
|
|
||||||
Name string
|
|
||||||
NumVoices int
|
|
||||||
Units []Unit
|
|
||||||
}
|
|
||||||
|
|
||||||
func (instr *Instrument) Copy() Instrument {
|
|
||||||
units := make([]Unit, len(instr.Units))
|
|
||||||
for i, u := range instr.Units {
|
|
||||||
units[i] = u.Copy()
|
|
||||||
}
|
|
||||||
return Instrument{Name: instr.Name, NumVoices: instr.NumVoices, Units: units}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Patch is simply a list of instruments used in a song
|
|
||||||
type Patch struct {
|
|
||||||
Instruments []Instrument
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Patch) Copy() Patch {
|
|
||||||
instruments := make([]Instrument, len(p.Instruments))
|
|
||||||
for i, instr := range p.Instruments {
|
|
||||||
instruments[i] = instr.Copy()
|
|
||||||
}
|
|
||||||
return Patch{Instruments: instruments}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p Patch) TotalVoices() int {
|
|
||||||
ret := 0
|
|
||||||
for _, i := range p.Instruments {
|
|
||||||
ret += i.NumVoices
|
|
||||||
}
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
func (patch Patch) InstrumentForVoice(voice int) (int, error) {
|
|
||||||
if voice < 0 {
|
|
||||||
return 0, errors.New("voice cannot be negative")
|
|
||||||
}
|
|
||||||
for i, instr := range patch.Instruments {
|
|
||||||
if voice < instr.NumVoices {
|
|
||||||
return i, nil
|
|
||||||
} else {
|
|
||||||
voice -= instr.NumVoices
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0, errors.New("voice number is beyond the total voices of an instrument")
|
|
||||||
}
|
|
||||||
|
|
||||||
type Track struct {
|
|
||||||
NumVoices int
|
|
||||||
Sequence []byte `yaml:",flow"`
|
|
||||||
Patterns [][]byte `yaml:",flow"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *Track) Copy() Track {
|
|
||||||
sequence := make([]byte, len(t.Sequence))
|
|
||||||
copy(sequence, t.Sequence)
|
|
||||||
patterns := make([][]byte, len(t.Patterns))
|
|
||||||
for i, oldPat := range t.Patterns {
|
|
||||||
newPat := make([]byte, len(oldPat))
|
|
||||||
copy(newPat, oldPat)
|
|
||||||
patterns[i] = newPat
|
|
||||||
}
|
|
||||||
return Track{
|
|
||||||
NumVoices: t.NumVoices,
|
|
||||||
Sequence: sequence,
|
|
||||||
Patterns: patterns,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type Synth interface {
|
|
||||||
Render(buffer []float32, maxtime int) (int, int, error)
|
|
||||||
Update(patch Patch) error
|
|
||||||
Trigger(voice int, note byte)
|
|
||||||
Release(voice int)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Render(synth Synth, buffer []float32) error {
|
|
||||||
s, _, err := synth.Render(buffer, math.MaxInt32)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("sointu.Render failed: %v", err)
|
|
||||||
}
|
|
||||||
if s != len(buffer)/2 {
|
|
||||||
return errors.New("in sointu.Render, synth.Render should have filled the whole buffer but did not")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type SynthService interface {
|
|
||||||
Compile(patch Patch) (Synth, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
type AudioSink interface {
|
|
||||||
WriteAudio(buffer []float32) (err error)
|
|
||||||
Close() error
|
|
||||||
}
|
|
||||||
|
|
||||||
type AudioSource interface {
|
|
||||||
ReadAudio(buffer []float32) (n int, err error)
|
|
||||||
Close() error
|
|
||||||
}
|
|
||||||
|
|
||||||
type AudioContext interface {
|
|
||||||
Output() AudioSink
|
|
||||||
Close() error
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnitParameter documents one parameter that an unit takes
|
|
||||||
type UnitParameter struct {
|
|
||||||
Name string // thould be found with this name in the Unit.Parameters map
|
|
||||||
MinValue int // minimum value of the parameter, inclusive
|
|
||||||
MaxValue int // maximum value of the parameter, inclusive
|
|
||||||
CanSet bool // if this parameter can be set before hand i.e. through the gui
|
|
||||||
CanModulate bool // if this parameter can be modulated i.e. has a port number in "send" unit
|
|
||||||
}
|
|
||||||
|
|
||||||
func engineeringTime(sec float64) string {
|
|
||||||
if sec < 1e-3 {
|
|
||||||
return fmt.Sprintf("%.2f us", sec*1e6)
|
|
||||||
} else if sec < 1 {
|
|
||||||
return fmt.Sprintf("%.2f ms", sec*1e3)
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("%.2f s", sec)
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnitTypes documents all the available unit types and if they support stereo variant
|
|
||||||
// and what parameters they take.
|
|
||||||
var UnitTypes = map[string]([]UnitParameter){
|
|
||||||
"add": []UnitParameter{{Name: "stereo", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false}},
|
|
||||||
"addp": []UnitParameter{{Name: "stereo", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false}},
|
|
||||||
"pop": []UnitParameter{{Name: "stereo", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false}},
|
|
||||||
"loadnote": []UnitParameter{{Name: "stereo", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false}},
|
|
||||||
"mul": []UnitParameter{{Name: "stereo", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false}},
|
|
||||||
"mulp": []UnitParameter{{Name: "stereo", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false}},
|
|
||||||
"push": []UnitParameter{{Name: "stereo", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false}},
|
|
||||||
"xch": []UnitParameter{{Name: "stereo", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false}},
|
|
||||||
"distort": []UnitParameter{
|
|
||||||
{Name: "stereo", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false},
|
|
||||||
{Name: "drive", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true}},
|
|
||||||
"hold": []UnitParameter{
|
|
||||||
{Name: "stereo", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false},
|
|
||||||
{Name: "holdfreq", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true}},
|
|
||||||
"crush": []UnitParameter{
|
|
||||||
{Name: "stereo", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false},
|
|
||||||
{Name: "resolution", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true}},
|
|
||||||
"gain": []UnitParameter{
|
|
||||||
{Name: "stereo", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false},
|
|
||||||
{Name: "gain", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true}},
|
|
||||||
"invgain": []UnitParameter{
|
|
||||||
{Name: "stereo", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false},
|
|
||||||
{Name: "invgain", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true}},
|
|
||||||
"filter": []UnitParameter{
|
|
||||||
{Name: "stereo", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false},
|
|
||||||
{Name: "frequency", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true},
|
|
||||||
{Name: "resonance", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true},
|
|
||||||
{Name: "lowpass", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false},
|
|
||||||
{Name: "bandpass", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false},
|
|
||||||
{Name: "highpass", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false},
|
|
||||||
{Name: "negbandpass", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false},
|
|
||||||
{Name: "neghighpass", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false}},
|
|
||||||
"clip": []UnitParameter{{Name: "stereo", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false}},
|
|
||||||
"pan": []UnitParameter{
|
|
||||||
{Name: "stereo", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false},
|
|
||||||
{Name: "panning", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true}},
|
|
||||||
"delay": []UnitParameter{
|
|
||||||
{Name: "stereo", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false},
|
|
||||||
{Name: "pregain", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true},
|
|
||||||
{Name: "dry", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true},
|
|
||||||
{Name: "feedback", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true},
|
|
||||||
{Name: "damp", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true},
|
|
||||||
{Name: "notetracking", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false},
|
|
||||||
{Name: "delaytime", MinValue: 0, MaxValue: -1, CanSet: false, CanModulate: true}},
|
|
||||||
"compressor": []UnitParameter{
|
|
||||||
{Name: "stereo", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false},
|
|
||||||
{Name: "attack", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true},
|
|
||||||
{Name: "release", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true},
|
|
||||||
{Name: "invgain", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true},
|
|
||||||
{Name: "threshold", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true},
|
|
||||||
{Name: "ratio", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true}},
|
|
||||||
"speed": []UnitParameter{},
|
|
||||||
"out": []UnitParameter{
|
|
||||||
{Name: "stereo", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false},
|
|
||||||
{Name: "gain", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true}},
|
|
||||||
"outaux": []UnitParameter{
|
|
||||||
{Name: "stereo", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false},
|
|
||||||
{Name: "outgain", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true},
|
|
||||||
{Name: "auxgain", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true}},
|
|
||||||
"aux": []UnitParameter{
|
|
||||||
{Name: "stereo", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false},
|
|
||||||
{Name: "gain", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true},
|
|
||||||
{Name: "channel", MinValue: 0, MaxValue: 6, CanSet: true, CanModulate: false}},
|
|
||||||
"send": []UnitParameter{
|
|
||||||
{Name: "stereo", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false},
|
|
||||||
{Name: "amount", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true},
|
|
||||||
{Name: "voice", MinValue: 0, MaxValue: 32, CanSet: true, CanModulate: false},
|
|
||||||
{Name: "unit", MinValue: 0, MaxValue: 63, CanSet: true, CanModulate: false},
|
|
||||||
{Name: "port", MinValue: 0, MaxValue: 7, CanSet: true, CanModulate: false},
|
|
||||||
{Name: "sendpop", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false}},
|
|
||||||
"envelope": []UnitParameter{
|
|
||||||
{Name: "stereo", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false},
|
|
||||||
{Name: "attack", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true},
|
|
||||||
{Name: "decay", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true},
|
|
||||||
{Name: "sustain", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true},
|
|
||||||
{Name: "release", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true},
|
|
||||||
{Name: "gain", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true}},
|
|
||||||
"noise": []UnitParameter{
|
|
||||||
{Name: "stereo", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false},
|
|
||||||
{Name: "shape", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true},
|
|
||||||
{Name: "gain", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true}},
|
|
||||||
"oscillator": []UnitParameter{
|
|
||||||
{Name: "stereo", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false},
|
|
||||||
{Name: "transpose", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true},
|
|
||||||
{Name: "detune", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true},
|
|
||||||
{Name: "phase", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true},
|
|
||||||
{Name: "color", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true},
|
|
||||||
{Name: "shape", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true},
|
|
||||||
{Name: "gain", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true},
|
|
||||||
{Name: "type", MinValue: int(Sine), MaxValue: int(Sample), CanSet: true, CanModulate: false},
|
|
||||||
{Name: "lfo", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false},
|
|
||||||
{Name: "unison", MinValue: 0, MaxValue: 3, CanSet: true, CanModulate: false},
|
|
||||||
{Name: "samplestart", MinValue: 0, MaxValue: 1720329, CanSet: true, CanModulate: false},
|
|
||||||
{Name: "loopstart", MinValue: 0, MaxValue: 65535, CanSet: true, CanModulate: false},
|
|
||||||
{Name: "looplength", MinValue: 0, MaxValue: 65535, CanSet: true, CanModulate: false}},
|
|
||||||
"loadval": []UnitParameter{
|
|
||||||
{Name: "stereo", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false},
|
|
||||||
{Name: "value", MinValue: 0, MaxValue: 128, CanSet: true, CanModulate: true}},
|
|
||||||
"receive": []UnitParameter{
|
|
||||||
{Name: "stereo", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false},
|
|
||||||
{Name: "left", MinValue: 0, MaxValue: -1, CanSet: false, CanModulate: true},
|
|
||||||
{Name: "right", MinValue: 0, MaxValue: -1, CanSet: false, CanModulate: true}},
|
|
||||||
"in": []UnitParameter{
|
|
||||||
{Name: "stereo", MinValue: 0, MaxValue: 1, CanSet: true, CanModulate: false},
|
|
||||||
{Name: "channel", MinValue: 0, MaxValue: 6, CanSet: true, CanModulate: false}},
|
|
||||||
}
|
|
||||||
|
|
||||||
var Ports = make(map[string]([]string))
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
for name, unitType := range UnitTypes {
|
|
||||||
unitPorts := make([]string, 0)
|
|
||||||
for _, param := range unitType {
|
|
||||||
if param.CanModulate {
|
|
||||||
unitPorts = append(unitPorts, param.Name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ports[name] = unitPorts
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type Song struct {
|
|
||||||
BPM int
|
|
||||||
RowsPerPattern int
|
|
||||||
RowsPerBeat int
|
|
||||||
Tracks []Track
|
|
||||||
Patch Patch
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Song) Copy() Song {
|
|
||||||
tracks := make([]Track, len(s.Tracks))
|
|
||||||
for i, t := range s.Tracks {
|
|
||||||
tracks[i] = t.Copy()
|
|
||||||
}
|
|
||||||
return Song{BPM: s.BPM, RowsPerPattern: s.RowsPerPattern, RowsPerBeat: s.RowsPerBeat, Tracks: tracks, Patch: s.Patch.Copy()}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Song) SequenceLength() int {
|
|
||||||
return len(s.Tracks[0].Sequence)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Song) TotalRows() int {
|
|
||||||
return s.RowsPerPattern * s.SequenceLength()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Song) SamplesPerRow() int {
|
|
||||||
return 44100 * 60 / (s.BPM * s.RowsPerBeat)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Song) FirstTrackVoice(track int) int {
|
|
||||||
ret := 0
|
|
||||||
for _, t := range s.Tracks[:track] {
|
|
||||||
ret += t.NumVoices
|
|
||||||
}
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Song) FirstInstrumentVoice(instrument int) int {
|
|
||||||
ret := 0
|
|
||||||
for _, i := range s.Patch.Instruments[:instrument] {
|
|
||||||
ret += i.NumVoices
|
|
||||||
}
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Song) TotalTrackVoices() int {
|
|
||||||
ret := 0
|
|
||||||
for _, t := range s.Tracks {
|
|
||||||
ret += t.NumVoices
|
|
||||||
}
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
// TBD: Where shall we put methods that work on pure domain types and have no dependencies
|
|
||||||
// e.g. Validate here
|
|
||||||
func (s *Song) Validate() error {
|
|
||||||
if s.BPM < 1 {
|
|
||||||
return errors.New("BPM should be > 0")
|
|
||||||
}
|
|
||||||
var patternLen int
|
|
||||||
for i, t := range s.Tracks {
|
|
||||||
for j, pat := range t.Patterns {
|
|
||||||
if i == 0 && j == 0 {
|
|
||||||
patternLen = len(pat)
|
|
||||||
} else {
|
|
||||||
if len(pat) != patternLen {
|
|
||||||
return errors.New("Every pattern should have the same length")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for i := range s.Tracks[:len(s.Tracks)-1] {
|
|
||||||
if len(s.Tracks[i].Sequence) != len(s.Tracks[i+1].Sequence) {
|
|
||||||
return errors.New("Every track should have the same sequence length")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
totalTrackVoices := 0
|
|
||||||
for _, track := range s.Tracks {
|
|
||||||
totalTrackVoices += track.NumVoices
|
|
||||||
for _, p := range track.Sequence {
|
|
||||||
if p < 0 || int(p) >= len(track.Patterns) {
|
|
||||||
return errors.New("Tracks use a non-existing pattern")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if totalTrackVoices > s.Patch.TotalVoices() {
|
|
||||||
return errors.New("Tracks use too many voices")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Patch) FindSendTarget(i, u int) (int, int, int, error) {
|
|
||||||
if i < 0 || i >= len(p.Instruments) {
|
|
||||||
return -1, -1, -1, errors.New("instrument index out of range")
|
|
||||||
}
|
|
||||||
instr := p.Instruments[i]
|
|
||||||
if u < 0 || u >= len(instr.Units) {
|
|
||||||
return -1, -1, -1, errors.New("unit index out of range")
|
|
||||||
}
|
|
||||||
unit := instr.Units[u]
|
|
||||||
var targetInstrIndex int
|
|
||||||
if unit.Parameters["voice"] == 0 {
|
|
||||||
targetInstrIndex = i
|
|
||||||
} else {
|
|
||||||
var err error
|
|
||||||
targetInstrIndex, err = p.InstrumentForVoice(unit.Parameters["voice"] - 1)
|
|
||||||
if err != nil {
|
|
||||||
return -1, -1, -1, errors.New("the target voice was out of range")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
targetInstr := p.Instruments[targetInstrIndex]
|
|
||||||
targetUnitIndex := unit.Parameters["unit"]
|
|
||||||
if targetUnitIndex < 0 || targetUnitIndex >= len(targetInstr.Units) {
|
|
||||||
return targetInstrIndex, -1, -1, errors.New("the target unit was out of range")
|
|
||||||
}
|
|
||||||
targetUnit := targetInstr.Units[targetUnitIndex]
|
|
||||||
port := unit.Parameters["port"]
|
|
||||||
if port < 0 {
|
|
||||||
return targetInstrIndex, targetUnitIndex, -1, errors.New("the target port was out of range")
|
|
||||||
}
|
|
||||||
for k, param := range UnitTypes[targetUnit.Type] {
|
|
||||||
if param.CanModulate {
|
|
||||||
port--
|
|
||||||
if port < 0 {
|
|
||||||
return targetInstrIndex, targetUnitIndex, k, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return targetInstrIndex, targetUnitIndex, -1, errors.New("the target port was out of range")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Song) ParamHintString(instrIndex, unitIndex int, param string) string {
|
|
||||||
if instrIndex < 0 || instrIndex >= len(s.Patch.Instruments) {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
instr := s.Patch.Instruments[instrIndex]
|
|
||||||
if unitIndex < 0 || unitIndex >= len(instr.Units) {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
unit := instr.Units[unitIndex]
|
|
||||||
value := unit.Parameters[param]
|
|
||||||
switch unit.Type {
|
|
||||||
case "envelope":
|
|
||||||
switch param {
|
|
||||||
case "attack":
|
|
||||||
return engineeringTime(math.Pow(2, 24*float64(value)/128) / 44100)
|
|
||||||
case "decay":
|
|
||||||
return engineeringTime(math.Pow(2, 24*float64(value)/128) / 44100 * (1 - float64(unit.Parameters["sustain"])/128))
|
|
||||||
case "release":
|
|
||||||
return engineeringTime(math.Pow(2, 24*float64(value)/128) / 44100 * float64(unit.Parameters["sustain"]) / 128)
|
|
||||||
}
|
|
||||||
case "oscillator":
|
|
||||||
switch param {
|
|
||||||
case "type":
|
|
||||||
switch value {
|
|
||||||
case Sine:
|
|
||||||
return "Sine"
|
|
||||||
case Trisaw:
|
|
||||||
return "Trisaw"
|
|
||||||
case Pulse:
|
|
||||||
return "Pulse"
|
|
||||||
case Gate:
|
|
||||||
return "Gate"
|
|
||||||
case Sample:
|
|
||||||
return "Sample"
|
|
||||||
default:
|
|
||||||
return "Unknown"
|
|
||||||
}
|
|
||||||
case "transpose":
|
|
||||||
relvalue := value - 64
|
|
||||||
octaves := relvalue / 12
|
|
||||||
semitones := relvalue % 12
|
|
||||||
if octaves != 0 {
|
|
||||||
return fmt.Sprintf("%v oct, %v st", octaves, semitones)
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("%v st", semitones)
|
|
||||||
case "detune":
|
|
||||||
return fmt.Sprintf("%v st", float32(value-64)/64.0)
|
|
||||||
}
|
|
||||||
case "compressor":
|
|
||||||
switch param {
|
|
||||||
case "attack":
|
|
||||||
fallthrough
|
|
||||||
case "release":
|
|
||||||
alpha := math.Pow(2, -24*float64(value)/128) // alpha is the "smoothing factor" of first order low pass iir
|
|
||||||
sec := -1 / (44100 * math.Log(1-alpha)) // from smoothing factor to time constant, https://en.wikipedia.org/wiki/Exponential_smoothing
|
|
||||||
return engineeringTime(sec)
|
|
||||||
case "ratio":
|
|
||||||
return fmt.Sprintf("1 : %.3f", 1-float64(value)/128)
|
|
||||||
}
|
|
||||||
case "send":
|
|
||||||
if param == "voice" || param == "unit" || param == "port" {
|
|
||||||
targetVoice := unit.Parameters["voice"]
|
|
||||||
if param == "voice" && targetVoice == 0 {
|
|
||||||
return "self"
|
|
||||||
}
|
|
||||||
targetInstrument := instrIndex
|
|
||||||
if targetVoice > 0 { // global send, find the instrument
|
|
||||||
if targetVoice > s.Patch.TotalVoices() {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
targetVoice--
|
|
||||||
targetInstrument = 0
|
|
||||||
for targetVoice >= s.Patch.Instruments[targetInstrument].NumVoices {
|
|
||||||
targetVoice -= s.Patch.Instruments[targetInstrument].NumVoices
|
|
||||||
targetInstrument++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if param == "voice" {
|
|
||||||
return fmt.Sprintf("%v (voice %v)", s.Patch.Instruments[targetInstrument].Name, targetVoice)
|
|
||||||
}
|
|
||||||
targetUnitIndex := unit.Parameters["unit"]
|
|
||||||
units := s.Patch.Instruments[targetInstrument].Units
|
|
||||||
if targetUnitIndex < 0 || targetUnitIndex >= len(units) {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
if param == "unit" {
|
|
||||||
return fmt.Sprintf("%v#%v", units[targetUnitIndex].Type, targetUnitIndex)
|
|
||||||
}
|
|
||||||
port := value
|
|
||||||
for _, param := range UnitTypes[units[targetUnitIndex].Type] {
|
|
||||||
if param.CanModulate {
|
|
||||||
port--
|
|
||||||
if port < 0 {
|
|
||||||
return param.Name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *Unit) StackChange() int {
|
|
||||||
switch u.Type {
|
|
||||||
case "addp", "mulp", "pop", "out", "outaux", "aux":
|
|
||||||
return -1 - u.Parameters["stereo"]
|
|
||||||
case "envelope", "oscillator", "push", "noise", "receive", "loadnote", "loadval", "in", "compressor":
|
|
||||||
return 1 + u.Parameters["stereo"]
|
|
||||||
case "pan":
|
|
||||||
return 1 - u.Parameters["stereo"]
|
|
||||||
case "speed":
|
|
||||||
return -1
|
|
||||||
case "send":
|
|
||||||
return (-1 - u.Parameters["stereo"]) * u.Parameters["sendpop"]
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *Unit) StackNeed() int {
|
|
||||||
switch u.Type {
|
|
||||||
case "", "envelope", "oscillator", "noise", "receive", "loadnote", "loadval", "in":
|
|
||||||
return 0
|
|
||||||
case "mulp", "mul", "add", "addp", "xch":
|
|
||||||
return 2 * (1 + u.Parameters["stereo"])
|
|
||||||
case "speed":
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
return 1 + u.Parameters["stereo"]
|
|
||||||
}
|
|
||||||
|
|
||||||
func Play(synth Synth, song Song) ([]float32, error) {
|
|
||||||
err := song.Validate()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
curVoices := make([]int, len(song.Tracks))
|
|
||||||
for i := range curVoices {
|
|
||||||
curVoices[i] = song.FirstTrackVoice(i)
|
|
||||||
}
|
|
||||||
initialCapacity := song.TotalRows() * song.SamplesPerRow() * 2
|
|
||||||
buffer := make([]float32, 0, initialCapacity)
|
|
||||||
rowbuffer := make([]float32, song.SamplesPerRow()*2)
|
|
||||||
for row := 0; row < song.TotalRows(); row++ {
|
|
||||||
patternRow := row % song.RowsPerPattern
|
|
||||||
pattern := row / song.RowsPerPattern
|
|
||||||
for t := range song.Tracks {
|
|
||||||
patternIndex := song.Tracks[t].Sequence[pattern]
|
|
||||||
note := song.Tracks[t].Patterns[patternIndex][patternRow]
|
|
||||||
if note > 0 && note <= 1 { // anything but hold causes an action.
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
synth.Release(curVoices[t])
|
|
||||||
if note > 1 {
|
|
||||||
curVoices[t]++
|
|
||||||
first := song.FirstTrackVoice(t)
|
|
||||||
if curVoices[t] >= first+song.Tracks[t].NumVoices {
|
|
||||||
curVoices[t] = first
|
|
||||||
}
|
|
||||||
synth.Trigger(curVoices[t], note)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tries := 0
|
|
||||||
for rowtime := 0; rowtime < song.SamplesPerRow(); {
|
|
||||||
samples, time, _ := synth.Render(rowbuffer, song.SamplesPerRow()-rowtime)
|
|
||||||
rowtime += time
|
|
||||||
buffer = append(buffer, rowbuffer[:samples*2]...)
|
|
||||||
if tries > 100 {
|
|
||||||
return nil, fmt.Errorf("Song speed modulation likely so slow that row never advances; error at pattern %v, row %v", pattern, patternRow)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return buffer, nil
|
|
||||||
}
|
|
61
song.go
Normal file
61
song.go
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
package sointu
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Song struct {
|
||||||
|
BPM int
|
||||||
|
RowsPerBeat int
|
||||||
|
Score Score
|
||||||
|
Patch Patch
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Song) Copy() Song {
|
||||||
|
return Song{BPM: s.BPM, RowsPerBeat: s.RowsPerBeat, Score: s.Score.Copy(), Patch: s.Patch.Copy()}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Song) SamplesPerRow() int {
|
||||||
|
return 44100 * 60 / (s.BPM * s.RowsPerBeat)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TBD: Where shall we put methods that work on pure domain types and have no dependencies
|
||||||
|
// e.g. Validate here
|
||||||
|
func (s *Song) Validate() error {
|
||||||
|
if s.BPM < 1 {
|
||||||
|
return errors.New("BPM should be > 0")
|
||||||
|
}
|
||||||
|
if len(s.Score.Tracks) == 0 {
|
||||||
|
return errors.New("song contains no tracks")
|
||||||
|
}
|
||||||
|
var patternLen int
|
||||||
|
for i, t := range s.Score.Tracks {
|
||||||
|
for j, pat := range t.Patterns {
|
||||||
|
if i == 0 && j == 0 {
|
||||||
|
patternLen = len(pat)
|
||||||
|
} else {
|
||||||
|
if len(pat) != patternLen {
|
||||||
|
return errors.New("Every pattern should have the same length")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for i := range s.Score.Tracks[:len(s.Score.Tracks)-1] {
|
||||||
|
if len(s.Score.Tracks[i].Order) != len(s.Score.Tracks[i+1].Order) {
|
||||||
|
return errors.New("Every track should have the same sequence length")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
totalTrackVoices := 0
|
||||||
|
for _, track := range s.Score.Tracks {
|
||||||
|
totalTrackVoices += track.NumVoices
|
||||||
|
for _, p := range track.Order {
|
||||||
|
if p < 0 || int(p) >= len(track.Patterns) {
|
||||||
|
return errors.New("Tracks use a non-existing pattern")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if totalTrackVoices > s.Patch.NumVoices() {
|
||||||
|
return errors.New("Tracks use too many voices")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
85
synth.go
Normal file
85
synth.go
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
package sointu
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Synth interface {
|
||||||
|
Render(buffer []float32, maxtime int) (int, int, error)
|
||||||
|
Update(patch Patch) error
|
||||||
|
Trigger(voice int, note byte)
|
||||||
|
Release(voice int)
|
||||||
|
}
|
||||||
|
|
||||||
|
type SynthService interface {
|
||||||
|
Compile(patch Patch) (Synth, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Render(synth Synth, buffer []float32) error {
|
||||||
|
s, _, err := synth.Render(buffer, math.MaxInt32)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("sointu.Render failed: %v", err)
|
||||||
|
}
|
||||||
|
if s != len(buffer)/2 {
|
||||||
|
return errors.New("in sointu.Render, synth.Render should have filled the whole buffer but did not")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Play(synth Synth, song Song) ([]float32, error) {
|
||||||
|
err := song.Validate()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
curVoices := make([]int, len(song.Score.Tracks))
|
||||||
|
for i := range curVoices {
|
||||||
|
curVoices[i] = song.Score.FirstVoiceForTrack(i)
|
||||||
|
}
|
||||||
|
initialCapacity := song.Score.LengthInRows() * song.SamplesPerRow() * 2
|
||||||
|
buffer := make([]float32, 0, initialCapacity)
|
||||||
|
rowbuffer := make([]float32, song.SamplesPerRow()*2)
|
||||||
|
for row := 0; row < song.Score.LengthInRows(); row++ {
|
||||||
|
patternRow := row % song.Score.RowsPerPattern
|
||||||
|
pattern := row / song.Score.RowsPerPattern
|
||||||
|
for t := range song.Score.Tracks {
|
||||||
|
order := song.Score.Tracks[t].Order
|
||||||
|
if pattern < 0 || pattern >= len(order) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
patternIndex := song.Score.Tracks[t].Order[pattern]
|
||||||
|
patterns := song.Score.Tracks[t].Patterns
|
||||||
|
if patternIndex < 0 || int(patternIndex) >= len(patterns) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
pattern := patterns[patternIndex]
|
||||||
|
if patternRow < 0 || patternRow >= len(pattern) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
note := pattern[patternRow]
|
||||||
|
if note > 0 && note <= 1 { // anything but hold causes an action.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
synth.Release(curVoices[t])
|
||||||
|
if note > 1 {
|
||||||
|
curVoices[t]++
|
||||||
|
first := song.Score.FirstVoiceForTrack(t)
|
||||||
|
if curVoices[t] >= first+song.Score.Tracks[t].NumVoices {
|
||||||
|
curVoices[t] = first
|
||||||
|
}
|
||||||
|
synth.Trigger(curVoices[t], note)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tries := 0
|
||||||
|
for rowtime := 0; rowtime < song.SamplesPerRow(); {
|
||||||
|
samples, time, _ := synth.Render(rowbuffer, song.SamplesPerRow()-rowtime)
|
||||||
|
rowtime += time
|
||||||
|
buffer = append(buffer, rowbuffer[:samples*2]...)
|
||||||
|
if tries > 100 {
|
||||||
|
return nil, fmt.Errorf("Song speed modulation likely so slow that row never advances; error at pattern %v, row %v", pattern, patternRow)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return buffer, nil
|
||||||
|
}
|
@ -40,7 +40,7 @@ su_render_sampleloop: ; loop through every sample in the row
|
|||||||
{{- if .SupportsPolyphony}}
|
{{- if .SupportsPolyphony}}
|
||||||
{{.Push (.PolyphonyBitmask | printf "%v") "PolyphonyBitmask"}} ; does the next voice reuse the current opcodes?
|
{{.Push (.PolyphonyBitmask | printf "%v") "PolyphonyBitmask"}} ; does the next voice reuse the current opcodes?
|
||||||
{{- end}}
|
{{- end}}
|
||||||
{{.Push (.Song.Patch.TotalVoices | printf "%v") "VoicesRemain"}}
|
{{.Push (.Song.Patch.NumVoices | printf "%v") "VoicesRemain"}}
|
||||||
mov {{.DX}}, {{.PTRWORD}} su_synth_obj ; {{.DX}} points to the synth object
|
mov {{.DX}}, {{.PTRWORD}} su_synth_obj ; {{.DX}} points to the synth object
|
||||||
mov {{.COM}}, {{.PTRWORD}} su_patch_code ; COM points to vm code
|
mov {{.COM}}, {{.PTRWORD}} su_patch_code ; COM points to vm code
|
||||||
mov {{.VAL}}, {{.PTRWORD}} su_patch_parameters ; VAL points to unit params
|
mov {{.VAL}}, {{.PTRWORD}} su_patch_parameters ; VAL points to unit params
|
||||||
@ -140,7 +140,7 @@ su_update_voices_nexttrack:
|
|||||||
pop {{.DX}} ; edx=patrnrow
|
pop {{.DX}} ; edx=patrnrow
|
||||||
add {{.SI}}, {{.SequenceLength}}
|
add {{.SI}}, {{.SequenceLength}}
|
||||||
inc {{.BP}}
|
inc {{.BP}}
|
||||||
{{- $addrname := len .Song.Tracks | printf "su_synth_obj + %v"}}
|
{{- $addrname := len .Song.Score.Tracks | printf "su_synth_obj + %v"}}
|
||||||
{{- .Prepare $addrname | indent 8}}
|
{{- .Prepare $addrname | indent 8}}
|
||||||
cmp {{.BP}},{{.Use $addrname}}
|
cmp {{.BP}},{{.Use $addrname}}
|
||||||
jl su_update_voices_trackloop
|
jl su_update_voices_trackloop
|
||||||
@ -154,7 +154,7 @@ su_update_voices_nexttrack:
|
|||||||
{{- .Prepare "su_tracks" | indent 4}}
|
{{- .Prepare "su_tracks" | indent 4}}
|
||||||
lea {{.SI}}, [{{.Use "su_tracks"}}+{{.AX}}]; esi points to the pattern data for current track
|
lea {{.SI}}, [{{.Use "su_tracks"}}+{{.AX}}]; esi points to the pattern data for current track
|
||||||
mov {{.DI}}, {{.PTRWORD}} su_synth_obj+su_synthworkspace.voices
|
mov {{.DI}}, {{.PTRWORD}} su_synth_obj+su_synthworkspace.voices
|
||||||
mov bl, {{len .Song.Tracks}} ; MAX_TRACKS is always <= 32 so this is ok
|
mov bl, {{len .Song.Score.Tracks}} ; MAX_TRACKS is always <= 32 so this is ok
|
||||||
su_update_voices_trackloop:
|
su_update_voices_trackloop:
|
||||||
movzx eax, byte [{{.SI}}] ; eax = current pattern
|
movzx eax, byte [{{.SI}}] ; eax = current pattern
|
||||||
imul eax, {{.PatternLength}} ; multiply by rows per pattern, eax = offset to current pattern data
|
imul eax, {{.PatternLength}} ; multiply by rows per pattern, eax = offset to current pattern data
|
||||||
|
@ -8,8 +8,8 @@
|
|||||||
#define SU_SAMPLE_RATE 44100
|
#define SU_SAMPLE_RATE 44100
|
||||||
#define SU_BPM {{.Song.BPM}}
|
#define SU_BPM {{.Song.BPM}}
|
||||||
#define SU_ROWS_PER_BEAT {{.Song.RowsPerBeat}}
|
#define SU_ROWS_PER_BEAT {{.Song.RowsPerBeat}}
|
||||||
#define SU_PATTERN_SIZE {{.Song.RowsPerPattern}}
|
#define SU_PATTERN_SIZE {{.Song.Score.RowsPerPattern}}
|
||||||
#define SU_MAX_PATTERNS {{.Song.SequenceLength}}
|
#define SU_MAX_PATTERNS {{.Song.Score.Length}}
|
||||||
#define SU_TOTAL_ROWS (SU_MAX_PATTERNS*SU_PATTERN_SIZE)
|
#define SU_TOTAL_ROWS (SU_MAX_PATTERNS*SU_PATTERN_SIZE)
|
||||||
#define SU_SAMPLES_PER_ROW (SU_SAMPLE_RATE*60/(SU_BPM*SU_ROWS_PER_BEAT))
|
#define SU_SAMPLES_PER_ROW (SU_SAMPLE_RATE*60/(SU_BPM*SU_ROWS_PER_BEAT))
|
||||||
|
|
||||||
|
@ -89,7 +89,7 @@ su_op_aux_mono:
|
|||||||
{{.Func "su_op_send" "Opcode"}}
|
{{.Func "su_op_send" "Opcode"}}
|
||||||
lodsw
|
lodsw
|
||||||
mov {{.CX}}, [{{.Stack "Voice"}}] ; load pointer to voice
|
mov {{.CX}}, [{{.Stack "Voice"}}] ; load pointer to voice
|
||||||
{{- if .SupportsParamValueOtherThan "send" "voice" 0}}
|
{{- if .SupportsGlobalSend}}
|
||||||
pushf ; uh ugly: we save the flags just for the stereo carry bit. Doing the .CX loading later crashed the synth for stereo sends as loading the synth address from stack was f'd up by the "call su_op_send_mono"
|
pushf ; uh ugly: we save the flags just for the stereo carry bit. Doing the .CX loading later crashed the synth for stereo sends as loading the synth address from stack was f'd up by the "call su_op_send_mono"
|
||||||
test {{.AX}}, 0x8000
|
test {{.AX}}, 0x8000
|
||||||
jz su_op_send_skipglobal
|
jz su_op_send_skipglobal
|
||||||
|
@ -170,7 +170,7 @@
|
|||||||
{{- end}}
|
{{- end}}
|
||||||
(global.set $WRK (i32.const 4160))
|
(global.set $WRK (i32.const 4160))
|
||||||
(global.set $voice (i32.const 4160))
|
(global.set $voice (i32.const 4160))
|
||||||
(global.set $voicesRemain (i32.const {{.Song.Patch.TotalVoices | printf "%v"}}))
|
(global.set $voicesRemain (i32.const {{.Song.Patch.NumVoices | printf "%v"}}))
|
||||||
{{- if .HasOp "delay"}}
|
{{- if .HasOp "delay"}}
|
||||||
(global.set $delayWRK (i32.const 262144)) ;; BAD IDEA: we are limited to something like 30 delay lines
|
(global.set $delayWRK (i32.const 262144)) ;; BAD IDEA: we are limited to something like 30 delay lines
|
||||||
;; after that, the delay lines start to overwrite the outputbuffer. Find a way to layout the memory
|
;; after that, the delay lines start to overwrite the outputbuffer. Find a way to layout the memory
|
||||||
|
@ -95,12 +95,12 @@
|
|||||||
loop $stereoLoop
|
loop $stereoLoop
|
||||||
{{- end}}
|
{{- end}}
|
||||||
(local.set $scaledAddress (i32.add (i32.mul (i32.and (local.get $address) (i32.const 0x7FF7)) (i32.const 4))
|
(local.set $scaledAddress (i32.add (i32.mul (i32.and (local.get $address) (i32.const 0x7FF7)) (i32.const 4))
|
||||||
{{- if .SupportsParamValueOtherThan "send" "voice" 0}}
|
{{- if .SupportsGlobalSend}}
|
||||||
(select
|
(select
|
||||||
(i32.const 4096)
|
(i32.const 4096)
|
||||||
{{- end}}
|
{{- end}}
|
||||||
(global.get $voice)
|
(global.get $voice)
|
||||||
{{- if .SupportsParamValueOtherThan "send" "voice" 0}}
|
{{- if .SupportsGlobalSend}}
|
||||||
(i32.and (local.get $address)(i32.const 0x8000))
|
(i32.and (local.get $address)(i32.const 0x8000))
|
||||||
)
|
)
|
||||||
{{- end}}
|
{{- end}}
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: loadval
|
- type: loadval
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: loadval
|
- type: loadval
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: loadval
|
- type: loadval
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: loadval
|
- type: loadval
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: loadval
|
- type: loadval
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: loadval
|
- type: loadval
|
||||||
|
@ -1,18 +1,19 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 0, 0, 0, 68, 0, 0, 0, 66, 0, 0, 0, 69, 0, 0, 0]]
|
patterns: [[64, 0, 0, 0, 68, 0, 0, 0, 66, 0, 0, 0, 69, 0, 0, 0]]
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[0, 68, 0, 0, 71, 0, 0, 0, 69, 0, 0, 0, 73, 0, 0, 0]]
|
patterns: [[0, 68, 0, 0, 71, 0, 0, 0, 69, 0, 0, 0, 73, 0, 0, 0]]
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[0, 0, 71, 0, 75, 0, 0, 0, 73, 0, 0, 0, 76, 0, 0, 0]]
|
patterns: [[0, 0, 71, 0, 75, 0, 0, 0, 73, 0, 0, 0, 76, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 3
|
- numvoices: 3
|
||||||
units:
|
units:
|
||||||
- type: envelope
|
- type: envelope
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0]]
|
patterns: [[64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: envelope
|
- type: envelope
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0]]
|
patterns: [[64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: envelope
|
- type: envelope
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 65, 65, 65, 65]]
|
patterns: [[64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 65, 65, 65, 65]]
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[76, 0, 0, 0, 0, 0, 0, 0, 76, 0, 0, 0, 0, 0, 0, 0]]
|
patterns: [[76, 0, 0, 0, 0, 0, 0, 0, 76, 0, 0, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: envelope
|
- type: envelope
|
||||||
@ -23,9 +24,9 @@ patch:
|
|||||||
- type: mulp
|
- type: mulp
|
||||||
parameters: {stereo: 1}
|
parameters: {stereo: 1}
|
||||||
- type: send
|
- type: send
|
||||||
parameters: {amount: 128, port: 0, sendpop: 1, stereo: 0, unit: 0, voice: 3}
|
parameters: {amount: 128, port: 0, sendpop: 1, stereo: 0, target: 1}
|
||||||
- type: send
|
- type: send
|
||||||
parameters: {amount: 128, port: 1, sendpop: 1, stereo: 0, unit: 0, voice: 3}
|
parameters: {amount: 128, port: 1, sendpop: 1, stereo: 0, target: 1}
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: envelope
|
- type: envelope
|
||||||
@ -39,13 +40,14 @@ patch:
|
|||||||
- type: mulp
|
- type: mulp
|
||||||
parameters: {stereo: 1}
|
parameters: {stereo: 1}
|
||||||
- type: send
|
- type: send
|
||||||
parameters: {amount: 128, port: 0, sendpop: 1, stereo: 0, unit: 0, voice: 3}
|
parameters: {amount: 128, port: 0, sendpop: 1, stereo: 0, target: 1}
|
||||||
- type: send
|
- type: send
|
||||||
parameters: {amount: 128, port: 1, sendpop: 1, stereo: 0, unit: 0, voice: 3}
|
parameters: {amount: 128, port: 1, sendpop: 1, stereo: 0, target: 1}
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: receive
|
- type: receive
|
||||||
parameters: {stereo: 1}
|
parameters: {stereo: 1}
|
||||||
|
id: 1
|
||||||
- type: compressor
|
- type: compressor
|
||||||
parameters: {attack: 32, invgain: 32, ratio: 96, release: 64, stereo: 0, threshold: 64}
|
parameters: {attack: 32, invgain: 32, ratio: 96, release: 64, stereo: 0, threshold: 64}
|
||||||
- type: mulp
|
- type: mulp
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 65, 65, 65, 65]]
|
patterns: [[64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 65, 65, 65, 65]]
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[76, 0, 0, 0, 0, 0, 0, 0, 76, 0, 0, 0, 0, 0, 0, 0]]
|
patterns: [[76, 0, 0, 0, 0, 0, 0, 0, 76, 0, 0, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: envelope
|
- type: envelope
|
||||||
@ -23,9 +24,9 @@ patch:
|
|||||||
- type: mulp
|
- type: mulp
|
||||||
parameters: {stereo: 1}
|
parameters: {stereo: 1}
|
||||||
- type: send
|
- type: send
|
||||||
parameters: {amount: 128, port: 0, sendpop: 1, stereo: 0, unit: 0, voice: 3}
|
parameters: {amount: 128, port: 0, sendpop: 1, stereo: 0, target: 1}
|
||||||
- type: send
|
- type: send
|
||||||
parameters: {amount: 128, port: 1, sendpop: 1, stereo: 0, unit: 0, voice: 3}
|
parameters: {amount: 128, port: 1, sendpop: 1, stereo: 0, target: 1}
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: envelope
|
- type: envelope
|
||||||
@ -39,13 +40,14 @@ patch:
|
|||||||
- type: mulp
|
- type: mulp
|
||||||
parameters: {stereo: 1}
|
parameters: {stereo: 1}
|
||||||
- type: send
|
- type: send
|
||||||
parameters: {amount: 128, port: 0, sendpop: 1, stereo: 0, unit: 0, voice: 3}
|
parameters: {amount: 128, port: 0, sendpop: 1, stereo: 0, target: 1}
|
||||||
- type: send
|
- type: send
|
||||||
parameters: {amount: 128, port: 1, sendpop: 1, stereo: 0, unit: 0, voice: 3}
|
parameters: {amount: 128, port: 1, sendpop: 1, stereo: 0, target: 1}
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: receive
|
- type: receive
|
||||||
parameters: {stereo: 1}
|
parameters: {stereo: 1}
|
||||||
|
id: 1
|
||||||
- type: compressor
|
- type: compressor
|
||||||
parameters: {attack: 32, invgain: 32, ratio: 96, release: 64, stereo: 1, threshold: 64}
|
parameters: {attack: 32, invgain: 32, ratio: 96, release: 64, stereo: 1, threshold: 64}
|
||||||
- type: mulp
|
- type: mulp
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0]]
|
patterns: [[64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: envelope
|
- type: envelope
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0]]
|
patterns: [[64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: envelope
|
- type: envelope
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0]]
|
patterns: [[64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: envelope
|
- type: envelope
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0]]
|
patterns: [[64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: envelope
|
- type: envelope
|
||||||
@ -18,6 +19,7 @@ patch:
|
|||||||
- type: delay
|
- type: delay
|
||||||
parameters: {damp: 64, dry: 128, feedback: 125, notetracking: 0, pregain: 40, stereo: 0}
|
parameters: {damp: 64, dry: 128, feedback: 125, notetracking: 0, pregain: 40, stereo: 0}
|
||||||
varargs: [11025]
|
varargs: [11025]
|
||||||
|
id: 1
|
||||||
- type: pan
|
- type: pan
|
||||||
parameters: {panning: 64, stereo: 0}
|
parameters: {panning: 64, stereo: 0}
|
||||||
- type: out
|
- type: out
|
||||||
@ -25,4 +27,4 @@ patch:
|
|||||||
- type: oscillator
|
- type: oscillator
|
||||||
parameters: {color: 128, detune: 64, gain: 128, lfo: 1, phase: 64, shape: 64, stereo: 0, transpose: 70, type: 0, unison: 0}
|
parameters: {color: 128, detune: 64, gain: 128, lfo: 1, phase: 64, shape: 64, stereo: 0, transpose: 70, type: 0, unison: 0}
|
||||||
- type: send
|
- type: send
|
||||||
parameters: {amount: 32, port: 3, sendpop: 1, stereo: 0, unit: 3, voice: 0}
|
parameters: {amount: 32, port: 3, sendpop: 1, stereo: 0, target: 1}
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0]]
|
patterns: [[64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: envelope
|
- type: envelope
|
||||||
@ -18,6 +19,7 @@ patch:
|
|||||||
- type: delay
|
- type: delay
|
||||||
parameters: {damp: 64, dry: 128, feedback: 125, notetracking: 0, pregain: 40, stereo: 0}
|
parameters: {damp: 64, dry: 128, feedback: 125, notetracking: 0, pregain: 40, stereo: 0}
|
||||||
varargs: [11025]
|
varargs: [11025]
|
||||||
|
id: 1
|
||||||
- type: pan
|
- type: pan
|
||||||
parameters: {panning: 64, stereo: 0}
|
parameters: {panning: 64, stereo: 0}
|
||||||
- type: out
|
- type: out
|
||||||
@ -25,4 +27,4 @@ patch:
|
|||||||
- type: oscillator
|
- type: oscillator
|
||||||
parameters: {color: 128, detune: 64, gain: 128, lfo: 1, phase: 64, shape: 64, stereo: 0, transpose: 70, type: 0, unison: 0}
|
parameters: {color: 128, detune: 64, gain: 128, lfo: 1, phase: 64, shape: 64, stereo: 0, transpose: 70, type: 0, unison: 0}
|
||||||
- type: send
|
- type: send
|
||||||
parameters: {amount: 32, port: 1, sendpop: 1, stereo: 0, unit: 3, voice: 0}
|
parameters: {amount: 32, port: 1, sendpop: 1, stereo: 0, target: 1}
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0]]
|
patterns: [[64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: envelope
|
- type: envelope
|
||||||
@ -18,6 +19,7 @@ patch:
|
|||||||
- type: delay
|
- type: delay
|
||||||
parameters: {damp: 64, dry: 128, feedback: 125, notetracking: 0, pregain: 40, stereo: 0}
|
parameters: {damp: 64, dry: 128, feedback: 125, notetracking: 0, pregain: 40, stereo: 0}
|
||||||
varargs: [11025]
|
varargs: [11025]
|
||||||
|
id: 1
|
||||||
- type: pan
|
- type: pan
|
||||||
parameters: {panning: 64, stereo: 0}
|
parameters: {panning: 64, stereo: 0}
|
||||||
- type: out
|
- type: out
|
||||||
@ -25,4 +27,4 @@ patch:
|
|||||||
- type: oscillator
|
- type: oscillator
|
||||||
parameters: {color: 128, detune: 64, gain: 128, lfo: 1, phase: 64, shape: 64, stereo: 0, transpose: 70, type: 0, unison: 0}
|
parameters: {color: 128, detune: 64, gain: 128, lfo: 1, phase: 64, shape: 64, stereo: 0, transpose: 70, type: 0, unison: 0}
|
||||||
- type: send
|
- type: send
|
||||||
parameters: {amount: 32, port: 2, sendpop: 1, stereo: 0, unit: 3, voice: 0}
|
parameters: {amount: 32, port: 2, sendpop: 1, stereo: 0, target: 1}
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[80, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0]]
|
patterns: [[80, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: envelope
|
- type: envelope
|
||||||
@ -18,6 +19,7 @@ patch:
|
|||||||
- type: delay
|
- type: delay
|
||||||
parameters: {damp: 64, dry: 128, feedback: 0, notetracking: 0, pregain: 40, stereo: 0}
|
parameters: {damp: 64, dry: 128, feedback: 0, notetracking: 0, pregain: 40, stereo: 0}
|
||||||
varargs: [1000]
|
varargs: [1000]
|
||||||
|
id: 1
|
||||||
- type: pan
|
- type: pan
|
||||||
parameters: {panning: 64, stereo: 0}
|
parameters: {panning: 64, stereo: 0}
|
||||||
- type: out
|
- type: out
|
||||||
@ -25,4 +27,4 @@ patch:
|
|||||||
- type: oscillator
|
- type: oscillator
|
||||||
parameters: {color: 128, detune: 64, gain: 128, lfo: 1, phase: 64, shape: 64, stereo: 0, transpose: 50, type: 0, unison: 0}
|
parameters: {color: 128, detune: 64, gain: 128, lfo: 1, phase: 64, shape: 64, stereo: 0, transpose: 50, type: 0, unison: 0}
|
||||||
- type: send
|
- type: send
|
||||||
parameters: {amount: 65, port: 4, sendpop: 1, stereo: 0, unit: 3, voice: 0}
|
parameters: {amount: 65, port: 4, sendpop: 1, stereo: 0, target: 1}
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0]]
|
patterns: [[64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: envelope
|
- type: envelope
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0]]
|
patterns: [[64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: envelope
|
- type: envelope
|
||||||
@ -18,6 +19,7 @@ patch:
|
|||||||
- type: delay
|
- type: delay
|
||||||
parameters: {damp: 64, dry: 128, feedback: 125, notetracking: 0, pregain: 40, stereo: 0}
|
parameters: {damp: 64, dry: 128, feedback: 125, notetracking: 0, pregain: 40, stereo: 0}
|
||||||
varargs: [11025]
|
varargs: [11025]
|
||||||
|
id: 1
|
||||||
- type: pan
|
- type: pan
|
||||||
parameters: {panning: 64, stereo: 0}
|
parameters: {panning: 64, stereo: 0}
|
||||||
- type: out
|
- type: out
|
||||||
@ -25,4 +27,4 @@ patch:
|
|||||||
- type: oscillator
|
- type: oscillator
|
||||||
parameters: {color: 128, detune: 64, gain: 128, lfo: 1, phase: 64, shape: 64, stereo: 0, transpose: 70, type: 0, unison: 0}
|
parameters: {color: 128, detune: 64, gain: 128, lfo: 1, phase: 64, shape: 64, stereo: 0, transpose: 70, type: 0, unison: 0}
|
||||||
- type: send
|
- type: send
|
||||||
parameters: {amount: 32, port: 0, sendpop: 1, stereo: 0, unit: 3, voice: 0}
|
parameters: {amount: 32, port: 0, sendpop: 1, stereo: 0, target: 1}
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0]]
|
patterns: [[64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: envelope
|
- type: envelope
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0]]
|
patterns: [[64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: envelope
|
- type: envelope
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: envelope
|
- type: envelope
|
||||||
|
@ -1,27 +1,30 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: envelope
|
- type: envelope
|
||||||
parameters: {attack: 64, decay: 64, gain: 128, release: 80, stereo: 0, sustain: 64}
|
parameters: {attack: 64, decay: 64, gain: 128, release: 80, stereo: 0, sustain: 64}
|
||||||
- type: distort
|
- type: distort
|
||||||
parameters: {drive: 32, stereo: 0}
|
parameters: {drive: 32, stereo: 0}
|
||||||
|
id: 1
|
||||||
- type: envelope
|
- type: envelope
|
||||||
parameters: {attack: 64, decay: 64, gain: 128, release: 80, stereo: 0, sustain: 64}
|
parameters: {attack: 64, decay: 64, gain: 128, release: 80, stereo: 0, sustain: 64}
|
||||||
- type: distort
|
- type: distort
|
||||||
parameters: {drive: 96, stereo: 0}
|
parameters: {drive: 96, stereo: 0}
|
||||||
|
id: 2
|
||||||
- type: oscillator
|
- type: oscillator
|
||||||
parameters: {color: 128, detune: 64, gain: 128, lfo: 1, phase: 64, shape: 64, stereo: 0, transpose: 70, type: 0, unison: 0}
|
parameters: {color: 128, detune: 64, gain: 128, lfo: 1, phase: 64, shape: 64, stereo: 0, transpose: 70, type: 0, unison: 0}
|
||||||
- type: send
|
- type: send
|
||||||
parameters: {amount: 68, port: 0, sendpop: 0, stereo: 0, unit: 1, voice: 0}
|
parameters: {amount: 68, port: 0, sendpop: 0, stereo: 0, target: 1}
|
||||||
- type: send
|
- type: send
|
||||||
parameters: {amount: 68, port: 0, sendpop: 1, stereo: 0, unit: 3, voice: 0}
|
parameters: {amount: 68, port: 0, sendpop: 1, stereo: 0, target: 2}
|
||||||
- type: out
|
- type: out
|
||||||
parameters: {gain: 128, stereo: 1}
|
parameters: {gain: 128, stereo: 1}
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: envelope
|
- type: envelope
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: envelope
|
- type: envelope
|
||||||
|
@ -1,27 +1,30 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0]]
|
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: envelope
|
- type: envelope
|
||||||
parameters: {attack: 80, decay: 80, gain: 128, release: 80, stereo: 0, sustain: 64}
|
parameters: {attack: 80, decay: 80, gain: 128, release: 80, stereo: 0, sustain: 64}
|
||||||
|
id: 1
|
||||||
- type: envelope
|
- type: envelope
|
||||||
parameters: {attack: 80, decay: 80, gain: 128, release: 80, stereo: 0, sustain: 64}
|
parameters: {attack: 80, decay: 80, gain: 128, release: 80, stereo: 0, sustain: 64}
|
||||||
|
id: 2
|
||||||
- type: oscillator
|
- type: oscillator
|
||||||
parameters: {color: 128, detune: 64, gain: 128, lfo: 1, phase: 0, shape: 96, stereo: 0, transpose: 120, type: 0, unison: 0}
|
parameters: {color: 128, detune: 64, gain: 128, lfo: 1, phase: 0, shape: 96, stereo: 0, transpose: 120, type: 0, unison: 0}
|
||||||
- type: send
|
- type: send
|
||||||
parameters: {amount: 68, port: 0, sendpop: 0, stereo: 0, unit: 0, voice: 0}
|
parameters: {amount: 68, port: 0, sendpop: 0, stereo: 0, target: 1}
|
||||||
- type: send
|
- type: send
|
||||||
parameters: {amount: 68, port: 1, sendpop: 0, stereo: 0, unit: 0, voice: 0}
|
parameters: {amount: 68, port: 1, sendpop: 0, stereo: 0, target: 1}
|
||||||
- type: send
|
- type: send
|
||||||
parameters: {amount: 68, port: 3, sendpop: 0, stereo: 0, unit: 0, voice: 0}
|
parameters: {amount: 68, port: 3, sendpop: 0, stereo: 0, target: 1}
|
||||||
- type: send
|
- type: send
|
||||||
parameters: {amount: 68, port: 4, sendpop: 1, stereo: 0, unit: 1, voice: 0}
|
parameters: {amount: 68, port: 4, sendpop: 1, stereo: 0, target: 2}
|
||||||
- type: out
|
- type: out
|
||||||
parameters: {gain: 110, stereo: 1}
|
parameters: {gain: 110, stereo: 1}
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: envelope
|
- type: envelope
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0]]
|
patterns: [[64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: envelope
|
- type: envelope
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0]]
|
patterns: [[64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: envelope
|
- type: envelope
|
||||||
@ -17,6 +18,7 @@ patch:
|
|||||||
parameters: {stereo: 0}
|
parameters: {stereo: 0}
|
||||||
- type: filter
|
- type: filter
|
||||||
parameters: {bandpass: 1, frequency: 32, highpass: 0, lowpass: 0, negbandpass: 0, neghighpass: 0, resonance: 64, stereo: 0}
|
parameters: {bandpass: 1, frequency: 32, highpass: 0, lowpass: 0, negbandpass: 0, neghighpass: 0, resonance: 64, stereo: 0}
|
||||||
|
id: 1
|
||||||
- type: pan
|
- type: pan
|
||||||
parameters: {panning: 64, stereo: 0}
|
parameters: {panning: 64, stereo: 0}
|
||||||
- type: out
|
- type: out
|
||||||
@ -24,4 +26,4 @@ patch:
|
|||||||
- type: oscillator
|
- type: oscillator
|
||||||
parameters: {color: 128, detune: 64, gain: 128, lfo: 1, phase: 64, shape: 64, stereo: 0, transpose: 70, type: 0, unison: 0}
|
parameters: {color: 128, detune: 64, gain: 128, lfo: 1, phase: 64, shape: 64, stereo: 0, transpose: 70, type: 0, unison: 0}
|
||||||
- type: send
|
- type: send
|
||||||
parameters: {amount: 32, port: 0, sendpop: 1, stereo: 0, unit: 3, voice: 0}
|
parameters: {amount: 32, port: 0, sendpop: 1, stereo: 0, target: 1}
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0]]
|
patterns: [[64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: envelope
|
- type: envelope
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0]]
|
patterns: [[64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: envelope
|
- type: envelope
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0]]
|
patterns: [[64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: envelope
|
- type: envelope
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0]]
|
patterns: [[64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: envelope
|
- type: envelope
|
||||||
@ -17,6 +18,7 @@ patch:
|
|||||||
parameters: {stereo: 0}
|
parameters: {stereo: 0}
|
||||||
- type: filter
|
- type: filter
|
||||||
parameters: {bandpass: 1, frequency: 32, highpass: 0, lowpass: 0, negbandpass: 0, neghighpass: 0, resonance: 64, stereo: 0}
|
parameters: {bandpass: 1, frequency: 32, highpass: 0, lowpass: 0, negbandpass: 0, neghighpass: 0, resonance: 64, stereo: 0}
|
||||||
|
id: 1
|
||||||
- type: pan
|
- type: pan
|
||||||
parameters: {panning: 64, stereo: 0}
|
parameters: {panning: 64, stereo: 0}
|
||||||
- type: out
|
- type: out
|
||||||
@ -24,4 +26,4 @@ patch:
|
|||||||
- type: oscillator
|
- type: oscillator
|
||||||
parameters: {color: 128, detune: 64, gain: 128, lfo: 1, phase: 64, shape: 64, stereo: 0, transpose: 70, type: 0, unison: 0}
|
parameters: {color: 128, detune: 64, gain: 128, lfo: 1, phase: 64, shape: 64, stereo: 0, transpose: 70, type: 0, unison: 0}
|
||||||
- type: send
|
- type: send
|
||||||
parameters: {amount: 32, port: 1, sendpop: 1, stereo: 0, unit: 3, voice: 0}
|
parameters: {amount: 32, port: 1, sendpop: 1, stereo: 0, target: 1}
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0]]
|
patterns: [[64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: envelope
|
- type: envelope
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: loadval
|
- type: loadval
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: loadval
|
- type: loadval
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: envelope
|
- type: envelope
|
||||||
|
@ -1,27 +1,30 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: envelope
|
- type: envelope
|
||||||
parameters: {attack: 64, decay: 64, gain: 128, release: 80, stereo: 0, sustain: 64}
|
parameters: {attack: 64, decay: 64, gain: 128, release: 80, stereo: 0, sustain: 64}
|
||||||
- type: hold
|
- type: hold
|
||||||
parameters: {holdfreq: 3, stereo: 0}
|
parameters: {holdfreq: 3, stereo: 0}
|
||||||
|
id: 1
|
||||||
- type: envelope
|
- type: envelope
|
||||||
parameters: {attack: 64, decay: 64, gain: 128, release: 80, stereo: 0, sustain: 64}
|
parameters: {attack: 64, decay: 64, gain: 128, release: 80, stereo: 0, sustain: 64}
|
||||||
- type: hold
|
- type: hold
|
||||||
parameters: {holdfreq: 3, stereo: 0}
|
parameters: {holdfreq: 3, stereo: 0}
|
||||||
|
id: 2
|
||||||
- type: oscillator
|
- type: oscillator
|
||||||
parameters: {color: 128, detune: 64, gain: 128, lfo: 1, phase: 64, shape: 64, stereo: 0, transpose: 70, type: 0, unison: 0}
|
parameters: {color: 128, detune: 64, gain: 128, lfo: 1, phase: 64, shape: 64, stereo: 0, transpose: 70, type: 0, unison: 0}
|
||||||
- type: send
|
- type: send
|
||||||
parameters: {amount: 68, port: 0, sendpop: 0, stereo: 0, unit: 1, voice: 0}
|
parameters: {amount: 68, port: 0, sendpop: 0, stereo: 0, target: 1}
|
||||||
- type: send
|
- type: send
|
||||||
parameters: {amount: 68, port: 0, sendpop: 1, stereo: 0, unit: 3, voice: 0}
|
parameters: {amount: 68, port: 0, sendpop: 1, stereo: 0, target: 2}
|
||||||
- type: out
|
- type: out
|
||||||
parameters: {gain: 128, stereo: 1}
|
parameters: {gain: 128, stereo: 1}
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: envelope
|
- type: envelope
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: loadval
|
- type: loadval
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: loadval
|
- type: loadval
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: loadval
|
- type: loadval
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: loadval
|
- type: loadval
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0]]
|
patterns: [[64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: loadnote
|
- type: loadnote
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0]]
|
patterns: [[64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: loadnote
|
- type: loadnote
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: loadval
|
- type: loadval
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: loadval
|
- type: loadval
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: loadval
|
- type: loadval
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: loadval
|
- type: loadval
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: loadval
|
- type: loadval
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: loadval
|
- type: loadval
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[0, 0, 0, 0, 0, 0, 0, 0, 64, 1, 1, 0, 0, 0, 0, 0]]
|
patterns: [[0, 0, 0, 0, 0, 0, 0, 0, 64, 1, 1, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: envelope
|
- type: envelope
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0]]
|
patterns: [[64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: envelope
|
- type: envelope
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0]]
|
patterns: [[64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: noise
|
- type: noise
|
||||||
|
@ -1,18 +1,20 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[80, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0]]
|
patterns: [[80, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: envelope
|
- type: envelope
|
||||||
parameters: {attack: 80, decay: 80, gain: 128, release: 80, stereo: 0, sustain: 64}
|
parameters: {attack: 80, decay: 80, gain: 128, release: 80, stereo: 0, sustain: 64}
|
||||||
- type: oscillator
|
- type: oscillator
|
||||||
parameters: {color: 128, detune: 64, gain: 128, lfo: 0, phase: 0, shape: 64, stereo: 0, transpose: 64, type: 0, unison: 0}
|
parameters: {color: 128, detune: 64, gain: 128, lfo: 0, phase: 0, shape: 64, stereo: 0, transpose: 64, type: 0, unison: 0}
|
||||||
|
id: 1
|
||||||
- type: mulp
|
- type: mulp
|
||||||
parameters: {stereo: 0}
|
parameters: {stereo: 0}
|
||||||
- type: push
|
- type: push
|
||||||
@ -20,6 +22,6 @@ patch:
|
|||||||
- type: oscillator
|
- type: oscillator
|
||||||
parameters: {color: 128, detune: 64, gain: 128, lfo: 1, phase: 64, shape: 64, stereo: 0, transpose: 70, type: 0, unison: 0}
|
parameters: {color: 128, detune: 64, gain: 128, lfo: 1, phase: 64, shape: 64, stereo: 0, transpose: 70, type: 0, unison: 0}
|
||||||
- type: send
|
- type: send
|
||||||
parameters: {amount: 68, port: 3, sendpop: 1, stereo: 0, unit: 1, voice: 0}
|
parameters: {amount: 68, port: 3, sendpop: 1, stereo: 0, target: 1}
|
||||||
- type: out
|
- type: out
|
||||||
parameters: {gain: 128, stereo: 1}
|
parameters: {gain: 128, stereo: 1}
|
||||||
|
@ -1,18 +1,20 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[80, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0]]
|
patterns: [[80, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: envelope
|
- type: envelope
|
||||||
parameters: {attack: 80, decay: 80, gain: 128, release: 80, stereo: 0, sustain: 64}
|
parameters: {attack: 80, decay: 80, gain: 128, release: 80, stereo: 0, sustain: 64}
|
||||||
- type: oscillator
|
- type: oscillator
|
||||||
parameters: {color: 128, detune: 64, gain: 128, lfo: 0, phase: 0, shape: 64, stereo: 0, transpose: 64, type: 0, unison: 0}
|
parameters: {color: 128, detune: 64, gain: 128, lfo: 0, phase: 0, shape: 64, stereo: 0, transpose: 64, type: 0, unison: 0}
|
||||||
|
id: 1
|
||||||
- type: mulp
|
- type: mulp
|
||||||
parameters: {stereo: 0}
|
parameters: {stereo: 0}
|
||||||
- type: push
|
- type: push
|
||||||
@ -20,6 +22,6 @@ patch:
|
|||||||
- type: oscillator
|
- type: oscillator
|
||||||
parameters: {color: 128, detune: 64, gain: 128, lfo: 1, phase: 64, shape: 64, stereo: 0, transpose: 70, type: 0, unison: 0}
|
parameters: {color: 128, detune: 64, gain: 128, lfo: 1, phase: 64, shape: 64, stereo: 0, transpose: 70, type: 0, unison: 0}
|
||||||
- type: send
|
- type: send
|
||||||
parameters: {amount: 96, port: 1, sendpop: 1, stereo: 0, unit: 1, voice: 0}
|
parameters: {amount: 96, port: 1, sendpop: 1, stereo: 0, target: 1}
|
||||||
- type: out
|
- type: out
|
||||||
parameters: {gain: 128, stereo: 1}
|
parameters: {gain: 128, stereo: 1}
|
||||||
|
@ -1,18 +1,20 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[80, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0]]
|
patterns: [[80, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: envelope
|
- type: envelope
|
||||||
parameters: {attack: 80, decay: 80, gain: 128, release: 80, stereo: 0, sustain: 64}
|
parameters: {attack: 80, decay: 80, gain: 128, release: 80, stereo: 0, sustain: 64}
|
||||||
- type: oscillator
|
- type: oscillator
|
||||||
parameters: {color: 128, detune: 64, gain: 128, lfo: 0, phase: 0, shape: 64, stereo: 0, transpose: 64, type: 0, unison: 0}
|
parameters: {color: 128, detune: 64, gain: 128, lfo: 0, phase: 0, shape: 64, stereo: 0, transpose: 64, type: 0, unison: 0}
|
||||||
|
id: 1
|
||||||
- type: mulp
|
- type: mulp
|
||||||
parameters: {stereo: 0}
|
parameters: {stereo: 0}
|
||||||
- type: push
|
- type: push
|
||||||
@ -20,6 +22,6 @@ patch:
|
|||||||
- type: oscillator
|
- type: oscillator
|
||||||
parameters: {color: 128, detune: 64, gain: 128, lfo: 1, phase: 64, shape: 64, stereo: 0, transpose: 70, type: 0, unison: 0}
|
parameters: {color: 128, detune: 64, gain: 128, lfo: 1, phase: 64, shape: 64, stereo: 0, transpose: 70, type: 0, unison: 0}
|
||||||
- type: send
|
- type: send
|
||||||
parameters: {amount: 68, port: 5, sendpop: 1, stereo: 0, unit: 1, voice: 0}
|
parameters: {amount: 68, port: 5, sendpop: 1, stereo: 0, target: 1}
|
||||||
- type: out
|
- type: out
|
||||||
parameters: {gain: 128, stereo: 1}
|
parameters: {gain: 128, stereo: 1}
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0]]
|
patterns: [[64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: envelope
|
- type: envelope
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0]]
|
patterns: [[64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: envelope
|
- type: envelope
|
||||||
|
@ -1,18 +1,20 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[80, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0]]
|
patterns: [[80, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: envelope
|
- type: envelope
|
||||||
parameters: {attack: 80, decay: 80, gain: 128, release: 80, stereo: 0, sustain: 64}
|
parameters: {attack: 80, decay: 80, gain: 128, release: 80, stereo: 0, sustain: 64}
|
||||||
- type: oscillator
|
- type: oscillator
|
||||||
parameters: {color: 128, detune: 64, gain: 128, lfo: 0, phase: 0, shape: 64, stereo: 0, transpose: 64, type: 0, unison: 0}
|
parameters: {color: 128, detune: 64, gain: 128, lfo: 0, phase: 0, shape: 64, stereo: 0, transpose: 64, type: 0, unison: 0}
|
||||||
|
id: 1
|
||||||
- type: mulp
|
- type: mulp
|
||||||
parameters: {stereo: 0}
|
parameters: {stereo: 0}
|
||||||
- type: push
|
- type: push
|
||||||
@ -20,6 +22,6 @@ patch:
|
|||||||
- type: oscillator
|
- type: oscillator
|
||||||
parameters: {color: 128, detune: 64, gain: 128, lfo: 1, phase: 64, shape: 64, stereo: 0, transpose: 70, type: 0, unison: 0}
|
parameters: {color: 128, detune: 64, gain: 128, lfo: 1, phase: 64, shape: 64, stereo: 0, transpose: 70, type: 0, unison: 0}
|
||||||
- type: send
|
- type: send
|
||||||
parameters: {amount: 128, port: 2, sendpop: 1, stereo: 0, unit: 1, voice: 0}
|
parameters: {amount: 128, port: 2, sendpop: 1, stereo: 0, target: 1}
|
||||||
- type: out
|
- type: out
|
||||||
parameters: {gain: 128, stereo: 1}
|
parameters: {gain: 128, stereo: 1}
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0]]
|
patterns: [[64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: envelope
|
- type: envelope
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 8
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 8
|
||||||
|
length: 8
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [1, 0, 2, 0, 3, 0, 4, 0]
|
order: [1, 0, 2, 0, 3, 0, 4, 0]
|
||||||
patterns: [[0, 0, 0, 0, 0, 0, 0, 0], [72, 1, 1, 1, 1, 1, 1, 0], [64, 1, 1, 1, 1, 1, 1, 0], [60, 1, 1, 1, 1, 1, 1, 0], [40, 1, 1, 1, 1, 1, 1, 0]]
|
patterns: [[0, 0, 0, 0, 0, 0, 0, 0], [72, 1, 1, 1, 1, 1, 1, 0], [64, 1, 1, 1, 1, 1, 1, 0], [60, 1, 1, 1, 1, 1, 1, 0], [40, 1, 1, 1, 1, 1, 1, 0]]
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0, 1, 0, 2, 0, 3, 0, 4]
|
order: [0, 1, 0, 2, 0, 3, 0, 4]
|
||||||
patterns: [[0, 0, 0, 0, 0, 0, 0, 0], [72, 1, 1, 1, 1, 1, 1, 0], [64, 1, 1, 1, 1, 1, 1, 0], [60, 1, 1, 1, 1, 1, 1, 0], [40, 1, 1, 1, 1, 1, 1, 0]]
|
patterns: [[0, 0, 0, 0, 0, 0, 0, 0], [72, 1, 1, 1, 1, 1, 1, 0], [64, 1, 1, 1, 1, 1, 1, 0], [60, 1, 1, 1, 1, 1, 1, 0], [40, 1, 1, 1, 1, 1, 1, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: envelope
|
- type: envelope
|
||||||
@ -17,9 +18,9 @@ patch:
|
|||||||
- type: envelope
|
- type: envelope
|
||||||
parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64}
|
parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64}
|
||||||
- type: oscillator
|
- type: oscillator
|
||||||
parameters: {color: 0, detune: 64, gain: 128, lfo: 0, looplength: 106, loopstart: 1341, phase: 64, shape: 64, samplestart: 1678611, stereo: 0, transpose: 68, type: 4, unison: 0}
|
parameters: {color: 0, detune: 64, gain: 128, lfo: 0, looplength: 106, loopstart: 1341, phase: 64, samplestart: 1678611, shape: 64, stereo: 0, transpose: 68, type: 4, unison: 0}
|
||||||
- type: oscillator
|
- type: oscillator
|
||||||
parameters: {color: 0, detune: 64, gain: 128, lfo: 0, looplength: 95, loopstart: 1483, phase: 64, shape: 64, samplestart: 1680142, stereo: 0, transpose: 66, type: 4, unison: 0}
|
parameters: {color: 0, detune: 64, gain: 128, lfo: 0, looplength: 95, loopstart: 1483, phase: 64, samplestart: 1680142, shape: 64, stereo: 0, transpose: 66, type: 4, unison: 0}
|
||||||
- type: mulp
|
- type: mulp
|
||||||
parameters: {stereo: 1}
|
parameters: {stereo: 1}
|
||||||
- type: out
|
- type: out
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 8
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 8
|
||||||
|
length: 8
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [1, 0, 2, 0, 3, 0, 4, 0]
|
order: [1, 0, 2, 0, 3, 0, 4, 0]
|
||||||
patterns: [[0, 0, 0, 0, 0, 0, 0, 0], [72, 1, 1, 1, 1, 1, 1, 0], [64, 1, 1, 1, 1, 1, 1, 0], [60, 1, 1, 1, 1, 1, 1, 0], [40, 1, 1, 1, 1, 1, 1, 0]]
|
patterns: [[0, 0, 0, 0, 0, 0, 0, 0], [72, 1, 1, 1, 1, 1, 1, 0], [64, 1, 1, 1, 1, 1, 1, 0], [60, 1, 1, 1, 1, 1, 1, 0], [40, 1, 1, 1, 1, 1, 1, 0]]
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0, 1, 0, 2, 0, 3, 0, 4]
|
order: [0, 1, 0, 2, 0, 3, 0, 4]
|
||||||
patterns: [[0, 0, 0, 0, 0, 0, 0, 0], [72, 1, 1, 1, 1, 1, 1, 0], [64, 1, 1, 1, 1, 1, 1, 0], [60, 1, 1, 1, 1, 1, 1, 0], [40, 1, 1, 1, 1, 1, 1, 0]]
|
patterns: [[0, 0, 0, 0, 0, 0, 0, 0], [72, 1, 1, 1, 1, 1, 1, 0], [64, 1, 1, 1, 1, 1, 1, 0], [60, 1, 1, 1, 1, 1, 1, 0], [40, 1, 1, 1, 1, 1, 1, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: envelope
|
- type: envelope
|
||||||
@ -17,7 +18,7 @@ patch:
|
|||||||
- type: envelope
|
- type: envelope
|
||||||
parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64}
|
parameters: {attack: 32, decay: 32, gain: 128, release: 64, stereo: 0, sustain: 64}
|
||||||
- type: oscillator
|
- type: oscillator
|
||||||
parameters: {color: 0, detune: 32, gain: 128, lfo: 0, looplength: 106, loopstart: 1341, phase: 64, shape: 64, samplestart: 1678611, stereo: 1, transpose: 68, type: 4, unison: 0}
|
parameters: {color: 0, detune: 32, gain: 128, lfo: 0, looplength: 106, loopstart: 1341, phase: 64, samplestart: 1678611, shape: 64, stereo: 1, transpose: 68, type: 4, unison: 0}
|
||||||
- type: mulp
|
- type: mulp
|
||||||
parameters: {stereo: 1}
|
parameters: {stereo: 1}
|
||||||
- type: out
|
- type: out
|
||||||
|
@ -1,18 +1,20 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[80, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0]]
|
patterns: [[80, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: envelope
|
- type: envelope
|
||||||
parameters: {attack: 80, decay: 80, gain: 128, release: 80, stereo: 0, sustain: 64}
|
parameters: {attack: 80, decay: 80, gain: 128, release: 80, stereo: 0, sustain: 64}
|
||||||
- type: oscillator
|
- type: oscillator
|
||||||
parameters: {color: 128, detune: 64, gain: 128, lfo: 0, phase: 0, shape: 64, stereo: 0, transpose: 64, type: 0, unison: 0}
|
parameters: {color: 128, detune: 64, gain: 128, lfo: 0, phase: 0, shape: 64, stereo: 0, transpose: 64, type: 0, unison: 0}
|
||||||
|
id: 1
|
||||||
- type: mulp
|
- type: mulp
|
||||||
parameters: {stereo: 0}
|
parameters: {stereo: 0}
|
||||||
- type: push
|
- type: push
|
||||||
@ -20,6 +22,6 @@ patch:
|
|||||||
- type: oscillator
|
- type: oscillator
|
||||||
parameters: {color: 128, detune: 64, gain: 128, lfo: 1, phase: 64, shape: 64, stereo: 0, transpose: 70, type: 0, unison: 0}
|
parameters: {color: 128, detune: 64, gain: 128, lfo: 1, phase: 64, shape: 64, stereo: 0, transpose: 70, type: 0, unison: 0}
|
||||||
- type: send
|
- type: send
|
||||||
parameters: {amount: 68, port: 4, sendpop: 1, stereo: 0, unit: 1, voice: 0}
|
parameters: {amount: 68, port: 4, sendpop: 1, stereo: 0, target: 1}
|
||||||
- type: out
|
- type: out
|
||||||
parameters: {gain: 128, stereo: 1}
|
parameters: {gain: 128, stereo: 1}
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0]]
|
patterns: [[64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: envelope
|
- type: envelope
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0]]
|
patterns: [[64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: envelope
|
- type: envelope
|
||||||
|
@ -1,18 +1,20 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[80, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0]]
|
patterns: [[80, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: envelope
|
- type: envelope
|
||||||
parameters: {attack: 80, decay: 80, gain: 128, release: 80, stereo: 0, sustain: 64}
|
parameters: {attack: 80, decay: 80, gain: 128, release: 80, stereo: 0, sustain: 64}
|
||||||
- type: oscillator
|
- type: oscillator
|
||||||
parameters: {color: 128, detune: 64, gain: 128, lfo: 0, phase: 0, shape: 64, stereo: 0, transpose: 64, type: 0, unison: 0}
|
parameters: {color: 128, detune: 64, gain: 128, lfo: 0, phase: 0, shape: 64, stereo: 0, transpose: 64, type: 0, unison: 0}
|
||||||
|
id: 1
|
||||||
- type: mulp
|
- type: mulp
|
||||||
parameters: {stereo: 0}
|
parameters: {stereo: 0}
|
||||||
- type: push
|
- type: push
|
||||||
@ -20,6 +22,6 @@ patch:
|
|||||||
- type: oscillator
|
- type: oscillator
|
||||||
parameters: {color: 128, detune: 64, gain: 128, lfo: 1, phase: 64, shape: 64, stereo: 0, transpose: 70, type: 0, unison: 0}
|
parameters: {color: 128, detune: 64, gain: 128, lfo: 1, phase: 64, shape: 64, stereo: 0, transpose: 70, type: 0, unison: 0}
|
||||||
- type: send
|
- type: send
|
||||||
parameters: {amount: 68, port: 0, sendpop: 1, stereo: 0, unit: 1, voice: 0}
|
parameters: {amount: 68, port: 0, sendpop: 1, stereo: 0, target: 1}
|
||||||
- type: out
|
- type: out
|
||||||
parameters: {gain: 128, stereo: 1}
|
parameters: {gain: 128, stereo: 1}
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0]]
|
patterns: [[64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: envelope
|
- type: envelope
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0]]
|
patterns: [[64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: envelope
|
- type: envelope
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0]]
|
patterns: [[64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: envelope
|
- type: envelope
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: loadval
|
- type: loadval
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: loadval
|
- type: loadval
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: envelope
|
- type: envelope
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: envelope
|
- type: envelope
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 2
|
- numvoices: 2
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 1, 68, 1, 32, 1, 1, 1, 75, 1, 78, 1, 1, 0, 0, 0]]
|
patterns: [[64, 1, 68, 1, 32, 1, 1, 1, 75, 1, 78, 1, 1, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: envelope
|
- type: envelope
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
bpm: 100
|
bpm: 100
|
||||||
rowsperpattern: 16
|
|
||||||
rowsperbeat: 4
|
rowsperbeat: 4
|
||||||
|
score:
|
||||||
|
rowsperpattern: 16
|
||||||
|
length: 1
|
||||||
tracks:
|
tracks:
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
sequence: [0]
|
order: [0]
|
||||||
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
patterns: [[64, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]
|
||||||
patch:
|
patch:
|
||||||
instruments:
|
|
||||||
- numvoices: 1
|
- numvoices: 1
|
||||||
units:
|
units:
|
||||||
- type: loadval
|
- type: loadval
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user