# Frequenzen vom Mikrofon bestimmen



## Poehli (29. Dezember 2012)

Hallo,
ich bin schon seit mehreren Tagen auf der Suche nach dem Thema, wie ich es hinbekomme Frequenzen aus meinem Mikro zu erhalten. Ich habe Grundlegende Kenntnisse im Audiobereich, weiß über Samples bescheid und hab von FFT gelesen (Versuche es zu verstehen, sobald sich mir erschließt wofür ich das brauche). Ein kleines Programm, was aufgenommenes Audio speichert konnte ich schreiben und verstehen:

```
public class AudioTest {
	AudioFormat format;
	TargetDataLine targetDataLine;
	public AudioTest() {

		format = new AudioFormat(8000.0F, 16, 1, true, false);

		DataLine.Info dataLineInfo =
			new DataLine.Info(
					TargetDataLine.class,
					format);
		try {
			targetDataLine = (TargetDataLine)
			AudioSystem.getLine(dataLineInfo);

			System.out.println("start");
			long time = System.currentTimeMillis();
			new CaptureThread().start();
			while (time + 3000 > System.currentTimeMillis())
				try {
					Thread.sleep(100);
				} catch (Exception e) {
					// TODO: handle exception
				}
				System.out.println("done rec");
				targetDataLine.stop();
				targetDataLine.close();
		} catch (LineUnavailableException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	class CaptureThread extends Thread{

		@Override
		public void run(){
		try {
			targetDataLine.open(format);
			targetDataLine.start();
			AudioInputStream istream = new AudioInputStream(targetDataLine);
			AudioSystem.write(istream, AudioFileFormat.Type.WAVE, new File("test.wav"));
			
		} catch (LineUnavailableException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		}
	}

	public static void main (String[] args){
		new AudioTest();
	}
```
 (Keine Weltneuheit, aber es funktioniert)
Leider verstehe ich absolut nicht, mit welchen Hilfsmitteln die Frequenzen herauszufinden sind. 

Wie bekomme ich die Samples, mit denen ich weiterarbeiten kann?
Wofür brauche ich die FFT?
Und was für Frequenzen bekommt man (Long, Double oder was auch immer)

Ich weiß, dass dies ein nicht zu unterschätzendes Thema ist, wäre trotzdem nett, wenn ihr mir dabei helfen könntet.
Vielen Dank
Pöhli


----------



## sheel (29. Dezember 2012)

Hi

was willst du denn am Ende eigentlich erreichen?

Hier drei Bilder im Post:
http://www.tutorials.de/c-c/155796-frequenzen-2.html#post2004125

Bild 3 sind Sampledaten als graphisches Diagramm.
Die bekommt man vom Mikrofon, die wollen Wiedergabegeräte zur Wiedergabe,
und die sind (als Array von irgendwelchen Kommazahlen) alles, was man braucht,
um Musik als Datei etc. zu speichern.
Mit bestimmten Komprimierungsverfahren und einigen anderen Kleinigkeiten
hat man Formate wie MP3, Ogg usw.

Fouriertransformation ist ein math. Verfahren, um diese Sampledaten
in die vielen einzelnen Schwingungen (wie Bild 1 und 2) zu zerlegen.
FFT (Fast F.T.) ist eine computermäßig relativ schnelle Methode zur Berechnung.

(warum wollen eigentlich immer mehr Leute eine FT auf Audiodaten machen?)


----------



## Poehli (29. Dezember 2012)

Ich habe als Hobby noch HIFI und allgemein Musik. Demanch ist es naheliegend diese beiden Bereiche zu verbinden 

Mein eigentlicher Wunsch ist es eine Art Stimmgerät für ein X-Beliebiges Instrument zu schreiben. 
Da jeder Ton eine eigene festgelegte Frequenz hat, liegt es Nahe, diese herauszufinden. Komprimierung ist erstmal nebensache und auch das speichern wird nicht nötig sein. Dieser Code zeigt nur meine bisheren Kenntnisse im Bereich Audioprogrammierung. Und da ich es liebe Algorythmen zu entwerfen und verstehen, lag es Nahe kein vorhandenes Programm zu verwenden (mal abgesehen davon, dass ich keins gefunden habe  ). 
(Wenn ich jetzt falsch liege korrigiert micht bitte
Ein Gesampeltes Audioformat besteht doch, wie der Name schon sagt aus einzelnen Samples, also Punkten auf dem Graphen der Audiowelle, wenn man das so beschreiben kann. Demnach müssten diese doch die Dezibel des Punktes angeben. Um nun die Frequenz zu bestimmen, müssten die jeweiligen Maxima bestimmt werden (z.B. über ableiten oder andere Prüfverfahren). Dafür müsste ich jedoch die Samples erst einmal bestimmen können. Deshalb versuche ich herzufinden, wie man die einzelnen Samples auslesen kann. 

Ich hätte gedacht, dass relativ häufig die Frequenz gebraucht wird und dehalb in irgendeiner API steht, die ich trotz ewig langem Suchen nicht gefunden habe. Das scheint offensichtlich nicht der Fall zu sein, womit nur noch die Frage des Samples bleibt 
Vielen Dank schonmal, für die schnelle Antwort


----------



## melmager (1. Januar 2013)

Also FFT brauchst du um Frequenzen aus einem Gemisch herauszufiltern - wobei der FFT Filter eine Bandbreite besitzt - sprich ist entsprechend ungenau.

Wenn du aber Stimmen willst hast du den Vorteil das du nur einen gegeben Ton hast - sprich nur eine Frequenz.
Da (denke ich) Würde sich anbieten aus der Eingangsfrequenz den Nulldurchgang zu bestimmen.
Also aus deinem Stream ermittelen wann genau der kleinste Eingangspegel vorhanden ist = Nulldurchgang.

Zu den Samples - da scheint es wirklich nichts zu geben was fertig ist 
da mache ich mir auch im Moment Gedanken wie man das Javatechnisch umsetzen kann.

Es gibt ja ettlichen Codierungsmöglichkeiten, auch wenn man sich auf  PCM einschränkt.
8/16/24 Bit
Mono / Stereo
erst Lo dann Hi Part oder umgekehrt wenn man mit mehr wie 8 bit arbeitet.

mal kucken wie weit ich komme


----------



## melmager (1. Januar 2013)

sheel hat gesagt.:


> Hi
> 
> (warum wollen eigentlich immer mehr Leute eine FT auf Audiodaten machen?)



weils geht 
Nee spass beiseite - ich möchte einfach mal sehen wie brauchbar solche ergebnisse sind wenn man mit FFT arbeitet
und wenn nur am Ende Eine Classe rauskommt die ein Equalizer für Swing bereitstellt - ist dat nix 

EDIT:
Ich verstehe nicht woher die Info kommen soll das vom Micro aufgenommen wird - ich habe schon andre Beispiele gesehen aber ich verstehe das nicht - wo wird die Info übergeben welcher Eingang benutzt wird


----------



## Poehli (3. Januar 2013)

Ja genau das hab ich mir auch gedacht melmager, aber wie bekommt man denn den eingangspegel? 
Dann würde ich ja auch selbst versuchen damit weiterzuarbeiten, aber ohne den komme ich nicht voran. 
Was genauch macht denn eigentlich die read() Methode von TargetDataLine, bzw AudioInputStream? Was kann ich mit den Bytes anfangen, bzw. was repräsentieren die? Ich werd aus der API leider nicht schlau....
Vielen Danke, schonmal


----------



## melmager (4. Januar 2013)

Die Bytes sind deine Samples - wobei es auf die Codierung ankommt wie die Daten ankommen.
mal gesetzt den einfachen Fall du nimmst ein Auflösung von 8 bit und MONO dann ist ein Sample genau ein Byte gross, bei 16 Bit auflösung, und Stereo brauchst für ein Sample 4 bytes.


```
int samplesize = 1;
byte block[] = new byte[samplesize];
// sound ist hier dein AudioInputStream
int rc = sound.read(block,0,samplesize);
```

jetz muss daraus ein int gemacht werden (Achtung es gibt Werte mit oder ohne Vorzeichen!)


```
int value = block[0]; // nimmt Vorzeichen mit
```

jetzt sollte man ein Samplewert haben. Gesetzt den Fall du hast nur ein Ton (am besten Sinus)
dann kann man die Frequenz dadurch ermitteln das man die Anzahl der Null durchgänge zählt im vorgegeben Zeitraum. Sprich Messung 1 sekunde -> 880 Durchgänge = 440 Hz


```
int messzeitraum = 8000; //samplerate 8000 = 1 sec
int null = 0; // samlewert von Null
boolean plus = true; // true bei positiver Schwingung 
int count = 0; // unser Zähler
for (int lo=0; lo < messzeitraum; lo++) {
 while (sound.available() <= samplesize) {//warte bis genug daten vorhanden
   // hier ev ein kleinen sleep rein
 } 
 // hole werte siehe oben!
 if ((value > null) ^ plus) { // test ob wechsel der Schwingung 
  plus = value > null;
  count++;
 }
}
```

alles theoretisch und ungetestet !!

Der Nullwert deiner Samples kommt auch auf die Codierung an - immer noch bei 8 Bit
ist der Null wert bei Werten mit Vorzeichen bei 0 da werte zwischen 127 und -127 liegen
bei Werten ohne Vorzeichen (hier im Coden nicht ausgewertet) liegt der Wert zwischen 0 und 254 daher ist da der nullwert 127.

Link: http://wiki.multimedia.cx/index.php?title=PCM

Oder noch ne Möglichkeit Frequenz ungefähr zu bestimmen:
Warte auf Wechel von Negativ auf Positiv Werte ; 
zähle die Samples bis erneuten Wechsel negativ / positiv; 
rechnen 

das ganze Verfahren hier klappt nicht wenn mehrere Frequezen gemischt sind !!
Und dat ganze ist nur eine Näherungsmessung je näher die Messfrequenz der Samplefrequenz ist um so ungenauer wird es!


----------



## genodeftest (4. Januar 2013)

melmager hat gesagt.:


> Also FFT brauchst du um Frequenzen aus einem Gemisch herauszufiltern - wobei der FFT Filter eine Bandbreite besitzt - sprich ist entsprechend ungenau.


Richtig. Wenn Sampledauer und Samplerate ausreichend groß sind, sollte das kein Problem geben.


melmager hat gesagt.:


> Wenn du aber Stimmen willst hast du den Vorteil das du nur einen gegeben Ton hast - sprich nur eine Frequenz.
> Da (denke ich) Würde sich anbieten aus der Eingangsfrequenz den Nulldurchgang zu bestimmen.
> Also aus deinem Stream ermittelen wann genau der kleinste Eingangspegel vorhanden ist = Nulldurchgang.


Nulldurchgang bringt dir überhaupt nichts, weil er durch Schwingungen anderer Frequenzen beliebig verzerrt/verschoben werden kann. FFT ist auf jeden Fall der richtige Ansatz. In der Praxis setzt man das so um, dass man die FFT per Formel/DSP berechnet und dann im Frequenzspektrum nach Peaks/Maxima sucht. Der höchste Peak liegt bei der Frequenz, bei der der Ton mit der höchsten Intensität schwingt, d.h. bei der stärksten Schwingung.


----------



## genodeftest (4. Januar 2013)

Poehli hat gesagt.:


> Ein Gesampeltes Audioformat besteht doch, wie der Name schon sagt aus einzelnen Samples, also Punkten auf dem Graphen der Audiowelle, wenn man das so beschreiben kann. Demnach müssten diese doch die Dezibel des Punktes angeben. Um nun die Frequenz zu bestimmen, müssten die jeweiligen Maxima bestimmt werden (z.B. über ableiten oder andere Prüfverfahren). Dafür müsste ich jedoch die Samples erst einmal bestimmen können. Deshalb versuche ich herzufinden, wie man die einzelnen Samples auslesen kann.


Ableiten wäre viel zu aufwändig, weil du die Funktion selbst ja nicht kennst, sondern nur approximieren kannst. Um das tatsächlich mit Ableitungen oder ähnlichen mathematischen Verfahren umzusetzen, solltest du fortgeschrittene Kentnisse in numerischen Verfahren mitbringen…


----------



## melmager (4. Januar 2013)

genodeftest hat gesagt.:


> Nulldurchgang bringt dir überhaupt nichts, weil er durch Schwingungen anderer Frequenzen beliebig verzerrt/verschoben werden kann. FFT ist auf jeden Fall der richtige Ansatz. In der Praxis setzt man das so um, dass man die FFT per Formel/DSP berechnet und dann im Frequenzspektrum nach Peaks/Maxima sucht. Der höchste Peak liegt bei der Frequenz, bei der der Ton mit der höchsten Intensität schwingt, d.h. bei der stärksten Schwingung.



Stimmt da ist das problem ..  ich weiss ja nicht wie ein Gitarrensound (Beispiel) aussieht aber wenn der Sound durch eine andre Frequenz überlagert wird dann fällt mein Messverfahren aus - ich gehe vom Sinus aus ...

sobald ich rausgefunden habe wie man die Quelle festlegt schreibe ich erstmal ein programm das mir die samples ausgibt um mal zu sehen wie die werte aussehen


----------



## genodeftest (4. Januar 2013)

Also für die praktische Umsetzung würde ich so vorgehen:

1. mir eine Bibliothek etc. suchen, mit der man auf Audio-Eingänge zugreifen kann. Ein paar Anregungen:
Java Sound, Teil der Java SE API, http://docs.oracle.com/javase/tutorial/sound/TOC.html , http://openjdk.java.net/groups/sound/ , http://onjava.com/pub/a/onjava/excerpt/jenut3_ch17/index.html , http://www.developer.com/java/other...turing-Microphone-Data-into-an-Audio-File.htm , ich weiß nicht, ob das auch auf Mikros oder ähnliche Eingänge in allen Fällen zugreifen kann
Pulseaudio/ALSA/… (auf Linux/Unix) per JNI
Über die Samplelänge muss man sich etwas Gedanken machen: Um eine Schwingung noch sicher detektieren zu können, sollte man wenigstens 10 Perioden dieser Schwingung aufnehmen. Wenn wir also eine Untergrenze von 30Hz erreichen wollen, die wir noch sicher detektieren können, dann brauchen wir eine Samplelänge von 1/3 Sekunde. Um auf Nummer sicher zu gehen nehmen wir lieber 1 Sekunde, also 44.100 oder 48.000 Samples je nach Samplingrate (u.U. wären auch 192 kHz Abtastfrequenz möglich, aber nicht mit jeder Hardware und Software).

2. FFT auf die Sampledaten ausführen. Wäre praktisch, wenn man eine Bibliothek finden würde, die das kann. Die reale Implementierung hat nämlich einige Optimierungsmöglichkeiten, die auch unbedingt nötig sind – man will ja unter Umständen 10 mal pro Sekunde eine FFT auf Sampledaten von 1 Sekunde ausführen. Außerdem werden je nach Implementierung komplexe Zahlen verwendet.

3. FFT analysieren, d.h. auf dem Frequenzspektrum das Maximum suchen (einfache for-Schleife). Eventuell (je nach gewünschter Präzision) werden dazu auch mehrere aufeinander folgende Werte betrachtet, um zu vermeiden, dass ein Peak genau zwischen 2 Frequenzen fällt und somit die Intensität falsch eingeschätzt wird.

4. Frequenz berechnen, bei der das Maximum gefunden wurde. – da kann ich gerade gar nicht weiter helfen.


----------



## Poehli (4. Januar 2013)

Vielen Dank schonmal an alle, die hier so tatrkäftig helfen!

```
import java.io.IOException;
import java.util.ArrayList;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.TargetDataLine;


public class AudioTest {
	AudioFormat format;
	TargetDataLine targetDataLine;
	int samplesize = 2;
	float samplerate = 44100f;
	public AudioTest() {

		format = new AudioFormat(samplerate, 8*samplesize, 1, true, false);

		DataLine.Info dataLineInfo =
				new DataLine.Info(
						TargetDataLine.class,
						format);
		try {
			targetDataLine = (TargetDataLine)AudioSystem.getLine(dataLineInfo);
			System.out.println("start");
			long time = System.currentTimeMillis();
			CaptureThread cp = new CaptureThread();
			cp.start();
			while (time + 2000 > System.currentTimeMillis())
				try {
					Thread.sleep(100);
				} catch (Exception e) {
					// TODO: handle exception
				}
			System.out.println("done rec");
			targetDataLine.stop();
			targetDataLine.close();
			cp.stop();
		} catch (LineUnavailableException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	class CaptureThread extends Thread{

		@Override
		public void run(){
			try {
				targetDataLine.open(format);
				targetDataLine.start();
				AudioInputStream ais = new AudioInputStream(targetDataLine);
				byte[] block = new byte[samplesize];
				ais.read(block, 0, samplesize);

				int value = block[0], oldValue=0;

				int messzeitraum = (int) samplerate; //samplerate 8000 = 1 sec
				boolean max = true; // true bei Maxima gesucht
				System.out.println("block länge: "+block.length);
				ArrayList<Frequenz> frequenzen = new ArrayList<Frequenz>();
				int sampleCount = 0;
				for (int lo=0; lo < messzeitraum; lo++) {

					while (ais.available() <= samplesize) {
						
					}
					ais.read(block,0,samplesize);
					value = block[0]+block[1];

					if (value > oldValue && max){
						sampleCount++;
					} else if (value <= oldValue && max){
						sampleCount++;
						max = false;
					} else if (value <= oldValue && !max)
						sampleCount++;
					else if (value > oldValue && !max){
						frequenzen.add(new Frequenz(sampleCount,samplerate));
						max = true;
						sampleCount = 1;
					}
					oldValue = value;
					System.out.println(oldValue + "\t - samples: "+sampleCount);
				}

				double b =0;
				
				// Testen ob Frequenz passt -> nein
				for (int i = 0; i < frequenzen.size(); i++) {
					b += frequenzen.get(i).frequenz;
					b /= 2;
					//System.out.println(b);
				}
			} catch (LineUnavailableException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	public static void main (String[] args){
		new AudioTest();
	}
}



_________________________



public class Frequenz {
	double frequenz = 0f;
	int sample = 0;
	double samplePerSec = 0;
	public Frequenz(int sample, double samplePerSec) {
		this.frequenz = 1/((double)sample/(samplePerSec));
		this.sample = sample;
		this.samplePerSec = samplePerSec;
	}
}
```

Ich habe hier ein kleines Testprogramm geschrieben (ohne Fourier Analyse) und würde jetzt gerne die Meinung hören. Ist das so korrekt und würde es den richtigen Wert liefern, wenn ich die Analyse durchführe? 
Mein Ansatz war der von einigen schon vorgeschlagen wurde, nämlich die Minima zu bestimmen und die Samples dazu auszurechnen. Mich wundert jedoch, dass ich viele Frequenzen mit wenigen Samples bekomme (2-3). Liegt es an meiner Überlegung mit der Bestimmung der Samples oder hab ich sostwo einen Fehler?
Außerdem noch die Frage: Was müsste ich ändern, damit ich mit 16bit arbeiten kann? Einfach die beiden Bytes addieren würde sicher nicht funktionieren oder?


----------



## melmager (4. Januar 2013)

wenn du schon soweit bist 
lass dir doch erstmal bei deinem Testsignal die samples ausprinten

einfach um zu sehen ob überhaupt eine auswertung egal Max oder Null sinnvoll ist 

ich fürchte du kommst nicht an FFT vorbei .... 


```
int messzeitraum = (int) samplerate / 100 ; //0.01sec
```


```
value = block[0];
System.out.println(value);
```

 ev umstellen auf datei als eingang und dann das 
http://www.felusch.com/blog/?tag=sinus-1khz

ich habe hier ein 440Hz Generator rumliegen bin aber code mässig nicht soweit :-(

tja ich bekomme nur null werte ... zurück zum problem - wie selectiere ich dat micro ...


----------



## genodeftest (4. Januar 2013)

melmager hat gesagt.:


> ich fürchte du kommst nicht an FFT vorbei ....


Daran wirst du sicher nicht vorbei kommen.
In den Links von mir (weiter oben) gibts Infos wie man den richtigen Kanal findet.


----------



## melmager (4. Januar 2013)

java sieht bei mir das (auszug)

```
CK8 [default] (Name: CK8 [default] / Vendor: ALSA (http://www.alsa-project.org) / Version: 1.0.23)
  Sources (2):
   Line: interface SourceDataLine supporting 84 audio formats, and buffers of at least 32 bytes        (Name: com.sun.media.sound.DirectAudioDevice$DirectSDL@1893efe)
   Clip: interface Clip supporting 84 audio formats, and buffers of at least 32 bytes        (Name: com.sun.media.sound.DirectAudioDevice$DirectClip@16b13c7)
  Targets (1):
   Line: interface TargetDataLine supporting 84 audio formats, and buffers of at least 32 bytes        (Name: com.sun.media.sound.DirectAudioDevice$DirectTDL@13d93f4)
```

ich harke mal Microfon ab - und beschäftige mich weiter mit meinem Problem  - ich muss ja von file einlesen ...


----------



## Poehli (5. Januar 2013)

Nach kleinen Anpassungen (Code wurde aktuallisiert) kommt folgendes Ablaufprotokoll raus. Der Sinus Signalton war 213Hz und auf laut eingestellt. Hier das Ergebnis: 
Anhang anzeigen ablauf.txt

(erster Wert ist das, was in Value steht)


----------



## melmager (5. Januar 2013)

Leider kann ich es nicht mehr nachtesten da sich mein Programm immer noch weigert vom Mirco einzu lesen
aber...


```
format = new AudioFormat(8800.0F, 16, 1, true, true);
```
also ein stellung Vorzeichen und BigEndian

dann sollte das Value bei 16 Bit wert so aussehen

```
int tmp = tl.read(block, 0, 2);
value = (block[0] << 8) | (block[1] & 0xFF);
```
höherwertiges Byte nach links geschoben und das unterere Byte dazu

wenn du wider dein Testsignal von 213 Hz und meine Einstellung SampleRate 8800 nimmst sollte also eine schwingung 41,3  Samples haben

wenn also bei 100 Testsamples nix dergleichen an den Werten zu sehen ist - muss weiter nachgedacht werden ...


----------



## Poehli (5. Januar 2013)

Hey danke, das hat echt geholfen! Jetzt verstehe ich jedoch nicht so ganz, warum ich das Doppelte der Frequenz herausbekomme? Ich bekomme bei einem Sinus von 201 einen Durschnittswert von 195 raus, wenn ich jede einzelne Frequenz Teile, ansonsten 395. (Ich habe einen gaaaaanz simplen Filter eingebaut, dass er mir die niedrigsten Samples rausschmeißt - alle unter 10  ). 
Übrigens bekomme ich unter meinem Mac auch des öfteren Fehlermeldungen aller:

```
java(6861,0x100501000) malloc: *** error for object 0x1ad: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
```


----------



## melmager (5. Januar 2013)

Malloc - ist eine Speichertregistrierung - 
ev hilft ein flush() am ende des messvorgangs weiter
stop();
flush();
close();

Doppelte Werte was zählst du denn ? Z.B den Nulldurchgang den ich mal vorgeschlagen hatte der passiert beim Sinus genau 2 Mal pro Schwingung 

Gegenfrage - ich welchen Wertebereichen liegen denn deine Samples - ich hätte da noch ne Idee um Störungen auszufiltern . Stichword Smitt Trigger


----------



## Poehli (5. Januar 2013)

Ach Gottchen bin ich blöd  Hast natürlich Recht, eine Frequenz hat logischerweise 2 Extrema :$
Der Bereich ist meistens knapp unterhalb der eigentlichen Frequenz (2-5hz), ich werde wohl auch noch die TTF verwenden und schaue mal nach was du damit meinst 
Der Fehler lies sich damit nicht beheben. Mein MacBook ist aus dem Jahre 2007. Es ist ein integriertes Micro mit 2 Kanälen (angeblich) und max. 96.000 Hz Aufnahmefrequenz. (Einstellungen laut Audio-Midi-Setup)
An meinem PC funktioniert es einwandfrei. Demnach würde ich schätzen (was man ja häufig liest), dass die Optimierung bei der Audio API das Problem ist. 
Falls du noch andere Tips hast, immer her damit


----------



## melmager (5. Januar 2013)

Dat Problem bei FFT ist: es ist noch ungenauer wie 5Hz ...

Also wenn du ein FFT Filter von 320Hz nimmst und 32 Eingänge benutzt hast du eine Bandbreite von 10Hz
Regeln für FFT 
die Anzahl der Eingänge muss immer eine 2er Potenz sein
Bandbreite pro Eingang ist Gesamtbandbreite / Gesamteingänge
Anzahl der Eingänge = Anzahl der Ausgänge

Man kann den FFT als die Mathematische Version von mehreren Bandpass Filtern sehen 
Wobei ich noch nicht weiss mit welcher Güte zu rechen ist ...

Sprich wie die Ergebnisse aussehen ...

Ich Kämpfe immer noch mit dem Eingang von meiner Kiste :-( - dazu mache ich mal ein eigenes Thema auf 

Nachtrag:
Ungenauigkeit von 1 Hz ist dem Problem geschultet das man irgendwann mitten einer Sinuswelle anfängt miit Messen
Wenn du also die Messung nach dem ersten Maximum startet haste den Fehler schon mal weg
Ob man die Restwelle noch berücksichtigt nach dem letzen Maximum ist ne andre Frage

Mit andren Worten genauer wirds nicht ...

PS: wenn du eine Code Hast der geht währe ein Posten cool für andre Leute die die gleiche Aufgabenstellung haben


----------



## genodeftest (5. Januar 2013)

@melmager: vielleicht hilft dir die Implementierung von https://sourceforge.net/projects/java-snd-record/files/java-snd-record/0.5/ weiter…


----------



## Poehli (5. Januar 2013)

bei 44100 Durchlaufen, macht glaube ich eine falsche Frequenz nicht so den Kohl Fett 
Viel schlimmer ist es jedoch, dass ich bei einer Frequenz von 349hz eine Ungenauigkeit von 1000 habe  Da schwanken die Ergebnisse von 1200hz-1800hz... 
Es funktioniert nur dann einigermaßen, wenn ich davon ausgehe, dass mehr als 30 Samples pro Frequenz gelten (Frequenz unter 1000 Hz). Das jedoch ist etwas unpraktisch für ein Stimmgerät .
Ich habe den Code ja schon einmal aktualisiert, werde ihn aber nochmal komplett hochladen, sobald er funktioniert 
Hast du/ habt ihr noch ne Idee, wie man das hinbekommen könnte?


----------



## melmager (5. Januar 2013)

Mir ist eben eine ganz abgefahrene Idee gekommen ..

Da du ja Stimmen willst - 

wenn man am Oszi zwei Frequenzen vergleichen will nimmt man ein mal den X für das Messsignal und Y für das Sollsignal.
Ich frage mich grade ob man das nicht auf dein Problem Rechnerisch anwenden kann.
Sprich du erstellst recherisch ein soll Sample (den Bereich von 1-2 Schwingungen) und wird mit dem Eingang Sampel  für Sampel verglichen und wenn Theoretisch über alle Samples den gleichen  (mit tolerzanzen wegen rippel usw) Unterscheid hast - Bingo Gleichstand ...

oder ist die Idee zu Irre ?

Wir bauen uns eine software Stimmgabel - smile


----------



## Poehli (5. Januar 2013)

An und für sich keine schlechte Idee. Nach dem Motto: 2x gleich falsch hat den selben Unterschied. 
Das Problem dabei ist nur, dass 
a) ich nicht sicher weiß ob der Unterschied immer gleichbleibend ist. Und 
b) woher ich ein Sample dieser Art nehmen soll. Ich kann demnach ja keine Sinusfrequenzen wählen. Es müsste jeweils eine richtige Frequenz von dem selben Instrument sein, damit das klappt...

abgesehen davon gehst du davon aus, dass es nach einem einzigen Ton gestimmt wird. Ich wollte aber nach einem x-beliebigen Ton stimmen, was die ganze Sache leider nicht möglich macht, irre ich? 
(daran hatte ich nämlich auch schon gedacht  )


----------



## melmager (6. Januar 2013)

Naja eine X beliebige Frequenz und deren Samples zu berechen sollte nicht so komplex sein ..

Samplerate 4400 > gewüschter Ton 440 = 10 Samples für den einheitskreis.
1. Wert berechen den Sinus von Cosinus 0,9 . 2. wert  .0,8 ... sprich der cosinus hat ein festen Bezug zur Zeitachse ...

du gibst dem Programm den Ton vor -  rechne rechne .. fertig

was mir auch sorgen macht ist das beim berechnen wir tatsächlich vom Sinus ausgehen - aber versuch wäre es wert  - denke ich (immerhin sind wir bei der zählung auch davon ausgegangen)

grobe abstimmung über die Vorhandnen Frequenzzählung - feinjustage über Differenz Vergleich mit Sinus

selbst mit den Klangoberwellen - hoffe ich - sollte da man ein ein Minimalwert rauskommen ... wenn nicht kann man (denke ich) die Idee eh adacta legen ...


----------



## genodeftest (13. Januar 2013)

Und noch eine bessere Einführung in die Java Sound API: http://docs.oracle.com/javase/7/docs/technotes/guides/sound/programmer_guide/contents.html


----------

