diff --git a/bridge/bridge_test.go b/bridge/bridge_test.go index 5e07b95..da996c4 100644 --- a/bridge/bridge_test.go +++ b/bridge/bridge_test.go @@ -40,7 +40,7 @@ func TestOscillatSine(t *testing.T) { sointu.Unit{Type: "out", Parameters: map[string]int{"stereo": 1, "gain": 128}}, }}}} tracks := []sointu.Track{{NumVoices: 1, Sequence: []byte{0}, Patterns: [][]byte{{64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0}}}} - song := sointu.Song{BPM: 100, RowsPerPattern: 16, Tracks: tracks, Patch: patch} + song := sointu.Song{BPM: 100, RowsPerPattern: 16, RowsPerBeat: 4, Tracks: tracks, Patch: patch} synth, err := bridge.Synth(patch) if err != nil { t.Fatalf("Compiling patch failed: %v", err) diff --git a/cmd/sointu-compile/main.go b/cmd/sointu-compile/main.go index fe547fe..baa2d61 100644 --- a/cmd/sointu-compile/main.go +++ b/cmd/sointu-compile/main.go @@ -119,6 +119,9 @@ func main() { return fmt.Errorf("song could not be unmarshaled as a .json (%v) or .yml (%v)", errJSON, errYaml) } } + if song.RowsPerBeat == 0 { + song.RowsPerBeat = 4 + } var compiledPlayer map[string]string if compile { var err error diff --git a/sointu.go b/sointu.go index 6efbfa7..5f3b422 100644 --- a/sointu.go +++ b/sointu.go @@ -257,6 +257,7 @@ var UnitTypes = map[string]([]UnitParameter){ type Song struct { BPM int RowsPerPattern int + RowsPerBeat int Tracks []Track Patch Patch } @@ -266,7 +267,7 @@ func (s *Song) Copy() Song { for i, t := range s.Tracks { tracks[i] = t.Copy() } - return Song{BPM: s.BPM, RowsPerPattern: s.RowsPerPattern, Tracks: tracks, Patch: s.Patch.Copy()} + return Song{BPM: s.BPM, RowsPerPattern: s.RowsPerPattern, RowsPerBeat: s.RowsPerBeat, Tracks: tracks, Patch: s.Patch.Copy()} } func (s *Song) SequenceLength() int { @@ -278,7 +279,7 @@ func (s *Song) TotalRows() int { } func (s *Song) SamplesPerRow() int { - return 44100 * 60 / (s.BPM * 4) + return 44100 * 60 / (s.BPM * s.RowsPerBeat) } func (s *Song) FirstTrackVoice(track int) int { diff --git a/templates/amd64-386/player.h b/templates/amd64-386/player.h index 35ebcbc..d2ce07a 100644 --- a/templates/amd64-386/player.h +++ b/templates/amd64-386/player.h @@ -7,10 +7,11 @@ #define SU_SAMPLE_RATE 44100 #define SU_BPM {{.Song.BPM}} +#define SU_ROWS_PER_BEAT {{.Song.RowsPerBeat}} #define SU_PATTERN_SIZE {{.Song.RowsPerPattern}} #define SU_MAX_PATTERNS {{.Song.SequenceLength}} #define SU_TOTAL_ROWS (SU_MAX_PATTERNS*SU_PATTERN_SIZE) -#define SU_SAMPLES_PER_ROW (SU_SAMPLE_RATE*4*60/(SU_BPM*16)) +#define SU_SAMPLES_PER_ROW (SU_SAMPLE_RATE*60/(SU_BPM*SU_ROWS_PER_BEAT)) #include #if UINTPTR_MAX == 0xffffffff diff --git a/tests/test_add.yml b/tests/test_add.yml index 98de67d..d3cef35 100644 --- a/tests/test_add.yml +++ b/tests/test_add.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_add_stereo.yml b/tests/test_add_stereo.yml index 58bebad..5b62dfa 100644 --- a/tests/test_add_stereo.yml +++ b/tests/test_add_stereo.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_addp.yml b/tests/test_addp.yml index 1cdae02..1d6b0c6 100644 --- a/tests/test_addp.yml +++ b/tests/test_addp.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_addp_stereo.yml b/tests/test_addp_stereo.yml index 8407593..79601ac 100644 --- a/tests/test_addp_stereo.yml +++ b/tests/test_addp_stereo.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_aux.yml b/tests/test_aux.yml index 317571b..9f572cd 100644 --- a/tests/test_aux.yml +++ b/tests/test_aux.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_aux_stereo.yml b/tests/test_aux_stereo.yml index e21e0fd..14c4614 100644 --- a/tests/test_aux_stereo.yml +++ b/tests/test_aux_stereo.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_chords.yml b/tests/test_chords.yml index 3977cfc..eb76529 100644 --- a/tests/test_chords.yml +++ b/tests/test_chords.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_clip.yml b/tests/test_clip.yml index 74e71e8..ed755b6 100644 --- a/tests/test_clip.yml +++ b/tests/test_clip.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_clip_stereo.yml b/tests/test_clip_stereo.yml index 8cef67a..c31d3f6 100644 --- a/tests/test_clip_stereo.yml +++ b/tests/test_clip_stereo.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_compressor.yml b/tests/test_compressor.yml index 121ff6d..0b33a52 100644 --- a/tests/test_compressor.yml +++ b/tests/test_compressor.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_compressor_stereo.yml b/tests/test_compressor_stereo.yml index eead46c..baf6a35 100644 --- a/tests/test_compressor_stereo.yml +++ b/tests/test_compressor_stereo.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_crush.yml b/tests/test_crush.yml index fc05acb..4a5a78b 100644 --- a/tests/test_crush.yml +++ b/tests/test_crush.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_crush_stereo.yml b/tests/test_crush_stereo.yml index a417085..cf1081d 100644 --- a/tests/test_crush_stereo.yml +++ b/tests/test_crush_stereo.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_delay.yml b/tests/test_delay.yml index 9e7146a..2be64b1 100644 --- a/tests/test_delay.yml +++ b/tests/test_delay.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_delay_dampmod.yml b/tests/test_delay_dampmod.yml index a2968c4..6aa2610 100644 --- a/tests/test_delay_dampmod.yml +++ b/tests/test_delay_dampmod.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_delay_drymod.yml b/tests/test_delay_drymod.yml index 733a58a..fb79830 100644 --- a/tests/test_delay_drymod.yml +++ b/tests/test_delay_drymod.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_delay_feedbackmod.yml b/tests/test_delay_feedbackmod.yml index 8e07db8..fbbf627 100644 --- a/tests/test_delay_feedbackmod.yml +++ b/tests/test_delay_feedbackmod.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_delay_flanger.yml b/tests/test_delay_flanger.yml index 3e5b815..7400ba4 100644 --- a/tests/test_delay_flanger.yml +++ b/tests/test_delay_flanger.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_delay_notetracking.yml b/tests/test_delay_notetracking.yml index f9747fe..164a1d8 100644 --- a/tests/test_delay_notetracking.yml +++ b/tests/test_delay_notetracking.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_delay_pregainmod.yml b/tests/test_delay_pregainmod.yml index 6edc98d..00756d9 100644 --- a/tests/test_delay_pregainmod.yml +++ b/tests/test_delay_pregainmod.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_delay_reverb.yml b/tests/test_delay_reverb.yml index 1a9aa36..7216677 100644 --- a/tests/test_delay_reverb.yml +++ b/tests/test_delay_reverb.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_delay_stereo.yml b/tests/test_delay_stereo.yml index 985cea3..06fe53b 100644 --- a/tests/test_delay_stereo.yml +++ b/tests/test_delay_stereo.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_distort.yml b/tests/test_distort.yml index e8ef272..cdf0835 100644 --- a/tests/test_distort.yml +++ b/tests/test_distort.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_distort_mod.yml b/tests/test_distort_mod.yml index 7bcf09d..21e7e37 100644 --- a/tests/test_distort_mod.yml +++ b/tests/test_distort_mod.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_distort_stereo.yml b/tests/test_distort_stereo.yml index 7fe6f84..a0d0962 100644 --- a/tests/test_distort_stereo.yml +++ b/tests/test_distort_stereo.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_envelope.yml b/tests/test_envelope.yml index 44f8725..0476bbf 100644 --- a/tests/test_envelope.yml +++ b/tests/test_envelope.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_envelope_mod.yml b/tests/test_envelope_mod.yml index 07f2d88..0f87765 100644 --- a/tests/test_envelope_mod.yml +++ b/tests/test_envelope_mod.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_envelope_stereo.yml b/tests/test_envelope_stereo.yml index 9bf8894..ea30b5d 100644 --- a/tests/test_envelope_stereo.yml +++ b/tests/test_envelope_stereo.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_filter_band.yml b/tests/test_filter_band.yml index 2e24afe..0abf3fa 100644 --- a/tests/test_filter_band.yml +++ b/tests/test_filter_band.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_filter_freqmod.yml b/tests/test_filter_freqmod.yml index 9b130b9..128ef36 100644 --- a/tests/test_filter_freqmod.yml +++ b/tests/test_filter_freqmod.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_filter_high.yml b/tests/test_filter_high.yml index 2d89af8..2f6fc26 100644 --- a/tests/test_filter_high.yml +++ b/tests/test_filter_high.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_filter_low.yml b/tests/test_filter_low.yml index f632c72..10cf30a 100644 --- a/tests/test_filter_low.yml +++ b/tests/test_filter_low.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_filter_peak.yml b/tests/test_filter_peak.yml index 2ea2a0f..8c03973 100644 --- a/tests/test_filter_peak.yml +++ b/tests/test_filter_peak.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_filter_resmod.yml b/tests/test_filter_resmod.yml index e5a1c39..bf33d07 100644 --- a/tests/test_filter_resmod.yml +++ b/tests/test_filter_resmod.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_filter_stereo.yml b/tests/test_filter_stereo.yml index cdf77fc..3a7752b 100644 --- a/tests/test_filter_stereo.yml +++ b/tests/test_filter_stereo.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_gain.yml b/tests/test_gain.yml index 9a66b9f..a2f1862 100644 --- a/tests/test_gain.yml +++ b/tests/test_gain.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_gain_stereo.yml b/tests/test_gain_stereo.yml index 5659eda..bfa3364 100644 --- a/tests/test_gain_stereo.yml +++ b/tests/test_gain_stereo.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_hold.yml b/tests/test_hold.yml index 6bbf6b5..73d5a68 100644 --- a/tests/test_hold.yml +++ b/tests/test_hold.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_hold_mod.yml b/tests/test_hold_mod.yml index cd69f54..5a0ad2d 100644 --- a/tests/test_hold_mod.yml +++ b/tests/test_hold_mod.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_hold_stereo.yml b/tests/test_hold_stereo.yml index 1bdec88..4290598 100644 --- a/tests/test_hold_stereo.yml +++ b/tests/test_hold_stereo.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_in.yml b/tests/test_in.yml index f37e7c3..1dd6772 100644 --- a/tests/test_in.yml +++ b/tests/test_in.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_in_stereo.yml b/tests/test_in_stereo.yml index 44961fb..cdb385b 100644 --- a/tests/test_in_stereo.yml +++ b/tests/test_in_stereo.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_invgain.yml b/tests/test_invgain.yml index 0408666..b1cf0b3 100644 --- a/tests/test_invgain.yml +++ b/tests/test_invgain.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_invgain_stereo.yml b/tests/test_invgain_stereo.yml index 0aa0025..d483140 100644 --- a/tests/test_invgain_stereo.yml +++ b/tests/test_invgain_stereo.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_loadnote.yml b/tests/test_loadnote.yml index 6d86821..16a1ca5 100644 --- a/tests/test_loadnote.yml +++ b/tests/test_loadnote.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_loadnote_stereo.yml b/tests/test_loadnote_stereo.yml index 96226f2..6393d29 100644 --- a/tests/test_loadnote_stereo.yml +++ b/tests/test_loadnote_stereo.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_loadval.yml b/tests/test_loadval.yml index 963d0fa..ea302f8 100644 --- a/tests/test_loadval.yml +++ b/tests/test_loadval.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_loadval_stereo.yml b/tests/test_loadval_stereo.yml index 2635f0c..2ea6dad 100644 --- a/tests/test_loadval_stereo.yml +++ b/tests/test_loadval_stereo.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_mul.yml b/tests/test_mul.yml index 3b4b9f1..8977269 100644 --- a/tests/test_mul.yml +++ b/tests/test_mul.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_mul_stereo.yml b/tests/test_mul_stereo.yml index d0af25c..be82a2c 100644 --- a/tests/test_mul_stereo.yml +++ b/tests/test_mul_stereo.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_mulp.yml b/tests/test_mulp.yml index 921d6f9..835d2ef 100644 --- a/tests/test_mulp.yml +++ b/tests/test_mulp.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_mulp_stereo.yml b/tests/test_mulp_stereo.yml index 7d8d4a9..6a1a3ce 100644 --- a/tests/test_mulp_stereo.yml +++ b/tests/test_mulp_stereo.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_multiple_instruments.yml b/tests/test_multiple_instruments.yml index 892326a..3b0e2f4 100644 --- a/tests/test_multiple_instruments.yml +++ b/tests/test_multiple_instruments.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_noise.yml b/tests/test_noise.yml index 43bda20..beaa1a4 100644 --- a/tests/test_noise.yml +++ b/tests/test_noise.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_noise_stereo.yml b/tests/test_noise_stereo.yml index 34e136f..4f19789 100644 --- a/tests/test_noise_stereo.yml +++ b/tests/test_noise_stereo.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_oscillat_colormod.yml b/tests/test_oscillat_colormod.yml index 4d8fe5f..f5b6485 100644 --- a/tests/test_oscillat_colormod.yml +++ b/tests/test_oscillat_colormod.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_oscillat_detunemod.yml b/tests/test_oscillat_detunemod.yml index 273cdf4..9496f9d 100644 --- a/tests/test_oscillat_detunemod.yml +++ b/tests/test_oscillat_detunemod.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_oscillat_gainmod.yml b/tests/test_oscillat_gainmod.yml index 9cee4a7..fa3bee9 100644 --- a/tests/test_oscillat_gainmod.yml +++ b/tests/test_oscillat_gainmod.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_oscillat_gate.yml b/tests/test_oscillat_gate.yml index 28e1307..ce86015 100644 --- a/tests/test_oscillat_gate.yml +++ b/tests/test_oscillat_gate.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_oscillat_lfo.yml b/tests/test_oscillat_lfo.yml index 4d7d6ea..133cfaf 100644 --- a/tests/test_oscillat_lfo.yml +++ b/tests/test_oscillat_lfo.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_oscillat_phasemod.yml b/tests/test_oscillat_phasemod.yml index abd0fc1..11caf02 100644 --- a/tests/test_oscillat_phasemod.yml +++ b/tests/test_oscillat_phasemod.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_oscillat_pulse.yml b/tests/test_oscillat_pulse.yml index b91978e..266f644 100644 --- a/tests/test_oscillat_pulse.yml +++ b/tests/test_oscillat_pulse.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_oscillat_sample.yml b/tests/test_oscillat_sample.yml index 175641b..9edd513 100644 --- a/tests/test_oscillat_sample.yml +++ b/tests/test_oscillat_sample.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 8 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [1, 0, 2, 0, 3, 0, 4, 0] diff --git a/tests/test_oscillat_sample_stereo.yml b/tests/test_oscillat_sample_stereo.yml index beebdb4..ea221dc 100644 --- a/tests/test_oscillat_sample_stereo.yml +++ b/tests/test_oscillat_sample_stereo.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 8 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [1, 0, 2, 0, 3, 0, 4, 0] diff --git a/tests/test_oscillat_shapemod.yml b/tests/test_oscillat_shapemod.yml index 27a69cc..e6996c6 100644 --- a/tests/test_oscillat_shapemod.yml +++ b/tests/test_oscillat_shapemod.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_oscillat_sine.yml b/tests/test_oscillat_sine.yml index ae07570..bf40b74 100644 --- a/tests/test_oscillat_sine.yml +++ b/tests/test_oscillat_sine.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_oscillat_stereo.yml b/tests/test_oscillat_stereo.yml index f571492..599f25e 100644 --- a/tests/test_oscillat_stereo.yml +++ b/tests/test_oscillat_stereo.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_oscillat_transposemod.yml b/tests/test_oscillat_transposemod.yml index dc00e56..945ae43 100644 --- a/tests/test_oscillat_transposemod.yml +++ b/tests/test_oscillat_transposemod.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_oscillat_trisaw.yml b/tests/test_oscillat_trisaw.yml index 8906078..31699d8 100644 --- a/tests/test_oscillat_trisaw.yml +++ b/tests/test_oscillat_trisaw.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_oscillat_unison.yml b/tests/test_oscillat_unison.yml index fd6a159..774468e 100644 --- a/tests/test_oscillat_unison.yml +++ b/tests/test_oscillat_unison.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_oscillat_unison_stereo.yml b/tests/test_oscillat_unison_stereo.yml index 5bf1032..2b1dac0 100644 --- a/tests/test_oscillat_unison_stereo.yml +++ b/tests/test_oscillat_unison_stereo.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_outaux.yml b/tests/test_outaux.yml index d1f779e..d40f480 100644 --- a/tests/test_outaux.yml +++ b/tests/test_outaux.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_outaux_stereo.yml b/tests/test_outaux_stereo.yml index 28bdc84..da8a1b4 100644 --- a/tests/test_outaux_stereo.yml +++ b/tests/test_outaux_stereo.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_panning.yml b/tests/test_panning.yml index 3b505b3..9f03be1 100644 --- a/tests/test_panning.yml +++ b/tests/test_panning.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_panning_stereo.yml b/tests/test_panning_stereo.yml index b41abc5..4259f84 100644 --- a/tests/test_panning_stereo.yml +++ b/tests/test_panning_stereo.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_polyphony.yml b/tests/test_polyphony.yml index 3b1a93c..34ec8ea 100644 --- a/tests/test_polyphony.yml +++ b/tests/test_polyphony.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 2 sequence: [0] diff --git a/tests/test_pop.yml b/tests/test_pop.yml index 460bfb8..b09c5e6 100644 --- a/tests/test_pop.yml +++ b/tests/test_pop.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_pop_stereo.yml b/tests/test_pop_stereo.yml index 04e662d..66c8bde 100644 --- a/tests/test_pop_stereo.yml +++ b/tests/test_pop_stereo.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_push.yml b/tests/test_push.yml index 9449a8c..73e1c27 100644 --- a/tests/test_push.yml +++ b/tests/test_push.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_push_stereo.yml b/tests/test_push_stereo.yml index ad096e8..7cce297 100644 --- a/tests/test_push_stereo.yml +++ b/tests/test_push_stereo.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_receive.yml b/tests/test_receive.yml index b731a79..363269b 100644 --- a/tests/test_receive.yml +++ b/tests/test_receive.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_receive_stereo.yml b/tests/test_receive_stereo.yml index c0c2254..fa4137c 100644 --- a/tests/test_receive_stereo.yml +++ b/tests/test_receive_stereo.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_send.yml b/tests/test_send.yml index 7b2b00e..7ba6a3d 100644 --- a/tests/test_send.yml +++ b/tests/test_send.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_send_global.yml b/tests/test_send_global.yml index 666193d..13ae5a0 100644 --- a/tests/test_send_global.yml +++ b/tests/test_send_global.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_send_stereo.yml b/tests/test_send_stereo.yml index 5095d9e..b810a9f 100644 --- a/tests/test_send_stereo.yml +++ b/tests/test_send_stereo.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_speed.yml b/tests/test_speed.yml index c49f66f..0807d39 100644 --- a/tests/test_speed.yml +++ b/tests/test_speed.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0, 0] diff --git a/tests/test_xch.yml b/tests/test_xch.yml index eff947c..97baf2a 100644 --- a/tests/test_xch.yml +++ b/tests/test_xch.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tests/test_xch_stereo.yml b/tests/test_xch_stereo.yml index ca12ece..64cd22c 100644 --- a/tests/test_xch_stereo.yml +++ b/tests/test_xch_stereo.yml @@ -1,5 +1,6 @@ bpm: 100 rowsperpattern: 16 +rowsperbeat: 4 tracks: - numvoices: 1 sequence: [0] diff --git a/tracker/defaultsong.go b/tracker/defaultsong.go index c4b269f..04cc936 100644 --- a/tracker/defaultsong.go +++ b/tracker/defaultsong.go @@ -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}}}, diff --git a/tracker/songpanel.go b/tracker/songpanel.go index e8f1b79..a2fd011 100644 --- a/tracker/songpanel.go +++ b/tracker/songpanel.go @@ -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 + }), + ) + }), ) } diff --git a/tracker/tracker.go b/tracker/tracker.go index 312ed12..8cf367f 100644 --- a/tracker/tracker.go +++ b/tracker/tracker.go @@ -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),