Portál AbcLinuxu, 30. dubna 2025 10:12
Ahojte. Zkusil jsem v Pythonu napsat jednoduchou kytarovou ladičku, která se pokouší dolní polovinu frekvenčního spektra přičíst k horní polovině tak, aby se všechny harmonické spojily do jedné frekvence (čert vem nelinearity). Možná by to mohlo lépe reagovat než „běžné“ ladičky, ale rád bych někoho poprosil o otestování:
#!/usr/bin/python # -*- coding:utf-8 -*- from __future__ import division from scipy import * import alsaaudio def record_and_analyze(N, recfreq): inp = alsaaudio.PCM(alsaaudio.PCM_CAPTURE) inp.setchannels(1) inp.setrate(recfreq) inp.setformat(alsaaudio.PCM_FORMAT_S16_LE) pos = 0 bytes = [] while True: l, chunk = inp.read() pos += l if pos == N: bytes.append(chunk) break if pos > N: bytes.append(chunk[:(N - pos)*2]) break bytes.append(chunk) data = fromstring(''.join(bytes), int16) spectrum = abs(fft(data)[:(N//2 + 1)]) spectrum[0] = 0 #remove DC component for i in range(1, (len(spectrum)+1)//2): #join harmonics spectrum[i*2] += spectrum[i] spectrum[i] = 0 return argmax(spectrum)*recfreq/N tones = ['A', 'B', 'H', 'C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#'] while True: f_fund = record_and_analyze(N = 2**16, recfreq = 48000) x_tone = 12*log(f_fund/440)/log(2) i_tone = int(x_tone + 0.5) print '%+.2f' %(x_tone - i_tone), tones[i_tone % 12]Zkuste podle toho někdo naladit kytaru nebo prostě jakýmkoli způsobem ověřit správnost. Mně to sice funguje líp než elektronická ladička (KORG), ale to nemusí nic znamenat. Nevím přesně, které balíčky jsou potřeba, ale rozhodně se nic nezkazí nainstalováním těchto:
python-alsaaudio scipy python-matplotlib numpy
Tiskni
Sdílej:
-0.06 C +0.13 C +0.05 D -0.00 E -0.08 E -0.18 F +0.03 G -0.10 G -0.08 A -0.11 H -0.11 CJsem opravdu silně rozladěn
No jestli to číslo x.yz jsou centy zobrazené s přesností na setiny, tak to není taková katastrofaBohužel to tak není, deset centů skutečně pro mně není žádná míra![]()
Btw. nějak mi uniká, jak funguje ten algoritmus. Teda ne že bych si nedokázal vyvodit, co se tam děje, ale není mi tak úplně jasné, jaktože to dělá to, co tvrdíš, že to dělá.Vycházím z toho, že kteroukoli frekvenci ve spektru můžu vynásobit dvěma a pořád se jedná o stejný tón. Takže vezmu nějakou frekvenci (třeba číslo 1) a přičtu k frekvenci číslo 2. Pak frekvenci číslo 2 přičtu ke čtvrté. Pak třetí k šesté. Pak čtvrtou k osmé. A tak dále až přestěhuju celé spektrum pouze do jedné oktávy, do horní poloviny spektra. No a tam se ty tóny lépe hledají – aspoň mi to tak přijde. Původně jsem chtěl nějak vyhledávat všechny vyšší harmonické, ale je to zrádné, protože už trojnásobek dává úplně jiný tón (v temperovaném ladění trochu falešný).
-0.02 A +0.01 A +0.01 Acož je doufám rozumné. Jenže, mám tam chybu! Bajty a vzorky nejsou totéž. Jak na potvoru se to ale nikde neprojevilo. Ale spravím to, i když to na funkci nebude mít vliv. Krát dva to mělo bejt!
program Ladicka; Uses Crt; var Ton : char; begin repeat Write('Zadej ton (E,H,G,D,A,6,K) : '); ReadLn(Ton); Ton := UpCase(Ton); Case Ton of 'E' : Sound(330); 'H' : Sound(247); 'G' : Sound(196); 'D' : Sound(147); 'A' : Sound(110); '6' : Sound( 82); Else NoSound; End; {of Case} until (Ton = 'K'); NoSound; end.
"Hudební sluch" je schopnost sluchem identifikovat přehrávané noty, což se dokazuje tak, že osoba s hudebním sluchem je schopna noty buď zapsat,...Řekl bych, že jsi opomněl rozpoznání toho, jestli něco ladí nebo ne v celé hudbě, například rozpoznat, že nějaký nástroj není správně naladěný (jsou lidi, kteří poznají, že basa v rockové muzice je o deset centů pod tónem, jsou lidi - např. já - kteří většinou nejsou schopni určit, co ta basa hraje
gentlespring% python ladicka.py Traceback (most recent call last): File "ladicka.py", line 40, in ? i_tone = int(x_tone + 0.5) OverflowError: cannot convert float infinity to longrecord_and_analyze vrací 0. V chuncích jsou samé nuly. Capture mám zapnuté na všech zařízeních, kde to šlo.
arecord -c 1 -r 48000 -f S16_LE -t wav > nahravka.wav || aplay nahravka.wavSpusť to, něco namluv a dej ctrl+c. Mělo to zopakovat, co jsi řekl.
-0.12 B -0.12 BNejtlustčí struna, E:
-0.12 B +0.33 F +0.33 F +0.48 F +0.48 F +0.48 F +0.33 F +0.33 F +0.33 FDalší, A
+0.23 F# +0.09 A +0.21 A +0.09 A +0.09 A +0.09 A +0.09 A +0.23 F# +0.09 ADalší, d
+0.23 F# -0.31 A -0.31 A -0.31 A -0.31 A -0.25 A -0.31 ADlaší, g
-0.12 B +0.03 G +0.09 G +0.09 G +0.09 G +0.09 G +0.09 G +0.09 GDalší, b
-0.12 B +0.04 H +0.25 H +0.09 H +0.25 H +0.09 H +0.09 HDalší, e
+0.09 H -0.38 F# -0.45 F# -0.38 F# -0.45 F# -0.38 F# -0.45 F# -0.45 F#Znova, E
-0.12 B +0.33 F +0.33 F +0.48 F -0.38 F# +0.30 HTakže test nedopadl moc dobře. Nemám teď moc čas se ladičkou zabývat, ale je to velmi zajímavé téma a někdy se na ni podívám a pohraju si s ní. Možná by jsi mohl ladičku testovat nahrávkama strun, kterých je an internetu habaděj. Já podle nich ladím kytaru. Hledej vp795 na http://freesound.iua.upf.edu/ BTW, zohledňuješ tam nějak temperované ladění? Myslím, že ne, co?
#!/usr/bin/python tones = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'B', 'H'] for i in xrange(-20, 37): print '%2s %10.2f Hz' %(tones[i%12], 440*2**((i-9)/12.0))
while len(bytes) < N: l, chunk = inp.read() bytes.append(chunk) bytes = bytes[:N] data = fromstring(''.join(bytes), int16)Je to víc strightforvard a o mnoho víc paměti si to neukousne. Jestli je to rychlejší samozřejmě nevim. Proč vůbec nepoužít všechny data, co jsme dostali a proč je ořezávat?
>>> from scipy import * >>> a = arange(2**17) >>> fft(a) # tohle je hned hotové array([ 8.58986906e+09 +0.00000000e+00j, -6.55360000e+04 +2.73426110e+09j, -6.55360000e+04 +1.36713055e+09j, ..., -6.55360000e+04 -9.11420366e+08j, -6.55360000e+04 -1.36713055e+09j, -6.55360000e+04 -2.73426110e+09j]) >>> a = arange(2**17-1) >>> fft(a) # ... a tady výpočet trvá celou věčnostOdřezávání dat anebo naopak doplňování nulami je celkem běžný trik, pokud jde o rychlost fft.
tlustej_jack(female) -> tenkej_jack(male)
?
Ty mi uděláš bezdrátovou kytaru? To by bylo super! :)Vysílačky se taky nechají koupit... např.: http://www.muzikus.cz/pro-muzikanty-testy/Samson-Airline-aneb-volny-pohyb-zarucen~07~brezen~2003/
ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.