mirror of
https://github.com/alda-lang/alda.git
synced 2026-02-27 18:24:13 +01:00
87 lines
2.2 KiB
Go
87 lines
2.2 KiB
Go
package model
|
|
|
|
import (
|
|
"alda.io/client/json"
|
|
"github.com/mohae/deepcopy"
|
|
)
|
|
|
|
// A Repeat expression repeats an event a number of times.
|
|
type Repeat struct {
|
|
SourceContext AldaSourceContext
|
|
Event ScoreUpdate
|
|
Times int32
|
|
}
|
|
|
|
// GetSourceContext implements HasSourceContext.GetSourceContext.
|
|
func (repeat Repeat) GetSourceContext() AldaSourceContext {
|
|
return repeat.SourceContext
|
|
}
|
|
|
|
// JSON implements RepresentableAsJSON.JSON.
|
|
func (repeat Repeat) JSON() *json.Container {
|
|
return json.Object(
|
|
"type", "repeat",
|
|
"value", json.Object(
|
|
"event", repeat.Event.JSON(),
|
|
"times", repeat.Times,
|
|
),
|
|
)
|
|
}
|
|
|
|
// UpdateScore implements ScoreUpdate.UpdateScore by repeatedly updating the
|
|
// score with an event a specified number of times.
|
|
func (repeat Repeat) UpdateScore(score *Score) error {
|
|
previousRepetitions := make([]int32, len(score.CurrentParts))
|
|
|
|
for i, part := range score.CurrentParts {
|
|
previousRepetitions[i] = part.currentRepetition
|
|
}
|
|
|
|
for repetition := int32(1); repetition <= repeat.Times; repetition++ {
|
|
for _, part := range score.CurrentParts {
|
|
part.currentRepetition = repetition
|
|
}
|
|
|
|
if err := score.Update(repeat.Event); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
for i, part := range score.CurrentParts {
|
|
part.currentRepetition = previousRepetitions[i]
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// DurationMs implements ScoreUpdate.DurationMs by returning the total duration
|
|
// of the event being repeated the specified number of times.
|
|
func (repeat Repeat) DurationMs(part *Part) float64 {
|
|
durationMs := 0.0
|
|
previousRepetition := part.currentRepetition
|
|
|
|
for repetition := int32(1); repetition <= repeat.Times; repetition++ {
|
|
part.currentRepetition = repetition
|
|
durationMs += repeat.Event.DurationMs(part)
|
|
}
|
|
|
|
part.currentRepetition = previousRepetition
|
|
return durationMs
|
|
}
|
|
|
|
// VariableValue implements ScoreUpdate.VariableValue by returning a version of
|
|
// the repeat where the value of the event to be repeated is captured.
|
|
func (repeat Repeat) VariableValue(score *Score) (ScoreUpdate, error) {
|
|
result := deepcopy.Copy(repeat).(Repeat)
|
|
|
|
eventValue, err := repeat.Event.VariableValue(score)
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
result.Event = eventValue
|
|
|
|
return result, nil
|
|
}
|