mirror of
https://github.com/vsariola/sointu.git
synced 2025-09-23 13:46:42 -04:00
refactor(tracker): put all recording data into struct Recording
This commit is contained in:
parent
453f45c48a
commit
d342fb860b
@ -25,10 +25,8 @@ type (
|
||||
peakVolumeMeter VolumeAnalyzer
|
||||
voiceStates [vm.MAX_VOICES]float32
|
||||
|
||||
recording bool
|
||||
recordingNoteArrived bool
|
||||
recordingFrames int
|
||||
recordingEvents []PlayerProcessEvent
|
||||
recState recState
|
||||
recording Recording
|
||||
|
||||
synther sointu.Synther
|
||||
playerMessages chan<- PlayerMessage
|
||||
@ -36,11 +34,11 @@ type (
|
||||
}
|
||||
|
||||
PlayerProcessContext interface {
|
||||
NextEvent() (event PlayerProcessEvent, ok bool)
|
||||
NextEvent() (event MIDINoteEvent, ok bool)
|
||||
BPM() (bpm float64, ok bool)
|
||||
}
|
||||
|
||||
PlayerProcessEvent struct {
|
||||
MIDINoteEvent struct {
|
||||
Frame int
|
||||
On bool
|
||||
Channel int
|
||||
@ -51,12 +49,6 @@ type (
|
||||
bool
|
||||
}
|
||||
|
||||
PlayerRecordedMessage struct {
|
||||
BPM float64 // vsts allow bpms as floats so for accurate reconstruction, keep it as float for recording
|
||||
Events []PlayerProcessEvent
|
||||
TotalFrames int
|
||||
}
|
||||
|
||||
// Volume and SongRow are transmitted so frequently that they are treated specially, to avoid boxing. All the
|
||||
// rest messages can be boxed to interface{}
|
||||
PlayerMessage struct {
|
||||
@ -74,6 +66,10 @@ type (
|
||||
PlayerVolumeErrorMessage struct {
|
||||
error
|
||||
}
|
||||
)
|
||||
|
||||
type (
|
||||
recState int
|
||||
|
||||
voiceNote struct {
|
||||
voice int
|
||||
@ -85,6 +81,12 @@ type (
|
||||
}
|
||||
)
|
||||
|
||||
const (
|
||||
recStateNone recState = iota
|
||||
recStateWaitingForNote
|
||||
recStateRecording
|
||||
)
|
||||
|
||||
const NUM_RENDER_TRIES = 10000
|
||||
|
||||
func NewPlayer(synther sointu.Synther, playerMessages chan<- PlayerMessage, modelMessages <-chan interface{}) *Player {
|
||||
@ -103,22 +105,22 @@ func (p *Player) Process(buffer sointu.AudioBuffer, context PlayerProcessContext
|
||||
midi, midiOk := context.NextEvent()
|
||||
frame := 0
|
||||
|
||||
if p.recording && p.recordingNoteArrived {
|
||||
p.recordingFrames += len(buffer)
|
||||
if p.recState == recStateRecording {
|
||||
p.recording.TotalFrames += len(buffer)
|
||||
}
|
||||
|
||||
oldBuffer := buffer
|
||||
|
||||
for i := 0; i < NUM_RENDER_TRIES; i++ {
|
||||
for midiOk && frame >= midi.Frame {
|
||||
if p.recording {
|
||||
if !p.recordingNoteArrived {
|
||||
p.recordingFrames = len(buffer)
|
||||
p.recordingNoteArrived = true
|
||||
}
|
||||
if p.recState == recStateWaitingForNote {
|
||||
p.recording.TotalFrames = len(buffer)
|
||||
p.recState = recStateRecording
|
||||
}
|
||||
if p.recState == recStateRecording {
|
||||
midiTotalFrame := midi
|
||||
midiTotalFrame.Frame = p.recordingFrames - len(buffer)
|
||||
p.recordingEvents = append(p.recordingEvents, midiTotalFrame)
|
||||
midiTotalFrame.Frame = p.recording.TotalFrames - len(buffer)
|
||||
p.recording.Events = append(p.recording.Events, midiTotalFrame)
|
||||
}
|
||||
if midi.On {
|
||||
p.triggerInstrument(midi.Channel, midi.Note)
|
||||
@ -278,20 +280,14 @@ loop:
|
||||
}
|
||||
case ModelRecordingMessage:
|
||||
if m.bool {
|
||||
p.recording = true
|
||||
p.recordingEvents = make([]PlayerProcessEvent, 0)
|
||||
p.recordingFrames = 0
|
||||
p.recordingNoteArrived = false
|
||||
p.recState = recStateWaitingForNote
|
||||
p.recording = Recording{}
|
||||
} else {
|
||||
if p.recording && len(p.recordingEvents) > 0 {
|
||||
bpm, _ := context.BPM()
|
||||
p.trySend(PlayerRecordedMessage{
|
||||
BPM: bpm,
|
||||
Events: p.recordingEvents,
|
||||
TotalFrames: p.recordingFrames,
|
||||
})
|
||||
if p.recState == recStateRecording && len(p.recording.Events) > 0 {
|
||||
p.recording.BPM, _ = context.BPM()
|
||||
p.trySend(p.recording)
|
||||
}
|
||||
p.recording = false
|
||||
p.recState = recStateNone
|
||||
}
|
||||
default:
|
||||
// ignore unknown messages
|
||||
|
Reference in New Issue
Block a user