Automação na amostra exata
O problema
O host grava a automação com a posição de cada amostra. Se o plugin só fica sabendo do valor uma vez por bloco, uma mudança que deveria acontecer no frame 300 de um bloco de 512 é aplicada no frame 0 ou no 512. Automação rápida vira degraus, e o tamanho dos degraus depende do buffer configurado no host.
No JUCE
AudioProcessor::processBlock recebe o áudio e um buffer de MIDI. As mudanças de parâmetro não fazem parte da chamada; o processador lê o valor atual de cada parâmetro, que o host atualiza entre um bloco e outro. Em maio de 2026, um membro da equipe do JUCE disse que a automação com precisão de amostra não ficaria pronta para o primeiro lançamento do JUCE 9 (tópico no fórum).
No Manguebyte
A chamada de processamento traz um EventBuffer em que cada mudança de parâmetro tem o frame em que cai. split_at_events renderiza até cada evento, aplica-o e continua, usando AudioBuffer::windowed para estreitar o buffer no próprio lugar. Nada é copiado nem alocado.
Confira
automation_lands_on_its_exact_frame_and_updates_the_parameter agenda mudanças nos frames 100, 101 e 250 e confere a saída amostra por amostra. automation_lands_on_its_frame_when_processing_in_place faz o mesmo pela interface C do CLAP, e um teste de mesmo nome faz pelo VST 3, em que o host envia uma fila de pontos por parâmetro e todos os pontos são entregues. (O wrapper VST3 do JUCE aplica o último ponto de cada fila: processParameterChanges em juce_audio_plugin_client_VST3.cpp.)
O VST 3 tem uma armadilha própria. O host informa cada mudança duas vezes: ao processador, com o número do frame, e ao controlador, na thread principal, para que um editor possa acompanhar. Se a cópia do controlador for gravada no parâmetro, o plugin salta para um valor um pouco adiantado ou atrasado até o ponto seguinte corrigir. Enquanto os blocos estão rodando, o wrapper do Manguebyte guarda a cópia do controlador só para exibição; what_the_controller_is_told_does_not_disturb_running_automation confere isso.
- pluginautomation_
lands_ okon_ its_ exact_ frame_ and_ updates_ the_ parameter - clapautomation_
lands_ okon_ its_ frame_ when_ processing_ in_ place - vst3automation_
lands_ okon_ its_ frame_ when_ processing_ in_ place - vst3what_
the_ okcontroller_ is_ told_ does_ not_ disturb_ running_ automation
Mostrar o teste
#[test]
fn automation_lands_on_its_exact_frame_and_updates_the_parameter() {
let mut harness = Harness::<Level>::new(48_000.0, 64);
harness.automate(100, "level", 2.0);
harness.automate(101, "level", 3.0);
harness.automate(250, "level", 0.5);
let output = harness.process(&ones(2, 300));
let left = output.channel(0);
assert_eq!(&left[..100], &[1.0; 100]);
assert_eq!(left[100], 2.0);
assert_eq!(&left[101..250], &[3.0; 149]);
assert_eq!(&left[250..], &[0.5; 50]);
assert_eq!(output.channel(1), left);
// Anything polling the parameter sees where automation left it.
assert_eq!(harness.params().level.value(), 0.5);
assert_eq!(harness.position(), 300);
}
c5835bf, como está no arquivo.