Skip to main content
Glama
emicklei

melrōse musical expression player

by emicklei
scale.go2.22 kB
package core import ( "fmt" "strings" "github.com/emicklei/melrose/notify" ) var _ Replaceable = Scale{} var _ Storable = Scale{} var _ Sequenceable = Scale{} type Scale struct { start Note variant int // https://en.wikipedia.org/wiki/Scale_(music)#Scales,_steps,_and_intervals scaleType string repeated int // default = 0 } func (s Scale) Storex() string { if s.repeated > 1 { return fmt.Sprintf("scale('%s %s',%d)", s.scaleType, s.start.String(), s.repeated) } return fmt.Sprintf("scale('%s %s')", s.scaleType, s.start.String()) } // Replaced is part of Replaceable func (s Scale) Replaced(from, to Sequenceable) Sequenceable { if IsIdenticalTo(from, s) { return to } return s } func NewScale(input string) (Scale, error) { s, err := ParseScale(input) if err != nil { return s, err } s.repeated = 1 return s, nil } func ParseScale(s string) (Scale, error) { style := "major" // Ionian mode tokens := strings.Split(s, " ") if len(tokens) == 2 { style = tokens[0] s = tokens[1] } parts := strings.Split(s, "/") n, err := ParseNote(parts[0]) v := Major if len(parts) == 2 && parts[1] == "m" { v = Minor } return Scale{start: n, variant: v, scaleType: style, repeated: 1}, err } var ( majorScale = [7]int{0, 2, 4, 5, 7, 9, 11} naturalMinorScale = [7]int{0, 1, 3, 5, 7, 8, 10} romans = [7]int{Major, Minor, Minor, Major, Major, Minor, Major} ) // ChordAt uses one-based index func (s Scale) ChordAt(index int) Chord { if index < 1 || index > 7 { notify.Warnf("invalid index for ChordAt, got %d", index) return zeroChord() } if s.variant == Major { offset := majorScale[index-1] return Chord{start: s.start.Pitched(offset), inversion: Ground, interval: Triad, quality: romans[index-1]} } // TODO return zeroChord() } func (s Scale) WithRepeated(times int) Scale { return Scale{start: s.start, repeated: times, variant: s.variant, scaleType: s.scaleType} } func (s Scale) S() Sequence { notes := []Note{} steps := majorScale if s.variant == Minor { steps = naturalMinorScale } for o := range s.repeated { for _, p := range steps { notes = append(notes, s.start.Pitched(p).Octaved(o)) } } return BuildSequence(notes) }

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