Loop in k-rate con istruzioni di stampa?
Siccome sono abbastanza handicappato nell’utilizzo del k-rate in csound e mi perdo sempre qualcosa, ho bisogno di una fase di test solida quando scrivo gli strumenti e l’unico modo (che conosco) su Csound è costruire un sistema di debug solido che non lascia spazio a dubbi sul funzionamento del motore.
Ho preparato un csd per ricordarmi ogni qual volta ho dei dubbi come funzionano i-rate e k-rate. Però è sempre il caso ricordarsi la differenza tra i due:
- Init‑pass (i‑time): qui vengono eseguiti tutti gli opcodes e le assegnazioni consentite solo a i‑rate; succede una sola volta quando lo strumento viene instanziato.
- Perf‑pass (k‑rate): qui avviene la generazione audio e il controllo a k‑rate, con cadenza determinata da kr e ksmps. Ogni k‑ciclo Csound aggiorna le k‑variabili e percorre il corpo dello strumento.
Oki grazie Tars per la semplicità di queste parole. Abbiamo bisogno adesso di una leggiadra spiegazione rattoppata delle istruzioni di stampa che ci fornisce il carissimo Csound:
i-rate | input | particolarità | Colonna 4 |
---|---|---|---|
uno o piu iarg | non è preciso, meglio printf | Dati 1,4 | |
prints | la stringa e gli iargs richiamati nella stringa | Dati 2,4 |
k-rate | input | particolarità |
---|---|---|
printk | itime, kargs | stampa valore preceduto da numero dello strumento |
printks | formato printf() a intervalli definiti | non può essere chiamato piu volte nello stesso k-rate. non funziona con i loop, while etc |
printsk | formato printf() | funziona che è una bomba |
println | formato printf() | è printsk ma con \n automatico |
poi ci sono printk2 e printks2, le versioni di printk e printks che hanno la peculiarità di stampare solo quando ricevono un bang. molto comodino.
Oki ho preparato questo test.csd molti simpatico. Il log è molto ordinato e comprensibile. Da notare le istruzioni di stampa a init-pass e quelli a perf-pass. Notare printks che stampa solamente al primo giro del loop.
<CsoundSynthesizer>
<CsOptions>
-n
</CsOptions>
<CsInstruments>
;----------------------------------------
; Impostazioni globali
;----------------------------------------
sr = 96000
ksmps = 1
nchnls = 2
0dbfs = 1
;----------------------------------------
; Creazione “tabelle sporche” con GEN02
;----------------------------------------
; GEN02: trasferisce dati dai p-fields in una function table
gi_active_octaves ftgen 0, 0, 8, -2, 60,62,64,65,67,69,71,72
gi_active_registers ftgen 0, 0, 4, -2, 1, 2, 3, 4
gi_octave_register_matrix ftgen 0, 0, 32, -2, 1,2,3,4, 1,2,3,4, 1,2,3,4, 1,2,3,4, 1,2,3,4, 1,2,3,4, 1,2,3,4, 1,2,3,4
;----------------------------------------
; Strumento: pulisce le tabelle a k-rate
;----------------------------------------
; dichiariamo un UDO con 6 parametri k‑rate:
; kfn, ktrig, kstart, kend, kstep, knumcols
instr AnalizzatoreArmonico
; bang a k-rate 10 Hz
kTrig metro p3*2 ; metro genera un bang (0→1→0) a k-rate
kCurrentTime times ; tempo assoluto in secondi a k-rate
kcountHowManyIfkTrig init 0
; array di numeri di tabella, k-rate
iArr[] = fillarray(gi_active_octaves, gi_active_registers, gi_octave_register_matrix)
iarrIdx = 0
prints "\n===========================================\n"
prints "\tlet's observe the tables at init-pass\n\n"
prints "gi_active_octaves\n"
ftprint gi_active_octaves
prints "\n"
prints "gi_active_registers\n"
ftprint gi_active_registers
prints "\n"
prints "gi_octave_register_matrix\n"
ftprint gi_octave_register_matrix
prints "\n===========================================\n"
prints "\tnow let's going on with the if k-rate!\n\n"
kLenArr = lenarray(iArr) ; conta quanti elementi (tabelle)
kcountHowManyIfkTrig += kTrig
if kTrig == 1 then ; al primo campione di ciascun bang
println "inside if n° %d\n",kcountHowManyIfkTrig
kBigIdx = 0 ; reset contatore esterno
LoopBig:
kfn = iArr[kBigIdx] ; numero di tabella corrente
println "\tPRINTSK bigLoop at k-cycle: %d and a-cycle: %d at abs time: %f", kCurrentTime*kr, kCurrentTime*sr, kCurrentTime
printks "\t\t*PRINTKS bigLoop at k-cycle: %d and a-cycle: %d at abs time: %f)\n\n",0, kCurrentTime*kr, kCurrentTime*sr, kCurrentTime
kLenTab = tableng(kfn) ; lunghezza di quella tabella a k-rate
kIdx = 0 ; reset contatore interno
LoopClear:
println "\t\t%d. PRINTSK LoopClear at k-cycle: %d and a-cycle: %d at abs time: %f", kIdx,kCurrentTime*kr, kCurrentTime*sr, kCurrentTime
printks "\t\t\t*PRINTKS LoopClear at k-cycle: %d and a-cycle: %d at abs time: %f\n \t\t\t*[[questo print si ripete un sola volta ogni if k-rate]]\n", 0,kCurrentTime*kr, kCurrentTime*sr, kCurrentTime
println "\n\t\t\t- before cleaning\n\t\t\t\tkIdx: %d, value: %d, kfn: %d\n", kIdx, tablekt(kIdx,kfn), kfn
tablewkt 0, kIdx, kfn ; scrive zero nella tabella kfn
println "\t\t\t- after cleaning\n\t\t\t\tkIdx: %d, value: %d, kfn: %d\n", kIdx, tablekt(kIdx,kfn), kfn
loop_lt kIdx, 1, kLenTab, LoopClear ; ripeti finché kIdx<kLenTab
loop_lt kBigIdx, 1, kLenArr, LoopBig ; passa alla prossima tabella
println "finish if\n\n"
endif
endin
</CsInstruments>
<CsScore>
; esegui lo strumento per 3 secondi
i "AnalizzatoreArmonico" 0 1
e
</CsScore>
</CsoundSynthesizer>