2 minute read

Riporto gli appunti e le considerazioni fatte nel processo di lavoro senza alterare l’autenticità del diario.


Descrizione dell'immagine
Plotting funzioni seno a frequenze diverse

Aggiunto dimensioni al dizionario globale. Operazione sulla frequenza.

        "dimensioni":{
            "frequenze": "PythagoreanSystem",
            "durate": [1],
            "ampiezze": [2]
        },

Migliorata classe Spazio aggiungendo PythagoreanSystem.

from PythagoreanSystem import PythagoreanSystem
class Spazio:
    def __init__(self, dizionario):
        self.sistema = eval(dizionario['frequenze'])
        self.durate = dizionario.get("durate", [])
        self.ampiezze = dizionario.get("ampiezze", [])
        self.frequenze = self.creaDimensioneFrequenze()

    def creaDimensioneFrequenze(self):
        return [freq for i in range(5, 14) for freq in self.sistema(i).frequencies]

Creata la Classe PythagoreanSystem presa in prestito dal repo tuning-systems che sto scrivendo.

from fractions import Fraction
class PythagoreanSystem:
    def __init__(self, octave=1, fundamental=32):
        self.fundamental = 2 ** octave
        self.ratios = self.generate_ratios()
        self.sort_ratios()  # Sort ratios based on their real value
        self.frequencies = self.calculate_frequencies()

    def generate_ratios(self):
        ratios = [Fraction(1, 1)]  # The fundamental is 1/1
        fifth_ratio = Fraction(3, 2)  # The ratio of a perfect fifth

        for _ in range(1, 53):  # Generate 53 intervals
            next_ratio = ratios[-1] * fifth_ratio
            # Reduce the ratio within the octave
            while next_ratio >= 2:
                next_ratio /= 2
            ratios.append(next_ratio)
        
        return ratios

    def calculate_frequencies(self):
        return [float(ratio * self.fundamental) for ratio in self.ratios]

    def sort_ratios(self):
        # Sort the ratios based on their real value
        self.ratios.sort(key=lambda ratio: ratio.numerator / ratio.denominator)

    def __repr__(self):
        return (f"PythagoreanSystem(fundamental={self.fundamental}, "
                f"ratios={self.ratios}, frequencies={self.frequencies})")

Funzione aggiornata della classe Comportamento.

    def calcolaPfield(self):
        # Ciclo attraverso gli attributi dinamici che iniziano con "pfield"
        for i in range(4, len(self.lista_tuples[2:]) + 2):  # Iniziamo da 3 per "pfield3"
            pfield_attr = f"pfield{i-1}"
            # Verifica se l'attributo esiste
            if hasattr(self, pfield_attr):
                # Recupera l'espressione come stringa o valore dall'attributo
                raw_value = getattr(self, self.lista_tuples[i][0])
                try:
                    # Valuta il valore se è una stringa, altrimenti usa direttamente l'oggetto
                    evaluated_value = eval(raw_value[0]) if isinstance(raw_value, list) else raw_value
                    # Se è una classe, crea un'istanza passando i valori richiesti
                    if callable(evaluated_value):
                        # Supponendo che i parametri richiesti siano, ad esempio, `self.pfield2`
                        instanceFunc = evaluated_value(raw_value[1],raw_value[2],raw_value[3],raw_value[4])  # Passa i valori come richiesto dalla classe
                        funzione = instanceFunc.crea_funzione()
                    else:
                        offsetFreq = evaluated_value
                        instanceFunc = None
                except Exception as e:
                    raise ValueError(f"Errore nel creare un'istanza da {raw_value}: {e}")

                cycled_ritmo = cycle(self.ritmo)
                # Usa la lunghezza di pfield2 per il ciclo
                for _ in range(len(self.pfield2)):  
                    if isinstance(instanceFunc, Funzione):
                    # Assegna i valori dinamicamente
                        valore = funzione(next(cycled_ritmo))
                    else:
                        # parte statica che va modificata
                        larghezzaLista = int(self.durataArmonica)
                        offsetIntervallo = int(offsetFreq*53/3) #andrebbe a terzi d'ottava
                        sottoinsieme_frequenze = self.spazio.frequenze[offsetIntervallo:(offsetIntervallo+larghezzaLista)]
                        valore = sottoinsieme_frequenze[next(cycled_ritmo)  % len(sottoinsieme_frequenze)]
                    getattr(self, pfield_attr).append(valore)  

Rimodellato EventoSonoro che popola una lista che uscirà su Csound attraverso il metodo toCsoundStr.

class EventoSonoro:
    def __init__(self, dizionario):
        self.dizionario = dizionario
        #pdb.set_trace()
        self.lista_tuples = list(dizionario.items())
        self.generaAttributi()

    def generaAttributi(self):
        # Itera su tutta la lista di tuple, partendo dall'indice 0
        for _, (chiave, valore) in enumerate(self.lista_tuples):
            # Assegna sempre dinamicamente l'attributo
            setattr(self, chiave, valore)
            # Crea dinamicamente un attributo "pfield{i}" solo se i >= 3

    def toCsoundStr(self):
        # Genera una stringa in formato Csound, partendo dall'ordine degli attributi in lista_tuples
        csound_str = "i1"  # Tipo di evento sonoro (i1 rappresenta un evento sonoro)
        for chiave, _ in self.lista_tuples:
            # Escludi l'attributo 'idEventoSonoro'
            if chiave != "idEventoSonoro":
                valore = getattr(self, chiave)
                csound_str += f"\t{valore}"
        return csound_str

E questa è la versione del reporitory allo stato di lavoro del diario.