mirror of
https://github.com/vsariola/sointu.git
synced 2025-07-14 02:54:37 -04:00
feat(sointu): add RowsPerBeat so non-power of 2 beat divisions are easier
This commit is contained in:
@ -15,6 +15,7 @@ var defaultInstrument = sointu.Instrument{
|
||||
var defaultSong = sointu.Song{
|
||||
BPM: 100,
|
||||
RowsPerPattern: 16,
|
||||
RowsPerBeat: 4,
|
||||
Tracks: []sointu.Track{
|
||||
{NumVoices: 2, Sequence: []byte{0, 0, 0, 1}, Patterns: [][]byte{{64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0}, {64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 75, 0, 75, 0, 80, 0}}},
|
||||
{NumVoices: 2, Sequence: []byte{0, 0, 0, 1}, Patterns: [][]byte{{0, 0, 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0}, {32, 0, 64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 68, 0, 68, 0}}},
|
||||
|
@ -110,5 +110,19 @@ func (t *Tracker) layoutSongOptions(gtx C) D {
|
||||
}),
|
||||
)
|
||||
}),
|
||||
layout.Rigid(func(gtx C) D {
|
||||
return layout.Flex{Axis: layout.Horizontal}.Layout(gtx,
|
||||
layout.Rigid(Label("RPB:", white)),
|
||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||
t.RowsPerBeat.Value = t.song.RowsPerBeat
|
||||
numStyle := NumericUpDown(t.Theme, t.RowsPerBeat, 1, 32)
|
||||
gtx.Constraints.Min.Y = gtx.Px(unit.Dp(20))
|
||||
gtx.Constraints.Min.X = gtx.Px(unit.Dp(70))
|
||||
dims := in.Layout(gtx, numStyle.Layout)
|
||||
t.SetRowsPerBeat(t.RowsPerBeat.Value)
|
||||
return dims
|
||||
}),
|
||||
)
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ type Tracker struct {
|
||||
Octave *NumberInput
|
||||
BPM *NumberInput
|
||||
RowsPerPattern *NumberInput
|
||||
RowsPerBeat *NumberInput
|
||||
NewTrackBtn *widget.Clickable
|
||||
NewInstrumentBtn *widget.Clickable
|
||||
DeleteInstrumentBtn *widget.Clickable
|
||||
@ -102,7 +103,7 @@ func (t *Tracker) sequencerLoop(closer <-chan struct{}) {
|
||||
panic("cannot create a synth with the default patch")
|
||||
}
|
||||
curVoices := make([]int, 32)
|
||||
t.sequencer = NewSequencer(synth, 44100*60/(4*t.song.BPM), func() ([]Note, bool) {
|
||||
t.sequencer = NewSequencer(synth, t.song.SamplesPerRow(), func() ([]Note, bool) {
|
||||
t.playRowPatMutex.Lock()
|
||||
if !t.Playing {
|
||||
t.playRowPatMutex.Unlock()
|
||||
@ -172,7 +173,23 @@ func (t *Tracker) SetBPM(value int) bool {
|
||||
if value != int(t.song.BPM) {
|
||||
t.SaveUndo()
|
||||
t.song.BPM = value
|
||||
t.sequencer.SetRowLength(44100 * 60 / (4 * t.song.BPM))
|
||||
t.sequencer.SetRowLength(t.song.SamplesPerRow())
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (t *Tracker) SetRowsPerBeat(value int) bool {
|
||||
if value < 1 {
|
||||
value = 1
|
||||
}
|
||||
if value > 32 {
|
||||
value = 32
|
||||
}
|
||||
if value != int(t.song.RowsPerBeat) {
|
||||
t.SaveUndo()
|
||||
t.song.RowsPerBeat = value
|
||||
t.sequencer.SetRowLength(t.song.SamplesPerRow())
|
||||
return true
|
||||
}
|
||||
return false
|
||||
@ -362,6 +379,7 @@ func New(audioContext sointu.AudioContext) *Tracker {
|
||||
Octave: new(NumberInput),
|
||||
SongLength: new(NumberInput),
|
||||
RowsPerPattern: new(NumberInput),
|
||||
RowsPerBeat: new(NumberInput),
|
||||
NewTrackBtn: new(widget.Clickable),
|
||||
NewInstrumentBtn: new(widget.Clickable),
|
||||
DeleteInstrumentBtn: new(widget.Clickable),
|
||||
|
Reference in New Issue
Block a user