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 17,4%
  • Interesse schon, aber kein interesse an einem Austausch

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

    Stimmen: 17 73,9%

  • Umfrageteilnehmer
    23
  • Diese Umfrage wird geschlossen: .
  • #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.
 

News

Zurück
Oben