diff --git a/TinnitusAnalyse/.idea/dictionaries/Julian.xml b/TinnitusAnalyse/.idea/dictionaries/Julian.xml index 6836398..4dc9a6a 100644 --- a/TinnitusAnalyse/.idea/dictionaries/Julian.xml +++ b/TinnitusAnalyse/.idea/dictionaries/Julian.xml @@ -7,6 +7,7 @@ beide beiden definieren + filterordnung fontcolor frequenz kommentar @@ -21,6 +22,7 @@ mittelfrequenz nachname ohren + passband rauschen rauschens rechtem @@ -30,6 +32,7 @@ rechts speichere speicherversuch + sperrbereichs variablen vorname zwischen diff --git a/TinnitusAnalyse/.idea/workspace.xml b/TinnitusAnalyse/.idea/workspace.xml index 4a0cfe4..fe2609b 100644 --- a/TinnitusAnalyse/.idea/workspace.xml +++ b/TinnitusAnalyse/.idea/workspace.xml @@ -2,16 +2,83 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TinnitusAnalyse/MyTinnitusFreeSong.wav b/TinnitusAnalyse/MyTinnitusFreeSong.wav new file mode 100644 index 0000000..18c35d0 Binary files /dev/null and b/TinnitusAnalyse/MyTinnitusFreeSong.wav differ diff --git a/TinnitusAnalyse/SoundGenerator.py b/TinnitusAnalyse/SoundGenerator.py index 4a6c511..ec3ad52 100644 --- a/TinnitusAnalyse/SoundGenerator.py +++ b/TinnitusAnalyse/SoundGenerator.py @@ -5,7 +5,9 @@ import numpy as np import sys # für Fehlermeldungen from scipy import signal import csv -#import matplotlib.pyplot as plt +import time +import matplotlib.pyplot as plt + """--------------------------------------------------------------------------------------------------------------------- In .wav-Dateien wird der Ton in absoluten Werte eingetragen. Die Standart-framerate ist 44100 das heißt für jede Sekunde an Ton gibt es 44100 Werte, die die Tonwelle über die Zeit beschreiben @@ -168,97 +170,140 @@ class Sound: return outdata def musik_filtern(self): - """ Die Tinnitus Frequenz aus der Musik Filtern... easy""" + """ + Diese Funktion filtert die Tinnitus Frequenz aus einer gewählten Musikdatei. Dabei geht sie in 3 großen + Schritten vor: + 1. Die nötigen Informationen über den Tinnitus aus der .csv Datei herausholen + 2. Die digitalen Filter erstellen und die Tinnitus Frequenz aus der Audiodatei "herausschneiden" + 3. Die fertigen Audiodatei als .wav Datei speichern + """ - # Die Parameter des Tinnitus aus .csv Datei getten + # ------------1. Die nötigen Informationen über den Tinnitus aus der .csv Datei herausholen--------------------- csvstring = open("TinnitusDaten.csv").read() - #print(csvstring) - x = csvstring.split("\n") - #print("\nx= ", x) + tinnitus_data = csvstring.split("\n") # linke Frequenz aus csv Datei holen - lf = x[2] + lf = tinnitus_data[2] lf = lf.split(";") lf = float(lf[1]) # rechte Frequenz aus csv Datei holen - rf = x[7] + rf = tinnitus_data[7] rf = rf.split(";") rf = float(rf[1]) # linke Lautstärke aus cvs Datei holen - ll = x[3] + ll = tinnitus_data[3] ll = ll.split(";") ll = float(ll[1]) # rechte Lautstärke aus cvs Datei holen - rl = x[8] + rl = tinnitus_data[8] rl = rl.split(";") rl = float(rl[1]) - - # Die Musik filtern - 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 corresponding to half of the sampling frequency. - Q = 30.0 # Quality factor. Dimensionless parameter that characterizes notch filter -3 dB bandwidth bw relative to its center frequency, Q = w0/bw. + # -------- 2. Die digitalen Filter erstellen und die Tinnitus Frequenz aus der Audiodatei "herausschneiden------ + 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 - + """ 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 + in the same units as fs. By default, it is a normalized scalar that must satisfy 0 < w0 < 1, with w0 = 1 + corresponding to half of the sampling frequency. + Q = 30.0 # Quality factor. Dimensionless parameter that characterizes notch filter -3 dB bandwidth bw relative + to its center frequency, Q = w0/bw. b, a = signal.iirnotch(lf, Q, fs=self.music_samplerate) - if ll != 0.0: - print("Links wird gefiltert...") - musicLinks = signal.lfilter(b, a , self.music_data[:, 0]) # links - print("Filtern beendet") + ---------------------------------------------------------------------------------------------------------------- + """ + + """ New IIR Notch Filter 5th order--------------------------------------------------------------------------""" + # ------------------------------------------LEFT EAR FILTERING------------------------------------------------- + # Filterparameter festlegen------------ + order = 5 # Filterordnung + bandwidth = 175 # Bandbreite des Sperrbereichs in Hz + #stop_attenuation = 100 # minimum Attenuation (Damping, Reduction) in stop Band [only for elliptic filter necessary] + cutoff_frequencies = [(lf - (bandwidth / 2)),(lf + (bandwidth / 2))] # the cutoff frequencies (lower and upper) + max_ripple_passband = 50 # Maximal erlaubte Welligkeit im Passbereich + # ------------------------------------- + + if ll != 0.0: # nur wenn die Lautstärke des linken Tinnitus ungleich 0 ist, wird auf diesem Ohr auch gefiltert + + b, a = signal.iirfilter(order, cutoff_frequencies, rp=max_ripple_passband, btype='bandstop', ftype='butter', + fs=self.music_samplerate) # Diese Funktion erstellt den IIR-Bandpassfilter (links) + + music_links = signal.lfilter(b, a, self.music_data[:, 0]) # diese Funktion filtert die Audiodaten else: - musicLinks = self.music_data[:, 0] # ungefiltert, wenn kein Tinnitus angegeben wurde + music_links = self.music_data[:, 0] # ungefiltert, wenn kein Tinnitus angegeben wurde - #Plot - # freq, h = signal.freqz(b, a, fs=self.music_samplerate) - # fig, ax = plt.subplots(2, 1, figsize=(8, 6)) - # ax[0].plot(freq, 20 * np.log10(abs(h)), color='blue') - # ax[0].set_title("Frequency Response") - # ax[0].set_ylabel("Amplitude (dB)", color='blue') - # ax[0].set_xlim([0, 10000]) - # ax[0].set_ylim([-25, 10]) - # ax[0].grid() - # ax[1].plot(freq, np.unwrap(np.angle(h)) * 180 / np.pi, color='green') - # ax[1].set_ylabel("Angle (degrees)", color='green') - # ax[1].set_xlabel("Frequency (Hz)") - # ax[1].set_xlim([0, 10000]) - # ax[1].set_yticks([-90, -60, -30, 0, 30, 60, 90]) - # ax[1].set_ylim([-90, 90]) - # ax[1].grid() - # plt.show() + # ------------------------------------- RIGHT EAR FILTERING ------------------------------------------------ + if rl != 0.0: # nur wenn die Lautstärke des rechten Tinnitus ungleich 0 ist, wird auf diesem Ohr auch gefiltert + cutoff_frequencies = [(rf - (bandwidth / 2)), ( + rf + (bandwidth / 2))] # change the cutoff frequencies to the tinnitus of the RIGHT EAR - b, a = signal.iirnotch(rf, Q, fs=self.music_samplerate) - if rl != 0.0: - print("Rechts wird gefiltert...") - musicRechts = signal.lfilter(b, a, self.music_data[:, 1]) # rechts - print("Filtern beendet") + b, a = signal.iirfilter(order, cutoff_frequencies, rp=max_ripple_passband, btype='bandstop', ftype='butter', + fs=self.music_samplerate) # Diese Funktion erstellt den IIR-Bandpassfilter (rechts) + + music_rechts = signal.lfilter(b, a, self.music_data[:, 1]) # rechts else: - musicRechts = self.music_data[:, 1] # ungefiltert, wenn kein Tinnitus angegeben wurde + music_rechts = self.music_data[:, 1] # diese Funktion filtert die Audiodaten(die Tinnitusfreq wird entfernt) + endTimeFiltering = time.time() + print("benötigte Zeit zum Filtern rechts Ohr =", endTimeFiltering - start_time, "s") - wav_obj = wave.open("musikTest.wav", "w") - + # ------------------------- 3. Die fertigen Audiodatei als .wav Datei speichern -------------------------------- + start_time = time.time() + wav_obj = wave.open("MyTinnitusFreeSong.wav", "w") # 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)) - print("Maximum musicLinks: ", max(musicLinks)) - print("Minimum musikLinks: ", min(musicLinks)) + """The values are stored in a temporary list, and when the process is finished, they are joined together into + an string which is then sent to the output with the traditional writeframes method.""" + packedMusic = [] # Liste an die wir die einzelnen frames bereits in binär umgewandelt aneinanderreihen # Die Audiosamples schreiben print("Musikdatei wird erstellt...") - for x in range(self.music_samplerate * 20): #Kann mit nframes ersetzt werden, für den ganzen Song + for tinnitus_data in range(self.music_samplerate * 60): #Kann mit nframes ersetzt werden, für den ganzen Song # Die Audiodaten müssen von float in einen passenden int-Wert umgerechnet werden - wav_obj.writeframes(struct.pack('h', int(musicLinks[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 - if x % 10000 == 0: - fortschritt = x/(self.music_samplerate*20)*100 + packedMusic.append(struct.pack('h', int(music_links[tinnitus_data] * 32767.0))) + packedMusic.append(struct.pack('h', int(music_rechts[tinnitus_data] * 32767.0))) + + # 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 + if tinnitus_data % 10000 == 0: + fortschritt = tinnitus_data/(self.music_samplerate*20)*100 print(" ", round(fortschritt, 1), "%") + end_time = time.time() + print("Zeitaufwand für das packen der einzelnen Samples =", end_time - start_time, "s") + + + value_str = b"".join(packedMusic) + + start = time.time() + wav_obj.writeframes(value_str) + end = time.time() + print("Zeitaufwand für das schreiben aller Frames in die wav Datei =", end - start, "s") wav_obj.close() + print("Speichern beendet.") + # # Plot (hilfreich für Filterentwurf) + # freq, h = signal.freqz(b, a, fs=self.music_samplerate) + # fig, ax = plt.subplots(2, 1, figsize=(8, 6)) + # ax[0].plot(freq, 20 * np.log10(abs(h)), color='blue') + # ax[0].set_title("Frequency Response") + # ax[0].set_ylabel("Amplitude (dB)", color='blue') + # ax[0].set_xlim([0, 10000]) + # ax[0].set_ylim([-120, 10]) + # ax[0].grid() + # ax[1].plot(freq, np.unwrap(np.angle(h)) * 180 / np.pi, color='green') + # ax[1].set_ylabel("Angle (degrees)", color='green') + # ax[1].set_xlabel("Frequency (Hz)") + # ax[1].set_xlim([0, 10000]) + # ax[1].set_yticks([-90, -60, -30, 0, 30, 60, 90]) + # ax[1].set_ylim([-90, 90]) + # ax[1].grid() + # plt.show() diff --git a/TinnitusAnalyse/TinnitusAnalyse_GUI.py b/TinnitusAnalyse/TinnitusAnalyse_GUI.py index 9b9755b..39904fa 100644 --- a/TinnitusAnalyse/TinnitusAnalyse_GUI.py +++ b/TinnitusAnalyse/TinnitusAnalyse_GUI.py @@ -6,9 +6,6 @@ import sounddevice as sd from scipy.io import wavfile - - - """--------------------------FUNKTIONEN DIE DURCH GUI KLICKS AUSGEFÃœHRT WERDEN---------------------------------------""" """-------Funktionen links-------------""" @@ -201,10 +198,15 @@ def unten_button_musikdatei_laden_press(): def unten_button_filtere_tinnitus_aus_musik(): print("button filtere tinnitus aus musik pressed") - feedback("Gefilterte Musikdatei erstellt", "blue") - sound.musik_filtern() - # except: - # feedback("Fehlgeschlagener Filterversuch!", "red", "white") + try: + feedback("Starte Filtervorgang (dies kann einige Minuten dauern)...", "blue") + sound.musik_filtern() + feedback("Filtervorgang erfolgreich abgeschlossen. \n" + "Audiodatei unter dem Namen MyTinnitusFreeSong.wav erstellt", "white", "green") + 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 """ diff --git a/TinnitusAnalyse/TinnitusDaten.csv b/TinnitusAnalyse/TinnitusDaten.csv index ec45a9f..2c27f60 100644 --- a/TinnitusAnalyse/TinnitusDaten.csv +++ b/TinnitusAnalyse/TinnitusDaten.csv @@ -1,13 +1,14 @@ Vorname;asd Nachname;asd -linke Frequenz;10000.0 -linke Lautstärke;0.2 +linke Frequenz;5040.0 +linke Lautstärke;0.04 linkes Rauschen Lautstärke;0.0 linkes Rauschen untere Grenzfrequenz;10.0 linkes Rauschen obere Grenzfrequenz;20000.0 -rechte Frequenz;920.0 -rechte Lautstärke;0.28 +rechte Frequenz;5040.0 +rechte Lautstärke;0.02 rechtes Rauschen Lautstärke;0.0 rechtes Rauschen untere Grenzfrequenz;10.0 rechtes Rauschen obere Grenzfrequenz;20000.0 Kommentar; + diff --git a/TinnitusAnalyse/__pycache__/SoundGenerator.cpython-35.pyc b/TinnitusAnalyse/__pycache__/SoundGenerator.cpython-35.pyc index a067d48..cc38bcb 100644 Binary files a/TinnitusAnalyse/__pycache__/SoundGenerator.cpython-35.pyc and b/TinnitusAnalyse/__pycache__/SoundGenerator.cpython-35.pyc differ diff --git a/TinnitusAnalyse/musikTest.wav b/TinnitusAnalyse/musikTest.wav index 7b3d029..8942419 100644 Binary files a/TinnitusAnalyse/musikTest.wav and b/TinnitusAnalyse/musikTest.wav differ