Portamento berechnen



  • Okay, ich versuch's.
    Mein aktuelles Programm zur Berechnung der Frequenz (* 10 für eine Nachkommastelle):

    uint32_t IRAM_ATTR getFreq(uint8_t note) {
      uint16_t freq[] = {654, 693, 734, 777, 824, 873, 925, 980, 1038, 1100, 1165, 1234};
      return freq[note % 12] << (note / 12);
    }
    

    Was genau ich machen möchte, ist, z.B. die Note 12.5 zu berechnen. Dafür könnte ich pow(2, (12.5 / 12)) * x rechnen, aber das ist zeitaufwändig. Ich könnte auch eine größere Tabelle nutzen mit z.B. 10tel-Tönen, aber dann könnte es ziemlich komisch kantig klingen, wenn ich einen Ton in den Halbton darüber übergehen lassen will und das über 2 Sekunden strecke. Generell bin ich gegen eine Tabelle.

    Beantwortet das deine Frage(n)?


  • Mod

    @NoobTracker sagte in Portamento berechnen:

    Beantwortet das deine Frage(n)?

    Ja. Wenn jetzt nicht gerade Freitag Abend wäre, bekämst du auch bestimmt eine Antwort 🙂

    Eine Frage hätte ich aber noch: Wieso 50000x pro Sekunde? Wenn das Frequenzen um die 1000 Herz sind, dann würdest du damit ja nach einem Bruchteil einer Schwingung schon die Frequenz wechseln. Kann dein Tongenerator überhaupt so schnell angesteuert werden?



  • Hallo,

    im C++ Standard gibt es noch die spezialisierte Funktion exp2.

    Aber versuche mal die Funktion get_scale aus den Antworten von Fast way to get a close power-of-2 number (floating-point).



  • @NoobTracker
    Hast du schon einen digitalen Filter ausprobiert?

    Je nach Größe des Filters sind die Verzögerungen relativ gering.

    Das Problem ist aber die Kompliziertheit. Mann muss schon wissen was Abtasttheorem, Fourier-, Laplacetransformation, FIR, IIR, lineare Gleichungssysteme, Butterworth Filter, Bandpass, Tiefpass,... sind.

    Im folgenden habe ich dir mal ein Github Projekt gelinkt.

    DSPFilters



  • @SeppJ 50000 Mal pro Sekunde kommen daher, dass das Programm mit 50 kHz arbeitet. Ich habe gleichzeitig bis zu 30 Stimmen (immer zwei im Doppelpack), da kann ich nicht so einfach den Timer verlangsamen. Außerdem ist das schon sinnreich, wenn ich nur 1000 Mal pro Sekunde die Frequenz berechnen würde, dann würde die Frequenz sich erst nach der durchlaufenen Wellenform ändern, das wäre ungenau und dieses Musikprogramm ist darauf ausgelegt, extrem genaue Ringmodulation und sowas verarbeiten zu können.



  • @Quiche-Lorraine Ich weiß nicht, was ein Filter bringen sollte. Ich habe schon einen, solange man auf die Resonanz verzichtet, ist ein Filter ja nur sowas wie filterValue = (newValue + (filterValue * filter)) / (filter + 1). Wenn man dann mit filterValue weiterrechnet, hat man einen Tiefpassfilter, wenn man mit newValue - filterValue rechnet, dann hat man einen Hochpassfilter und durch Kombination einen Bandpassfilter, soweit ich weiß.



  • @Th69 Puh, irgendwie verstehe ich das nicht, weil mein Englisch nicht das Beste ist und ich auch die Programme nicht verstehe.



  • Sorry, das war ein falscher Link von mir.

    Probiere mal fastapprox, s.a. Erklärung in Fast Approximate Logarithm, Exponential, Power, and Inverse Root (ist aber auch leider alles in englisch).
    Die Funktion heißt fastpow2 in fastexp.h.

    Ich habe auch noch Fast pow() With Adjustable Accuracy gefunden, aber das verwendet eine Lookup-Tabelle.

    Diese setzen beide auf Bitmanipulationen der Floating-Point-Repräsentation IEEE 754.
    Geht natürlich ein bißchen auf Kosten der Genauigkeit (accurency), aber das solltest du mal bei dir testen, ob das für deine Werte (und Wertebereich) ein Rolle spielt.



  • Schade, daß keine Antwort mehr kommt...



  • @Th69 Doch, doch, ich hatte nur den Link für's Forum verloren und nicht mehr danach gesucht.
    Ich habe mal ein wenig rumprobiert und konnte feststellen, dass ich meine Töne mithilfe eines 256-Wertearrays multiplizieren kann, sodass sie in den nächsten Ton übergehen. Mein Fehler war, dass ich dachte, dass ich meine Tabelle der untersten Oktave erweitern müsste. Darum dachte ich, dass man eine wirklich große Liste bräuchte, ein zwölftel reicht aber aus.