Browse Source

Stereo-Sound eingebaut und Formatierungen/Kommentare geändert

master
Heiko Ommert 4 years ago
parent
commit
6359602a4b
2 changed files with 72 additions and 60 deletions
  1. 66
    54
      TinnitusAnalyse/SoundGenerator.py
  2. 6
    6
      TinnitusAnalyse/TinnitusAnalyse_GUI.py

+ 66
- 54
TinnitusAnalyse/SoundGenerator.py View File

import math import math
import wave #bearbeiten von .wav-Dateien
import wave # bearbeiten von .wav-Dateien
import struct import struct
import sounddevice as sd #zum abspielen des audio-arrays
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
def __init__(self, l_freq=600, r_freq=600, l_amp=0, r_amp=0, l_rausch=0, r_rausch=0, ear=0):

class Tinnitus: # beinhaltet alle Werte, die vom Nutzer eingestellt werden
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 = ""
self.rechtsFrequenz = r_freq self.rechtsFrequenz = r_freq
self.linksLautstaerke = l_amp self.linksLautstaerke = l_amp
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
return

def speichern(self): #speichert die Nutzerdaten in eine .csv-Datei
self.ohr = ohr # 0:both 1:left 2:right 3:links/rechts unterschiedlich


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"
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
self.name = name self.name = name
self.audio = audio #ein Array, in das die Sound-Werte geschrieben werden
self.nchannels = nchannels #Zahl der audio channels (1:mono 2:stereo)
self.sampwidth = sampwidth #Größe eines einzelnen Sound-Werts (in bytes)
self.framerate = framerate #Abtastrate
self.nframes = len(audio) #Anzahl der Sound-Werte -> Muss bei jeder audio-Änderung aktuallisiert werden
self.audio = audio # ein Array, in das die Sound-Werte geschrieben werden
self.nchannels = nchannels # Zahl der audio channels (1:mono 2:stereo)
self.sampwidth = sampwidth # Größe eines einzelnen Sound-Werts (in bytes)
self.framerate = framerate # Abtastrate
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.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
return
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.start_idx = 0 # wird für sound_obj benötigt


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")
print("Sound wird als .wav-Datei gespeichert. Bitte warten...\nDer Vorgang kann ca. 30 Sekunden dauern") print("Sound wird als .wav-Datei gespeichert. Bitte warten...\nDer Vorgang kann ca. 30 Sekunden dauern")


#zuerst muss ein Array mit Audiodaten gefüllt werden
# zuerst muss ein Array mit Audiodaten gefüllt werden
audio = [] audio = []
freq = self.tinnitus.linksFrequenz freq = self.tinnitus.linksFrequenz
dauer_ms = 10000.0 #10 Sekunden
dauer_ms = 10000.0 # 10 Sekunden
amp = self.tinnitus.linksLautstaerke amp = self.tinnitus.linksLautstaerke
rauschen = self.tinnitus.linksRauschenLautstaerke rauschen = self.tinnitus.linksRauschenLautstaerke


num_samples = dauer_ms * (self.framerate / 1000.0) #framerate -pro Sekunde- umgerechnet in -pro Millisekunde-
num_samples = dauer_ms * (self.framerate / 1000.0) # framerate -pro Sekunde- umgerechnet in -pro Millisekunde-


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))


#dann wird das audio-Array an die Datei übertragen
# dann wird das audio-Array an die Datei übertragen
for sample in audio: for sample in audio:
wav_file.writeframes(struct.pack('h', int(sample * 32767.0))) wav_file.writeframes(struct.pack('h', int(sample * 32767.0)))


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
self.sound_obj.__enter__()
return
if not self.mute: # NEVER play sound when patient mutes GUI
self.sound_obj.start()


def stop(self): def stop(self):
self.sound_obj.__exit__() #beendet die asynchrone Soundwiedergabe
return
self.sound_obj.stop() # beendet die asynchrone Soundwiedergabe


"""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
outdata[:] = self.tinnitus.linksLautstaerke * np.sin(2 * np.pi * self.tinnitus.linksFrequenz * t)

#Rauschen addieren
if(self.tinnitus.linksRauschenLautstaerke):
for x in range(len(outdata)):
rand = (np.random.rand() - 0.5) * self.tinnitus.linksRauschenLautstaerke
outdata[x] += rand
# Sinus ins Array schreiben: f(t) = A * sin(2 * pi * f * 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
for x in range(frames):
rand = (np.random.rand() - 0.5) * self.tinnitus.linksRauschenLautstaerke
#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


+ 6
- 6
TinnitusAnalyse/TinnitusAnalyse_GUI.py View File





def rechts_scale_lautstärke_change(self): def rechts_scale_lautstärke_change(self):
rechtsLautstärke = float(rechtsScaleLautstärke.get())
print("Rechts Lautstärke =", rechtsLautstärke)
tinnitus.rechtsLautstaerke = float(rechtsScaleLautstärke.get()/100)
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())
print("Rechts Frequenz= ", rechtsFrequenz)
tinnitus.rechtsFrequenz = float(rechtsScaleFrequenz.get()*1000)
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())
print("Rechts Rauschen Lautstärke = ", rechtsRauschenLautstärke)
tinnitus.rechtsRauschenLautstaerke = float(rechtsScaleRauschenLautstärke.get()/1000)
print("Rechts Rauschen Lautstärke = ", rechtsRauschenLautstärke*1000, "%")
sound.play() sound.play()





Loading…
Cancel
Save