Forum: Digitale Signalverarbeitung / DSP / Machine Learning Matlab / Simulink / Raspberry Pi - Gitarrenstimmgerät


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von mick (Gast)


Lesenswert?

Hi,
im Zuge meines Studiums soll ich ein Gitarrenstimmgerät bauen, welches 
auf dem Raspberry Pi läuft und mittels Simulink implementiert wird.
Leider habe ich weder Ahnung von der Signalanlyse, noch von Simulink.

Ich habe jetz diverse sachen ausprobiert, aber ich bekomme es einfach 
nicht hin, das eingelsene Signal korrekt zu bestimmen.

Moment teste ich auf Windows und verwende für das einlesen des 
Microphonesignals den Block "Audio Device Reader". (Sample rate 96000, 
Samples per frame 1024)

Das Signal wird dann an folgende Funktion übergeben:
function res = fcn(x)
Fs = 96000;
xdft = fft(x);
fftabs = abs(xdft(1:length(x)/2+1));
freq = 0:Fs/length(x):(Fs/2);
[~,maxindex] = max(fftabs);
mx = freq(maxindex);
res = fftabs;
fprintf('Frequenz %s Hz\n',mx );
end

Eigentlich würde ich erwarten, dass wenn ich einen Ton mit,zum Beispiel, 
440 Hertz abspiele, die Textausgabe auch 440Hertz ausgibt, realität ist 
aber 654 Hertz. Kann mir das jemand erklären?

wenn ich Anstatt wenn ich "x" auf folgendes setze:
t = linspace(0,1,Fs);
x = cos(2*pi*4999*t)+randn(size(t));

Dann bekomme ich die erwartete Frequenz 4999 ausgegebn, wieso 
funktioniert dass aber nicht mit einem richtigen Audiosignal?

Ebenfalls hab ich versucht das Eingangssignal mit Blöcken zu analysieren 
(also nicht mit einem MATLAB Function Block, wie oben beschrieben),
jedoch habe ich dann auch immer nur komische Werte zurückbekommen.


Ich bin offen für andere Vorschläge, wie ich das Stimmgerät realisieren 
kann, wichtig ist nur dass ich das Microphonesignal in eine Frequenz 
umwandele, sodass ich erkennen kann, ob der Zielton getroffen wird.

Ich finde leider nichts zu dieser Thematik über Google, wenn, dann nur 
im zusammenhang mit Matlab, aber nicht mit Simulink.

Im bezug zu Matlab habe ich folgendes gefunden:
https://de.mathworks.com/matlabcentral/fileexchange/29538-pianotuner

Ich denke der Analysepart stimmt mit meinem Code überein, jedoch 
verwendet dieses Beispiel die classe "audiorecorder", welche ich leider 
nicht in simulink verwenden kann, da es scheinbar nicht auf dem 
Raspberry pi laufen wird.

Ich bin ziemlich am verzweifeln und habe auch keine Ahnung, wie meine 
nächsten Schritte aussehen sollen. Ich hoffe jemand kann mir weiter 
helfen.


Vielen Dank im Vorraus,
Mick

von Jürgen S. (engineer) Benutzerseite


Lesenswert?

Ich nehme an, dass Simuling den Code aus einem MBD automatisch erzeugen 
soll (?) Dazu brauchst du erst mal ein Modell des Systems. Simlink 
versteht embedded MATLAB, damit kannst Du den MATLAB-Code direkt 
eingeben. Was Du ab der Code-Gerneration noch machen musst, erfagst Du 
mal im PI-Forum. MATLAB wird Dir nur C auswerfen. Das sollte sich aber 
einbinden lassen.

Was mich eher beschäftigt, ist die Herangehensweise, eine präzise 
Stimmung über Messung zu machen. Dazu muss die FFT sehr genau sein und 
man muss die effektive Frequenz aus den Stützstellen der FFT ermitteln. 
Das geht, ist aber umständlich. Dann müsste man auch noch dem 
Gitarristen eine Skala anzeigen, damit er die richtige Frequenz weiß.

Ich würde das wohl eher so machen, daß er die Frequenz anhand der 
gewünschten Stimmung vorwählen kann und sie ihm erzeugt wird. Das kann 
man dann per Gehör oder optisch einstellen, wenn man 3 Frequenzen 
vorgibt und sie einfach durch Mittelung schwerpunktmässig verrechnet. 
Dann entsteht nur eine eher aussagenfreie Elongation nach links oder 
rechts vom Ideal, die er Nullen muss.

Gute Gitarristen - besonders im Bereich der akustischen Musik - stimmen 
aber ein nach Gehör, weil sie den Saiten etwas Spreizung verpassen - 
d.h. die Saiten klingen per perfektem Griff nicht 100% auf der idealen 
Frequenz sondern etwas daneben, um eine leichte Schwebung zu 
produzieren, wenn man zwei gleiche Töne auf zwei unterschiedlichen 
Saiten greift. Wenn man es dann ganz genau macht und einen sehr guten 
Gitarristen hat, der wirklich mit den Tönen spielt, stimmt man das so, 
dass die Schwebung zum Rhythmus der Musik passt.

Wichtig ist dabei, dass man eine Tongeneration hinbekommt, die sehr 
präzise ist, d.h. besser als 0,01 Cent definiert ist. Das erfordert 
schon etwas DSP-Power und entsprechende Mechanismen bei der DDS. Weil 
viele billige Geräte das nicht gut hinbekommen, erreicht man erheblich 
bessere Ergebnisse, wenn der Gitarrist einen einzigen Ton anstimmt und 
den Rest nach Gehör macht, so wie er greift.

von mick (Gast)


Angehängte Dateien:

Lesenswert?

Vielen Dank für die Antwort.
Mein oben gennanter Code ist bereit als Matlab Function Block 
implementiert.
Die Usability und der Nutzen des Projektes ist nicht wichtig. Würde ich 
ein das Ziel ernsthaft verfolgen, ein Stimmgerät zu baun, würde ich auf 
garkeinen Fall Simulink dazu verwenden. Mir wäre C++ lieber, aber unser 
Professor zwingt uns leider dazu Simulink zu verwenden.

Im Endeffekt soll es darum gehn, dass das Gerät die Gitarre mit einem 
angeschlossenen Motor selbst Stimmt, was aber aufgrund der vermutlich 
signifikanten Latenz ein Problem sein wird, daber dass sei zum jetzigen 
Stand mal dahin gestellt.

Mein Problem ist es in erster Linie zunächst einmal das korrekte 
Inputsignal zu erkennen, selbst daran scheitere ich schon und leider 
habe ich keine Ahnung, wie ich fortfahren soll oder woran das Problem 
liegt.

Im Anhang befindet sich die Ausgabe meines Matlab Functionblocks.
Das Eingangssignal betrug 440hz und wurde von meinem Stimmgerät erzeugt 
und ist frei von Obertönen. Selbst wenn ich das gerät als Line-In 
anschließe, wird ein ähnlicher Graph erzeugt. Ich verstehe nicht, warum 
die Funktion bei einem Generierten Signal (x = cos(2*pi*4999*t)) 
funktioniert und bei einem Signal von diesem "Audio Device Reader"-Block 
stammenden Signal nicht.

von Karl (Gast)


Lesenswert?

Weil Du, mit Verlaub, wenig von Signalverarbeitung mit FFT zu verstehen 
scheinst.

Die Länge deines Samples legt die Auflösung der Frequenzen fest. Hier in 
Forum hab es aber Mal einen guten Thread "genaue Frequenzmessung mit 
FFT" oder ähnlich.

Das sind deine Themen. C++ oder Simulink macht da keinen Unterschied 
mehr.

von Michael W. (Gast)


Lesenswert?

Das ist eben der Unterschied zwischen Theorie und Praxis. Bei der FFT 
kann man da schön reinfallen. Der Klavierdozentin meiner Cousine hat 
einst ein Typ auf der Musikmesse ein Stimmgerät auf der Basis eines 
Rohde & Schwarz Audio Analysators präsentiert und wollte nachweisen, 
dass er damit einen genaueren Klang einstellen kann. Das konnte er auch, 
jedenfalls zeigten das die Messergebnisse, aber der Klang war nach 
Meinung aller Umstehenden besch....en. Da kam ein Klavierbaumeister vom 
anderen Stand und hat mit dem Schraubenschlüssel nach Gehör dran rum 
geschraubt und dann ging es wieder. Warum, konnte keiner erklären.

von mick (Gast)


Lesenswert?

@markus das kann vielleicht auch daran liegen, dass dieser typ nicht 
genau wusste, wie man ein piano "richtig" stimmt. wenn man es genau 
stimmt, geht es nämlich nach einer weile bei der oktave oder so nicht 
mehr richtig auf, daher wird etwas "geschummelt". (Wenn du es genauer 
wissen möchtest: https://de.wikipedia.org/wiki/Temperierte_Stimmung)

@karl: ja richtig, wie bereits erwähnt weiß ich kaum etwas darüber und 
matlab bietet mir eine zusätzliche hürde - ich glaube nicht, dass mein 
problem ist, dass meine messung ungenau ist, sondern eher, dass 
irgentwas an meinem code oder an meiner matlabeinstellung nicht stimmt.
als resultat vom fft bekomme ich ja keine frequenzen zurück, sondern 
diese verrückten "bins". die frequenzgenauigkeit würde dann ja 
fs/fftpoints betragen, also in meinem fall 96000/1024 = ca 94hz 
betragen.
hab ich das richtig verstanden? also müsste ich ja eigentlich 
schlimmstenfalls 530hz rausbekommen und keine 654 oder?

habe ich es richtig verstanden, dass die maximale frequenz die ich 
messen kann ungefähr fs/2 is?
ich habe daher beschlossen, meine samplerate auf 3000 runterzudrehen um 
nicht so viele störungen im signal zu haben, da die höchste frequenz die 
ich messen muss ca 1320hz beträgt.
dann wäre die genauigkeit wenn ich die samplerate auf 512 runterstelle 
immernoch 5hz, dass würde mir erstmal reichen. Dann könnte ich alle 
200ms die stimmung korrigieren.

oder ist das alles blödsinn was ich hier rede?



macht dass sinn?

von Karl (Gast)


Lesenswert?

Bleib doch Mal bei deinen Ausgangsdaten.
Auch dein Code funktioniert und liefert brav 468 Hz.

Das Problem muss wo anders liegen.

von Jürgen S. (engineer) Benutzerseite


Lesenswert?

mick schrieb:
> @markus das kann vielleicht auch daran liegen, dass dieser typ nicht
> genau wusste, wie man ein piano "richtig" stimmt. wenn man es genau
> stimmt, geht es nämlich nach einer weile bei der oktave oder so nicht
> mehr richtig auf, daher wird etwas "geschummelt". (Wenn du es genauer
> wissen möchtest: https://de.wikipedia.org/wiki/Temperierte_Stimmung)
>

Moment, da liegt wohl eine Verwechslung vor: Die "temperierte Stimmung" 
ist die "normale" Stimmung der meisten Instrumente und auch heutiger 
Klaviere und ermöglicht es, in allen Tonarten zu spielen. Davon 
abweichend kann bei reiner Stimmung streng genommen nur in der 
jeweiligen Tonart gespielt werden.

Dass speziell Klaviertöne nicht exakt dem jeweiligen idealen Verlauf 
folgen, hat andere Gründe. Unter anderem lässt sich der hohe Tonanteil, 
der obere Diskant, in seinen Oberwellen nicht exakt genug anpassen, was 
an den kurzen Saiten liegt, bei denen zusehens von der idealen 
Schwingungsgleichung abgewichen wird. Daher wird bei der Intonation nach 
Gehör anders eingestellt. Das dürfte der Klavierstimmer (unbewusst?) 
gemacht haben und der Analyzertyp nicht gewusst haben.

Das Ergebnis ist eine Spreizung des Notenspektrums, d.h. tiefe Töne sind 
zu tief, hohe Töne etwas zu hoch. Dazu gibt es auch einiges an Literatur 
und Untersuchungen mit Blindtests von Klavierstimmern.

Diese Unvollständigkeit des Klaviers macht einen großen Anteil des 
natürlichen Klangs aus, da die nicht koheränt schwingenden Oberwellen zu 
"lebendigem Klang" und - wie man auch zeigen kann - zu einem anderen, 
als dem berechenbaren Energieaustausch zwischen den Saiten einer 
Dreiklanggruppe führt.  Mithin ist es dieser Effekt, der den 
Klavierklang macht.

Das hat man gemerkt, als man versucht hat, Klavierklänge synthetisch zu 
erzeugen. Man dachte zunächst, dass man auf diese Weise ein ideales 
Klavier bauen könnte, aber dem fehlt dann etwas. Bei samples fehlt der 
Energieaustausch und bei generischen Klängen aus dem physical modelling 
zudem die Lebendigkeit der Oberwellen. Wenn man das nicht nachbildet, 
kommt es beim Anschlag gerne zu phasenbedingten Auslöschungen, weil die 
Oberwellen zu präzise zu einander passen.

Daher verwende ich bei meinem Synthesizer 2 Skalen: Für akustische 
Begleitung eine Spreizung wie man sie bei natürlichen Klavieren kennt, 
auf der Basis entweder der temperierten oder seltener harmonischen 
Stimmung, oder für electro und trance die von mir am C64 gefundene 
e-music-scale mit einem Tonabstand von 196/185. Dieser garantiert immer 
ein festes Verhältnis von Dreiklangtönen, bildet also IMMER eine 
konstante Schwebung und zugleich passen die Oktaven nicht exkat, wodurch 
es ebenso zu keinen Auslöschungen kommt. Dennoch muss man meistens, die 
Töne etwas verstellen, um unschönen Effekten zu entgehen.

Beim echten Klavier - wie gesagt - besorgen das die Dreiklanggruppen, 
die über den Energieaustausch ständig wechselnde Phasenbeziehungen 
erzeugen.

von Jürgen S. (engineer) Benutzerseite


Lesenswert?

Was heißst das jetzt für das Gitarrenstimmgerät:

Auch die Gitarre hat solche Effekte, durch die Nachbarsaiten und den 
Hals - wenn auch schwach. Das muss man beim Messen berücksichtigen. Man 
muss also geschickt fenstern, am besten exakt ganzzahlig zu den Perioden 
und nicht nur über eine Periode messen, sondern vielleicht mal 10. Und 
ja, das  gibt eine lange FFT, die aber ist dann auch genau genug - 
zumindest wenn man die Zwischenfrequenzberechnung zwischen zwei Stützen 
durchführt.

Generell muss man sich aber nochmal vor Augen führen, was man will: Die 
Saiten sollen exakt passen, daher ist eine exakte Vorgabe mit Anpassung 
nach Gehör / einem optischen Ausschlag der Abweichung besser.

Zu beachten ist dabei wie schon erwähnt, die Temperatur: Manche 
Gitarristen möchten rein stimmen, bzw sie tun es unbewusst, ohne es zu 
wissen, wenn sie aufgrund eines Tons nach Gehör stimmen. Mir fällt dazu 
eine Szene mit einem Gitarristen, der klassische spanische Gitarre 
spielte, ein, der mit seinem Stimmgerät nicht klar kam. Es passte nicht 
Rest der Truppe, wenn er mit anderen zusammenspielte und er war auch 
generell mit dem Klang nicht zufrieden. Er hatte sehr feine Ohren. Es 
gibt Fälle, da lässt man das Stimmgerät besser zur Seite.

von mick (Gast)


Lesenswert?

@Jürgen, du haßt recht, ich meinte eigentlich das hier: 
https://en.wikipedia.org/wiki/Equal_temperament


Karl schrieb:
> Bleib doch Mal bei deinen Ausgangsdaten.
> Auch dein Code funktioniert und liefert brav 468 Hz.
Heißt das du hast ihn getestet?

von Karl (Gast)


Lesenswert?

Jain. In Matlab und dann geplottet.
Testsignal 1024 Samples des 440 Hz Sinus.

von Jürgen S. (engineer) Benutzerseite


Lesenswert?

Karl schrieb:
> des 440 Hz Sinus.
Bei der Gelegenheit gleich der beiläufige Hinweis auf den gerne 
gemachten Fehler, bei Instrumententrimmung pauschal von einer 440er 
Stimmung auszugehen. Wenigstens bei sinfonischer Musik fällt man da 
gerne auf die Nase. Mir fällt jetzt kein Werk ein, das eine Gitarre 
aufbietet, aber wenn wer auf die Idee kommt, mit dem Gitarrenstimmgerät 
eine Konzertharfe trimmen zu wollen, kriegt bei der Festlegung ein 
Problem.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.