Always on
Documentazione dell’Analizzatore e dei Calcoli di Durata
1. Funzionamento dell’Analizzatore nel Delta-Engine
L’Analizzatore nel sistema Delta-Engine è un componente fondamentale che monitora, traccia e registra l’evoluzione temporale della composizione generativa. È implementato principalmente attraverso due strumenti Csound:
instr Analizzatore
- Esegue analisi in tempo reale durante la generazioneinstr AnalisiFinale
- Esegue analisi finale e genera reportistica al termine della composizione
1.1 Analizzatore in Tempo Reale
Lo strumento Analizzatore
viene avviato all’inizio della composizione con il comando alwayson "Analizzatore"
e rimane attivo per tutta la durata della sessione. Le sue funzioni principali sono:
- Monitoraggio degli eventi attivi: Tiene traccia di quanti eventi sonori sono attivi simultaneamente in un dato momento, permettendo di calcolare la densità o “sovrapposizione” degli eventi.
- Campionamento periodico: Campiona lo stato del sistema a intervalli regolari (10Hz) per registrare l’evoluzione temporale della composizione.
- Comunicazione con il Comportamento: Condivide informazioni sulla sovrapposizione degli eventi attraverso variabili globali che vengono utilizzate dai Comportamenti per auto-regolarsi.
instr Analizzatore
; Analisi della sovrapposizione di eventi - eseguita a k-rate
kTrig metro 10 ; 10 Hz per avere una buona risoluzione temporale
if kTrig == 1 then
; Ottieni tempo corrente
kCurrentTime timeinsts
; Calcolo eventi attivi in questo momento
kActiveEventsCount = 0
; Analisi delle tabelle di eventi
kEventIdx = 0
while kEventIdx < gi_Index do ; gi_Index contiene il numero totale di eventi creati
kAttackTime table kEventIdx, gi_eve_attacco
kDuration table kEventIdx, gi_eve_durata
; Verifica se l'evento è attualmente attivo
if kAttackTime <= kCurrentTime && kAttackTime + kDuration >= kCurrentTime then
kActiveEventsCount += 1
endif
kEventIdx += 1
od
; Aggiorna la variabile globale per comunicare con il Comportamento
gk_current_overlap = kActiveEventsCount
; Memorizza il conteggio degli eventi attivi e il timestamp
tabw kActiveEventsCount, gk_analysis_index, gi_analysis_active_events
tabw kCurrentTime, gk_analysis_index, gi_analysis_timepoints
; Avanzamento ciclico nell'indice della tabella
gk_analysis_index = (gk_analysis_index + 1) % gi_analysis_buffer_size
endif
L’Analizzatore inoltre crea e aggiorna una “memoria compositiva” che tiene traccia dell’evoluzione temporale della composizione su una scala più ampia:
kMemTrig metro 1/gi_memory_resolution
if kMemTrig == 1 then
kCurrentTime timeinsts
kMemIdx = int(kCurrentTime / gi_memory_resolution)
if kMemIdx >= 0 && kMemIdx < gi_memory_size then
tabw gk_current_overlap, kMemIdx, gi_memory_overlap
tabw kActiveEventsCount, kMemIdx, gi_memory_events
endif
endif
1.2 Analisi Finale
Lo strumento AnalisiFinale
viene eseguito al termine della composizione e si occupa di:
- Esportare i dati raccolti in file CSV
- Calcolare statistiche sui dati raccolti
- Generare rappresentazioni grafiche attraverso script Python esterni
- Fornire un riassunto dell’evoluzione compositiva
instr AnalisiFinale
; Crea la directory per i risultati
iRes system_i 1, "mkdir -p ./docs/analysis", 0
; Esporta i dati di sovrapposizione in CSV
SdataFile = "docs/analysis/overlap_data.csv"
fprints SdataFile, "time,active_events\n"
; ... [codice per l'esportazione dei dati] ...
; Calcola e stampa statistiche di base
iMaxOverlap = 0
iOverlapSum = 0
; ... [calcolo delle statistiche] ...
; Avvia automaticamente l'analisi Python tramite make
prints "\nAvvio dell'analisi Python...\n"
iAnalysisRes system_i 1, "make analyze-all", 0
endin
2. UDO per il Calcolo della Durata nel Comportamento
Nel ciclo while
all’interno dello strumento Comportamento
, vengono utilizzati diversi UDO (User-Defined Opcodes) per calcolare la durata degli eventi. I più significativi sono:
2.1 analyzeCompositionMemory
Questo UDO analizza un intervallo specifico della memoria compositiva per estrarre informazioni sulla densità degli eventi:
opcode analyzeCompositionMemory, iiii, ii
iStartTime, iEndTime xin
; Calcola indici nella tabella di memoria
iStartIdx = int(iStartTime / gi_memory_resolution)
iEndIdx = int(iEndTime / gi_memory_resolution)
; Assicurati che gli indici siano entro i limiti
iStartIdx = limit(iStartIdx, 0, gi_memory_size-1)
iEndIdx = limit(iEndIdx, 0, gi_memory_size-1)
; Inizializza contatori
iSumOverlap = 0
iMaxOverlap = 0
iActivePoints = 0
iCount = 0
; Analizza il range temporale
iIdx = iStartIdx
while iIdx <= iEndIdx do
iOverlap table iIdx, gi_memory_overlap
if iOverlap > 0 then
iSumOverlap += iOverlap
iMaxOverlap = max(iMaxOverlap, iOverlap)
iActivePoints += 1
endif
iCount += 1
iIdx += 1
od
; Calcola valori aggregati
iAvgOverlap = (iActivePoints > 0) ? iSumOverlap / iActivePoints : 0
iDensity = (iCount > 0) ? iActivePoints / iCount : 0
xout iAvgOverlap, iMaxOverlap, iDensity, iCount
endop
Questo UDO restituisce quattro valori:
iAvgOverlap
- Sovrapposizione media nell’intervalloiMaxOverlap
- Sovrapposizione massima nell’intervalloiDensity
- Percentuale di punti attivi nell’intervalloiCount
- Numero totale di punti analizzati
2.2 suggestDurationFactor
Questo UDO utilizza l’analisi della memoria compositiva per suggerire un fattore di durata adattivo:
opcode suggestDurationFactor, i, iii
iStartTime, iEndTime, iRitmoCorrente xin
; Analizza la memoria compositiva nel range specificato
iAvgOverlap, iMaxOverlap, iDensity, iSampleCount = analyzeCompositionMemory(iStartTime, iEndTime)
; Se non abbiamo abbastanza dati o il range è vuoto, usa valori predefiniti
if iSampleCount < 2 || iDensity < 0.05 then
iSuggestedFactor = 1.0 ; Valore neutro
goto end
endif
; Altrimenti, suggerisci un fattore basato sull'analisi
iMaxReference = 8 ; Livello di riferimento per la sovrapposizione massima
iAvgReference = 3 ; Livello di riferimento per la sovrapposizione media
; Calcola un fattore basato sia sul massimo che sulla media
iFactorFromMax = 1.0 + (iMaxReference - iMaxOverlap) * 0.1
iFactorFromAvg = 1.0 + (iAvgReference - iAvgOverlap) * 0.2
; Combina i fattori dando più peso alla media
iSuggestedFactor = (iFactorFromMax + iFactorFromAvg * 2) / 3
; Limita il fattore all'intervallo desiderato
iSuggestedFactor = limit(iSuggestedFactor, 1.0, iRitmoCorrente)
end:
xout iSuggestedFactor
endop
Questo UDO è fondamentale per l’auto-regolazione del sistema: se la sovrapposizione di eventi è superiore ai valori di riferimento, suggerisce durate più brevi; se è inferiore, suggerisce durate più lunghe.
2.3 Applicazione nel Comportamento
Nel ciclo while
dell’istrumento Comportamento
, questi UDO vengono utilizzati per calcolare la durata di ogni evento:
; Calcola il lookback time (tempo da analizzare per l'adattamento)
iCurrentTime = i_time + i_CAttacco
iLookbackTime = max(0, iCurrentTime - 30) ; Guarda agli ultimi 30 secondi
; Ottieni il fattore di durata suggerito
i_OverlapFactor = suggestDurationFactor(iLookbackTime, iCurrentTime, i_RitmoCorrente)
; Durante la fase di bootstrap, utilizza durate maggiori
if gi_Index < 10 then ; Per i primi 10 eventi
prints "MODALITÀ BOOTSTRAP: Forzatura durata evento\n"
i_DurEvento = (i_DurataArmonica/i_RitmoCorrente) * 3.0
else
; Calcola la durata dell'evento con il fattore di adattamento
i_DurEvento = (i_DurataArmonica/i_RitmoCorrente) * i_OverlapFactor
endif
3. Funzionamento del Ciclo di Generazione dei Comportamenti
Il ciclo principale che genera i comportamenti si trova nello strumento Comportamento
e funziona così:
- Legge i parametri iniziali (ritmi, posizioni, ottave, ecc.)
- Inizia un ciclo che continua finché non viene raggiunta la durata desiderata
- Per ogni iterazione:
- Calcola il ritmo corrente (o lo genera usando la funzione
NonlinearFunc
se necessario) - Calcola il tempo di attacco
- Calcola l’ampiezza usando
calcAmpiezza
- Calcola la frequenza usando
calcFrequenza
- Determina la durata dell’evento in base all’analisi della sovrapposizione
- Memorizza i parametri nelle tabelle globali
- Pianifica l’evento sonoro
- Calcola il ritmo corrente (o lo genera usando la funzione
while i_time < i_Durata do
; Determina il ritmo corrente
if i_Index < i_LenRitmi then
i_RitmoCorrente tab_i i_Index, gi_comp_temp_ritmi
else
i_Vecchio_Ritmo tab_i i_Index-1, gi_comp_temp_ritmi
i_RitmoCorrente NonlinearFunc i_Vecchio_Ritmo
tabw_i i_RitmoCorrente, i_Index, gi_comp_temp_ritmi
endif
; ... [calcolo dei parametri] ...
; Calcola la durata dell'evento
i_OverlapFactor = suggestDurationFactor(iLookbackTime, iCurrentTime, i_RitmoCorrente)
i_DurEvento = (i_DurataArmonica/i_RitmoCorrente) * i_OverlapFactor
; ... [memorizzazione e scheduling] ...
i_Index += 1
gi_Index += 1
i_time = i_Pfield2 + i_DurEvento
od
4. Potenziali Miglioramenti
Per generare un nuovo comportamento a partire da quello iniziale, si potrebbero apportare i seguenti miglioramenti all’analizzatore:
- Analisi dei pattern emergenti: Rilevare schemi ricorrenti nella sovrapposizione e nella generazione dei ritmi.
- Clustering temporale: Identificare sezioni con caratteristiche simili e utilizzarle come semi per nuovi comportamenti.
- Apprendimento adattivo: Modellare come i fattori di durata influenzano l’evoluzione della composizione e utilizzare questi modelli per migliorare i suggerimenti.
- Transizioni tra comportamenti: Implementare logiche per transizioni fluide tra diversi comportamenti basate sullo stato corrente del sistema.
- Memoria a lungo termine: Estendere l’analisi oltre la semplice sovrapposizione per includere pattern melodici, ritmici e armonici.
Questi miglioramenti permetterebbero al sistema di evolvere in modo più complesso e organico, generando comportamenti che non sono semplicemente variazioni casuali, ma risposte adattive al contesto musicale emergente.