Pure Data | Organelle | Max/MSP | Q&A

da haben wir uns wohl gekreuzt.
mit check ich nicht meinte ich dass ich nicht checke was genau du meinst.
meinst du dass es egal sein soll ob es 3 oder 4 slider sind? in meinem beispiel funktioniert das.
 
Also die Singularität habe ich jetzt im Griff. Dafür stürzen die Massen früher oder später aber ineinander...



Aber so im Großen und Ganzen läuft es schon ganz gut mit dem Tanz der Planeten. Vielleicht platziere ich einfach eine sehr große (unsichtbare) Masse im Zentrum des Systems? Gerade groß genug, damit nichts abhauen kann?
 
Jetzt auch mit wirr tanzendem Black-Hole:

1746864595470.png

Ich muss jetzt aufhören damit...
 
Zuletzt bearbeitet:
Du hast ja so Recht. Es ist halt einfach zu faszinierend. Jetzt gerade habe ich einen "Respawn-Modus" eingebaut. Mit einer extremen Masse in der Mitte die alles im Umkreis schluckt. Aber dann (aufgrund der mathematisch entstehenden Singularität) extrem beschleunigt. Eine Dämpfung die dann wiederum greift lässt den Körper dann wieder im gesetzten Wertebereich, relativ zur nach Einstein unmöglich zu erreichten Geschwindigkeit, aufploppen. Was man damit alles machen kann.

Aber ich muss damit jetzt wirklich aufhören. Letztendlich ist das alles sowieso nur eine andere Art von berechnetem "Zufall". Ein anderes Zufallsverhalten sozusagen. Aber da kann der Mensch eh nicht so wirklich unterscheiden. Aber spannend ist es trotzdem.
 
mit sinus ud rauschen/drunk habe ich es nicht so.

aber chaotische attraktoren z.b. sind musikalisch gut einsetzbar, weil sie quasi-periodisch bzw. selbstähnlich sind.
 
Wenns wen interessiert:


Läuft aber aktuell nur unter Linux. Wer es mal testen will: im Unterverzeichnis app liegt ein auf Node basierender Server. Da kann man sich dann im Browser die fliegenden Kringel anschauen.

Das schwarze Loch könnte noch einen Bug haben. Wer Lust, Interesse und Know How hat kann mal versuchen die Binaries unter Windows oder Mac zu erstellen. Das Makefile (make debug/release) sollte vorbereitet sein. Mangels Betriebssystemen konnte ich das bisher aber nicht testen. Jetzt muss ich mit nur noch eine Build-Umgebung für den Raspi bauen, dann läuft die Extension auch auf dem Organelle.
 
Hier mein erster komplett selbst designter und entwickelter Synthi. Audio Host ist aktuell Pure Data. Geplant ist aber zumindest noch LV2.

Angefangen habe ich mit dem Thema, weil ich einen Supersaw in PD haben wollte. 6 Wochen später ist dann ein Ding herausgekommen, das den JP8000 als Vorbild hat.

Die Organelle-Version (plus kurze Beschreibung) gibt's hier: https://patchstorage.com/jpvoice-demo-for-organelle/

Die Linux-Version hängt hier am Beitrag. Pure Data auf dem Linux-Desktop reicht. Im Patch gibt das main-oui.pd, welches ein UI ähnlich zum Organelle bereitstellt. Ist nicht komfortabel, aber für die Entwicklung reicht es.

Sollte es jemand testen: Feedback würde mich freuen. Ich habe recht viel Zeit reingesteckt. Die letzten Tage habe ich mit der Entwicklung eines Reverbs verbracht. Es ist noch nicht fertig, aber man kann es als Plate und auch als Dreamy-Cloud nutzen. Mir gefällt es bis jetzt. Ein paar Sachen fehlen aber noch. Die Sound-Engine ist so weit aber eigentlich fertig. Ein paar Effekte werden noch dazu kommen, und natürlich Modulation. Wie der JP8000 sollen zwei LFOs zur Verfügung stehen.
 

Anhänge

  • linux_x64.zip
    1,1 MB · Aufrufe: 1
So, fertig. In vier Monaten einen kompletten JP-8000-Style Synth "from scratch" hochgezogen. PD ist "nur" noch Audio-Host und MIDI-Lieferant. Steile Lernkurve mit ganz viel Spaß dabei gehabt. Jetzt bin ich wieder etwas besser im Thema c/c++.

Anbei die Linux-Version. Die Organelle-Version gibt's hier:


Ab jetzt wird wieder Musik gemacht. Wobei das coden in c natürlich ganz neue DSP-Welten eröffnet... Aber ich bleibe jetzt hart.
 

Anhänge

  • linux_x64.zip
    3,6 MB · Aufrufe: 0
Ich bin schier am verzweifeln. Ich integriere gerade meine neu DSP-Infrastruktur in PD. Zwei Externals (adsr und lfo). Annähernd identisch, aber beim lfo haut PD eine Puffer-Warnung raus.

Das Problem sitzt wahrscheinlich vorm Monitor. Ich kann den Fehler nicht finden:

Registrierungprozess LFO:

Code:
t_int *lfo_tilde_perform(t_int *w)
{
    t_lfo_tilde *x = (t_lfo_tilde *)(w[1]);

    x->lfo->process();

    return (w + 4);
}

void lfo_tilde_dsp(t_lfo_tilde *x, t_signal **sp)
{
    t_sample *out = sp[0]->s_vec;
    x->samplerate = sp[0]->s_sr;
    x->blockSize = sp[0]->s_n;

    DSP::initializeAudio(x->samplerate, x->blockSize);

    x->lfo->initialize(dsp_math::unique_string_id("lfo"));
    x->lfo->setMode(LFOMode::Buffered);

    x->lfo->connectOutputToBus(DSPBusManager::registerModulationBus(x->lfo->getName() + "_bus", out));

    dsp_add(lfo_tilde_perform, 3, x, sp[0]->s_vec, sp[0]->s_n);
}

void *lfo_tilde_new(t_floatarg f)
{
    t_lfo_tilde *x = (t_lfo_tilde *)pd_new(lfo_tilde_class);

    DSP::registerLogger(&log);

    x->lfo = new LFO();
    x->lfo->setIdleSignal(f);
    x->lfo->onPhaseWrap = [x]()
    {
        outlet_bang(x->x_out_bang);
    };

    x->x_out_sig = outlet_new(&x->x_obj, &s_signal);
    x->x_out_bang = outlet_new(&x->x_obj, &s_bang);

    return (void *)x;
}

void lfo_tilde_free(t_lfo_tilde *x)
{
    delete x->lfo;
}

extern "C"
{
    void lfo_tilde_setup(void)
    {
        lfo_tilde_class = class_new(gensym("lfo~"),
                                    (t_newmethod)lfo_tilde_new,
                                    (t_method)lfo_tilde_free,
                                    sizeof(t_lfo_tilde),
                                    CLASS_DEFAULT,
                                    A_DEFFLOAT,
                                    0);
                                   
        class_addmethod(lfo_tilde_class, (t_method)lfo_tilde_dsp, gensym("dsp"), A_CANT, 0);
        CLASS_MAINSIGNALIN(lfo_tilde_class, t_lfo_tilde, inletValue);

        class_addmethod(lfo_tilde_class, (t_method)lfo_tilde_setfreq, gensym("freq"), A_DEFFLOAT, A_NULL);
        class_addmethod(lfo_tilde_class, (t_method)lfo_tilde_settype, gensym("type"), A_DEFFLOAT, A_NULL);
        class_addmethod(lfo_tilde_class, (t_method)lfo_tilde_setoffset, gensym("offset"), A_DEFFLOAT, A_NULL);
        class_addmethod(lfo_tilde_class, (t_method)lfo_tilde_setdepth, gensym("depth"), A_DEFFLOAT, A_NULL);
        class_addmethod(lfo_tilde_class, (t_method)lfo_tilde_setshape, gensym("shape"), A_DEFFLOAT, A_NULL);
        class_addmethod(lfo_tilde_class, (t_method)lfo_tilde_setpw, gensym("pw"), A_DEFFLOAT, A_NULL);
        class_addmethod(lfo_tilde_class, (t_method)lfo_tilde_setsmooth, gensym("smooth"), A_DEFFLOAT, A_NULL);
        class_addmethod(lfo_tilde_class, (t_method)lfo_tilde_unipolar, gensym("unipolar"), A_DEFFLOAT, A_NULL);
        class_addmethod(lfo_tilde_class, (t_method)lfo_tilde_reset, gensym("reset"), A_NULL);
    }
}

Registrierungprozess ADSR:

Code:
t_int *adsr_perform(t_int *w)
{
    t_adsr_tilde *x = (t_adsr_tilde *)(w[1]);

    x->adsr->process();
   
    return (w + 4);
}

void adsr_dsp(t_adsr_tilde *x, t_signal **sp)
{
    t_sample *out = sp[0]->s_vec;
    x->samplerate = sp[0]->s_sr;
    x->blockSize = sp[0]->s_n;
   
    DSP::initializeAudio(x->samplerate, x->blockSize);
   
    x->adsr->initialize(dsp_math::unique_string_id("adsr"));

    x->adsr->connectOutputToBus(DSPBusManager::registerModulationBus(x->adsr->getName() + "_bus", out));

    dsp_add(adsr_perform, 3, x, sp[0]->s_vec, sp[0]->s_n);
}

// === Object constructor ===
void *adsr_new(t_floatarg f)
{
    t_adsr_tilde *x = (t_adsr_tilde *)pd_new(adsr_tilde_class);
    x->x_out = outlet_new(&x->x_obj, &s_signal);

    DSP::registerLogger(&log);

    x->adsr = new ADSR();
    x->adsr->setStartAtCurrent(f != 0);

    return (void *)x;
}

void adsr_tilde_free(t_adsr_tilde *x)
{
    delete x->adsr;
}

extern "C"
{
    void adsr_tilde_setup(void)
    {
        adsr_tilde_class = class_new(gensym("adsr~"),
                                     (t_newmethod)adsr_new,
                                     (t_method)adsr_tilde_free,
                                     sizeof(t_adsr_tilde),
                                     CLASS_DEFAULT,
                                     A_DEFFLOAT,
                                     0);

        class_addmethod(adsr_tilde_class, (t_method)adsr_dsp, gensym("dsp"), A_CANT, 0);
        CLASS_MAINSIGNALIN(adsr_tilde_class, t_adsr_tilde, inletValue);

        class_addmethod(adsr_tilde_class, (t_method)adsr_trigger_start, gensym("start"), A_NULL);
        class_addmethod(adsr_tilde_class, (t_method)adsr_trigger_stop, gensym("stop"), A_NULL);
        class_addmethod(adsr_tilde_class, (t_method)adsr_attack, gensym("attack"), A_DEFFLOAT, A_NULL);
        class_addmethod(adsr_tilde_class, (t_method)adsr_decay, gensym("decay"), A_DEFFLOAT, A_NULL);
        class_addmethod(adsr_tilde_class, (t_method)adsr_sustain, gensym("sustain"), A_DEFFLOAT, A_NULL);
        class_addmethod(adsr_tilde_class, (t_method)adsr_release, gensym("release"), A_DEFFLOAT, A_NULL);
        class_addmethod(adsr_tilde_class, (t_method)adsr_attackshape, gensym("attackshape"), A_DEFFLOAT, A_NULL);
        class_addmethod(adsr_tilde_class, (t_method)adsr_releaseshape, gensym("releaseshape"), A_DEFFLOAT, A_NULL);
        class_addmethod(adsr_tilde_class, (t_method)adsr_g, gensym("g"), A_DEFFLOAT, A_NULL);
        class_addmethod(adsr_tilde_class, (t_method)adsr_oneshot, gensym("oneshot"), A_DEFFLOAT, A_NULL);
    }
}

Vielleicht hat jemand von euch ja Rat...
 
Zuletzt bearbeitet:
overflow oder underrun? oder sagt pd dir das nicht.

ich könnte ja schwören, dass du mit dem coden eine pause machen wolltest...


wenn ich das gerade mal im browser nebeneinanderlege dann ist hier der erste unterschied:

x->lfo->setMode(LFOMode::Buffered);

ob man das wirklich groß schreiben muss?
 
Zuletzt bearbeitet:
Ja, das will ich auch. Es ist allerdings nicht so, dass ich so ca. 1000 Ideen für sonst was habe. Aber ich habe jetzt eine gute, modulare, performante und stabile Basis. Allerdings bin ich auch gerade etwas Coding-müde. Der nächste Sprung ist dann Core Audio/LV2/VST und ein Wechsel auf wahrscheinlich den Zynthian. Für den ganzen Boilerplate-Code und Doku kann man mittlerweile glücklicherweise KI ganz gut einsetzen. Sonst wäre das in der Komplexität für einen Einzelkämpfer gar nicht möglich.

Aber nach meiner letzten Optimierung muss ich jetzt noch meine PD-Externals auf Vordermann bringen damit ich das für mich auch ordentlich abgeschlossen habe. Das hat auch alles so weit funktioniert, nur der LFO will nicht.

Ich habe nur diese Information: warning: buffer: multiply defined

Das kommt ein Mal pro Block. Interessanterweise funktioniert der LFO und gibt das korrekte Signal am Outlet aus. Beim ADSR mit einer fast identischen Code-Basis ist das kein Problem. Vielleicht muss ich aber doch dort suchen, auch wenn es mir gerade mehr als unwahrscheinlich erscheint, dass da was falsch ist.

Schaut man im PD-Source nach ist das eher eine generische Meldung. Vielleicht muss ich mir das mal Debug-fähig bauen um dem Fehler auf die Spur zu kommen.
 


Neueste Beiträge

News


Zurück
Oben