Skip to main content
Glama
emicklei

melrōse musical expression player

by emicklei
language_test.go7.18 kB
package dsl import ( "os" "testing" "github.com/emicklei/melrose/core" ) func TestStatementSeparator(t *testing.T) { t.Skip() r := eval(t, "a=note('c');b=note('d');a") checkStorex(t, r, "note('C')") checkStorex(t, r.(core.Sequenceable).S(), "sequence('C')") } func TestNote(t *testing.T) { r := eval(t, "note('c')") checkStorex(t, r, "note('C')") checkStorex(t, r.(core.Sequenceable).S(), "sequence('C')") } func TestNoteUsingB(t *testing.T) { r := eval(t, "note('cb')") checkStorex(t, r, "note('C_')") } func TestNote_Invalid(t *testing.T) { mustError(t, "note('k')", "illegal note") } func TestChord(t *testing.T) { r := eval(t, "chord('C#/m')") checkStorex(t, r, "chord('C#/m')") checkStorex(t, r.(core.Sequenceable).S(), "sequence('(C# E A_)')") } func TestChord_Invalid(t *testing.T) { mustError(t, "chord('k')", "illegal note") } func TestSequence(t *testing.T) { r := eval(t, "sequence('c (d e g) =')") checkStorex(t, r, "sequence('C (D E G) =')") } func TestSequence_Invalid(t *testing.T) { mustError(t, "sequence('k')", "illegal note") } func TestProgression(t *testing.T) { r := eval(t, "chordsequence('c/m (d7 e g) =')") checkStorex(t, r, "chordsequence('C/m (D7 E G) =')") checkStorex(t, r.(core.Sequenceable).S(), "sequence('(C E_ G) (D7 G_7 A7 E A_ B G B D5) =')") } func TestChordSequence_Invalid(t *testing.T) { mustError(t, "chordsequence('k')", "illegal note") } func TestScale(t *testing.T) { r := eval(t, "scale('16e2')") checkStorex(t, r, "scale('major 16E2')") checkStorex(t, r.(core.Sequenceable).S(), "sequence('16E2 16G_2 16A_2 16A2 16B2 16D_3 16E_3')") } func TestScaleRepeated(t *testing.T) { r := eval(t, "scale('16e2',2)") checkStorex(t, r, "scale('major 16E2',2)") checkStorex(t, r.(core.Sequenceable).S(), "sequence('16E2 16G_2 16A_2 16A2 16B2 16D_3 16E_3 16E3 16G_3 16A_3 16A3 16B3 16D_ 16E_')") } func TestTranspose_ChordSequence(t *testing.T) { r := eval(t, "transpose(1,chordsequence('c/m (d7 e g) ='))") checkStorex(t, r, "transpose(1,chordsequence('C/m (D7 E G) ='))") checkStorex(t, r.(core.Sequenceable).S(), "sequence('(D_ E A_) (E_7 G7 B_7 F A C5 A_ C5 E_5) =')") } func TestTrack(t *testing.T) { r := eval(t, "track('test',1,onbar(1,note('c')))") checkStorex(t, r, "track('test',1,onbar(1,note('C')))") } func TestChannelSelector(t *testing.T) { r := eval(t, "channel(1,note('f'))") checkStorex(t, r, "channel(1,note('F'))") } func TestDeviceSelector(t *testing.T) { r := eval(t, "device(1,note('f'))") checkStorex(t, r, "device(1,note('F'))") } func TestBars(t *testing.T) { r := eval(t, "bars(sequence('a b c d'))") if got, want := r.(int), 1; got != want { t.Errorf("got [%v:%T] want [%v:%T]", got, got, want, want) } } func TestBars_Arithmetic(t *testing.T) { r := eval(t, "1+bars(sequence('a b c d'))") if got, want := r.(core.HasValue).Value(), 2; got != want { t.Errorf("got [%v:%T] want [%v:%T]", got, got, want, want) } } func TestNotemapNumbers(t *testing.T) { r := eval(t, "notemap('2 4 11',note('c'))") checkStorex(t, r, "notemap('2 4 11',note('C'))") checkStorex(t, r.(core.Sequenceable).S(), "sequence('= C = C = = = = = = C')") } func TestTwoBarsNote(t *testing.T) { r := eval(t, "stretch(2,note('1c'))") checkStorex(t, r, "stretch(2,note('1C'))") s := r.(core.Sequenceable).S() n := s.At(0)[0] if got, want := n.DurationFactor(), float32(2.0); got != want { t.Errorf("got [%v:%T] want [%v:%T]", got, got, want, want) } } func TestStretchChord(t *testing.T) { r := eval(t, "stretch(2,chord('1c'))") checkStorex(t, r, "stretch(2,chord('1C'))") s := r.(core.Sequenceable).S() n := s.At(0)[0] if got, want := n.DurationFactor(), float32(2.0); got != want { t.Errorf("got [%v:%T] want [%v:%T]", got, got, want, want) } } func TestChordSequenceWithSustain(t *testing.T) { r := eval(t, "chordsequence('> 1g/m/2 ^ 1d5 <')") checkStorex(t, r, "chordsequence('> 1G/m/2 ^ 1D5 <')") checkStorex(t, r.(core.Sequenceable).S(), "sequence('> (1D5 1G5 1B_5) ^ (1D5 1G_5 1A5) <')") } func TestNotemapDots(t *testing.T) { r := eval(t, "notemap('.!.!',note('16c'))") checkStorex(t, r, "notemap('.!.!',note('16C'))") checkStorex(t, r.(core.Sequenceable).S(), "sequence('16= 16C 16= 16C')") } func TestNotemapSequence(t *testing.T) { r := eval(t, "notemap('.!.!',sequence('16c A'))") checkStorex(t, r, "notemap('.!.!',sequence('16C A'))") checkStorex(t, r.(core.Sequenceable).S(), "sequence('16= 16C 16= 16C')") } func TestSequenceMapFromStringIterator(t *testing.T) { r := eval(t, `ar = iterator('1','2') sm = resequence(ar,sequence('c d'))`) checkStorex(t, r, "resequence(ar,sequence('C D'))") checkStorex(t, r.(core.Sequenceable).S(), "sequence('C')") } func TestDeviceOnChannelOnNote(t *testing.T) { r := eval(t, `d = device(1,channel(2,note('e')))`) checkStorex(t, r.(core.Sequenceable).S(), "sequence('E')") } func TestDynamicMapWithTwoSequenceables(t *testing.T) { r := eval(t, `s = sequence('c e g') t = note('b') dm = dynamicmap(' 1:+ , 2:-- ,3:o,4:o',s,t)`) checkStorex(t, r, "dynamicmap('1:+,2:--,3:o,4:o',s,t)") checkStorex(t, r.(core.Sequenceable).S(), "sequence('C+ E-- G B')") } func TestDynamic_String(t *testing.T) { r := eval(t, `d = dynamic('+',note('c'))`) checkStorex(t, r, "dynamic('+',note('C'))") } func TestDynamic_Number(t *testing.T) { r := eval(t, `d = dynamic(55,note('c'))`) checkStorex(t, r, "dynamic(55,note('C'))") } func TestDynamic_Var(t *testing.T) { r := eval(t, `v = 55 d = dynamic(v,note('c'))`) checkStorex(t, r, "dynamic(v,note('C'))") } func TestProcessLanguageTest(t *testing.T) { src, _ := os.ReadFile("language_test.mel") defer func() { if err := recover(); err != nil { t.Fatal("panic recovered:", err) } }() eval(t, string(src)) } func TestVelocityMap(t *testing.T) { r := eval(t, "velocitymap('1:30,2:60,2:0',sequence('c g'))") checkStorex(t, r, "velocitymap('1:30,2:60,2:0',sequence('C G'))") checkStorex(t, r.(core.Sequenceable).S(), "sequence('C--- G+ G')") } func TestValueOfVar(t *testing.T) { r := eval(t, ` i = iterator(1) v = value(i)`) checkStorex(t, r, "value(i)") if got, want := core.ValueOf(r), 1; got != want { t.Errorf("got [%v:%T] want [%v:%T]", got, got, want, want) } } func TestDeviceOnTrack(t *testing.T) { t.Skip() // TODO r := eval(t, ` s = sequence('a b') dt = device(1,track('title',4, onbar(1,s)))`) checkStorex(t, r, "value(i)") } func TestIteratorIndex(t *testing.T) { r := eval(t, `it = iterator(1,2,3) idx = it.Index()`) checkStorex(t, r, "it.Index()") } func TestTempo(t *testing.T) { r := eval(t, `t = tempo(120)`) checkStorex(t, r, "bpm(120)") } func TestDeviceChannelNote(t *testing.T) { r := eval(t, `d = device(1,channel(2,note('c')))`) checkStorex(t, r, "device(1,channel(2,note('C')))") } func TestChannelDeviceNote(t *testing.T) { mustError(t, `channel(1,device(2,note('c')))`, "swap") } func TestPlayDeviceChannelNote(t *testing.T) { r := eval(t, `p = play(device(1,channel(2,note('c'))))`) checkStorex(t, r, "play(device(1,channel(2,note('C'))))") } func TestIfCondition(t *testing.T) { r := eval(t, `when(true,note("="))`) checkStorex(t, r, `when(true,note('='))`) }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/emicklei/melrose'

If you have feedback or need assistance with the MCP directory API, please join our Discord server