Neu

Interessiert an einem Austausch zum Thema DSP-Entwicklung?

Interessiert an einem Austausch zum Thema DSP-Entwicklung?

  • Gar kein Interesse, ich mach lieber Musik

    Stimmen: 4 16,7%
  • Interesse schon, aber kein interesse an einem Austausch

    Stimmen: 2 8,3%
  • Spannendes Thema, auf jeden Fall

    Stimmen: 18 75,0%

  • Umfrageteilnehmer
    24
  • Umfrage geschlossen .
  • #62
Sehr interessantes Video über die Nachbildung von Synthesizer DSPs auf Softwarebasis.

 
  • #63
Ich arbeite komplett Block-basiert. Da dürfte das etwas schwierig werden.

Fast alle Speichermedien und Netzwerkprotokolle arbeiten in der untersten Schicht blockbasiert. Und wenn der ganze Kram gut designt ist, dann u. U. eine drüberliegende Schicht eben nicht.

Allerdings gebe ich dir recht, das dürfte etwas aufwändiger in der Implementierung sein als eine rein blockbasierte Vorgehensweise. Sie hätte aber eben auch Vorteile, würde aber mehr Rechenzeit kosten.
 
  • Zustimmung
M.i.a.u.: claudio
  • #64
Hier findet man interessante Vorträge zum Thema:

Stefan Stenzel (ex Waldorf) über "band limited impulse trains", wahrscheinlich aus der Streichfett-Entwicklung heraus:
 
  • hilfreich
M.i.a.u.: claudio, PhonicGate und Dagalos
  • #66
Berichte mal nachher, ob du damit zufrieden bist.
Gestern hatte ich mal zwei Stunden Zeit und habe zwei Ansätze für die Verkürzung getestet:

Das letzte Sample nach der Verkürzung linear auf das erste Sample im Puffer interpolieren. Ziemlich trivial mit
Code:
size_t fadeLen = 10 * DSP::SAMPLERATE_MS; // 10 ms cross fade zeit fix

signal target = buffer[0]; // erstes sample im puffer
signal start = buffer[newSize - 1]; //letztes sample nach verkürzung
signal phaseInc = 1.0f / static_cast<signal>(fadeLen);
signal fade = 0.0f;

for (size_t i = 0; i < fadeLen; ++i)
{
    buffer[i] = start * (1.0f - fade) + target * fade;
    fade += phaseInc;
}

Das Log zeigt eine perfekte Interpolation, nur leider bleiben die Crackels. Ich vermute, dass ich das so nicht machen kann, da das zwar eine tolle Transition ist, leider aber wohl eine Diskontinuität in der Phase erzeugt. Stattdessen habe ich versucht die Phasen zu interpolieren (buffer[newSize - 1], buffer[newSize - 2], buffer[1], buffer[0]). Brachte auch nix. Das lässt sich mit 4 Samples wahrscheinlich auch nicht umsetzen.

Nachtrag: Allerdings frage ich mich, ob die Phase wirklich ein Problem sein kann, das zu Knacksern führen kann.

Der nächste Versuch ist dann, Pufferende und Pufferanfang über die gesamte fadeLen zu überblenden. Mals ehen, ob's dann besser wird.

Noch ein Nachtrag: Schreib- und Lesekopf habe ich nicht neu positioniert. Das könnte natürlich DAS Problem sein...
 
Zuletzt bearbeitet:
  • Daumen hoch
M.i.a.u.: Dagalos
  • #68
Ich spreche hier von einem richtig harten Knacksen. Dass bei einer Irritation der Phase irgendwelche Artefakte entstehen können ist klar. Aber wirklich hartes Knacksen? Wir haben hier einen interpolierten Puffer.

Und bei einem Oszillator ist mir das auch noch nie aufgefallen. Allerdings wird hier ja mit der Frequenz sowieso die Phase geändert. Da muss der Sprung aber arg hoch sein, denke ich. Für mich eher ein theoretisches Problem. Aber man möge mich natürlich gern eines Besseren belehren, da ich ja noch am Anfang stehe.
 
  • #69
Habe ich ein Audio-Beispiel des Knacksens übersehen? Sonst könntest Du ja mal ein kurzes wav hochladen
 
  • #70
Habe ich ein Audio-Beispiel des Knacksens übersehen?
Nee, haste nicht. In meinem Beispiel wechsle ich den Grain-Pitch von Quinte auf Oktave (glaube ich). Da hätte man es hören können, allerdings war da der Puffer durchs Herumspielen wahrscheinlich schon angepasst.

Hier nochmal extrem von 0 auf 2 Oktaven ohne Crossfade, was eine vierfache Vergrößerung des Puffers (100ms => 400ms) bedeutet:
Anhang anzeigen recording_0.wav

Und ich habe jetzt auch erstmal alles reverted, da ich frustriert bin. Es sind immer mehr Fragen dabei entstanden. Wahrscheinlich muss ich das sowieso sauberer trennen. Dass es solch eine Pain ist, hätte ich nicht gedacht.

Grains und normales Delay sind unterschiedlich in der Nutzung. Das Delay sitzt stoisch immer auf dem ältesten Sample-Block (writehead + blocksize), während Grains random (Position im Puffer sowie Länge) das komplette Schnippsel jenseits des RT-Prozesses im Rahmen einer Parameter-Änderung für eine unabhängige Nutzung lesen und speichern.

Was mir aber klar geworden ist: das direkt im Puffer zu machen ist zwar schön einfach, bringt aber nichts. Der Writehead wird die interpolierten Samples früher oder später platt machen. Ich muss über die Zeit interpolieren/crossdfaden/was auch immer.

Problematisch nach einer Verkleinerung der Puffergröße (Time) ist die Neupositionierung des Writeheads, sollte er jenseitig liegen. Zur Erinnerung: der Readhead liegt einen Block weiter auf dem ältesten Sample-Block. Positioniere ich den Writehead also z. B. auf dem ersten Segment des Puffers, liegt der Delay-Readhead dann urplötzlich auf dem 2. Segement => Diskontinuität. Was genau muss ich da eigentlich Crossfaden? Den alten, jenseiten Block mit was? Der Block auf dem er nach der Grössenänderung sitzt kann sonstwas enthalten.

Vielleicht ist mein ganzes Konzept für den Ringpuffer basierend auf einem einfachem Modulo für den Wrap auf den ersten Block im Puffer auch viel zu hemdsärmlich/straight forward gedacht. Man findet erstaunlich wenig zu diesem Problem im Internet. Als würde es gar nicht existieren. Für mich immer ein Hinweis, dass ich wohl was Grundlegendes falsch mache. Konkrete Implementierungen kann ich so direkt auch keine finden.

Ich verschiebe das wohl erst mal.
 
  • #71
Für den Granulator habe ich das Problem jetzt erstmal gelöst, indem ich den Ringpuffer komplett leere nach einer Größenänderung. Die Grains laden sich die Samples ja sowieso in ihren eigenen Speicher.

Gerade sitze ich daran, die Modulation einzubauen. Meine Stimme am LFO, der den Pitch moduliert:

Anhang anzeigen mickeymouse.mp3

😆
 
  • #72
Arbeitet hier jemand mit Max Msp? Vor allem in Verbindung mit RNBO? Mich würde mal interessieren wie gut das funktioniert? Hat jemand Erfahrung damit?
 
  • #73
Gestern hatte ich mal zwei Stunden Zeit und habe zwei Ansätze für die Verkürzung getestet:

Das letzte Sample nach der Verkürzung linear auf das erste Sample im Puffer interpolieren. Ziemlich trivial mit
Code:
size_t fadeLen = 10 * DSP::SAMPLERATE_MS; // 10 ms cross fade zeit fix

signal target = buffer[0]; // erstes sample im puffer
signal start = buffer[newSize - 1]; //letztes sample nach verkürzung
signal phaseInc = 1.0f / static_cast<signal>(fadeLen);
signal fade = 0.0f;

for (size_t i = 0; i < fadeLen; ++i)
{
    buffer[i] = start * (1.0f - fade) + target * fade;
    fade += phaseInc;
}

Das Log zeigt eine perfekte Interpolation, nur leider bleiben die Crackels. Ich vermute, dass ich das so nicht machen kann, da das zwar eine tolle Transition ist, leider aber wohl eine Diskontinuität in der Phase erzeugt. Stattdessen habe ich versucht die Phasen zu interpolieren (buffer[newSize - 1], buffer[newSize - 2], buffer[1], buffer[0]). Brachte auch nix. Das lässt sich mit 4 Samples wahrscheinlich auch nicht umsetzen.

Nachtrag: Allerdings frage ich mich, ob die Phase wirklich ein Problem sein kann, das zu Knacksern führen kann.

Der nächste Versuch ist dann, Pufferende und Pufferanfang über die gesamte fadeLen zu überblenden. Mals ehen, ob's dann besser wird.

Noch ein Nachtrag: Schreib- und Lesekopf habe ich nicht neu positioniert. Das könnte natürlich DAS Problem sein...

Weiß gar nicht, ob das Thema noch aktuell ist. Bei deiner oben beschriebenen Lösung sehe ich aber mindestens noch zwei problematische Punkte. Eine lineare Rampe von 10ms ist ja selbst noch im Audiobereich. D.h. idealerweise musst du erstens die Rampe selbst bandbreitenbegrenzen (sie ist ja quasi ein Viertel einer Dreiecksschwingung), sonst bekommst du Aliasing. Außerdem hast du natürlich nach wie vor das Problem, dass du in der 1. Ableitung der Rampe einen Knick hast. Es gibt wohl verschiedene Verfahren, das zu umgehen, wie Raised-Cosine, Hann oder Half-Sine-Fade zu nutzen, aber da bin ich jetzt auch kein Experte.

Bei einer Änderung der Pufferlänge würde ich jetzt aber intuitiv sowieso ein Beschleunigen/Verlangsamen der Abspielgeschwindigkeit implementieren bis die neue Pufferlänge erreicht ist. Das machen ja viele Delays auch so, dass sie quasi das Verhalten eines Band-Delays simulieren. Rein intuitiv würde ich auch da sagen, dass die Änderung der Samplerate dann aber nicht einer linearen Rampe folgen sollte, sonder am Besten eine Art viertel Sinus ist.
 
  • Daumen hoch
  • hilfreich
M.i.a.u.: _thomas_, Scenturio und DanReed
  • #74
Arbeitet hier jemand mit Max Msp? Vor allem in Verbindung mit RNBO? Mich würde mal interessieren wie gut das funktioniert? Hat jemand Erfahrung damit?
Ich weiß nicht genau, was du mit der Frage meinst, aber ja, es funktioniert gut :)

Bei neuen Devices versuche ich alles in RNBO zu machen, da ich es potentiell dann leicht auf Hardware wie das Push oder einen Raspberry bringen kann. Mann muss sich etwas umgewöhnen, da es ja nicht alle Objekte gibt, sonst ist es eh mehr oder wenige das gleiche. Polyphonie haben sie super gelöst, kein Poly-Wahnsinn mehr, man gibt nur an, wie viel Stimmen man haben möchte, fertig.
 
  • Daumen hoch
M.i.a.u.: AlexDozer
  • #75
Weiß gar nicht, ob das Thema noch aktuell ist.
Doch, ist es auf jeden Fall noch. Danke für deinen Tipp! Ich habe mich sehr viel (wenn die Zeit es zuließ) mit exakt dem befasst was du beschrieben hast. Als Freund allumfassender Lösungen habe ich sehr viel herumexperimentiert um dann am Ende festzustellen, dass manchmal nur ein Griff in die Kiste mit Tricksereien hilft.

Nur habe ich die ganzen Tricks halt noch nicht drauf.

Mein vielversprechendster Kandidat war bisher die Rampe aus der Historie der 1. und 2. Ableitung sowie der "Zukunft" zu interpolieren. Was aber dann zu Latenzen führt, wenn auch nur minimal.

Aktuell geht die Entwicklung aufgrund beruflicher Tätigkeiten nur langsam voran.
 
Zuletzt bearbeitet:

Neue Beiträge

Zurück
Oben