Skip to main content
Glama
emicklei

melrōse musical expression player

by emicklei
dynamic_map.go2.52 kB
package op import ( "bytes" "fmt" "strconv" "strings" "github.com/emicklei/melrose/core" ) type DynamicMap struct { Target []core.Sequenceable IndexDynamics []index2dynamic } type index2dynamic struct { at int // at is one-based dynamic string } func NewDynamicMap(slist []core.Sequenceable, dynamics string) (DynamicMap, error) { id, err := parseIndex2Dynamics(dynamics) dm := DynamicMap{Target: slist, IndexDynamics: id} if err != nil { return dm, err } return dm, nil } func (d DynamicMap) S() core.Sequence { target := [][]core.Note{} source := Join{Target: d.Target}.S().Notes for _, entry := range d.IndexDynamics { if entry.at <= 0 || entry.at > len(source) { // invalid offset, skip continue } eachGroup := source[entry.at-1] // at is one-based newGroup := []core.Note{} for _, eachNote := range eachGroup { newGroup = append(newGroup, eachNote.WithVelocity(core.ParseVelocity(entry.dynamic))) } target = append(target, newGroup) } return core.Sequence{Notes: target} } func (d DynamicMap) Storex() string { var b bytes.Buffer fmt.Fprintf(&b, "dynamicmap('%s'", formatIndex2Dynamics(d.IndexDynamics)) core.AppendStorexList(&b, false, d.Target) fmt.Fprintf(&b, ")") return b.String() } // "1:++,2:--" func parseIndex2Dynamics(s string) (list []index2dynamic, err error) { entries := strings.Split(s, ",") for _, each := range entries { kv := strings.Split(strings.TrimSpace(each), ":") if len(kv) != 2 { return list, fmt.Errorf("bad pair syntax [%s], expected [<positive int>:<dynamic>]", each) } ik, err := strconv.Atoi(kv[0]) if err != nil || ik < 1 { // silent ignore error TODO return list, fmt.Errorf("bad number syntax [%s], expected [<positive int>:<dynamic>]", each) } dynamic := strings.TrimSpace(kv[1]) if core.ParseVelocity(dynamic) == -1 { return list, fmt.Errorf("bad dynamic syntax [%s], expected [<positive int>:<dynamic>]", each) } list = append(list, index2dynamic{at: ik, dynamic: dynamic}) } return } // "1:++,2:--" func formatIndex2Dynamics(list []index2dynamic) string { var b bytes.Buffer for i, each := range list { if i > 0 { fmt.Fprintf(&b, ",") } fmt.Fprintf(&b, "%d:%s", each.at, each.dynamic) } return b.String() } // Replaced is part of Replaceable func (d DynamicMap) Replaced(from, to core.Sequenceable) core.Sequenceable { if core.IsIdenticalTo(d, from) { return to } return DynamicMap{Target: replacedAll(d.Target, from, to), IndexDynamics: d.IndexDynamics} }

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