• Das Erstellen neuer Accounts wurde ausgesetzt. Bei berechtigtem Interesse bitte Kontaktaufnahme über die üblichen Wege. Beste Grüße der Admin

Spektrum passend zur Frequenzskala rendern.

xorg1990

New member
Hallo ich habe mal wieder ein mehr oder weniger kompliziertes Problemchen.

Ich komme bein rendern meines Spektranalysers nicht weiter. Und zwar stimmen die Anzeigen nicht überein ein, wenn ich ein 1000Hz Träger bringe komme ich in meinen Spektrum bei 1750Hz raus. Ich muss also irgendwas an der for Schleife machen, aber was keinen Plan.

Für die fft benutze ich die von audiolib.js
Die FFT Puffergröße ist 4096.
Die Samplerate ist 44100Hz.

Laut den Berechnung von dlyhf ist ein FFT Bin 10,76Hz wide.
44100/4096=10,76Hz FFT Bin Width.
Ich werde das Gefühl nicht los das ich irgendwas mit dem Wert machen muss um mein Problem zu lösen.

Die anzuzeigende Bandbreite ist in diesem Beispiel 15Khz, 0-15Khz.
Es sollen aber auch nur 100Hz Bandbreite möglich sein z.B 400-500Hz oder sogar noch kleiner 400.00Hz-400.10Hz, je nachdem was der User einstellt.

Der code wo das Rendern geschiet:
Code:
	Window.prototype.drawSpectrogram = function(){
	    	var FFT_Data =  this.Analyser1.spectrum;
            //var drawLength = FFT_Data.length < this.canvas_height ? this.canvas_height : FFT_Data.length;
            this.tempCtx.drawImage(this.waterCanvas, 0, 0, this.waterCanvas.width, this.waterCanvas.height);
             document.getElementById("ausgabe2a").innerHTML = "FFT value: "+ FFT_Data[4];
            for (var i = 0; i < this.waterCanvas.height; i++) {
                // draw each pixel with the specific color
                var value = FFT_Data[i];
                this.waterCanvasCtx.fillStyle = this.colors.getColor(value).hex();
               document.getElementById("ausgabe3").innerHTML = this.colors.getColor(value).hex();
                // draw the line at the right side of the canvas
               this.waterCanvasCtx.fillRect(this.waterCanvas.width - 1, this.waterCanvas.height - i, 1, 1);
            }
            // set translate on the canvas
            this.waterCanvasCtx.translate(-1, 0);
            // draw the copied image
            this.waterCanvasCtx.drawImage(this.tempCanvas, 0, 0, this.waterCanvas.width, this.waterCanvas.height, 0, 0, this.waterCanvas.width, this.waterCanvas.height);
            // reset the transformation matrix
            this.waterCanvasCtx.setTransform(1, 0, 0, 1, 0, 0);
            //draw the water canvas on the main cnavas 
            this.canvas_ctx.drawImage(this.waterCanvas,0,0,this.waterCanvas.width, this.waterCanvas.height);
     };
Ich denke doch das dieser Codeschnipsel reicht, das wesentliche passiert hier. Das ganze Prinzip stammt aus den smartjava Tutorial
Die Höhe das canvases bestimmt auch der User. Das kann 600px sein, kann aber auch 150px sein. Mir ist klar das man keine 15kHz auf ein 150px hohen canvas darstellen kann.

Noch ein Bildchen um sich das besser vorstellen zu können.
render.png
Die Frequenzskala ist im ein Separates canvas was über das "Main canvas" darübergelegt wird.

Mir ist beim schreiben noch was eingefallen:
Wenn ich ein Spektrum von 400-500hz darstellen möchte dann muss ja die Zählervariabele I nicht bei 0 anfangen sondern irgend wo höher. Dafür müsste man ja erst einmal herausfinden wo im FFT Array 400Hz anfangen.
Das Problem ist aber das die FFT Puffergröße nicht immer 4096 ist, sondern auch vom user eingestellt werden kann, aber immer um Faktor 2 Multipliziert.

Wenn ich den Kompletten Code liefern sol müsst ihr's nur sagen... ist halt nur ne Menge

Puh ganz schön viel stoff bin ja mal gespannt :dejection:
VG Xorg1990
 
Schade keiner hat eine Idee:(

das Rednern der Skala geht logarithmisch wie hier besprochen:
http://forum.jswelt.de/javascript/60107-dynamisch-anpassende-frequenzskala.html

dann habe ich noch raus bekommen wo im FFT Buffer 400Hz sind.
Mann muss nur die fft bin width durch 400Hz teilen . 400/10,76=37,17...
Wenn ich die for Schleife nun von 0 bis 37 zählen lasse hört das rendern bei 400hz auf allerdings nicht auf die gesamte canvas höhe.


Mann muss passend dazu noch in der FillRect Methode die höhe des Rechtecks einstellen sonst geht es ja nicht auf.


In Sl seht das dann so aus:
fft in sl.png
Wie man seiht ist der träger sehr breit.
Wenn mein canvas nun auch so aussehen würde habe ich alles richtig gemacht tut es aber leider nicht.


So kurz vorm Ziel und doch weit entfernt:crushed:
 
Das ist ziemlich speziell. Und Korbinian macht ein bisschen Forenpause wg. viel Arbeit. Wenn das hier nicht dringend ist würde ich es einfach nochmal pushen, wenn kkapsner wieder da ist. Voraussichtlich ab Mitte Januar ist er wieder hier. Wobei das nicht heißt, dass nicht jemand anders hier antworten darf/kann/soll!
Hast du hesst mal eine PN geschickt? Ich glaube, er kennt sich damit auch aus.
 
mikdoe schrieb:
Das ist ziemlich speziell.
Oh ja wie recht du hast, habe ich mir vor 2 Jahren auch gedacht das das einfacher geht einen online qrss viewer zu Programmieren.


mkidoe schrieb:
Und Korbinian macht ein bisschen Forenpause wg. viel Arbeit.
Oha der Arme jetzt zum Jahresende, wo jeder froh ist das es weniger wird mit der Arbeit. (zumiest die Bau Menschen).

mikdoe schrieb:
Hast du hesst mal eine PN geschickt? Ich glaube, er kennt sich damit auch aus.
nee noch nicht wollte nicht aufdringlich sein, mach ich gleich.
 
Zuletzt bearbeitet:
also viel zeit habe ich auch nicht. dann das übliche,
Und zwar stimmen die Anzeigen nicht überein ein, wenn ich ein 1000Hz Träger bringe komme ich in meinen Spektrum bei 1750Hz raus. Ich muss also irgendwas an der for Schleife machen, aber was keinen Plan.
damit kann ich nichts anfangen, was genau ist dein problem?
wenn ich es richtig verstanden habe, ist es die skalierung?
du hast die höhe des canvas (H).
du hast ein array.
du willst aus diesem array einen ausschnitt im canvas darstellen.
du musst den startindex berechnen (minA), also auf welchem index liegt die unterste darzustellende frequenz.
du musst den endindex berechnen (maxA), also auf welchem index liegt die oberste darzustellende frequenz.
anzahl der darzustellenden arrayeinträge L=maxA-minA+1
du willst also L punkte auf H pixel darstellen
for (i=0; i<H; ++i) // über alle pixel
{
arrayidx=minA+L/H*i; // arrayindex für pixel i
}
 
hesst schrieb:
wenn ich es richtig verstanden habe, ist es die skalierung?
Jo, das meinte ich.

du hast die höhe des canvas (H).
H=768;

du hast ein array.
Die FFT Array length ist 2048.


hesst schrieb:
du willst aus diesem array einen ausschnitt im canvas darstellen.
Jupp.

hesst schrieb:
du musst den startindex berechnen (minA), also auf welchem index liegt die unterste darzustellende frequenz.
Die FFT Puffergröße ist 4096.
Die Samplerate ist 44100Hz.
44100/4096=10,76Hz
Ein fft bin ist 10,76Hz wide.

Darstellen möchte ich 3000Hz bis 8000Hz.
Startindex = 3000Hz/10,76 = 278.81041 i =~279
Der Endindex ist demzufolge 743.
Ist das soweit richtig?


hesst schrieb:
anzahl der darzustellenden arrayeinträge L=maxA-minA+1
L= 464

hesst schrieb:
du willst also L punkte auf H pixel darstellen
genau so ist es.

hesst schrieb:
arrayidx=minA+L/H*i; // arrayindex für pixel i
Alles klar aber wo muss ich mit den Wert arrayidx hin oder anders gesagt wie muss die FillRect Methode aussehn? So:
this.waterCanvasCtx.fillRect(this.waterCanvas.width - 1, this.waterCanvas.height - arrayidx, 1, 1);

Irgendwas stimmt da aber immer noch nicht.
Wenn ich ein Sinus von 4000Hz in die Soundkarte reinschaufle, kommt das dann auch bei den 4000Hz die in der Skala stehen raus?
Ich meine damit die Skalierung der Skala muss auch mit der Skalierung des Spektrums übereinstimmen.

Ich tippe erst mal das geschriebene von hesst ein, dann werde ich schon sehn was passiert.

- - - Aktualisiert - - -

Nee also von dem was ich will ist das Spektrum noch weit entfernt.

3000-8000 Spektrum.png
Es fängt zwar bei 3000Hz an zu rendern und hört bei 8000Hz auf(getestet mit Sinus Generator), aber nicht auf die gesamte canvas höhe.
Von der Skala kann keine rede sein.

Irgendwie muss mann noch die höhe des Rechteks anpassen. Die steht auf ein Pixel
this.waterCanvasCtx.fillRect(this.waterCanvas.width - 1, this.waterCanvas.height - arrayidx, 1, 1);

Es kann ja wohl kaum 10,76 sein das wäre zu einfach, außerdem stimme die Werte in der for schleife dann wider nicht.

Junge, Junge, Junge,.... ist das kompliziert:grief:
 
Alles klar aber wo muss ich mit den Wert arrayidx hin oder anders gesagt wie muss die FillRect Methode aussehn?
keine ahnung, wenn du L punkte auf H pixel darstellen willst, ist das der index für pixel i

Wenn ich ein Sinus von 4000Hz in die Soundkarte reinschaufle, kommt das dann auch bei den 4000Hz die in der Skala stehen raus?
Ich meine damit die Skalierung der Skala muss auch mit der Skalierung des Spektrums übereinstimmen.
heisst jetzt was?

Nee also von dem was ich will ist das Spektrum noch weit entfernt.
ja, was willst du denn?

Es fängt zwar bei 3000Hz an zu rendern und hört bei 8000Hz auf(getestet mit Sinus Generator), aber nicht auf die gesamte canvas höhe.
Von der Skala kann keine rede sein.
???

Irgendwie muss mann noch die höhe des Rechteks anpassen. Die steht auf ein Pixel
welche höhe des rechtecks? das rechteck ist so wie ich es verstanden habe 1 pixel

- - - Aktualisiert - - -

wie muss die FillRect Methode aussehn? So:
this.waterCanvasCtx.fillRect(this.waterCanvas.width - 1, this.waterCanvas.height - arrayidx, 1, 1);
hier musst du natürlich den pixel nehmen, also i-1(minus 1, weil du nocht bei 0, sondern bei height-1 beginnst)
this.waterCanvasCtx.fillRect(this.waterCanvas.width - 1, this.waterCanvas.height - i-1, 1, 1);
das wäre der pixel, der zum arrayidx gehört
 
hesst schrieb:
hier musst du natürlich den pixel nehmen, also i-1(minus 1, weil du nocht bei 0, sondern bei height-1 beginnst)
Asso jetzt hast es klick gemacht.
arryidx ist der Wert mit dem ich mein FFT Werte aus dem FFT Array abhole.

In Firefox geht das einwandfrei die die Skala stimmt in etwa mit dem gerenderten Spektrum überein. In Chrome kommt nur Müll raus, wenn ich am Frequenz/Sinus Generator langsam die Frequenz erhöhe,
geht ein Träger im Spektrum hoch (wie es sein soll) aber dann kommt noch ein Träger runter wie eine art Spiegelfrequenz. Wo das nun wider her kommt???

Danke dir erst einmal hesst, mache jetzt ein paar Tests wenn mir was nicht passt werde mich schon melden.:cheerful:
 
Zuletzt bearbeitet:
Zurück
Oben