mirror of
https://github.com/vsariola/sointu.git
synced 2025-05-28 03:10:24 -04:00
46 lines
1.4 KiB
Go
46 lines
1.4 KiB
Go
package sointu
|
|
|
|
import (
|
|
"errors"
|
|
)
|
|
|
|
// Song includes a Score(the arrangement of notes in the song in one or more
|
|
// tracks) and a Patch (the list of one or more instruments). Additionally, BPM
|
|
// and RowsPerBeat fields set how fast the song should be played. Currently, BPM
|
|
// is an integer as it offers already quite much granularity for controlling the
|
|
// playback speed, but this could be changed to a floating point in future if
|
|
// finer adjustments are necessary.
|
|
type Song struct {
|
|
BPM int
|
|
RowsPerBeat int
|
|
Score Score
|
|
Patch Patch
|
|
}
|
|
|
|
// Copy makes a deep copy of a Score.
|
|
func (s *Song) Copy() Song {
|
|
return Song{BPM: s.BPM, RowsPerBeat: s.RowsPerBeat, Score: s.Score.Copy(), Patch: s.Patch.Copy()}
|
|
}
|
|
|
|
// Assuming 44100 Hz playback speed, return the number of samples of each row of
|
|
// the song.
|
|
func (s *Song) SamplesPerRow() int {
|
|
return 44100 * 60 / (s.BPM * s.RowsPerBeat)
|
|
}
|
|
|
|
// Validate checks if the Song looks like a valid song: BPM > 0, one or more
|
|
// tracks, score uses less than or equal number of voices than patch. Not used
|
|
// much so we could probably get rid of this function.
|
|
func (s *Song) Validate() error {
|
|
if s.BPM < 1 {
|
|
return errors.New("BPM should be > 0")
|
|
}
|
|
if len(s.Score.Tracks) == 0 {
|
|
return errors.New("song contains no tracks")
|
|
}
|
|
if s.Score.NumVoices() > s.Patch.NumVoices() {
|
|
return errors.New("Tracks use too many voices")
|
|
}
|
|
return nil
|
|
}
|