Einen Akkord programmieren
-
;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. 882Bei 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?