kleine Aenderungen:
-Die samples werden nach dem Filtern jetzt auf einen maximalen wert von 1 normiert -Layout der GUI verbessert -Feedback verbessert (v. a. Filterstatus) ACHTUNG: Der Filter liefert bei niedrigen Filterfrequenzen unendlich hohe Werte, was das Filtern unmoeglich macht Fehlt: Filter fuers Rauschen
This commit is contained in:
parent
14394db487
commit
23784cc6f7
@ -81,7 +81,7 @@ class Sound:
|
|||||||
self.start_idx = 0 # wird für sound_obj benötigt
|
self.start_idx = 0 # wird für sound_obj benötigt
|
||||||
self.music_samplerate = 0 # die samplerate der ausgewählten Musikdatei
|
self.music_samplerate = 0 # die samplerate der ausgewählten Musikdatei
|
||||||
self.music_data = 0 # das Numpy Array der ausgewählten Musikdatei
|
self.music_data = 0 # das Numpy Array der ausgewählten Musikdatei
|
||||||
self.filterfortschritt = 0 # siehe musik_filtern(), zwischen 0 und 100, wird für die feedback-fkt gebraucht
|
self.filterfortschritt = 0, 0. # für feedback-fkt, 1.Position: Abschnitt-Nmr, 2.Positon: Speicherfortschritt
|
||||||
|
|
||||||
|
|
||||||
def wav_speichern(self): # ezeugt/aktuallisiert die .wav-Datei
|
def wav_speichern(self): # ezeugt/aktuallisiert die .wav-Datei
|
||||||
@ -105,7 +105,7 @@ class Sound:
|
|||||||
for x in range(self.nframes): # geht jeden Sample-Wert der Musikdatei einzeln durch
|
for x in range(self.nframes): # geht jeden Sample-Wert der Musikdatei einzeln durch
|
||||||
# Die Audiodaten müssen von float in einen passenden int-Wert umgerechnet werden
|
# Die Audiodaten müssen von float in einen passenden int-Wert umgerechnet werden
|
||||||
packedMusic.append(struct.pack('h', int(audio[x][0] * 32767.0)))
|
packedMusic.append(struct.pack('h', int(audio[x][0] * 32767.0)))
|
||||||
packedMusic.append(struct.pack('h', int(audio[x][0] * 32767.0)))
|
packedMusic.append(struct.pack('h', int(audio[x][1] * 32767.0)))
|
||||||
|
|
||||||
value_str = b"".join(packedMusic)
|
value_str = b"".join(packedMusic)
|
||||||
wav_obj.writeframes(value_str)
|
wav_obj.writeframes(value_str)
|
||||||
@ -183,8 +183,10 @@ class Sound:
|
|||||||
2. Die digitalen Filter erstellen und die Tinnitus Frequenz aus der Audiodatei "herausschneiden"
|
2. Die digitalen Filter erstellen und die Tinnitus Frequenz aus der Audiodatei "herausschneiden"
|
||||||
3. Die fertigen Audiodatei als .wav Datei speichern
|
3. Die fertigen Audiodatei als .wav Datei speichern
|
||||||
"""
|
"""
|
||||||
|
nframes = len(self.music_data) # Gesamtanzahl der Frames in der Musikdatei
|
||||||
|
|
||||||
# ------------1. Die nötigen Informationen über den Tinnitus aus der .csv Datei herausholen---------------------
|
# ------------1. Die nötigen Informationen über den Tinnitus aus der .csv Datei herausholen---------------------
|
||||||
|
self.filterfortschritt = 1, 0 # der erste schritt
|
||||||
csvstring = open("TinnitusDaten.csv").read()
|
csvstring = open("TinnitusDaten.csv").read()
|
||||||
tinnitus_data = csvstring.split("\n")
|
tinnitus_data = csvstring.split("\n")
|
||||||
|
|
||||||
@ -211,9 +213,10 @@ class Sound:
|
|||||||
rl = float(rl[1])
|
rl = float(rl[1])
|
||||||
|
|
||||||
# -------- 2. Die digitalen Filter erstellen und die Tinnitus Frequenz aus der Audiodatei "herausschneiden------
|
# -------- 2. Die digitalen Filter erstellen und die Tinnitus Frequenz aus der Audiodatei "herausschneiden------
|
||||||
|
self.filterfortschritt = 2, 0 # der zweite schritt
|
||||||
start_time = time.time() # einen Timer laufen lassen um zu sehen wie lange Filterung dauert
|
start_time = time.time() # einen Timer laufen lassen um zu sehen wie lange Filterung dauert
|
||||||
|
|
||||||
self.music_data = self.music_data/32767 * 0.8 # convert array from int16 to float
|
self.music_data = self.music_data/32767 # convert array from int16 to float
|
||||||
""" OLD IIR Notch Filter 2nd Order----------------------------------------------------------------------
|
""" OLD IIR Notch Filter 2nd Order----------------------------------------------------------------------
|
||||||
w0 = float(lf / (self.music_samplerate / 2)) # Frequency to remove from a signal. If fs is specified, this is
|
w0 = float(lf / (self.music_samplerate / 2)) # Frequency to remove from a signal. If fs is specified, this is
|
||||||
in the same units as fs. By default, it is a normalized scalar that must satisfy 0 < w0 < 1, with w0 = 1
|
in the same units as fs. By default, it is a normalized scalar that must satisfy 0 < w0 < 1, with w0 = 1
|
||||||
@ -258,11 +261,46 @@ class Sound:
|
|||||||
endTimeFiltering = time.time()
|
endTimeFiltering = time.time()
|
||||||
print("benötigte Zeit zum Filtern rechts Ohr =", endTimeFiltering - start_time, "s")
|
print("benötigte Zeit zum Filtern rechts Ohr =", endTimeFiltering - start_time, "s")
|
||||||
|
|
||||||
# ------------------------- 3. Die fertigen Audiodatei als .wav Datei speichern --------------------------------
|
#----------------------- 3. Maxima finden und Samples auf 1 normieren ----------------------------
|
||||||
|
self.filterfortschritt = 3, 0 # der dritte schritt
|
||||||
|
|
||||||
|
#Maximum finden (Funktion max(...) ist minimal schneller, macht aber Probleme beim Feedback)
|
||||||
|
start_time = time.time()
|
||||||
|
max_ges = 0
|
||||||
|
for i in range(nframes):
|
||||||
|
if max_ges < abs(music_links[i]):
|
||||||
|
max_ges = abs(music_links[i])
|
||||||
|
if max_ges < abs(music_rechts[i]):
|
||||||
|
max_ges = abs(music_rechts[i])
|
||||||
|
if i % 50000 == 0:
|
||||||
|
fortschritt = i / nframes * 100
|
||||||
|
self.filterfortschritt = 3, round(fortschritt, 1)
|
||||||
|
print(" max: ", self.filterfortschritt[1], "%")
|
||||||
|
end_time = time.time()
|
||||||
|
print("Zeitaufwand Maxima-Suche: ", end_time - start_time)
|
||||||
|
|
||||||
|
#auf 4 Nachkommastellen aufrunden
|
||||||
|
start_time = time.time()
|
||||||
|
max_ges = int(max_ges * 10000)
|
||||||
|
max_ges += 1
|
||||||
|
max_ges /= 10000
|
||||||
|
end_time = time.time()
|
||||||
|
print("Zeitaufwand Maximum runden: ", end_time - start_time)
|
||||||
|
|
||||||
|
#Alle samples normieren
|
||||||
|
start_time = time.time()
|
||||||
|
music_links /= max_ges
|
||||||
|
music_rechts /= max_ges
|
||||||
|
end_time = time.time()
|
||||||
|
print("Zeitaufwand samples normieren: ", end_time - start_time)
|
||||||
|
|
||||||
|
|
||||||
|
# ------------------------- 4. Die fertigen Audiodatei als .wav Datei speichern --------------------------------
|
||||||
|
self.filterfortschritt = [4, 0] # der vierte Schritt
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
wav_obj = wave.open("MyTinnitusFreeSong.wav", "w")
|
wav_obj = wave.open("MyTinnitusFreeSong.wav", "w")
|
||||||
|
|
||||||
# Rahmenparameter für die .wav-Datei setzen
|
# Rahmenparameter für die .wav-Datei setzen
|
||||||
nframes = len(self.music_data) #Gesamtanzahl der Frames in der Musikdatei
|
|
||||||
wav_obj.setparams((self.nchannels, self.sampwidth, self.music_samplerate, nframes, self.comptype, self.compname))
|
wav_obj.setparams((self.nchannels, self.sampwidth, self.music_samplerate, nframes, self.comptype, self.compname))
|
||||||
|
|
||||||
"""The values are stored in a temporary list, and when the process is finished, they are joined together into
|
"""The values are stored in a temporary list, and when the process is finished, they are joined together into
|
||||||
@ -279,10 +317,10 @@ class Sound:
|
|||||||
|
|
||||||
# wav_obj.writeframes(struct.pack('h', int(music_links[x] * 32767.0))) # Werte für links und rechts werden bei
|
# wav_obj.writeframes(struct.pack('h', int(music_links[x] * 32767.0))) # Werte für links und rechts werden bei
|
||||||
# wav_obj.writeframes(struct.pack('h', int(musicRechts[x] * 32767.0))) # wav abwechselnd eingetragen
|
# wav_obj.writeframes(struct.pack('h', int(musicRechts[x] * 32767.0))) # wav abwechselnd eingetragen
|
||||||
if tinnitus_data % 10000 == 0:
|
if tinnitus_data % 50000 == 0:
|
||||||
fortschritt = tinnitus_data/nframes*100
|
fortschritt = tinnitus_data/nframes*100
|
||||||
self.filterfortschritt = round(fortschritt, 1)
|
self.filterfortschritt = 4, round(fortschritt, 1)
|
||||||
print(" ", self.filterfortschritt, "%")
|
print(" samples: ", self.filterfortschritt[1], "%")
|
||||||
|
|
||||||
end_time = time.time()
|
end_time = time.time()
|
||||||
print("Zeitaufwand für das packen der einzelnen Samples =", end_time - start_time, "s")
|
print("Zeitaufwand für das packen der einzelnen Samples =", end_time - start_time, "s")
|
||||||
@ -297,6 +335,7 @@ class Sound:
|
|||||||
wav_obj.close()
|
wav_obj.close()
|
||||||
|
|
||||||
print("Speichern beendet.")
|
print("Speichern beendet.")
|
||||||
|
self.filterfortschritt = 5, 0 #Nach erfolgreichem Filtern Fortschritt zur Bestätigung auf 5 setzen
|
||||||
# # Plot (hilfreich für Filterentwurf)
|
# # Plot (hilfreich für Filterentwurf)
|
||||||
# freq, h = signal.freqz(b, a, fs=self.music_samplerate)
|
# freq, h = signal.freqz(b, a, fs=self.music_samplerate)
|
||||||
# fig, ax = plt.subplots(2, 1, figsize=(8, 6))
|
# fig, ax = plt.subplots(2, 1, figsize=(8, 6))
|
||||||
|
@ -126,11 +126,11 @@ def unten_button_speichern_press():
|
|||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
unten_button_stop_press() # Wiedergabe beenden, durch den Rechenaufwand gibt es sonst Wiedergabeprobleme
|
unten_button_stop_press() # Wiedergabe beenden, durch den Rechenaufwand gibt es sonst Wiedergabeprobleme
|
||||||
feedback("Speichere Sound als '.wav'-Datei. Bitte warten...")
|
|
||||||
tinnitus.vorname = untenEntryVorname.get()
|
tinnitus.vorname = untenEntryVorname.get()
|
||||||
tinnitus.nachname = untenEntryNachname.get()
|
tinnitus.nachname = untenEntryNachname.get()
|
||||||
tinnitus.kommentar = untenTextKommentar.get("1.0", END)
|
tinnitus.kommentar = untenTextKommentar.get("1.0", END)
|
||||||
tinnitus.speichern()
|
tinnitus.speichern()
|
||||||
|
feedback("Speichere Sound als '.wav'-Datei. Bitte warten...")
|
||||||
sound.wav_speichern()
|
sound.wav_speichern()
|
||||||
feedback("Daten erfolgreich gespeichert. Siehe: " + sound.wav_name, "white", "green")
|
feedback("Daten erfolgreich gespeichert. Siehe: " + sound.wav_name, "white", "green")
|
||||||
except:
|
except:
|
||||||
@ -156,7 +156,6 @@ def feedback(text, fontcolor="black", backgroundcolor="lightsteelblue"):
|
|||||||
right of the GUI) in the text widget. The parameter color is also a string and defines the font color. Same with
|
right of the GUI) in the text widget. The parameter color is also a string and defines the font color. Same with
|
||||||
background. Honestly this function is way too complicated, but Tkinter has no nicer/easier builtin way of doing the
|
background. Honestly this function is way too complicated, but Tkinter has no nicer/easier builtin way of doing the
|
||||||
coloring nicely """
|
coloring nicely """
|
||||||
|
|
||||||
feedback.lineCounter += 1 # in order to color the texts nicely we need to count the lines of text we add
|
feedback.lineCounter += 1 # in order to color the texts nicely we need to count the lines of text we add
|
||||||
untenFeedbackText.config(state=NORMAL) # activate text field (otherwise it is readonly)
|
untenFeedbackText.config(state=NORMAL) # activate text field (otherwise it is readonly)
|
||||||
|
|
||||||
@ -199,23 +198,38 @@ def unten_button_musikdatei_laden_press():
|
|||||||
|
|
||||||
def unten_button_filtere_tinnitus_aus_musik():
|
def unten_button_filtere_tinnitus_aus_musik():
|
||||||
print("button filtere tinnitus aus musik pressed")
|
print("button filtere tinnitus aus musik pressed")
|
||||||
try:
|
print(untenTextMusikDatei.get('1.0', END))
|
||||||
|
if untenTextMusikDatei.get('1.0', END) == "Einen Song deiner Wahl hier auswählen\n":
|
||||||
|
feedback("Wähle zuerst eine Musikdatei aus", "white", "red")
|
||||||
|
else:
|
||||||
|
unten_button_stop_press() # Wiedergabe beenden, durch den Rechenaufwand gibt es sonst Wiedergabeprobleme
|
||||||
feedback("Starte Filtervorgang (dies kann etwas dauern)...", "blue")
|
feedback("Starte Filtervorgang (dies kann etwas dauern)...", "blue")
|
||||||
# Filtern in extra thread, damit sich die GUI nicht aufhängt: (daemon beendet den Thread, wenn das Hauptprogramm beendet wird)
|
|
||||||
filter_thread = threading.Thread(target=sound.musik_filtern, daemon=True)
|
|
||||||
filter_thread.start()
|
|
||||||
|
|
||||||
while filter_thread.is_alive() == True:
|
try:
|
||||||
fb = "Status: " + str(sound.filterfortschritt) + "%"
|
# Filtern in extra thread, damit sich die GUI nicht aufhängt: (daemon beendet den Thread, wenn das Hauptprogramm beendet wird)
|
||||||
feedback(fb)
|
filter_thread = threading.Thread(target=sound.musik_filtern, daemon=True)
|
||||||
time.sleep(0.2)
|
filter_thread.start()
|
||||||
print("-- filtern beendet --")
|
time.sleep(3) # Zeit, damit man das Feedback lesen kann, bevor es gelöscht wird (siehe übernächste Zeile)
|
||||||
feedback("Filtervorgang erfolgreich abgeschlossen. \n"
|
|
||||||
"Audiodatei unter dem Namen MyTinnitusFreeSong.wav erstellt", "white", "green")
|
while filter_thread.is_alive():
|
||||||
except:
|
feedback.lineCounter = 11 # "Workaround" um Zeilen überschreiben zu können
|
||||||
feedback("Fehlgeschlagener Filterversuch. Drücke zuerst den Speichern Knopf"
|
if sound.filterfortschritt[0] > 2: #Nur bei dem 3. und 4. Schritt wird der Fortschritt in Prozent angezeigt
|
||||||
"Stelle sicher, dass die Lautstärke mindestens einer Seite über 0"
|
fb = "Schritt " + str(sound.filterfortschritt[0]) + " von 4 (" + str(sound.filterfortschritt[1]) + "%)"
|
||||||
"gestellt ist. Sonst gehen wir davon aus, dass auf diesem Ohr kein Tinnitus vorliegt.", "red", "white")
|
else:
|
||||||
|
fb = "Schritt " + str(sound.filterfortschritt[0]) + " von 4"
|
||||||
|
feedback(fb)
|
||||||
|
if sound.filterfortschritt[0] == 5: #ist 5, wenn erfolgreich gefiltert wurde
|
||||||
|
print("-- filtern beendet --")
|
||||||
|
feedback("Filtervorgang erfolgreich abgeschlossen. \n"
|
||||||
|
"Audiodatei unter dem Namen MyTinnitusFreeSong.wav erstellt", "white", "green")
|
||||||
|
else:
|
||||||
|
print("Fehler bei Filterfunktion. Siehe Compiler-Meldungen")
|
||||||
|
feedback("Fehlgeschlagener Filterversuch!", "red", "white")
|
||||||
|
except:
|
||||||
|
feedback("Fehlgeschlagener Filterversuch. Drücke zuerst den Speichern Knopf"
|
||||||
|
"Stelle sicher, dass die Lautstärke mindestens einer Seite über 0"
|
||||||
|
"gestellt ist. Sonst gehen wir davon aus, dass auf diesem Ohr kein Tinnitus vorliegt.", "red",
|
||||||
|
"white")
|
||||||
|
|
||||||
|
|
||||||
""" Initialisierungen """
|
""" Initialisierungen """
|
||||||
@ -349,17 +363,17 @@ untenLabelOhrenSynchro2 = Label(untererFrame, text=" für beide übernehmen")
|
|||||||
untenLabelOhrenSynchro2.grid(column=2, row=0, sticky=(N + W + E + S))
|
untenLabelOhrenSynchro2.grid(column=2, row=0, sticky=(N + W + E + S))
|
||||||
untenButtonOhrenSynchro = Button(untererFrame, text="Bestätigen",
|
untenButtonOhrenSynchro = Button(untererFrame, text="Bestätigen",
|
||||||
command=unten_button_ohren_synchro)
|
command=unten_button_ohren_synchro)
|
||||||
untenButtonOhrenSynchro.grid(column=3, row=0, sticky=(N + W + E + S))
|
untenButtonOhrenSynchro.grid(column=3, row=0, sticky=(N + S))
|
||||||
|
|
||||||
#----------- PLAY BUTTON
|
#----------- PLAY BUTTON
|
||||||
untenButtonPlay = Button(untererFrame, text="PLAY", font="bold", relief="raised", bg="green", fg="white",
|
untenButtonPlay = Button(untererFrame, text="PLAY", font="bold", relief="raised", bg="green", fg="white",
|
||||||
command=unten_button_play_press)
|
command=unten_button_play_press)
|
||||||
untenButtonPlay.grid(column=8, row=0, sticky=(N + W + E + S))
|
untenButtonPlay.grid(column=7, row=0, sticky=(N + W + E + S))
|
||||||
|
|
||||||
#------------STOP BUTTON-------------
|
#------------STOP BUTTON-------------
|
||||||
untenButtonStop = Button(untererFrame, text="STOP", font="bold", relief="raised", bg="red", fg="white",
|
untenButtonStop = Button(untererFrame, text="STOP", font="bold", relief="raised", bg="red", fg="white",
|
||||||
command=unten_button_stop_press)
|
command=unten_button_stop_press)
|
||||||
untenButtonStop.grid(column=9, row=0, sticky=(N + W + E + S))
|
untenButtonStop.grid(column=8, row=0, sticky=(N + W + E + S))
|
||||||
|
|
||||||
# ----------- ABTRENNSTRICHE ----------------
|
# ----------- ABTRENNSTRICHE ----------------
|
||||||
untenSeparator = Separator(untererFrame, orient="horizontal")
|
untenSeparator = Separator(untererFrame, orient="horizontal")
|
||||||
@ -381,13 +395,15 @@ untenEntryVorname.grid(column=1, row=3, sticky=W)
|
|||||||
# ------------ KOMMENTAR ----------------
|
# ------------ KOMMENTAR ----------------
|
||||||
untenLabelKommentar = Label(untererFrame, text="weitere Kommentare:")
|
untenLabelKommentar = Label(untererFrame, text="weitere Kommentare:")
|
||||||
untenLabelKommentar.grid(column=0, row=4, sticky=W)
|
untenLabelKommentar.grid(column=0, row=4, sticky=W)
|
||||||
untenTextKommentar = Text(untererFrame, height=10, width=50) # create a field where u can enter text
|
untenLabelKommentar = Label(untererFrame, text="(optional)")
|
||||||
untenTextKommentar.grid(column=1, row=4, columnspan=3, rowspan=3)
|
untenLabelKommentar.grid(column=0, row=5, sticky=N)
|
||||||
|
untenTextKommentar = Text(untererFrame, height=10, width=60) # create a field where u can enter text
|
||||||
|
untenTextKommentar.grid(column=1, row=4, sticky=W, columnspan=3, rowspan=3)
|
||||||
|
|
||||||
# ----------- SPEICHERN --------------------
|
# ----------- SPEICHERN --------------------
|
||||||
untenButtonSpeichern = Button(untererFrame, text="Speichern", font="bold",
|
untenButtonSpeichern = Button(untererFrame, text="Speichern", font="bold",
|
||||||
command=unten_button_speichern_press)
|
command=unten_button_speichern_press)
|
||||||
untenButtonSpeichern.grid(column=4, row=6, sticky=S)
|
untenButtonSpeichern.grid(column=4, row=6, sticky=(S+E+W))
|
||||||
|
|
||||||
|
|
||||||
"""--------------------------------------UNTERER RECHTER FRAME-------------------------------------------------------"""
|
"""--------------------------------------UNTERER RECHTER FRAME-------------------------------------------------------"""
|
||||||
@ -405,20 +421,20 @@ untenFeedbackText.place(relx=.5, rely=.5, anchor="center") # the only time I us
|
|||||||
|
|
||||||
# -------------- LOAD MUSIC FILE--------------
|
# -------------- LOAD MUSIC FILE--------------
|
||||||
untenTextMusikDatei = Text(untererFrame, height=1, width=50)
|
untenTextMusikDatei = Text(untererFrame, height=1, width=50)
|
||||||
untenTextMusikDatei.grid(column=0, row=7, sticky=(N+S+E+W), columnspan=6)
|
untenTextMusikDatei.grid(column=1, row=7, sticky=(N+S+E+W), columnspan=4)
|
||||||
untenTextMusikDatei.insert(INSERT, "Einen Song deiner Wahl hier auswählen") # insert selected file path to text widget
|
untenTextMusikDatei.insert(INSERT, "Einen Song deiner Wahl hier auswählen") # insert selected file path to text widget
|
||||||
untenTextMusikDatei.config(state=DISABLED) # activate text field (otherwise it is readonly)
|
untenTextMusikDatei.config(state=DISABLED, font=("Arial", 8)) # activate text field (otherwise it is readonly)
|
||||||
|
|
||||||
untenButtonMusikDateiLaden = Button(untererFrame, text="Musikdatei auswählen",
|
untenButtonMusikDateiLaden = Button(untererFrame, text="Musikdatei auswählen",
|
||||||
command=unten_button_musikdatei_laden_press)
|
command=unten_button_musikdatei_laden_press)
|
||||||
untenButtonMusikDateiLaden.grid(column=7, row=7, sticky=(N+S+E+W))
|
untenButtonMusikDateiLaden.grid(column=4, row=7, sticky=(N+S+E+W))
|
||||||
|
|
||||||
|
|
||||||
#------------BUTTON FILTERE TINNITUS AUS MUSIK-----------------
|
#------------BUTTON FILTERE TINNITUS AUS MUSIK-----------------
|
||||||
untenButtonFiltereTinnitusAusMusik = Button(untererFrame, text="Filtere Tinnitus Frequenzen aus Musik",
|
untenButtonFiltereTinnitusAusMusik = Button(untererFrame, text="Filtere Tinnitus-Frequenzen aus Musik",
|
||||||
command=unten_button_filtere_tinnitus_aus_musik, font="bold",
|
command=unten_button_filtere_tinnitus_aus_musik, font="bold",
|
||||||
relief="raised", bg="blue", fg="white",)
|
relief="raised", bg="blue", fg="white",)
|
||||||
untenButtonFiltereTinnitusAusMusik.grid(column=0, row=9, sticky=(N+S+E+W))
|
untenButtonFiltereTinnitusAusMusik.grid(column=3, row=9, sticky=(N+S+E+W), columnspan=3)
|
||||||
|
|
||||||
|
|
||||||
root.mainloop()
|
root.mainloop()
|
Loading…
x
Reference in New Issue
Block a user