Reorganize the project folder structure and how go packages are organized.

Sointu.asm / lib stuff lives at the root folder. There is a folder called "go4k", which is where
all go stuff lives. Following the ideas from https://medium.com/@benbjohnson/standard-package-layout-7cdbc8391fc1
the go4k folder is the "domain-model" of the go side, and should have no dependencies.
It contains Unit, Instrument, Synth interface etc. Putting go4k under a sub-folder is actually
in the spirit of Ben, as go4k adds dependency to the go language.

Bridge ties the domain-model to the sointulib through cgo. It returns C.Synth, but
makes sure the C.Synth implements the Synth interface, so others are able to use the
Synth no matter how it actually is done. MockSynth and WebProxy synth are good
prospects for other implementations of Synth.

It is a bit fuzzy where methods like "Play" that have no dependencies other than domain
model structs should go. They probably should live in the go4k package as well.

The file-organization on the Go-side is not at all finalized. But how packages are broken
into files is mostly a documentation issue; it does not affect the users of the packages at
all.

BTW: The name go4k was chosen because Ben advocated naming the subpackages
according to the dependency they introduce AND because the prototype of 4klang was
called go4k (there are still some defines in the 4klang source revealing this). go4k thus
honors our roots but is also not so bad name: it's the main package of a 4k synth tracker,
written in go.
This commit is contained in:
Veikko Sariola 2020-10-30 22:05:26 +02:00
parent 23e8bc0c5f
commit e0a793ea6d
116 changed files with 530 additions and 635 deletions

View File

@ -30,8 +30,17 @@ enable_language(ASM_NASM)
# By putting them there, we can pass the same compile definitions to C and ASM # By putting them there, we can pass the same compile definitions to C and ASM
set(CMAKE_ASM_NASM_COMPILE_OBJECT "<CMAKE_ASM_NASM_COMPILER> <INCLUDES> <DEFINES> <FLAGS> -f ${CMAKE_ASM_NASM_OBJECT_FORMAT} -o <OBJECT> <SOURCE>") set(CMAKE_ASM_NASM_COMPILE_OBJECT "<CMAKE_ASM_NASM_COMPILER> <INCLUDES> <DEFINES> <FLAGS> -f ${CMAKE_ASM_NASM_OBJECT_FORMAT} -o <OBJECT> <SOURCE>")
# The compiled VSTi is here # Sointu as a header-only library
add_subdirectory(src) set(HEADERLIB sointuinterface)
add_library(${HEADERLIB} INTERFACE)
target_include_directories(${HEADERLIB} INTERFACE ${PROJECT_SOURCE_DIR}/include/sointu)
# Sointu as static library
set(STATICLIB sointu)
add_library(${STATICLIB} render.asm)
set_target_properties(${STATICLIB} PROPERTIES LINKER_LANGUAGE C)
target_link_libraries(${STATICLIB} ${HEADERLIB})
target_compile_definitions(${STATICLIB} PUBLIC SU_USE_INTROSPECTION)
# We should put examples here # We should put examples here
# add_subdirectory(examples) # add_subdirectory(examples)

View File

@ -1,191 +0,0 @@
package bridge
import (
"errors"
)
// #cgo CFLAGS: -I"${SRCDIR}/../include"
// #cgo LDFLAGS: "${SRCDIR}/../build/src/libsointu.a"
// #include <sointu.h>
import "C"
// SynthState contains the entire state of sointu sound engine
type Synth C.Synth // hide C.Synth, explicit cast is still possible if needed
type SynthState C.SynthState // hide C.Synthstate, explicit cast is still possible if needed
// Opcode is a single byte, representing the virtual machine commands used in Sointu
type Opcode byte
// Unit includes command (filter, oscillator, envelope etc.) and its parameters
type Unit struct {
Command Opcode
Params []byte
}
// Instrument includes a list of units consisting of the instrument, and the number of polyphonic voices for this instrument
type Instrument struct {
NumVoices int
Units []Unit
}
type Patch []Instrument
func (p Patch) TotalVoices() int {
ret := 0
for _, i := range p {
ret += i.NumVoices
}
return ret
}
var ( // cannot be const as the rhs are not known at compile-time
Add = Opcode(C.su_add_id)
Addp = Opcode(C.su_addp_id)
Pop = Opcode(C.su_pop_id)
Loadnote = Opcode(C.su_loadnote_id)
Mul = Opcode(C.su_mul_id)
Mulp = Opcode(C.su_mulp_id)
Push = Opcode(C.su_push_id)
Xch = Opcode(C.su_xch_id)
Distort = Opcode(C.su_distort_id)
Hold = Opcode(C.su_hold_id)
Crush = Opcode(C.su_crush_id)
Gain = Opcode(C.su_gain_id)
Invgain = Opcode(C.su_invgain_id)
Filter = Opcode(C.su_filter_id)
Clip = Opcode(C.su_clip_id)
Pan = Opcode(C.su_pan_id)
Delay = Opcode(C.su_delay_id)
Compres = Opcode(C.su_compres_id)
Advance = Opcode(C.su_advance_id)
Speed = Opcode(C.su_speed_id)
Out = Opcode(C.su_out_id)
Outaux = Opcode(C.su_outaux_id)
Aux = Opcode(C.su_aux_id)
Send = Opcode(C.su_send_id)
Envelope = Opcode(C.su_envelope_id)
Noise = Opcode(C.su_noise_id)
Oscillat = Opcode(C.su_oscillat_id)
Loadval = Opcode(C.su_loadval_id)
Receive = Opcode(C.su_receive_id)
In = Opcode(C.su_in_id)
)
// Stereo returns the stereo version of any (mono or stereo) opcode
func (o Opcode) Stereo() Opcode {
return Opcode(byte(o) | 1) // set lowest bit
}
// Mono returns the mono version of any (mono or stereo) opcode
func (o Opcode) Mono() Opcode {
return Opcode(byte(o) & 0xFE) // clear lowest bit
}
// Render tries to fill the buffer with samples rendered by Sointu.
// Use this version if you are not interested in time modulation. Will always
// fill the buffer.
// Parameters:
// buffer float32 slice to fill with rendered samples. Stereo signal, so
// should have even length.
// Returns an error if something went wrong.
func (synth *Synth) Render(state *SynthState, buffer []float32) error {
if len(buffer)%1 == 1 {
return errors.New("Render writes stereo signals, so buffer should have even length")
}
maxSamples := len(buffer) / 2
state.RandSeed += 1 // if you initialize with empty struct, you will get randseed 1 which is sointu default behavior
errcode := C.su_render((*C.Synth)(synth), (*C.SynthState)(state), (*C.float)(&buffer[0]), C.int(maxSamples))
state.RandSeed -= 1
if errcode > 0 {
return errors.New("Render failed")
}
return nil
}
// RenderTime renders until the buffer is full or the modulated time is reached, whichever
// happens first.
// Parameters:
// buffer float32 slice to fill with rendered samples. Stereo signal, so
// should have even length.
// maxtime how long nominal time to render in samples. Speed unit might modulate time
// so the actual number of samples rendered depends on the modulation and if
// buffer is full before maxtime is reached.
// Returns a tuple (int, int, error), consisting of:
// samples number of samples rendered in the buffer
// time how much the time advanced
// error potential error
// In practice, if nsamples = len(buffer)/2, then time <= maxtime. If maxtime was reached
// first, then nsamples <= len(buffer)/2 and time >= maxtime. Note that it could happen that
// time > maxtime, as it is modulated and the time could advance by 2 or more, so the loop
// exit condition would fire when the time is already past maxtime.
// Under no conditions, nsamples >= len(buffer)/2 i.e. guaranteed to never overwrite the buffer.
func (synth *Synth) RenderTime(state *SynthState, buffer []float32, maxtime int) (int, int, error) {
if len(buffer)%1 == 1 {
return -1, -1, errors.New("RenderTime writes stereo signals, so buffer should have even length")
}
samples := C.int(len(buffer) / 2)
time := C.int(maxtime)
state.RandSeed += 1 // if you initialize with empty struct, you will get randseed 1 which is sointu default behavior
errcode := int(C.su_render_time((*C.Synth)(synth), (*C.SynthState)(state), (*C.float)(&buffer[0]), &samples, &time))
state.RandSeed -= 1
if errcode > 0 {
return -1, -1, errors.New("RenderTime failed")
}
return int(samples), int(time), nil
}
func Compile(patch Patch) (*Synth, error) {
totalVoices := 0
commands := make([]Opcode, 0)
values := make([]byte, 0)
polyphonyBitmask := 0
for _, instr := range patch {
if len(instr.Units) > 63 {
return nil, errors.New("An instrument can have a maximum of 63 units")
}
if instr.NumVoices < 1 {
return nil, errors.New("Each instrument must have at least 1 voice")
}
for _, unit := range instr.Units {
commands = append(commands, unit.Command)
values = append(values, unit.Params...)
}
commands = append(commands, Advance)
totalVoices += instr.NumVoices
for k := 0; k < instr.NumVoices-1; k++ {
polyphonyBitmask = (polyphonyBitmask << 1) + 1
}
polyphonyBitmask <<= 1
}
if totalVoices > 32 {
return nil, errors.New("Sointu does not support more than 32 concurrent voices")
}
if len(commands) > 2048 { // TODO: 2048 could probably be pulled automatically from cgo
return nil, errors.New("The patch would result in more than 2048 commands")
}
if len(values) > 16384 { // TODO: 16384 could probably be pulled automatically from cgo
return nil, errors.New("The patch would result in more than 16384 values")
}
s := new(Synth)
for i := range commands {
s.Commands[i] = (C.uchar)(commands[i])
}
for i := range values {
s.Values[i] = (C.uchar)(values[i])
}
s.NumVoices = C.uint(totalVoices)
s.Polyphony = C.uint(polyphonyBitmask)
return s, nil
}
func (s *SynthState) Trigger(voice int, note byte) {
cs := (*C.SynthState)(s)
cs.SynthWrk.Voices[voice] = C.Voice{}
cs.SynthWrk.Voices[voice].Note = C.int(note)
}
func (s *SynthState) Release(voice int) {
cs := (*C.SynthState)(s)
cs.SynthWrk.Voices[voice].Release = 1
}

148
go4k/bridge/bridge.go Normal file
View File

@ -0,0 +1,148 @@
package bridge
import (
"errors"
"fmt"
"github.com/vsariola/sointu/go4k"
)
// #cgo CFLAGS: -I"${SRCDIR}/../../include/sointu"
// #cgo LDFLAGS: "${SRCDIR}/../../build/libsointu.a"
// #include <sointu.h>
import "C"
type opTableEntry struct {
opcode C.int
parameterList []string
}
var opcodeTable = map[string]opTableEntry{
"add": opTableEntry{C.su_add_id, []string{}},
"addp": opTableEntry{C.su_addp_id, []string{}},
"pop": opTableEntry{C.su_pop_id, []string{}},
"loadnote": opTableEntry{C.su_loadnote_id, []string{}},
"mul": opTableEntry{C.su_mul_id, []string{}},
"mulp": opTableEntry{C.su_mulp_id, []string{}},
"push": opTableEntry{C.su_push_id, []string{}},
"xch": opTableEntry{C.su_xch_id, []string{}},
"distortion": opTableEntry{C.su_distort_id, []string{"drive"}},
"hold": opTableEntry{C.su_hold_id, []string{"holdfreq"}},
"crush": opTableEntry{C.su_crush_id, []string{"resolution"}},
"gain": opTableEntry{C.su_gain_id, []string{"gain"}},
"invgain": opTableEntry{C.su_invgain_id, []string{"invgain"}},
"filter": opTableEntry{C.su_filter_id, []string{"frequency", "resonance", "flags"}},
"clip": opTableEntry{C.su_clip_id, []string{}},
"pan": opTableEntry{C.su_pan_id, []string{"panning"}},
"delay": opTableEntry{C.su_delay_id, []string{"pregain", "dry", "feedback", "depth", "damp", "delay", "count"}},
"compressor": opTableEntry{C.su_compres_id, []string{"attack", "release", "invgain", "threshold", "ratio"}},
"speed": opTableEntry{C.su_speed_id, []string{}},
"out": opTableEntry{C.su_out_id, []string{"gain"}},
"outaux": opTableEntry{C.su_outaux_id, []string{"outgain", "auxgain"}},
"aux": opTableEntry{C.su_aux_id, []string{"gain", "channel"}},
"send": opTableEntry{C.su_send_id, []string{"amount", "port"}},
"envelope": opTableEntry{C.su_envelope_id, []string{"attack", "decay", "sustain", "release", "gain"}},
"noise": opTableEntry{C.su_noise_id, []string{"shape", "gain"}},
"oscillator": opTableEntry{C.su_oscillat_id, []string{"transpose", "detune", "phase", "color", "shape", "gain", "flags"}},
"loadval": opTableEntry{C.su_loadval_id, []string{"value"}},
"receive": opTableEntry{C.su_receive_id, []string{}},
"in": opTableEntry{C.su_in_id, []string{"channel"}},
}
// Render renders until the buffer is full or the modulated time is reached, whichever
// happens first.
// Parameters:
// buffer float32 slice to fill with rendered samples. Stereo signal, so
// should have even length.
// maxtime how long nominal time to render in samples. Speed unit might modulate time
// so the actual number of samples rendered depends on the modulation and if
// buffer is full before maxtime is reached.
// Returns a tuple (int, int, error), consisting of:
// samples number of samples rendered in the buffer
// time how much the time advanced
// error potential error
// In practice, if nsamples = len(buffer)/2, then time <= maxtime. If maxtime was reached
// first, then nsamples <= len(buffer)/2 and time >= maxtime. Note that it could happen that
// time > maxtime, as it is modulated and the time could advance by 2 or more, so the loop
// exit condition would fire when the time is already past maxtime.
// Under no conditions, nsamples >= len(buffer)/2 i.e. guaranteed to never overwrite the buffer.
func (synth *C.Synth) Render(buffer []float32, maxtime int) (int, int, error) {
if len(buffer)%1 == 1 {
return -1, -1, errors.New("RenderTime writes stereo signals, so buffer should have even length")
}
samples := C.int(len(buffer) / 2)
time := C.int(maxtime)
errcode := int(C.su_render(synth, (*C.float)(&buffer[0]), &samples, &time))
if errcode > 0 {
return -1, -1, errors.New("RenderTime failed")
}
return int(samples), int(time), nil
}
func Synth(patch go4k.Patch) (*C.Synth, error) {
totalVoices := 0
commands := make([]byte, 0)
values := make([]byte, 0)
polyphonyBitmask := 0
for insid, instr := range patch {
if len(instr.Units) > 63 {
return nil, errors.New("An instrument can have a maximum of 63 units")
}
if instr.NumVoices < 1 {
return nil, errors.New("Each instrument must have at least 1 voice")
}
for unitid, unit := range instr.Units {
if val, ok := opcodeTable[unit.Type]; ok {
if unit.Stereo {
commands = append(commands, byte(val.opcode+1))
} else {
commands = append(commands, byte(val.opcode))
}
for _, paramname := range val.parameterList {
if pval, ok := unit.Parameters[paramname]; ok {
values = append(values, byte(pval))
} else {
return nil, fmt.Errorf("Unit parameter undefined: %v (at instrument %v, unit %v)", paramname, insid, unitid)
}
}
} else {
return nil, fmt.Errorf("Unknown unit type: %v (at instrument %v, unit %v)", unit.Type, insid, unitid)
}
}
commands = append(commands, byte(C.su_advance_id))
totalVoices += instr.NumVoices
for k := 0; k < instr.NumVoices-1; k++ {
polyphonyBitmask = (polyphonyBitmask << 1) + 1
}
polyphonyBitmask <<= 1
}
if totalVoices > 32 {
return nil, errors.New("Sointu does not support more than 32 concurrent voices")
}
if len(commands) > 2048 { // TODO: 2048 could probably be pulled automatically from cgo
return nil, errors.New("The patch would result in more than 2048 commands")
}
if len(values) > 16384 { // TODO: 16384 could probably be pulled automatically from cgo
return nil, errors.New("The patch would result in more than 16384 values")
}
s := new(C.Synth)
for i := range commands {
s.Commands[i] = (C.uchar)(commands[i])
}
for i := range values {
s.Values[i] = (C.uchar)(values[i])
}
s.NumVoices = C.uint(totalVoices)
s.Polyphony = C.uint(polyphonyBitmask)
s.RandSeed = 1
return s, nil
}
func (s *C.Synth) Trigger(voice int, note byte) {
s.SynthWrk.Voices[voice] = C.Voice{}
s.SynthWrk.Voices[voice].Note = C.int(note)
}
func (s *C.Synth) Release(voice int) {
s.SynthWrk.Voices[voice].Release = 1
}

View File

@ -8,7 +8,8 @@ import (
"runtime" "runtime"
"testing" "testing"
"github.com/vsariola/sointu/bridge" "github.com/vsariola/sointu/go4k"
"github.com/vsariola/sointu/go4k/bridge"
) )
const BPM = 100 const BPM = 100
@ -21,30 +22,29 @@ const su_max_samples = SAMPLES_PER_ROW * TOTAL_ROWS
// const bufsize = su_max_samples * 2 // const bufsize = su_max_samples * 2
func TestBridge(t *testing.T) { func TestBridge(t *testing.T) {
patch := []bridge.Instrument{ patch := []go4k.Instrument{
bridge.Instrument{1, []bridge.Unit{ go4k.Instrument{1, []go4k.Unit{
bridge.Unit{bridge.Envelope, []byte{64, 64, 64, 80, 128}}, go4k.Unit{"envelope", false, map[string]int{"attack": 64, "decay": 64, "sustain": 64, "release": 80, "gain": 128}},
bridge.Unit{bridge.Envelope, []byte{95, 64, 64, 80, 128}}, go4k.Unit{"envelope", false, map[string]int{"attack": 95, "decay": 64, "sustain": 64, "release": 80, "gain": 128}},
bridge.Unit{bridge.Out.Stereo(), []byte{128}}, go4k.Unit{"out", true, map[string]int{"gain": 128}},
}}} }}}
synth, err := bridge.Compile(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)
} }
var state bridge.SynthState synth.Trigger(0, 64)
state.Trigger(0, 64)
buffer := make([]float32, 2*su_max_samples) buffer := make([]float32, 2*su_max_samples)
err = synth.Render(&state, buffer[:len(buffer)/2]) err = go4k.Render(synth, buffer[:len(buffer)/2])
if err != nil { if err != nil {
t.Fatalf("first render gave an error") t.Fatalf("first render gave an error")
} }
state.Release(0) synth.Release(0)
err = synth.Render(&state, buffer[len(buffer)/2:]) err = go4k.Render(synth, buffer[len(buffer)/2:])
if err != nil { if err != nil {
t.Fatalf("first render gave an error") t.Fatalf("first render gave an error")
} }
_, filename, _, _ := runtime.Caller(0) _, filename, _, _ := runtime.Caller(0)
expectedb, err := ioutil.ReadFile(path.Join(path.Dir(filename), "..", "tests", "expected_output", "test_render_samples.raw")) expectedb, err := ioutil.ReadFile(path.Join(path.Dir(filename), "..", "..", "tests", "expected_output", "test_render_samples.raw"))
if err != nil { if err != nil {
t.Fatalf("cannot read expected: %v", err) t.Fatalf("cannot read expected: %v", err)
} }

49
go4k/go4k.go Normal file
View File

@ -0,0 +1,49 @@
package go4k
import (
"errors"
"math"
)
// Unit is e.g. a filter, oscillator, envelope and its parameters
type Unit struct {
Type string
Stereo bool
Parameters map[string]int
}
// Instrument includes a list of units consisting of the instrument, and the number of polyphonic voices for this instrument
type Instrument struct {
NumVoices int
Units []Unit
}
// Patch is simply a list of instruments used in a song
type Patch []Instrument
func (p Patch) TotalVoices() int {
ret := 0
for _, i := range p {
ret += i.NumVoices
}
return ret
}
type Track struct {
NumVoices int
Sequence []byte
}
type Synth interface {
Render(buffer []float32, maxtime int) (int, int, error)
Trigger(voice int, note byte)
Release(voice int)
}
func Render(synth Synth, buffer []float32) error {
s, _, err := synth.Render(buffer, math.MaxInt32)
if s != len(buffer)/2 {
return errors.New("synth.Render should have filled the whole buffer")
}
return err
}

View File

@ -1,38 +1,41 @@
package song package go4k
import ( import "errors"
"errors"
"github.com/vsariola/sointu/bridge"
)
type Track struct {
NumVoices int
Sequence []byte
}
type Song struct { type Song struct {
BPM int BPM int
Patterns [][]byte Patterns [][]byte
Tracks []Track Tracks []Track
Patch bridge.Patch SongLength int // in samples, 0 means calculate automatically from BPM and Track lengths, but can also set manually
Samples int // -1 means calculate automatically, but you can also set it manually Patch Patch
} }
func NewSong(bpm int, patterns [][]byte, tracks []Track, patch bridge.Patch) (*Song, error) { func (s *Song) PatternRows() int {
s := new(Song) return len(s.Patterns[0])
s.BPM = bpm }
s.Patterns = patterns
s.Tracks = tracks func (s *Song) SequenceLength() int {
s.Patch = patch return len(s.Tracks[0].Sequence)
err := s.Validate() }
if err != nil {
return nil, err func (s *Song) TotalRows() int {
return s.PatternRows() * s.SequenceLength()
}
func (s *Song) SamplesPerRow() int {
return 44100 * 60 / (s.BPM * 4)
}
func (s *Song) FirstTrackVoice(track int) int {
ret := 0
for _, t := range s.Tracks[:track] {
ret += t.NumVoices
} }
s.Samples = -1 return ret
return s, nil
} }
// 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 { func (s *Song) Validate() error {
if s.BPM < 1 { if s.BPM < 1 {
return errors.New("BPM should be > 0") return errors.New("BPM should be > 0")
@ -62,66 +65,42 @@ func (s *Song) Validate() error {
return nil return nil
} }
func (s *Song) PatternRows() int { func Play(synth Synth, song Song) ([]float32, error) {
return len(s.Patterns[0]) err := song.Validate()
}
func (s *Song) SequenceLength() int {
return len(s.Tracks[0].Sequence)
}
func (s *Song) TotalRows() int {
return s.PatternRows() * s.SequenceLength()
}
func (s *Song) SamplesPerRow() int {
return 44100 * 60 / (s.BPM * 4)
}
func (s *Song) FirstTrackVoice(track int) int {
ret := 0
for _, t := range s.Tracks[:track] {
ret += t.NumVoices
}
return ret
}
func (s *Song) Render(synth *bridge.Synth, state *bridge.SynthState) ([]float32, error) {
err := s.Validate()
if err != nil { if err != nil {
return nil, err return nil, err
} }
curVoices := make([]int, len(s.Tracks)) curVoices := make([]int, len(song.Tracks))
for i := range curVoices { for i := range curVoices {
curVoices[i] = s.FirstTrackVoice(i) curVoices[i] = song.FirstTrackVoice(i)
} }
samples := s.Samples samples := song.SongLength
if samples < 0 { if samples <= 0 {
samples = s.TotalRows() * s.SamplesPerRow() samples = song.TotalRows() * song.SamplesPerRow()
} }
buffer := make([]float32, samples*2) buffer := make([]float32, samples*2)
totaln := 0 totaln := 0
rowtime := 44100 * 60 / (s.BPM * 4) rowtime := song.SamplesPerRow()
for row := 0; row < s.TotalRows(); row++ { for row := 0; row < song.TotalRows(); row++ {
patternRow := row % s.PatternRows() patternRow := row % song.PatternRows()
pattern := row / s.PatternRows() pattern := row / song.PatternRows()
for t := range s.Tracks { for t := range song.Tracks {
patternIndex := s.Tracks[t].Sequence[pattern] patternIndex := song.Tracks[t].Sequence[pattern]
note := s.Patterns[patternIndex][patternRow] note := song.Patterns[patternIndex][patternRow]
if note == 1 { // anything but hold causes an action. if note == 1 { // anything but hold causes an action.
continue // TODO: can hold be actually something else than 1? continue // TODO: can hold be actually something else than 1?
} }
state.Release(curVoices[t]) synth.Release(curVoices[t])
if note > 1 { if note > 1 {
curVoices[t]++ curVoices[t]++
first := s.FirstTrackVoice(t) first := song.FirstTrackVoice(t)
if curVoices[t] >= first+s.Tracks[t].NumVoices { if curVoices[t] >= first+song.Tracks[t].NumVoices {
curVoices[t] = first curVoices[t] = first
} }
state.Trigger(curVoices[t], note) synth.Trigger(curVoices[t], note)
} }
} }
samples, _, _ := synth.RenderTime(state, buffer[2*totaln:], rowtime) samples, _, _ := synth.Render(buffer[2*totaln:], rowtime)
totaln += samples totaln += samples
} }
return buffer, nil return buffer, nil

View File

@ -1,4 +1,4 @@
package song_test package go4k_test
import ( import (
"bytes" "bytes"
@ -8,8 +8,9 @@ import (
"runtime" "runtime"
"testing" "testing"
"github.com/vsariola/sointu/bridge" "github.com/vsariola/sointu/go4k"
"github.com/vsariola/sointu/song" "github.com/vsariola/sointu/go4k/bridge"
// TODO: test the song using a mocks instead
) )
const BPM = 100 const BPM = 100
@ -21,29 +22,24 @@ const su_max_samples = SAMPLES_PER_ROW * TOTAL_ROWS
// const bufsize = su_max_samples * 2 // const bufsize = su_max_samples * 2
func TestSongRender(t *testing.T) { func TestPlayer(t *testing.T) {
patch := []bridge.Instrument{ patch := go4k.Patch{go4k.Instrument{1, []go4k.Unit{
bridge.Instrument{1, []bridge.Unit{ go4k.Unit{"envelope", false, map[string]int{"attack": 32, "decay": 32, "sustain": 64, "release": 64, "gain": 128}},
bridge.Unit{bridge.Envelope, []byte{32, 32, 64, 64, 128}}, go4k.Unit{"oscillator", false, map[string]int{"transpose": 64, "detune": 64, "phase": 0, "color": 96, "shape": 64, "gain": 128, "flags": 0x40}},
bridge.Unit{bridge.Oscillat, []byte{64, 64, 0, 96, 64, 128, 0x40}}, go4k.Unit{"mulp", false, map[string]int{}},
bridge.Unit{bridge.Mulp, []byte{}}, go4k.Unit{"envelope", false, map[string]int{"attack": 32, "decay": 32, "sustain": 64, "release": 64, "gain": 128}},
bridge.Unit{bridge.Envelope, []byte{32, 32, 64, 64, 128}}, go4k.Unit{"oscillator", false, map[string]int{"transpose": 72, "detune": 64, "phase": 64, "color": 64, "shape": 96, "gain": 128, "flags": 0x40}},
bridge.Unit{bridge.Oscillat, []byte{72, 64, 64, 64, 96, 128, 0x40}}, go4k.Unit{"mulp", false, map[string]int{}},
bridge.Unit{bridge.Mulp, []byte{}}, go4k.Unit{"out", true, map[string]int{"gain": 128}},
bridge.Unit{bridge.Out.Stereo(), []byte{128}},
}}} }}}
patterns := [][]byte{{64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0}} patterns := [][]byte{{64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0}}
tracks := []song.Track{song.Track{1, []byte{0}}} tracks := []go4k.Track{go4k.Track{1, []byte{0}}}
song, err := song.NewSong(100, patterns, tracks, patch) song := go4k.Song{100, patterns, tracks, 0, patch}
if err != nil { synth, err := bridge.Synth(patch)
t.Fatalf("NewSong failed: %v", err)
}
synth, err := bridge.Compile(patch)
if err != nil { if err != nil {
t.Fatalf("Compiling patch failed: %v", err) t.Fatalf("Compiling patch failed: %v", err)
} }
var state bridge.SynthState buffer, err := go4k.Play(synth, song)
buffer, err := song.Render(synth, &state)
if err != nil { if err != nil {
t.Fatalf("Render failed: %v", err) t.Fatalf("Render failed: %v", err)
} }

View File

@ -30,14 +30,11 @@ typedef struct SynthWorkspace {
struct Voice Voices[32]; struct Voice Voices[32];
} SynthWorkspace; } SynthWorkspace;
typedef struct SynthState { typedef struct Synth {
struct SynthWorkspace SynthWrk; struct SynthWorkspace SynthWrk;
struct DelayWorkspace DelayWrks[64]; // let's keep this as 64 for now, so the delays take 16 meg. If that's too little or too much, we can change this in future. struct DelayWorkspace DelayWrks[64]; // let's keep this as 64 for now, so the delays take 16 meg. If that's too little or too much, we can change this in future.
unsigned int RandSeed; unsigned int RandSeed;
unsigned int GlobalTick; unsigned int GlobalTick;
} SynthState;
typedef struct Synth {
unsigned char Commands[32 * 64]; unsigned char Commands[32 * 64];
unsigned char Values[32 * 64 * 8]; unsigned char Values[32 * 64 * 8];
unsigned int Polyphony; unsigned int Polyphony;
@ -59,35 +56,14 @@ typedef struct Synth {
extern void CALLCONV su_load_gmdls(void); extern void CALLCONV su_load_gmdls(void);
#endif #endif
// int su_render(Synth* synth,SynthState* synthState, float* buffer, int samples): // int su_render(Synth* synth, float* buffer, int* samples, int* time):
// Renders 'samples' number of 'samples' to the 'buffer', using 'synth'.
// Modifies 'synthState' and fills the 'buffer'.
//
// Parameters:
// synth pointer to the synthesizer used. Won't get modified by the call.
// synthState pointer to current synthState. RandSeed should be > 0 e.g. 1
// buffer audio sample buffer, L R L R ...
// samples maximum number of samples to be rendered. WARNING: buffer
// should have a length of 2 * samples as the audio is stereo.
//
// Returns error code:
// 0 everything ok
// (returns always 0 as no errors are implemented yet)
int CALLCONV su_render(Synth* synth,SynthState* synthState, float* buffer, int samples);
// int su_render_time(Synth* synth,SynthState* synthState, float* buffer, int* samples, int* time):
// Renders samples until 'samples' number of samples are reached or 'time' number of // Renders samples until 'samples' number of samples are reached or 'time' number of
// modulated time ticks are reached, whichever happens first. 'samples' and 'time' are // modulated time ticks are reached, whichever happens first. 'samples' and 'time' are
// are passed by reference as the function modifies to tell how many samples were // are passed by reference as the function modifies to tell how many samples were
// actually rendered and how many time ticks were actually advanced. // actually rendered and how many time ticks were actually advanced.
// //
// Parameters: // Parameters:
// synth pointer to the synthesizer used. Won't get modified by the call. // synth pointer to the synthesizer used. RandSeed should be > 0 e.g. 1
// synthState pointer to current synthState. RandSeed should be > 0 e.g. 1
// Also synthState->SamplesPerRow cannot be 0 or nothing will be
// rendered; either set it to INT32_MAX to always render full
// buffer, or something like SAMPLE_RATE * 60 / (BPM * 4) for
// having 4 rows per beat.
// buffer audio sample buffer, L R L R ... // buffer audio sample buffer, L R L R ...
// samples pointer to the maximum number of samples to be rendered. // samples pointer to the maximum number of samples to be rendered.
// buffer should have a length of 2 * maxsamples as the audio // buffer should have a length of 2 * maxsamples as the audio
@ -104,7 +80,7 @@ int CALLCONV su_render(Synth* synth,SynthState* synthState, float* buffer, int s
// Returns error code: // Returns error code:
// 0 everything ok // 0 everything ok
// (no actual errors implemented yet) // (no actual errors implemented yet)
int CALLCONV su_render_time(Synth* synth,SynthState* synthState, float* buffer, int* samples, int* time); int CALLCONV su_render(Synth* synth, float* buffer, int* samples, int* time);
// Arithmetic opcode ids // Arithmetic opcode ids
extern const int su_add_id; extern const int su_add_id;

View File

@ -25,14 +25,11 @@ USE_OUT
section .text section .text
struc su_synth_state struc su_synth
.synthwrk resb su_synthworkspace.size .synthwrk resb su_synthworkspace.size
.delaywrks resb su_delayline_wrk.size * 64 .delaywrks resb su_delayline_wrk.size * 64
.randseed resd 1 .randseed resd 1
.globaltime resd 1 .globaltime resd 1
endstruc
struc su_synth
.commands resb 32 * 64 .commands resb 32 * 64
.values resb 32 * 64 * 8 .values resb 32 * 64 * 8
.polyphony resd 1 .polyphony resd 1
@ -41,35 +38,25 @@ endstruc
SECT_TEXT(sursampl) SECT_TEXT(sursampl)
EXPORT MANGLE_FUNC(su_render_time,20) EXPORT MANGLE_FUNC(su_render,16)
%if BITS == 32 ; stdcall %if BITS == 32 ; stdcall
pushad ; push registers pushad ; push registers
mov eax, [esp + 4 + 32] ; eax = &synth mov ecx, [esp + 4 + 32] ; ecx = &synthState
mov ecx, [esp + 8 + 32] ; ecx = &synthState mov edx, [esp + 8 + 32] ; edx = &buffer
mov edx, [esp + 12 + 32] ; edx = &buffer mov esi, [esp + 12 + 32] ; esi = &samples
mov esi, [esp + 16 + 32] ; esi = &samples mov ebx, [esp + 16 + 32] ; ebx = &time
mov ebx, [esp + 20 + 32] ; ebx = &time
%else %else
%ifidn __OUTPUT_FORMAT__,win64 %ifidn __OUTPUT_FORMAT__,win64 ; win64 ABI: rcx = &synth, rdx = &buffer, r8 = &bufsize, r9 = &time
; win64 ABI parameter order: RCX, RDX, R8, R9; rest in stack (right-to-left, note shadow space!)
; here: rcx = &synth, rdx = &synthstate, r8 = &buffer, r9 = &bufsize, stack1 = &time
push_registers rdi, rsi, rbx, rbp ; win64 ABI: these registers are non-volatile push_registers rdi, rsi, rbx, rbp ; win64 ABI: these registers are non-volatile
mov rbx, [rsp + 0x28 + PUSH_REG_SIZE(4)] ; rbx = &time, note the shadow space so &time is at rsp + 0x28 mov rsi, r8 ; rsi = &samples
mov rax, rcx mov rbx, r9 ; rbx = &time
mov rcx, rdx %else ; System V ABI: rdi = &synth, rsi = &buffer, rdx = &samples, rcx = &time
mov rdx, r8
mov rsi, r9
%else
; System V ABI parameter order: RDI, RSI, RDX, RCX, R8, R9; rest in stack (right-to-left)
; here: rdi = &synth, rsi = &synthstate, rdx = &buffer, rcx = &samples, r8 = &time
push_registers rbx, rbp ; System V ABI: these registers are non-volatile push_registers rbx, rbp ; System V ABI: these registers are non-volatile
mov rax, rdi mov rbx, rcx ; rbx points to time
mov rbx, r8 xchg rsi, rdx ; rdx points to buffer, rsi points to samples
xchg rcx, rsi mov rcx, rdi ; rcx = &Synthstate
%endif %endif
%endif %endif
; _AX = &synth, _BX == &time, _CX == &synthstate, _DX == &buf, _SI == &samples,
push _AX ; push the pointer to synth to stack
push _SI ; push the pointer to samples push _SI ; push the pointer to samples
push _BX ; push the pointer to time push _BX ; push the pointer to time
xor eax, eax ; samplenumber starts at 0 xor eax, eax ; samplenumber starts at 0
@ -78,9 +65,9 @@ EXPORT MANGLE_FUNC(su_render_time,20)
push _SI ; push bufsize push _SI ; push bufsize
push _DX ; push bufptr push _DX ; push bufptr
push _CX ; this takes place of the voicetrack push _CX ; this takes place of the voicetrack
mov eax, [_CX + su_synth_state.randseed] mov eax, [_CX + su_synth.randseed]
push _AX ; randseed push _AX ; randseed
mov eax, [_CX + su_synth_state.globaltime] mov eax, [_CX + su_synth.globaltime]
push _AX ; global tick time push _AX ; global tick time
mov ebx, dword [_BX] ; zero extend dereferenced pointer mov ebx, dword [_BX] ; zero extend dereferenced pointer
push _BX ; the nominal rowlength should be time_in push _BX ; the nominal rowlength should be time_in
@ -93,24 +80,23 @@ su_render_samples_loop:
jge su_render_samples_time_finish ; goto finish jge su_render_samples_time_finish ; goto finish
inc eax ; time++ inc eax ; time++
inc dword [_SP + PTRSIZE*6] ; samples++ inc dword [_SP + PTRSIZE*6] ; samples++
mov _CX, [_SP + PTRSIZE*3] ; _CX = &synthstate mov _CX, [_SP + PTRSIZE*3]
mov _BP, [_SP + PTRSIZE*9] ; _BP = &synth
push _AX ; push rowtick push _AX ; push rowtick
mov eax, [_BP + su_synth.polyphony] mov eax, [_CX + su_synth.polyphony]
push _AX ;polyphony push _AX ;polyphony
mov eax, [_BP + su_synth.numvoices] mov eax, [_CX + su_synth.numvoices]
push _AX ;numvoices push _AX ;numvoices
lea _DX, [_CX + su_synth_state.synthwrk] lea _DX, [_CX+ su_synth.synthwrk]
lea COM, [_BP + su_synth.commands] lea COM, [_CX+ su_synth.commands]
lea VAL, [_BP + su_synth.values] lea VAL, [_CX+ su_synth.values]
lea WRK, [_DX + su_synthworkspace.voices] ; _BP and WRK are actually the same thing so here _BP gets overwritten lea WRK, [_DX + su_synthworkspace.voices]
lea _CX, [_CX + su_synth_state.delaywrks - su_delayline_wrk.filtstate] lea _CX, [_CX+ su_synth.delaywrks - su_delayline_wrk.filtstate]
call MANGLE_FUNC(su_run_vm,0) call MANGLE_FUNC(su_run_vm,0)
pop _AX pop _AX
pop _AX pop _AX
mov _DI, [_SP + PTRSIZE*5] ; edi containts buffer ptr mov _DI, [_SP + PTRSIZE*5] ; edi containts buffer ptr
mov _CX, [_SP + PTRSIZE*4] mov _CX, [_SP + PTRSIZE*4]
lea _SI, [_CX + su_synth_state.synthwrk + su_synthworkspace.left] lea _SI, [_CX + su_synth.synthwrk + su_synthworkspace.left]
movsd ; copy left channel to output buffer movsd ; copy left channel to output buffer
movsd ; copy right channel to output buffer movsd ; copy right channel to output buffer
mov [_SP + PTRSIZE*5], _DI ; save back the updated ptr mov [_SP + PTRSIZE*5], _DI ; save back the updated ptr
@ -126,8 +112,8 @@ su_render_samples_time_finish:
pop _BX pop _BX
pop _DX pop _DX
pop _CX pop _CX
mov [_CX + su_synth_state.randseed], edx mov [_CX + su_synth.randseed], edx
mov [_CX + su_synth_state.globaltime], ebx mov [_CX + su_synth.globaltime], ebx
pop _BX pop _BX
pop _BX pop _BX
pop _DX pop _DX
@ -135,12 +121,11 @@ su_render_samples_time_finish:
pop _SI ; pop the pointer to samples pop _SI ; pop the pointer to samples
mov dword [_SI], edx ; *samples = samples rendered mov dword [_SI], edx ; *samples = samples rendered
mov dword [_BX], eax ; *time = time ticks rendered mov dword [_BX], eax ; *time = time ticks rendered
pop _AX ; pop the synth pointer
xor eax, eax ; TODO: set eax to possible error code, now just 0 xor eax, eax ; TODO: set eax to possible error code, now just 0
%if BITS == 32 ; stdcall %if BITS == 32 ; stdcall
mov [_SP + 28],eax ; we want to return eax, but popad pops everything, so put eax to stack for popad to pop mov [_SP + 28],eax ; we want to return eax, but popad pops everything, so put eax to stack for popad to pop
popad popad
ret 20 ret 16
%else %else
%ifidn __OUTPUT_FORMAT__,win64 %ifidn __OUTPUT_FORMAT__,win64
pop_registers rdi, rsi, rbx, rbp ; win64 ABI: these registers are non-volatile pop_registers rdi, rsi, rbx, rbp ; win64 ABI: these registers are non-volatile
@ -149,45 +134,3 @@ su_render_samples_time_finish:
%endif %endif
ret ret
%endif %endif
EXPORT MANGLE_FUNC(su_render,16)
%if BITS == 32 ; stdcall
mov eax, 0x7FFFFFFF ; don't care about time, just try to fill the buffer
push eax
push esp
lea eax, [esp + 24]
push eax
push dword [esp + 24]
push dword [esp + 24]
push dword [esp + 24]
%else
%ifidn __OUTPUT_FORMAT__,win64
; win64 ABI parameter order: RCX, RDX, R8, R9; rest in stack (right-to-left, note shadow space!)
; here: rcx = &synth, rdx = &synthstate, r8 = &buffer, r9 = samples
; put the values in shadow space and get pointers to them
mov [_SP+0x8],r9
lea r9, [_SP+0x8]
mov [_SP+0x10], dword 0x7FFFFFFF ; don't care about time, just try to fill the buffer
lea r10, [_SP+0x10]
mov [_SP+0x20], r10
%else
; System V ABI parameter order: RDI, RSI, RDX, RCX, R8, R9; rest in stack (right-to-left)
; here: rdi = &synth, rsi = &synthstate, rdx = &buffer, rcx = samples
push rcx
mov rcx, _SP ; pass a pointer to samples instead of direct value
mov r8, 0x7FFFFFFF ; don't care about time, just try to fill the buffer
push r8
mov r8, _SP ; still, we have to pass a pointer to time, so pointer to stack
%endif
%endif
call MANGLE_FUNC(su_render_time,20)
%if BITS == 32 ; stdcall
pop ecx
ret 16
%else
%ifnidn __OUTPUT_FORMAT__,win64 ; win64 ABI: rdx = bufsize, r8 = &buffer, rcx = &synthstate
pop rcx
pop r8
%endif
ret
%endif

View File

@ -1,12 +0,0 @@
set(LIB sointu)
set(SOURCES sointu.asm)
# Headers
include_directories(${PROJECT_SOURCE_DIR}/include)
# Library target
add_library(${LIB} ${SOURCES})
set_target_properties(${LIB} PROPERTIES LINKER_LANGUAGE C)
target_link_libraries(${LIB})
target_compile_definitions(${LIB} PUBLIC SU_USE_INTROSPECTION)

View File

@ -21,6 +21,7 @@ function(regression_test testname)
add_test(${testname} ${testname}) add_test(${testname} ${testname})
target_compile_definitions(${testname} PUBLIC TEST_NAME="${testname}" SU_USE_INTROSPECTION SU_USE_PLAYER) target_compile_definitions(${testname} PUBLIC TEST_NAME="${testname}" SU_USE_INTROSPECTION SU_USE_PLAYER)
target_link_libraries(${testname} ${HEADERLIB})
set (rawinput ${CMAKE_CURRENT_SOURCE_DIR}/expected_output/${testname}.raw) set (rawinput ${CMAKE_CURRENT_SOURCE_DIR}/expected_output/${testname}.raw)
set (rawoutput ${CMAKE_CURRENT_BINARY_DIR}/expected_output/${testname}.raw) set (rawoutput ${CMAKE_CURRENT_BINARY_DIR}/expected_output/${testname}.raw)
@ -151,8 +152,8 @@ regression_test(test_chords "ENVELOPE;VCO_SINE")
regression_test(test_speed "ENVELOPE;VCO_SINE") regression_test(test_speed "ENVELOPE;VCO_SINE")
regression_test(test_render_samples ENVELOPE "" test_render_samples.c) regression_test(test_render_samples ENVELOPE "" test_render_samples.c)
target_link_libraries(test_render_samples sointu) target_link_libraries(test_render_samples ${STATICLIB})
add_executable(test_render_samples_api test_render_samples_api.c) add_executable(test_render_samples_api test_render_samples_api.c)
target_link_libraries(test_render_samples_api sointu) target_link_libraries(test_render_samples_api ${STATICLIB})
add_test(test_render_samples_api test_render_samples_api) add_test(test_render_samples_api test_render_samples_api)

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0, PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0,
@ -19,4 +19,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0, PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0,
@ -24,4 +24,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0 PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0
@ -22,4 +22,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0 PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0
@ -21,4 +21,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0 PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0
@ -19,4 +19,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0 PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0
@ -25,4 +25,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, 0, 0, 0, 68, 0, 0, 0, 66, 0, 0, 0, 69, 0, 0, 0, PATTERN 64, 0, 0, 0, 68, 0, 0, 0, 66, 0, 0, 0, 69, 0, 0, 0,
@ -25,4 +25,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0, PATTERN 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0,
@ -24,4 +24,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0, PATTERN 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0,
@ -24,4 +24,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 65, 65, 65, 65, PATTERN 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 65, 65, 65, 65,
@ -39,4 +39,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 65, 65, 65, 65, PATTERN 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 65, 65, 65, 65,
@ -39,4 +39,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0, PATTERN 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0,
@ -24,4 +24,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0, PATTERN 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0,
@ -23,4 +23,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0, PATTERN 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0,
@ -25,4 +25,4 @@ BEGIN_DELTIMES
DELTIME 11025 DELTIME 11025
END_DELTIMES END_DELTIMES
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0, PATTERN 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0,
@ -27,4 +27,4 @@ BEGIN_DELTIMES
DELTIME 11025 DELTIME 11025
END_DELTIMES END_DELTIMES
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0, PATTERN 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0,
@ -27,4 +27,4 @@ BEGIN_DELTIMES
DELTIME 11025 DELTIME 11025
END_DELTIMES END_DELTIMES
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0, PATTERN 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0,
@ -27,4 +27,4 @@ BEGIN_DELTIMES
DELTIME 11025 DELTIME 11025
END_DELTIMES END_DELTIMES
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,7 +1,7 @@
%define BPM 100 %define BPM 100
%define INCLUDE_DELAY_MODULATION %define INCLUDE_DELAY_MODULATION
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 80, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0 PATTERN 80, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0
@ -28,4 +28,4 @@ BEGIN_DELTIMES
DELTIME 1000 DELTIME 1000
END_DELTIMES END_DELTIMES
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0, PATTERN 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0,
@ -31,4 +31,4 @@ BEGIN_DELTIMES
DELTIME 10787 DELTIME 10787
END_DELTIMES END_DELTIMES
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0, PATTERN 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0,
@ -27,4 +27,4 @@ BEGIN_DELTIMES
DELTIME 11025 DELTIME 11025
END_DELTIMES END_DELTIMES
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0, PATTERN 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0,
@ -25,4 +25,4 @@ BEGIN_DELTIMES
DELTIME 1116,1188,1276,1356,1422,1492,1556,1618 DELTIME 1116,1188,1276,1356,1422,1492,1556,1618
END_DELTIMES END_DELTIMES
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0, PATTERN 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0,
@ -26,4 +26,4 @@ BEGIN_DELTIMES
DELTIME 21025 DELTIME 21025
END_DELTIMES END_DELTIMES
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0 PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0
@ -20,4 +20,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0 PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0
@ -23,4 +23,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0 PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0
@ -18,4 +18,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0 PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0
@ -18,4 +18,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD,HLD, HLD, HLD, 0, 0, 0, 0, 0, PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD,HLD, HLD, HLD, 0, 0, 0, 0, 0,
@ -24,4 +24,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0 PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0
@ -17,4 +17,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0, PATTERN 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0,
@ -21,4 +21,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0, PATTERN 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0,
@ -23,4 +23,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0, PATTERN 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0,
@ -21,4 +21,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0, PATTERN 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0,
@ -21,4 +21,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0, PATTERN 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0,
@ -21,4 +21,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0, PATTERN 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0,
@ -23,4 +23,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0, PATTERN 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0,
@ -21,4 +21,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0 PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0
@ -19,4 +19,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0 PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0
@ -20,4 +20,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0 PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0
@ -20,4 +20,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0 PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0
@ -23,4 +23,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0 PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0
@ -19,4 +19,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0 PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0
@ -24,4 +24,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0 PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0
@ -23,4 +23,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0 PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0
@ -20,4 +20,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0 PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0
@ -19,4 +19,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0 PATTERN 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0
@ -18,4 +18,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0 PATTERN 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0
@ -17,4 +17,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0 PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0
@ -18,4 +18,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0 PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0
@ -17,4 +17,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0 PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0
@ -19,4 +19,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0 PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0
@ -24,4 +24,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0 PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0
@ -22,4 +22,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0 PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0
@ -21,4 +21,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64,HLD,HLD,HLD,HLD,HLD,HLD,HLD, 0, 0, 0,0,0,0,0,0, PATTERN 64,HLD,HLD,HLD,HLD,HLD,HLD,HLD, 0, 0, 0,0,0,0,0,0,
@ -25,4 +25,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0, PATTERN 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0,
@ -22,4 +22,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0, PATTERN 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0,
@ -20,4 +20,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 80, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0 PATTERN 80, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0
@ -22,4 +22,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 80, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0 PATTERN 80, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0
@ -22,4 +22,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 80, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0 PATTERN 80, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0
@ -22,4 +22,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0, PATTERN 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0,
@ -21,4 +21,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0, PATTERN 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0,
@ -21,4 +21,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 80, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0 PATTERN 80, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0
@ -22,4 +22,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0, PATTERN 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0,
@ -21,4 +21,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 0,0,0,0,0,0,0,0, PATTERN 0,0,0,0,0,0,0,0,
@ -39,4 +39,4 @@ BEGIN_SAMPLE_OFFSETS
SAMPLE_OFFSET START(1680142),LOOPSTART(1483),LOOPLENGTH(95) ; name VIOLN70, unitynote 58 (transpose to 2), data length 1579 SAMPLE_OFFSET START(1680142),LOOPSTART(1483),LOOPLENGTH(95) ; name VIOLN70, unitynote 58 (transpose to 2), data length 1579
END_SAMPLE_OFFSETS END_SAMPLE_OFFSETS
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 0,0,0,0,0,0,0,0, PATTERN 0,0,0,0,0,0,0,0,
@ -36,4 +36,4 @@ BEGIN_SAMPLE_OFFSETS
SAMPLE_OFFSET START(1678611),LOOPSTART(1341),LOOPLENGTH(106) ; name VIOLN68, unitynote 56 (transpose to 4), data length 1448 SAMPLE_OFFSET START(1678611),LOOPSTART(1341),LOOPLENGTH(106) ; name VIOLN68, unitynote 56 (transpose to 4), data length 1448
END_SAMPLE_OFFSETS END_SAMPLE_OFFSETS
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 80, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0 PATTERN 80, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0
@ -22,4 +22,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0, PATTERN 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0,
@ -21,4 +21,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0, PATTERN 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0,
@ -20,4 +20,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 80, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0 PATTERN 80, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0
@ -22,4 +22,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0, PATTERN 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0,
@ -21,4 +21,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0, PATTERN 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0,
@ -20,4 +20,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0, PATTERN 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0,
@ -19,4 +19,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0 PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0
@ -23,4 +23,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0 PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0
@ -24,4 +24,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

View File

@ -1,6 +1,6 @@
%define BPM 100 %define BPM 100
%include "../src/sointu_header.inc" %include "sointu_header.inc"
BEGIN_PATTERNS BEGIN_PATTERNS
PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0 PATTERN 64, HLD, HLD, HLD, HLD, HLD, HLD, HLD, 0, 0, 0, 0, 0, 0, 0, 0
@ -18,4 +18,4 @@ BEGIN_PATCH
END_INSTRUMENT END_INSTRUMENT
END_PATCH END_PATCH
%include "../src/sointu_footer.inc" %include "sointu_footer.inc"

Some files were not shown because too many files have changed in this diff Show More