mirror of
https://github.com/vsariola/sointu.git
synced 2025-05-27 10:50:23 -04:00
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:
parent
23e8bc0c5f
commit
e0a793ea6d
@ -30,8 +30,17 @@ enable_language(ASM_NASM)
|
||||
# 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>")
|
||||
|
||||
# The compiled VSTi is here
|
||||
add_subdirectory(src)
|
||||
# Sointu as a header-only library
|
||||
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
|
||||
# add_subdirectory(examples)
|
||||
|
191
bridge/bridge.go
191
bridge/bridge.go
@ -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
148
go4k/bridge/bridge.go
Normal 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
|
||||
}
|
@ -8,7 +8,8 @@ import (
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"github.com/vsariola/sointu/bridge"
|
||||
"github.com/vsariola/sointu/go4k"
|
||||
"github.com/vsariola/sointu/go4k/bridge"
|
||||
)
|
||||
|
||||
const BPM = 100
|
||||
@ -21,30 +22,29 @@ const su_max_samples = SAMPLES_PER_ROW * TOTAL_ROWS
|
||||
// const bufsize = su_max_samples * 2
|
||||
|
||||
func TestBridge(t *testing.T) {
|
||||
patch := []bridge.Instrument{
|
||||
bridge.Instrument{1, []bridge.Unit{
|
||||
bridge.Unit{bridge.Envelope, []byte{64, 64, 64, 80, 128}},
|
||||
bridge.Unit{bridge.Envelope, []byte{95, 64, 64, 80, 128}},
|
||||
bridge.Unit{bridge.Out.Stereo(), []byte{128}},
|
||||
patch := []go4k.Instrument{
|
||||
go4k.Instrument{1, []go4k.Unit{
|
||||
go4k.Unit{"envelope", false, map[string]int{"attack": 64, "decay": 64, "sustain": 64, "release": 80, "gain": 128}},
|
||||
go4k.Unit{"envelope", false, map[string]int{"attack": 95, "decay": 64, "sustain": 64, "release": 80, "gain": 128}},
|
||||
go4k.Unit{"out", true, map[string]int{"gain": 128}},
|
||||
}}}
|
||||
synth, err := bridge.Compile(patch)
|
||||
synth, err := bridge.Synth(patch)
|
||||
if err != nil {
|
||||
t.Fatalf("bridge compile error: %v", err)
|
||||
}
|
||||
var state bridge.SynthState
|
||||
state.Trigger(0, 64)
|
||||
synth.Trigger(0, 64)
|
||||
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 {
|
||||
t.Fatalf("first render gave an error")
|
||||
}
|
||||
state.Release(0)
|
||||
err = synth.Render(&state, buffer[len(buffer)/2:])
|
||||
synth.Release(0)
|
||||
err = go4k.Render(synth, buffer[len(buffer)/2:])
|
||||
if err != nil {
|
||||
t.Fatalf("first render gave an error")
|
||||
}
|
||||
_, 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 {
|
||||
t.Fatalf("cannot read expected: %v", err)
|
||||
}
|
49
go4k/go4k.go
Normal file
49
go4k/go4k.go
Normal 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
|
||||
}
|
@ -1,38 +1,41 @@
|
||||
package song
|
||||
package go4k
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/vsariola/sointu/bridge"
|
||||
)
|
||||
|
||||
type Track struct {
|
||||
NumVoices int
|
||||
Sequence []byte
|
||||
}
|
||||
import "errors"
|
||||
|
||||
type Song struct {
|
||||
BPM int
|
||||
Patterns [][]byte
|
||||
Tracks []Track
|
||||
Patch bridge.Patch
|
||||
Samples int // -1 means calculate automatically, but you can also set it manually
|
||||
BPM int
|
||||
Patterns [][]byte
|
||||
Tracks []Track
|
||||
SongLength int // in samples, 0 means calculate automatically from BPM and Track lengths, but can also set manually
|
||||
Patch Patch
|
||||
}
|
||||
|
||||
func NewSong(bpm int, patterns [][]byte, tracks []Track, patch bridge.Patch) (*Song, error) {
|
||||
s := new(Song)
|
||||
s.BPM = bpm
|
||||
s.Patterns = patterns
|
||||
s.Tracks = tracks
|
||||
s.Patch = patch
|
||||
err := s.Validate()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
func (s *Song) PatternRows() int {
|
||||
return len(s.Patterns[0])
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
s.Samples = -1
|
||||
return s, nil
|
||||
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")
|
||||
@ -62,66 +65,42 @@ func (s *Song) Validate() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Song) PatternRows() int {
|
||||
return len(s.Patterns[0])
|
||||
}
|
||||
|
||||
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()
|
||||
func Play(synth Synth, song Song) ([]float32, error) {
|
||||
err := song.Validate()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
curVoices := make([]int, len(s.Tracks))
|
||||
curVoices := make([]int, len(song.Tracks))
|
||||
for i := range curVoices {
|
||||
curVoices[i] = s.FirstTrackVoice(i)
|
||||
curVoices[i] = song.FirstTrackVoice(i)
|
||||
}
|
||||
samples := s.Samples
|
||||
if samples < 0 {
|
||||
samples = s.TotalRows() * s.SamplesPerRow()
|
||||
samples := song.SongLength
|
||||
if samples <= 0 {
|
||||
samples = song.TotalRows() * song.SamplesPerRow()
|
||||
}
|
||||
buffer := make([]float32, samples*2)
|
||||
totaln := 0
|
||||
rowtime := 44100 * 60 / (s.BPM * 4)
|
||||
for row := 0; row < s.TotalRows(); row++ {
|
||||
patternRow := row % s.PatternRows()
|
||||
pattern := row / s.PatternRows()
|
||||
for t := range s.Tracks {
|
||||
patternIndex := s.Tracks[t].Sequence[pattern]
|
||||
note := s.Patterns[patternIndex][patternRow]
|
||||
rowtime := song.SamplesPerRow()
|
||||
for row := 0; row < song.TotalRows(); row++ {
|
||||
patternRow := row % song.PatternRows()
|
||||
pattern := row / song.PatternRows()
|
||||
for t := range song.Tracks {
|
||||
patternIndex := song.Tracks[t].Sequence[pattern]
|
||||
note := song.Patterns[patternIndex][patternRow]
|
||||
if note == 1 { // anything but hold causes an action.
|
||||
continue // TODO: can hold be actually something else than 1?
|
||||
}
|
||||
state.Release(curVoices[t])
|
||||
synth.Release(curVoices[t])
|
||||
if note > 1 {
|
||||
curVoices[t]++
|
||||
first := s.FirstTrackVoice(t)
|
||||
if curVoices[t] >= first+s.Tracks[t].NumVoices {
|
||||
first := song.FirstTrackVoice(t)
|
||||
if curVoices[t] >= first+song.Tracks[t].NumVoices {
|
||||
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
|
||||
}
|
||||
return buffer, nil
|
@ -1,4 +1,4 @@
|
||||
package song_test
|
||||
package go4k_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@ -8,8 +8,9 @@ import (
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"github.com/vsariola/sointu/bridge"
|
||||
"github.com/vsariola/sointu/song"
|
||||
"github.com/vsariola/sointu/go4k"
|
||||
"github.com/vsariola/sointu/go4k/bridge"
|
||||
// TODO: test the song using a mocks instead
|
||||
)
|
||||
|
||||
const BPM = 100
|
||||
@ -21,29 +22,24 @@ const su_max_samples = SAMPLES_PER_ROW * TOTAL_ROWS
|
||||
|
||||
// const bufsize = su_max_samples * 2
|
||||
|
||||
func TestSongRender(t *testing.T) {
|
||||
patch := []bridge.Instrument{
|
||||
bridge.Instrument{1, []bridge.Unit{
|
||||
bridge.Unit{bridge.Envelope, []byte{32, 32, 64, 64, 128}},
|
||||
bridge.Unit{bridge.Oscillat, []byte{64, 64, 0, 96, 64, 128, 0x40}},
|
||||
bridge.Unit{bridge.Mulp, []byte{}},
|
||||
bridge.Unit{bridge.Envelope, []byte{32, 32, 64, 64, 128}},
|
||||
bridge.Unit{bridge.Oscillat, []byte{72, 64, 64, 64, 96, 128, 0x40}},
|
||||
bridge.Unit{bridge.Mulp, []byte{}},
|
||||
bridge.Unit{bridge.Out.Stereo(), []byte{128}},
|
||||
}}}
|
||||
func TestPlayer(t *testing.T) {
|
||||
patch := go4k.Patch{go4k.Instrument{1, []go4k.Unit{
|
||||
go4k.Unit{"envelope", false, map[string]int{"attack": 32, "decay": 32, "sustain": 64, "release": 64, "gain": 128}},
|
||||
go4k.Unit{"oscillator", false, map[string]int{"transpose": 64, "detune": 64, "phase": 0, "color": 96, "shape": 64, "gain": 128, "flags": 0x40}},
|
||||
go4k.Unit{"mulp", false, map[string]int{}},
|
||||
go4k.Unit{"envelope", false, map[string]int{"attack": 32, "decay": 32, "sustain": 64, "release": 64, "gain": 128}},
|
||||
go4k.Unit{"oscillator", false, map[string]int{"transpose": 72, "detune": 64, "phase": 64, "color": 64, "shape": 96, "gain": 128, "flags": 0x40}},
|
||||
go4k.Unit{"mulp", false, map[string]int{}},
|
||||
go4k.Unit{"out", true, map[string]int{"gain": 128}},
|
||||
}}}
|
||||
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}}}
|
||||
song, err := song.NewSong(100, patterns, tracks, patch)
|
||||
if err != nil {
|
||||
t.Fatalf("NewSong failed: %v", err)
|
||||
}
|
||||
synth, err := bridge.Compile(patch)
|
||||
tracks := []go4k.Track{go4k.Track{1, []byte{0}}}
|
||||
song := go4k.Song{100, patterns, tracks, 0, patch}
|
||||
synth, err := bridge.Synth(patch)
|
||||
if err != nil {
|
||||
t.Fatalf("Compiling patch failed: %v", err)
|
||||
}
|
||||
var state bridge.SynthState
|
||||
buffer, err := song.Render(synth, &state)
|
||||
buffer, err := go4k.Play(synth, song)
|
||||
if err != nil {
|
||||
t.Fatalf("Render failed: %v", err)
|
||||
}
|
@ -30,14 +30,11 @@ typedef struct SynthWorkspace {
|
||||
struct Voice Voices[32];
|
||||
} SynthWorkspace;
|
||||
|
||||
typedef struct SynthState {
|
||||
typedef struct Synth {
|
||||
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.
|
||||
unsigned int RandSeed;
|
||||
unsigned int GlobalTick;
|
||||
} SynthState;
|
||||
|
||||
typedef struct Synth {
|
||||
unsigned char Commands[32 * 64];
|
||||
unsigned char Values[32 * 64 * 8];
|
||||
unsigned int Polyphony;
|
||||
@ -59,35 +56,14 @@ typedef struct Synth {
|
||||
extern void CALLCONV su_load_gmdls(void);
|
||||
#endif
|
||||
|
||||
// int su_render(Synth* synth,SynthState* synthState, float* buffer, int samples):
|
||||
// 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):
|
||||
// int su_render(Synth* synth, float* buffer, int* samples, int* time):
|
||||
// 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
|
||||
// are passed by reference as the function modifies to tell how many samples were
|
||||
// actually rendered and how many time ticks were actually advanced.
|
||||
//
|
||||
// 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
|
||||
// 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.
|
||||
// synth pointer to the synthesizer used. RandSeed should be > 0 e.g. 1
|
||||
// buffer audio sample buffer, L R L R ...
|
||||
// samples pointer to the maximum number of samples to be rendered.
|
||||
// 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:
|
||||
// 0 everything ok
|
||||
// (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
|
||||
extern const int su_add_id;
|
@ -25,14 +25,11 @@ USE_OUT
|
||||
|
||||
section .text
|
||||
|
||||
struc su_synth_state
|
||||
struc su_synth
|
||||
.synthwrk resb su_synthworkspace.size
|
||||
.delaywrks resb su_delayline_wrk.size * 64
|
||||
.randseed resd 1
|
||||
.globaltime resd 1
|
||||
endstruc
|
||||
|
||||
struc su_synth
|
||||
.globaltime resd 1
|
||||
.commands resb 32 * 64
|
||||
.values resb 32 * 64 * 8
|
||||
.polyphony resd 1
|
||||
@ -41,35 +38,25 @@ endstruc
|
||||
|
||||
SECT_TEXT(sursampl)
|
||||
|
||||
EXPORT MANGLE_FUNC(su_render_time,20)
|
||||
EXPORT MANGLE_FUNC(su_render,16)
|
||||
%if BITS == 32 ; stdcall
|
||||
pushad ; push registers
|
||||
mov eax, [esp + 4 + 32] ; eax = &synth
|
||||
mov ecx, [esp + 8 + 32] ; ecx = &synthState
|
||||
mov edx, [esp + 12 + 32] ; edx = &buffer
|
||||
mov esi, [esp + 16 + 32] ; esi = &samples
|
||||
mov ebx, [esp + 20 + 32] ; ebx = &time
|
||||
pushad ; push registers
|
||||
mov ecx, [esp + 4 + 32] ; ecx = &synthState
|
||||
mov edx, [esp + 8 + 32] ; edx = &buffer
|
||||
mov esi, [esp + 12 + 32] ; esi = &samples
|
||||
mov ebx, [esp + 16 + 32] ; ebx = &time
|
||||
%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 = &bufsize, stack1 = &time
|
||||
%ifidn __OUTPUT_FORMAT__,win64 ; win64 ABI: rcx = &synth, rdx = &buffer, r8 = &bufsize, r9 = &time
|
||||
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 rax, rcx
|
||||
mov rcx, rdx
|
||||
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
|
||||
mov rsi, r8 ; rsi = &samples
|
||||
mov rbx, r9 ; rbx = &time
|
||||
%else ; System V ABI: rdi = &synth, rsi = &buffer, rdx = &samples, rcx = &time
|
||||
push_registers rbx, rbp ; System V ABI: these registers are non-volatile
|
||||
mov rax, rdi
|
||||
mov rbx, r8
|
||||
xchg rcx, rsi
|
||||
mov rbx, rcx ; rbx points to time
|
||||
xchg rsi, rdx ; rdx points to buffer, rsi points to samples
|
||||
mov rcx, rdi ; rcx = &Synthstate
|
||||
%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 _BX ; push the pointer to time
|
||||
xor eax, eax ; samplenumber starts at 0
|
||||
@ -78,9 +65,9 @@ EXPORT MANGLE_FUNC(su_render_time,20)
|
||||
push _SI ; push bufsize
|
||||
push _DX ; push bufptr
|
||||
push _CX ; this takes place of the voicetrack
|
||||
mov eax, [_CX + su_synth_state.randseed]
|
||||
mov eax, [_CX + su_synth.randseed]
|
||||
push _AX ; randseed
|
||||
mov eax, [_CX + su_synth_state.globaltime]
|
||||
mov eax, [_CX + su_synth.globaltime]
|
||||
push _AX ; global tick time
|
||||
mov ebx, dword [_BX] ; zero extend dereferenced pointer
|
||||
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
|
||||
inc eax ; time++
|
||||
inc dword [_SP + PTRSIZE*6] ; samples++
|
||||
mov _CX, [_SP + PTRSIZE*3] ; _CX = &synthstate
|
||||
mov _BP, [_SP + PTRSIZE*9] ; _BP = &synth
|
||||
mov _CX, [_SP + PTRSIZE*3]
|
||||
push _AX ; push rowtick
|
||||
mov eax, [_BP + su_synth.polyphony]
|
||||
mov eax, [_CX + su_synth.polyphony]
|
||||
push _AX ;polyphony
|
||||
mov eax, [_BP + su_synth.numvoices]
|
||||
mov eax, [_CX + su_synth.numvoices]
|
||||
push _AX ;numvoices
|
||||
lea _DX, [_CX + su_synth_state.synthwrk]
|
||||
lea COM, [_BP + su_synth.commands]
|
||||
lea VAL, [_BP + su_synth.values]
|
||||
lea WRK, [_DX + su_synthworkspace.voices] ; _BP and WRK are actually the same thing so here _BP gets overwritten
|
||||
lea _CX, [_CX + su_synth_state.delaywrks - su_delayline_wrk.filtstate]
|
||||
lea _DX, [_CX+ su_synth.synthwrk]
|
||||
lea COM, [_CX+ su_synth.commands]
|
||||
lea VAL, [_CX+ su_synth.values]
|
||||
lea WRK, [_DX + su_synthworkspace.voices]
|
||||
lea _CX, [_CX+ su_synth.delaywrks - su_delayline_wrk.filtstate]
|
||||
call MANGLE_FUNC(su_run_vm,0)
|
||||
pop _AX
|
||||
pop _AX
|
||||
mov _DI, [_SP + PTRSIZE*5] ; edi containts buffer ptr
|
||||
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 right channel to output buffer
|
||||
mov [_SP + PTRSIZE*5], _DI ; save back the updated ptr
|
||||
@ -126,8 +112,8 @@ su_render_samples_time_finish:
|
||||
pop _BX
|
||||
pop _DX
|
||||
pop _CX
|
||||
mov [_CX + su_synth_state.randseed], edx
|
||||
mov [_CX + su_synth_state.globaltime], ebx
|
||||
mov [_CX + su_synth.randseed], edx
|
||||
mov [_CX + su_synth.globaltime], ebx
|
||||
pop _BX
|
||||
pop _BX
|
||||
pop _DX
|
||||
@ -135,12 +121,11 @@ su_render_samples_time_finish:
|
||||
pop _SI ; pop the pointer to samples
|
||||
mov dword [_SI], edx ; *samples = samples 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
|
||||
%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
|
||||
popad
|
||||
ret 20
|
||||
ret 16
|
||||
%else
|
||||
%ifidn __OUTPUT_FORMAT__,win64
|
||||
pop_registers rdi, rsi, rbx, rbp ; win64 ABI: these registers are non-volatile
|
||||
@ -149,45 +134,3 @@ su_render_samples_time_finish:
|
||||
%endif
|
||||
ret
|
||||
%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
|
@ -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)
|
@ -21,6 +21,7 @@ function(regression_test testname)
|
||||
|
||||
add_test(${testname} ${testname})
|
||||
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 (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_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)
|
||||
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)
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_PATCH
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_PATCH
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_PATCH
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_PATCH
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_PATCH
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_PATCH
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_PATCH
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_PATCH
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_PATCH
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_PATCH
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_PATCH
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_PATCH
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_PATCH
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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
|
||||
END_DELTIMES
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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
|
||||
END_DELTIMES
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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
|
||||
END_DELTIMES
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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
|
||||
END_DELTIMES
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,7 +1,7 @@
|
||||
%define BPM 100
|
||||
%define INCLUDE_DELAY_MODULATION
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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
|
||||
END_DELTIMES
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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
|
||||
END_DELTIMES
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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
|
||||
END_DELTIMES
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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
|
||||
END_DELTIMES
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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
|
||||
END_DELTIMES
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_PATCH
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_PATCH
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_PATCH
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_PATCH
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_PATCH
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_PATCH
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_PATCH
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_PATCH
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_PATCH
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_PATCH
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_PATCH
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_PATCH
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_PATCH
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_PATCH
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_PATCH
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_PATCH
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_PATCH
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_PATCH
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_PATCH
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_PATCH
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_PATCH
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_PATCH
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_PATCH
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_PATCH
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_PATCH
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_PATCH
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_PATCH
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_PATCH
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_PATCH
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_PATCH
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_PATCH
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_PATCH
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_PATCH
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_PATCH
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_PATCH
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_PATCH
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_PATCH
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_PATCH
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_PATCH
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_PATCH
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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
|
||||
END_SAMPLE_OFFSETS
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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
|
||||
END_SAMPLE_OFFSETS
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_PATCH
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_PATCH
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_PATCH
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_PATCH
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_PATCH
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_PATCH
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_PATCH
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_PATCH
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_PATCH
|
||||
|
||||
%include "../src/sointu_footer.inc"
|
||||
%include "sointu_footer.inc"
|
||||
|
@ -1,6 +1,6 @@
|
||||
%define BPM 100
|
||||
|
||||
%include "../src/sointu_header.inc"
|
||||
%include "sointu_header.inc"
|
||||
|
||||
BEGIN_PATTERNS
|
||||
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_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
Loading…
Reference in New Issue
Block a user