Einen Akkord programmieren



  • Wenn es wie ein bestimmtes Instrument klingen soll musst du dazu noch die passenden Obertöne (also die gleichen Frequenzen * n) dazuaddieren. Wenn ich mich richtig entsinne waren es bei Blaßinstrumenten vor allem Obertöne ungerader Ordnung und bei Saiteninstrumenten Obertöne mit gerader Ordnung.



  • Storm.Xapek.de schrieb:

    Wenn es wie ein bestimmtes Instrument klingen soll musst du dazu noch die passenden Obertöne (also die gleichen Frequenzen * n) dazuaddieren. Wenn ich mich richtig entsinne waren es bei Blaßinstrumenten vor allem Obertöne ungerader Ordnung und bei Saiteninstrumenten Obertöne mit gerader Ordnung.

    und noch 'ne passende, sogenannte 'ADSR-hüllkurve' drüberlegen.
    🙂



  • Storm.Xapek.de schrieb:

    Wenn es wie ein bestimmtes Instrument klingen soll musst du dazu noch die passenden Obertöne (also die gleichen Frequenzen * n) dazuaddieren. Wenn ich mich richtig entsinne waren es bei Blaßinstrumenten vor allem Obertöne ungerader Ordnung und bei Saiteninstrumenten Obertöne mit gerader Ordnung.

    http://cnx.org/content/m12589/latest/

    heutzutage (so seit 25 jahren) macht man aber coolere sachen
    http://lab.andre-michelle.com/karplus-strong-guitar
    http://en.wikipedia.org/wiki/Karplus-Strong_string_synthesis



  • ^^alter hut: http://www.falstad.com/dfilter/
    (filter-typ auf 'plucked string' stellen)
    🙂



  • Kann mir jemand noch ein wenig weiter helfen? Irgendwie verstehe ich das ganze nicht.
    Also wenn ich 3 Frequenzen habe, wie kann die zu einem Akkord zusammenfuehren? Also z.B.

    frequenzen = [400.0, 500.0, 600.0];
    float akkord;
    for (float freq : frequenzen) {
        akkord = ...??
    }
    


  • DEvent schrieb:

    Also wenn ich 3 Frequenzen habe, wie kann die zu einem Akkord zusammenfuehren?

    von allen 3 frequenzen ein sample berechnen, alles addieren und abspeichern. dann das das nächste sample usw. oben hab ich 'ne funktion gepostet, die genau das macht (mit sinussen).
    🙂



  • ;fricky schrieb:

    DEvent schrieb:

    Also wenn ich 3 Frequenzen habe, wie kann die zu einem Akkord zusammenfuehren?

    von allen 3 frequenzen ein sample berechnen, alles addieren und abspeichern. dann das das nächste sample usw. oben hab ich 'ne funktion gepostet, die genau das macht (mit sinussen).
    🙂

    Mein Generator ist darauf ausgelegt aus einer Frequenz die samples zu erzeugen. Kann man also aus 3 Frequenzen eine Frequenz berechnen, die den Akkord representiert?

    Also so z.B.

    frequenzen = [400.0, 500.0, 600.0];
    
    float getAkkordFrequenz(List frequenzen) {
        float akkord;
        for (float freq : frequenzen) {
            akkord = ...??
        }
        return akkord;
    }
    
    // erstellt den byte-stream aus den von getAkkordFrequenz()
    // berechneten Akkord
    byte[] getSamples(float frequenz) {
        // mit sinus und so
    }
    


  • DEvent schrieb:

    Kann man also aus 3 Frequenzen eine Frequenz berechnen, die den Akkord representiert?

    nee, ein akkord besteht aus mehreren tönen (normalerweise 3), daraus kannste nicht eine frequenz machen.
    beispiel: http://img402.imageshack.us/img402/3549/unbenanntzx.jpg
    (300, 400 und 500 Hz)



  • ;fricky schrieb:

    DEvent schrieb:

    Kann man also aus 3 Frequenzen eine Frequenz berechnen, die den Akkord representiert?

    nee, ein akkord besteht aus mehreren tönen (normalerweise 3), daraus kannste nicht eine frequenz machen.
    beispiel: http://img402.imageshack.us/img402/3549/unbenanntzx.jpg
    (300, 400 und 500 Hz)

    Danke, jetzt verstehe ich.
    Wie kann man den berechnen wieviele samples man fuer eine volle Schwing braucht?
    Z.b. bei den Frequenzen 300, 400 und 500 wiederholt sich die Schwingung bei samples ca. 882

    Bei einer normalen Sinuswelle ist es
    samples = samplingRate / frequency
    Bei einer samplingRate von 44100Hz und einer Frequenz von 300Hz sind es 147 samples. Und wie berechnet man das bei einem Akkord von x Frequenzen?



  • DEvent schrieb:

    Wie kann man den berechnen wieviele samples man fuer eine volle Schwing braucht?

    ganz einfach: anzahl_samples = samplingrate/frequenz. also z.b. bei 'ner samplingrate von 22050 samples/s und einer frequenz von 1000Hz bekommste 22050/1000 = 23(aufgerundet) samples für eine volle schwingung.
    🙂



  • ;fricky schrieb:

    DEvent schrieb:

    Wie kann man den berechnen wieviele samples man fuer eine volle Schwing braucht?

    ganz einfach: anzahl_samples = samplingrate/frequenz. also z.b. bei 'ner samplingrate von 22050 samples/s und einer frequenz von 1000Hz bekommste 22050/1000 = 23(aufgerundet) samples für eine volle schwingung.
    🙂

    Und bei einem Akkord von 3 Frequenzen?



  • DEvent schrieb:

    Und bei einem Akkord von 3 Frequenzen?

    versuch doch mal die samples für jede frequenz einzeln auszurechnen und berechne dann das kleinste gemeinsame vielfache. das dürfte der erste gemeinsame nulldurchgang nach dem start sein. was gescheiteres fällt mir jetzt auch nicht ein.
    🙂



  • so müsste es richtig gehen: http://www.physik.uni-kl.de/ziegler/Skripte/Exphys-BC-4_1-4_3.pdf
    (ab seite 66, verschiedene frequenzen, schwebung)
    🙂



  • ;fricky schrieb:

    DEvent schrieb:

    Und bei einem Akkord von 3 Frequenzen?

    versuch doch mal die samples für jede frequenz einzeln auszurechnen und berechne dann das kleinste gemeinsame vielfache. das dürfte der erste gemeinsame nulldurchgang nach dem start sein. was gescheiteres fällt mir jetzt auch nicht ein.
    🙂

    Das ist korrekt. Wenn es kein gemeinsames vielfaches außer 0 gibt (wie bei eigentlich jedem akkord in einer wohltemperierten stimmung) gibt es auch keine minimale samplezahl. in anderen stimmungen, in denen die verhältnisse der frequenzen immer rationale zahlen sind, geht das. Das ausrechnen der Schwebungsfrequenz reicht nicht aus, da die schwingung nicht zwingend translationsinvariant mit der periode der schwebungsfrequenz ist. (es mag aber eine gute näherung sein... )



  • Danke, ich denk ich habe es nun. Fuer die, die es interessiert:

    public getSinus(frequencies) {
            int samples = sampleRate / ggt(frequencies)
            float[] data = new float[samples]
            float period
            for (int x = 0; x < samples; x++) {
                float f = 0;
                for (def freq : frequencies)
                {
                	f = f + (Math.sin(2.0f * x * Math.PI / sampleRate * freq));
                }
                data[x] = f / frequencies.size();
            } 		
            return data
        }
    

    Wobei ggt(frequencies) den groesten gemeinsamen Teiler aus den uebgebenen Frequenzen liefert. Dies stammt aus dem Dokument, den fricky lieferte. Wenn sich jemand fuer den ggT interessiert, ich berechne ihn so:

    /**
         * Berechnung des ggT aus einer Liste aus Zahlen.
         */
        private static int ggt(values) {
        	if (values.size() > 2) {
        		return ggt(values[0], values[1..<values.size()])
        	} else {
        		return values[0]
        	}
        }
    
        /**
         * Berechnung des ggT aus einer Liste von Zahlen, wobei <code>value</code>
         * das erste Element aus der Liste der Zahlen ist.
         */
        private static int ggt(value, values) {
        	if (values.size() == 1) {
        		return ggt(value, values[0])
        	}
        	def t = ggt(values[0], values[1..<values.size()])
        	return t
        }
    
        /**
         * Berechnung des ggT zweier Zahlen 
         * nach dem Euklidischen Algorithmus
         */
        private static int ggt(int zahl1, int zahl2) {
            while (zahl2 != 0) {
                if (zahl1 > zahl2) {
                    zahl1 = zahl1 - zahl2;
                } else {
                    zahl2 = zahl2 - zahl1;
                }
            }
            return zahl1;
        }
    

    Ich wuerde noch gerne wissen wie man die Wellen einer Eckzahn-, Vierecks-, und Saegezahnfunktion addiert, so das ich auch da einen Akkord habe.



  • DEvent schrieb:

    Danke, ich denk ich habe es nun. Fuer die, die es interessiert:

    //...
                for (def freq : frequencies)
                {
                	f = f + (Math.sin(2.0f * x * Math.PI / sampleRate * freq));
                }
                data[x] = f / frequencies.size();
    //...
    

    (...)

    Ich wuerde noch gerne wissen wie man die Wellen einer Eckzahn-, Vierecks-, und Saegezahnfunktion addiert, so das ich auch da einen Akkord habe.

    Indem man statt Math.sin eine andere Funktion einsetzt, und sonst alles gleich lässt.
    Addieren bleibt Addieren, was soll sich da ändern?


Anmelden zum Antworten