Stereo-Sound eingebaut und Formatierungen/Kommentare geändert

This commit is contained in:
Heiko Ommert 2020-06-15 10:31:56 +02:00
parent 600968195e
commit 6359602a4b
2 changed files with 71 additions and 59 deletions

View File

@ -5,11 +5,14 @@ import sounddevice as sd #zum abspielen des audio-arrays
import numpy as np import numpy as np
import sys # für Fehlermeldungen import sys # für Fehlermeldungen
#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 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
---------------------------------------------------------------------------------------------------------------------"""
class Tinnitus: # beinhaltet alle Werte, die vom Nutzer eingestellt werden class Tinnitus: # beinhaltet alle Werte, die vom Nutzer eingestellt werden
def __init__(self, l_freq=600, r_freq=600, l_amp=0, r_amp=0, l_rausch=0, r_rausch=0, ear=0): def __init__(self, l_freq=0, r_freq=0, l_amp=0, r_amp=0, l_rausch=0, r_rausch=0, ohr=0):
self.vorname = "" self.vorname = ""
self.nachname = "" self.nachname = ""
self.kommentar = "" self.kommentar = ""
@ -19,11 +22,9 @@ class Tinnitus: #beinhaltet alle Werte, die vom Nutzer eingestellt werden
self.rechtsLautstaerke = r_amp self.rechtsLautstaerke = r_amp
self.linksRauschenLautstaerke = l_rausch # float von 0-1 (0 ist aus) self.linksRauschenLautstaerke = l_rausch # float von 0-1 (0 ist aus)
self.rechtsRauschenLautstaerke = r_rausch self.rechtsRauschenLautstaerke = r_rausch
self.ear = ear # 0:both 1:left 2:right 3:links/rechts unterschiedlich self.ohr = ohr # 0:both 1:left 2:right 3:links/rechts unterschiedlich
return
def speichern(self): # speichert die Nutzerdaten in eine .csv-Datei def speichern(self): # speichert die Nutzerdaten in eine .csv-Datei
datei = open("TinnitusDaten.csv", "w") datei = open("TinnitusDaten.csv", "w")
daten = "Vorname;" + self.vorname + "\n" daten = "Vorname;" + self.vorname + "\n"
@ -38,13 +39,17 @@ class Tinnitus: #beinhaltet alle Werte, die vom Nutzer eingestellt werden
datei.write(daten) datei.write(daten)
datei.close() datei.close()
return
"""Sound beinhaltet alle Variablen, die zum erstellen einer .wav-Datei benötigt werden (siehe soun.wav_speichern()) """---------------------------------KLASSE: SOUND-----------------------------------------------------------------------
Sound beinhaltet alle Variablen, die zum erstellen einer .wav-Datei benötigt werden (siehe soun.wav_speichern())
Das 'sound_obj' ist für das dynamische abspielen zuständig (siehe sound.play()) Das 'sound_obj' ist für das dynamische abspielen zuständig (siehe sound.play())
Beim Initialisieren muss eine Tinnitus-Objekt übergeben werden""" Beim Initialisieren muss eine Tinnitus-Objekt übergeben werden
---------------------------------------------------------------------------------------------------------------------"""
class Sound: class Sound:
def __init__(self, tinnitus, name="sound.wav", audio=None, nchannels=1, sampwidth=2, framerate=44100, comptype="NONE", compname="not compressed", mute=True): def __init__(self, tinnitus, name="sound.wav", audio=None, nchannels=1, sampwidth=2, framerate=44100,
comptype="NONE", compname="not compressed", mute=True):
if audio is None: if audio is None:
audio = [] audio = []
self.tinnitus = tinnitus self.tinnitus = tinnitus
@ -56,10 +61,10 @@ class Sound:
self.nframes = len(audio) # Anzahl der Sound-Werte -> Muss bei jeder audio-Änderung aktuallisiert werden self.nframes = len(audio) # Anzahl der Sound-Werte -> Muss bei jeder audio-Änderung aktuallisiert werden
self.comptype = comptype self.comptype = comptype
self.compname = compname self.compname = compname
self.mute = True # wenn der mute boolean auf true gesetzt ist, sollte kein Ton ausgegeben werden self.mute = mute # wenn der mute boolean auf true gesetzt ist, sollte kein Ton ausgegeben werden
self.sound_obj = sd.OutputStream(channels=2, callback=self.callback, samplerate=self.framerate) #Objekt fürs Abspielen (siehe sound.play()) self.sound_obj = sd.OutputStream(channels=2, callback=self.callback,
samplerate=self.framerate) # Objekt fürs Abspielen (siehe sound.play())
self.start_idx = 0 # wird für sound_obj benötigt self.start_idx = 0 # wird für sound_obj benötigt
return
def wav_speichern(self): # ezeugt/aktuallisiert die .wav-Datei def wav_speichern(self): # ezeugt/aktuallisiert die .wav-Datei
wav_file = wave.open(self.name, "w") wav_file = wave.open(self.name, "w")
@ -77,11 +82,10 @@ class Sound:
for x in range(int(num_samples)): # einen einfachen Sinus ins array schreiben for x in range(int(num_samples)): # einen einfachen Sinus ins array schreiben
audio.append(amp * math.sin(2 * math.pi * freq * (x / self.framerate))) audio.append(amp * math.sin(2 * math.pi * freq * (x / self.framerate)))
if(rauschen): #das Rauschen addieren if rauschen: # das Rauschen addieren
for x in range(int(num_samples)): for x in range(int(num_samples)):
audio[x] += (np.random.rand() - 0.5) * rauschen audio[x] += (np.random.rand() - 0.5) * rauschen
# erst werden die Rahmen-Parameter gesetzt # erst werden die Rahmen-Parameter gesetzt
self.nframes = len(audio) # Anpassen des nframes-Parameters self.nframes = len(audio) # Anpassen des nframes-Parameters
wav_file.setparams((self.nchannels, self.sampwidth, self.framerate, self.nframes, self.comptype, self.compname)) wav_file.setparams((self.nchannels, self.sampwidth, self.framerate, self.nframes, self.comptype, self.compname))
@ -92,36 +96,44 @@ class Sound:
wav_file.close() wav_file.close()
print("Speichern beendet.") print("Speichern beendet.")
return
"""Die Objekt-Funktion __enter__() startet die asynchrone Soundwiedergabe. Sie ruft dabei immer wieder die Funktion """Die Objekt-Funktion 'start()' startet die asynchrone Soundwiedergabe. Sie ruft dabei immer wieder die Funktion
sound.callback() auf. Daher können die dort genutzten Variablen dynamisch geändert werden. """ sound.callback() auf. Daher können die dort genutzten Variablen dynamisch geändert werden. """
def play(self): def play(self):
if not self.mute: # NEVER play sound when patient mutes GUI if not self.mute: # NEVER play sound when patient mutes GUI
self.sound_obj.__enter__() self.sound_obj.start()
return
def stop(self): def stop(self):
self.sound_obj.__exit__() #beendet die asynchrone Soundwiedergabe self.sound_obj.stop() # beendet die asynchrone Soundwiedergabe
return
"""Die Funktion callback() erzeugt bei jedem Aufruf die Audiodaten, abhängig von den aktuellen Tinnitus-Variablen. """Die Funktion callback() erzeugt bei jedem Aufruf die Audiodaten, abhängig von den aktuellen Tinnitus-Variablen.
Die errechneten Werte werden in das NumPy-Array 'outdata' geschrieben """ Die errechneten Werte werden in das NumPy-Array 'outdata' geschrieben """
# momentan nur Mono. Es werden die Werte des linken Ohrs genutzt # momentan nur Mono. Es werden die Werte des linken Ohrs genutzt
def callback(self, outdata, frames, time, status): def callback(self, outdata, frames, time, status):
if status: #gibt Warnungen aus, wenn das Soundobjekt auf Fehler stößt (hauptsächlich over/underflow wegen timingproblemen) if status: # Warnungen, wenn das Soundobj. auf Fehler stößt (hauptsächlich over/underflow wg. Timingproblemen)
print(status, file=sys.stderr) print(status, file=sys.stderr)
t = (self.start_idx + np.arange(frames)) / self.framerate
t = t.reshape(-1, 1)
#Sinuston ins Array schreiben # Sinus ins Array schreiben: f(t) = A * sin(2 * pi * f * t)
outdata[:] = self.tinnitus.linksLautstaerke * np.sin(2 * np.pi * self.tinnitus.linksFrequenz * t) for x in range(frames):
# links:
if self.tinnitus.linksLautstaerke:
outdata[x][0] = self.tinnitus.linksLautstaerke * np.sin(2 * np.pi * self.tinnitus.linksFrequenz *
((x + self.start_idx) / self.framerate))
# rechts:
if self.tinnitus.rechtsLautstaerke:
outdata[x][1] = self.tinnitus.rechtsLautstaerke * np.sin(2 * np.pi * self.tinnitus.rechtsFrequenz *
((x + self.start_idx) / self.framerate))
# Rauschen addieren # Rauschen addieren
if(self.tinnitus.linksRauschenLautstaerke): for x in range(frames):
for x in range(len(outdata)):
rand = (np.random.rand() - 0.5) * self.tinnitus.linksRauschenLautstaerke rand = (np.random.rand() - 0.5) * self.tinnitus.linksRauschenLautstaerke
outdata[x] += rand #links:
if self.tinnitus.linksRauschenLautstaerke:
outdata[x][0] += rand
#rechts:
if self.tinnitus.rechtsRauschenLautstaerke:
outdata[x][1] += rand
self.start_idx += frames self.start_idx += frames

View File

@ -42,20 +42,20 @@ def links_scale_rauschen_bandbreite_change(self):
def rechts_scale_lautstärke_change(self): def rechts_scale_lautstärke_change(self):
rechtsLautstärke = float(rechtsScaleLautstärke.get()) tinnitus.rechtsLautstaerke = float(rechtsScaleLautstärke.get()/100)
print("Rechts Lautstärke =", rechtsLautstärke) print("Rechts Lautstärke =", tinnitus.rechtsLautstaerke, "%")
sound.play() sound.play()
def rechts_scale_frequenz_change(self): def rechts_scale_frequenz_change(self):
rechtsFrequenz = float(rechtsScaleFrequenz.get()) tinnitus.rechtsFrequenz = float(rechtsScaleFrequenz.get()*1000)
print("Rechts Frequenz= ", rechtsFrequenz) print("Rechts Frequenz= ", tinnitus.rechtsFrequenz, " Hz")
sound.play() sound.play()
def rechts_scale_rauschen_lautstärke_change(self): def rechts_scale_rauschen_lautstärke_change(self):
rechtsRauschenLautstärke = float(rechtsScaleRauschenLautstärke.get()) tinnitus.rechtsRauschenLautstaerke = float(rechtsScaleRauschenLautstärke.get()/1000)
print("Rechts Rauschen Lautstärke = ", rechtsRauschenLautstärke) print("Rechts Rauschen Lautstärke = ", rechtsRauschenLautstärke*1000, "%")
sound.play() sound.play()