Hoe pauzeer je een modulatiepositie en hervat je die achterwaarts bij de volgende trigger in SuperCollider
Om een modulatiepositie te pauzeren en achterwaarts te hervatten, laat je de fasegenerator doorlopen met een increment van nul en schakel je dat increment bij de volgende trigger om naar een negatieve waarde. Laat de fase-resetingang losgekoppeld van die triggers, zodat de beweging vanaf de vastgehouden positie verdergaat.
In deze tutorial bouw je dat gedrag op in SuperCollider: een oplopende toonhoogtesweep pauzeert bij de eerste trigger en volgt bij de tweede zijn pad terug. De tutorial is bedoeld voor een sound designer die een herhaalbaar modulatiegebaar wil aansturen met opeenvolgende gebeurtenissen. Hetzelfde fasesignaal kan later een andere parameter aansturen.
Wat moet tijdens de pauze behouden blijven?
Zie modulatie als twee verbonden bewerkingen: een positie beweegt door een cyclus en een mapping zet die positie om in een bruikbare parameterwaarde. Hier loopt de positie van nul naar één en zet de mapping die om in de oscillatorfrequentie.
SuperCollider’s Phasor levert de positie. Het argument rate geeft het increment per sample aan; de triggeringang springt daarentegen naar resetPos. Dit zijn afzonderlijke bedieningselementen, dus een trigger die wordt gebruikt om de richting te veranderen, mag de positie niet ook resetten. Phasor-documentatie
De implementatie bewaart een interne waarde en telt de snelheid daarbij op. Op basis van dat gedrag houdt een snelheid van nul de waarde vast, terwijl een negatieve snelheid deze laat dalen. De onderstaande patch past dit rechtstreeks toe en behoudt de toestand van de generator tijdens de hele pauze. Implementatie van SuperCollider 3.14.0 TriggerUGens.cpp
Wat moet elke volgende trigger doen?
Bepaal de gebeurtenisvolgorde voordat je de klank aansluit. In deze patch begint de beweging onmiddellijk voorwaarts. Elke volgende trigger gaat één toestand verder:
| Ontvangen triggers | Toestand | Richtingsfactor |
|---|---|---|
| 0 | Voorwaarts bewegen | +1 |
| 1 | Huidige positie vasthouden | 0 |
| 2 | Achterwaarts hervatten | −1 |
| 3 | Huidige positie vasthouden | 0 |
| 4 | Voorwaarts hervatten | +1 |
Deze cyclus met vier toestanden scheidt de twee vasthoudtoestanden: de ene leidt naar achterwaartse beweging en de andere naar voorwaartse beweging. Zo zijn herhaalde gebaren voorspelbaar zonder dat je een extra richtingsknop nodig hebt.
PulseCount wordt verhoogd wanneer de ingang verandert van niet-positief naar positief. Als je de telling modulo vier neemt, krijg je de herhalende indices 0–3. Vervolgens kiest Select de bijbehorende factor uit [1, 0, -1, 0]. Dit zijn de gedocumenteerde functies van PulseCount en Select.
Hoe bouw je de volledige patch?
Gebruik een lokale SuperCollider-installatie met werkende audio-uitvoer; het voorbeeld volgt de documentatie voor versie 3.14.0. Het gebruikt ingebouwde unit generators en genereert zelf geluid, dus je hebt geen samplebestanden of extensies nodig. Evalueer het hele blok één keer en wacht op het gereedbericht.
waitForBoot start de server indien nodig. De definitie wordt verzonden voordat de synth wordt aangemaakt, waarbij s.sync wacht op nog lopende serverbewerkingen. Zie de Server-documentatie en SynthDef-documentatie.
(
s = Server.default;
s.waitForBoot({
SynthDef(\pauseReverseMod, {
|out = 0, t_step = 0, cycleSeconds = 8, amp = 0.08|
var state, direction, increment, phase, frequency, sound;
state = PulseCount.kr(t_step) % 4;
direction = Select.kr(state, [1, 0, -1, 0]);
// A full 0..1 traversal takes cycleSeconds seconds.
increment = direction * SampleDur.ir
/ cycleSeconds.max(0.01);
// State-changing triggers never reset this phase.
phase = Phasor.ar(
trig: 0,
rate: increment,
start: 0,
end: 1,
resetPos: 0
);
frequency = LinExp.ar(phase, 0, 1, 220, 880);
sound = SinOsc.ar(frequency, 0, amp);
Out.ar(out, sound ! 2);
Poll.kr(Impulse.kr(2), state, "state");
Poll.kr(Impulse.kr(2), A2K.kr(phase), "phase");
}).add;
s.sync;
~pauseReverseSynth = Synth(\pauseReverseMod);
"Ready: evaluate ~pauseReverseSynth.set(\\t_step, 1);".postln;
});
)
Het increment is de richting vermenigvuldigd met de sampleduur en gedeeld door de cyclusduur. SampleDur geeft het omgekeerde van de samplefrequentie van de server terug, dus bij de instelling van acht seconden wordt geen specifieke samplefrequentie verondersteld. SampleDur-documentatie
De toonhoogtemapping loopt van 220 tot 880 Hz. LinExp zet een lineair invoerbereik om in een exponentieel uitvoerbereik; de eindpunten van de bestemming moeten niet-nul zijn en hetzelfde teken hebben. Beide eindpunten voldoen hier aan die eis. LinExp-documentatie
Ik heb het SuperCollider-voorbeeld gecontroleerd aan de hand van de opgehaalde documentatie. De SuperCollider-runtime was niet beschikbaar in de onderzoeksomgeving, dus ik heb deze patch niet uitgevoerd of beluisterd. Een afzonderlijke deterministische rekencontrole bevestigde de richtingsvolgorde en het vasthouden bij een increment van nul.
Hoe pauzeer je en hervat je achterwaarts?
Laat de toonhoogte na het gereedbericht ongeveer twee seconden stijgen. Evalueer daarna deze interactieopdracht één keer:
~pauseReverseSynth.set(\t_step, 1);
De toestand moet 1 worden en de afgedrukte fase moet op één waarde stabiliseren. Wacht even en evalueer daarna dezelfde opdracht opnieuw. De toestand moet 2 worden en de fase moet vanaf de vastgehouden positie dalen. Bij de derde evaluatie wordt de dalende sweep vastgehouden; bij de vierde begint deze weer voorwaarts.
Het voorvoegsel t_ maakt van t_step een triggerbesturing. Door deze in te stellen ontstaat een impuls op control rate, zodat je dezelfde opdracht herhaald kunt gebruiken zonder tussen normale, gespreide evaluaties handmatig een afzonderlijke nul te sturen. Documentatie over triggerbesturing in SynthDef
Bij wijze van voorbeeldberekening gaat de fase bij een cyclus van acht seconden per seconde 0,125 van het bereik vooruit. Pauzeer je na twee seconden, dan wordt ongeveer 0,25 vastgehouden. Na elke willekeurige pauzeduur brengt één seconde achterwaartse beweging de fase naar ongeveer 0,125. Dit zijn berekende verwachtingen; de timing van handmatige opdrachten bepaalt de werkelijke stoppositie.
Evalueer de opdracht voor opruimen om af te sluiten:
~pauseReverseSynth.free;
Hoe controleer je of de positie echt op zijn plek bleef?
Gebruik de afgedrukte fase als belangrijkste diagnostiek. Tijdens voorwaartse beweging moet deze toenemen; in beide vasthoudtoestanden moet deze constant blijven; tijdens achterwaartse beweging moet deze afnemen totdat de cyclusgrens wordt bereikt.
De patch drukt twee keer per seconde een waarde af, dus de weergave bemonstert het gedrag en toont niet elke sample. Bekijk tijdens de pauze meerdere opeenvolgende waarden en vergelijk die vervolgens met de eerste dalende waarden nadat je de beweging hervat. Poll is bedoeld om waarden van unit generators te debuggen; verwijder de twee pollingregels wanneer je de definitie voor normaal gebruik aanpast. Poll-documentatie
Deze test geeft meer informatie dan alleen luisteren. Een constante klank toont aan dat de bestemmingswaarde niet meer verandert, terwijl een stabiele fasewaarde bevestigt dat ook de onderliggende positie is gestopt. Als je de mapping tijdens de hele test ongewijzigd laat, is het resultaat makkelijker te interpreteren.
Waarom kan de patch opnieuw beginnen, verspringen of een trigger missen?
De patch begint opnieuw wanneer je hervat. Controleer of de gebeurtenis ook de triggerinput van Phasor bereikt. Die ingang reset de positie expliciet. In deze patch blijft die op nul staan en gaan gebeurtenissen alleen naar de toestandteller. Phasor-documentatie
De fase springt nadat een eindpunt is bereikt. Dit voorbeeld loopt bewust rond. De implementatie laat de fase teruglopen binnen het ingestelde bereik, ook bij achterwaartse beweging. Zodra de achterwaartse beweging onder nul komt, keert de fase terug naar vlak bij de bovengrens, wat bij deze rampmapping een sprong in toonhoogte veroorzaakt. Test de pauze en richtingsomkering eerst buiten die grens. Phasor-implementatie
Meerdere snelle opdrachten leveren niet meerdere toestanden op. De teller heeft afzonderlijke stijgende overgangen nodig. Triggerbesturingen werken op control rate, dus ga er niet van uit dat meerdere opdrachten binnen één control block afzonderlijke gebeurtenissen worden. Begin met bewuste, gespreide opdrachten; ontwerp voor strak getimede reeksen de gebeurtenisbron rond afzonderlijke pulsen. PulseCount-documentatie, SynthDef-documentatie
De klank verandert terwijl de fase wordt vastgehouden. Controleer of je ook de bestemmingsmapping of een andere klankparameter wijzigt. Laat voor deze test de toonhoogte-eindpunten ongewijzigd en gebruik de afgedrukte fase om het modulatieverloop afzonderlijk te controleren.
Het voltooide gebaar is: voorwaarts, vasthouden, achterwaarts, vasthouden en vervolgens weer voorwaarts. Zodra die volgorde goed werkt, kun je de toestandteller en fasegenerator als herbruikbare modulatiebron behouden en de bestemmingsmapping aanpassen aan de klank die je maakt.
Bronnen
- Phasor — SuperCollider 3.14.0 Help
- TriggerUGens.cpp — SuperCollider, Versie-3.14.0
- PulseCount — SuperCollider 3.14.0 Help
- Select — SuperCollider 3.14.0 Help
- Server — SuperCollider 3.14.0 Help
- SynthDef — SuperCollider 3.14.0 Help
- SampleDur — SuperCollider 3.14.0 Help
- LinExp — SuperCollider 3.14.0 Help
- Poll — SuperCollider 3.14.0 Help
