mirror of
https://github.com/vsariola/sointu.git
synced 2025-05-28 03:10:24 -04:00
refactor(song): Remove song length from Song and assume the user knows MAX_SAMPLES
Trying to force a specific song length other than the default never quite worked, so we'll only support the default MAX_SAMPLES & will calculate it for the user in the user in the exported .h header file.
This commit is contained in:
parent
e2c6d4b70c
commit
a1e7e82d6d
@ -158,7 +158,7 @@ func DeserializeAsm(asmcode string) (*Song, error) {
|
||||
}
|
||||
}
|
||||
}
|
||||
s := Song{BPM: bpm, Patterns: patterns, Tracks: tracks, Patch: patch, SongLength: -1}
|
||||
s := Song{BPM: bpm, Patterns: patterns, Tracks: tracks, Patch: patch}
|
||||
return &s, nil
|
||||
}
|
||||
|
||||
|
35
go4k/song.go
35
go4k/song.go
@ -1,13 +1,15 @@
|
||||
package go4k
|
||||
|
||||
import "errors"
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type Song struct {
|
||||
BPM int
|
||||
Patterns [][]byte
|
||||
Tracks []Track
|
||||
SongLength int // in samples, 0 means calculate automatically from BPM and Track lengths, but can also set manually
|
||||
Patch Patch
|
||||
BPM int
|
||||
Patterns [][]byte
|
||||
Tracks []Track
|
||||
Patch Patch
|
||||
}
|
||||
|
||||
func (s *Song) PatternRows() int {
|
||||
@ -74,13 +76,9 @@ func Play(synth Synth, song Song) ([]float32, error) {
|
||||
for i := range curVoices {
|
||||
curVoices[i] = song.FirstTrackVoice(i)
|
||||
}
|
||||
samples := song.SongLength
|
||||
if samples <= 0 {
|
||||
samples = song.TotalRows() * song.SamplesPerRow()
|
||||
}
|
||||
buffer := make([]float32, samples*2)
|
||||
totaln := 0
|
||||
rowtime := song.SamplesPerRow()
|
||||
initialCapacity := song.TotalRows() * song.SamplesPerRow() * 2
|
||||
buffer := make([]float32, 0, initialCapacity)
|
||||
rowbuffer := make([]float32, song.SamplesPerRow()*2)
|
||||
for row := 0; row < song.TotalRows(); row++ {
|
||||
patternRow := row % song.PatternRows()
|
||||
pattern := row / song.PatternRows()
|
||||
@ -100,8 +98,15 @@ func Play(synth Synth, song Song) ([]float32, error) {
|
||||
synth.Trigger(curVoices[t], note)
|
||||
}
|
||||
}
|
||||
samples, _, _ := synth.Render(buffer[2*totaln:], rowtime)
|
||||
totaln += samples
|
||||
tries := 0
|
||||
for rowtime := 0; rowtime < song.SamplesPerRow(); {
|
||||
samples, time, _ := synth.Render(rowbuffer, song.SamplesPerRow()-rowtime)
|
||||
rowtime += time
|
||||
buffer = append(buffer, rowbuffer[:samples*2]...)
|
||||
if tries > 100 {
|
||||
return nil, fmt.Errorf("Song speed modulation likely so slow that row never advances; error at pattern %v, row %v", pattern, patternRow)
|
||||
}
|
||||
}
|
||||
}
|
||||
return buffer, nil
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ import (
|
||||
"github.com/vsariola/sointu/go4k"
|
||||
)
|
||||
|
||||
const expectedMarshaled = `{"BPM":100,"Patterns":["QABEACAAAABLAE4AAAAAAA=="],"Tracks":[{"NumVoices":1,"Sequence":"AA=="}],"SongLength":0,"Patch":{"Instruments":[{"NumVoices":1,"Units":[{"Type":"envelope","Parameters":{"attack":32,"decay":32,"gain":128,"release":64,"stereo":0,"sustain":64}},{"Type":"oscillator","Parameters":{"color":96,"detune":64,"flags":64,"gain":128,"phase":0,"shape":64,"stereo":0,"transpose":64}},{"Type":"mulp","Parameters":{"stereo":0}},{"Type":"envelope","Parameters":{"attack":32,"decay":32,"gain":128,"release":64,"stereo":0,"sustain":64}},{"Type":"oscillator","Parameters":{"color":64,"detune":64,"flags":64,"gain":128,"phase":64,"shape":96,"stereo":0,"transpose":72}},{"Type":"mulp","Parameters":{"stereo":0}},{"Type":"out","Parameters":{"gain":128,"stereo":1}}]}],"DelayTimes":[],"SampleOffsets":[]}}`
|
||||
const expectedMarshaled = `{"BPM":100,"Patterns":["QABEACAAAABLAE4AAAAAAA=="],"Tracks":[{"NumVoices":1,"Sequence":"AA=="}],"Patch":{"Instruments":[{"NumVoices":1,"Units":[{"Type":"envelope","Parameters":{"attack":32,"decay":32,"gain":128,"release":64,"stereo":0,"sustain":64}},{"Type":"oscillator","Parameters":{"color":96,"detune":64,"flags":64,"gain":128,"phase":0,"shape":64,"stereo":0,"transpose":64}},{"Type":"mulp","Parameters":{"stereo":0}},{"Type":"envelope","Parameters":{"attack":32,"decay":32,"gain":128,"release":64,"stereo":0,"sustain":64}},{"Type":"oscillator","Parameters":{"color":64,"detune":64,"flags":64,"gain":128,"phase":64,"shape":96,"stereo":0,"transpose":72}},{"Type":"mulp","Parameters":{"stereo":0}},{"Type":"out","Parameters":{"gain":128,"stereo":1}}]}],"DelayTimes":[],"SampleOffsets":[]}}`
|
||||
|
||||
var testSong = go4k.Song{
|
||||
BPM: 100,
|
||||
@ -16,7 +16,6 @@ var testSong = go4k.Song{
|
||||
Tracks: []go4k.Track{
|
||||
{NumVoices: 1, Sequence: []byte{0}},
|
||||
},
|
||||
SongLength: 0,
|
||||
Patch: go4k.Patch{
|
||||
Instruments: []go4k.Instrument{{NumVoices: 1, Units: []go4k.Unit{
|
||||
{"envelope", map[string]int{"stereo": 0, "attack": 32, "decay": 32, "sustain": 64, "release": 64, "gain": 128}},
|
||||
|
@ -37,7 +37,7 @@ func TestPlayer(t *testing.T) {
|
||||
SampleOffsets: []go4k.SampleOffset{}}
|
||||
patterns := [][]byte{{64, 0, 68, 0, 32, 0, 0, 0, 75, 0, 78, 0, 0, 0, 0, 0}}
|
||||
tracks := []go4k.Track{go4k.Track{1, []byte{0}}}
|
||||
song := go4k.Song{100, patterns, tracks, 0, patch}
|
||||
song := go4k.Song{100, patterns, tracks, patch}
|
||||
synth, err := bridge.Synth(patch)
|
||||
if err != nil {
|
||||
t.Fatalf("Compiling patch failed: %v", err)
|
||||
|
@ -12,7 +12,6 @@ var defaultSong = go4k.Song{
|
||||
{NumVoices: 1, Sequence: []byte{0}},
|
||||
{NumVoices: 1, Sequence: []byte{1}},
|
||||
},
|
||||
SongLength: 0,
|
||||
Patch: go4k.Patch{
|
||||
Instruments: []go4k.Instrument{{NumVoices: 2, Units: []go4k.Unit{
|
||||
{"envelope", map[string]int{"stereo": 0, "attack": 32, "decay": 32, "sustain": 64, "release": 64, "gain": 128}},
|
||||
|
@ -115,7 +115,9 @@ section .text ; yasm throws section redeclaration warnings if strucs are defined
|
||||
|
||||
%define TOTAL_ROWS (MAX_PATTERNS*PATTERN_SIZE)
|
||||
%define SAMPLES_PER_ROW (SAMPLE_RATE*4*60/(BPM*16))
|
||||
%define MAX_SAMPLES (SAMPLES_PER_ROW*TOTAL_ROWS)
|
||||
%ifndef MAX_SAMPLES
|
||||
%define MAX_SAMPLES (SAMPLES_PER_ROW*TOTAL_ROWS)
|
||||
%endif
|
||||
|
||||
%macro BEGIN_PATCH 0
|
||||
SECT_DATA(params)
|
||||
|
@ -159,6 +159,7 @@ target_compile_definitions(test_envelope_16bit PUBLIC SU_USE_16BIT_OUTPUT)
|
||||
regression_test(test_polyphony "ENVELOPE;VCO_SINE")
|
||||
regression_test(test_chords "ENVELOPE;VCO_SINE")
|
||||
regression_test(test_speed "ENVELOPE;VCO_SINE")
|
||||
target_compile_definitions(test_speed PUBLIC MAX_SAMPLES=211592)
|
||||
|
||||
regression_test(test_render_samples ENVELOPE "" test_render_samples.c)
|
||||
target_link_libraries(test_render_samples ${STATICLIB})
|
||||
|
Binary file not shown.
Loading…
Reference in New Issue
Block a user