Created
June 3, 2022 17:56
-
-
Save FabulousCodingFox/af37aeb69809c1f7925dcde07532b1e1 to your computer and use it in GitHub Desktop.
A UI Interface generating and playing certain frequencies using a speaker
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Alle notwendigen Module importieren | |
import numpy as np | |
import wave, os, pygame, tkinter | |
from time import perf_counter | |
############################################################################################################# | |
# Ein Dictionary um alle Sounds zu speichern | |
soundBuffer = {} | |
# Eine .wav Datei mit einer bestimmten Frequenz erstellen | |
def createWavFile(freq=50, samples=44100, length=5): | |
freq = float(freq) | |
# calculate the length of the wav file | |
nSamples = samples * length #44100 Samples = CD Qualität = 1 Sekunde | |
# create the raw waveform data | |
x = np.arange(nSamples)/samples | |
vals = np.sin(2*np.pi*freq*x) | |
data = np.array(vals*32767, dtype=np.int16).tobytes() | |
# create the wav file | |
wavFile = os.path.join(os.path.dirname(__file__),"wav/", "{}hz.wav".format(freq)) | |
w = wave.open(wavFile, "wb") | |
w.setnchannels(1) | |
w.setsampwidth(2) | |
w.setframerate(samples) | |
w.writeframes(data) | |
w.close() | |
# Die Datei im Soundbuffer als pygame.moxer.Sound Objekt speichern | |
soundBuffer[float(freq)] = pygame.mixer.Sound(wavFile) | |
# Den Pfad zur Datei zurückgeben | |
return wavFile | |
# Mehrere .wav Dateien erstellen | |
def generateWavFiles(start:int=40,end:int=80,step:int=1)->list[str]: | |
print("Generiert Sounds... [0/0] 0%") | |
filenames = [] | |
i:int = 0 | |
while start+i <= end: | |
filenames.append(createWavFile(start+i)) | |
print( | |
"Generiert Sounddateien... [{}{}/{}] {}%".format( | |
'0'*(len(str(int((end-start)//step)))-len(str(int(i//step)))), # 0-padding | |
int(i//step), # Bisherige Anzahl | |
int((end-start)//step), # Gesamtanzahl | |
int(((i//step)/((end-start)//step))*100) # Prozent | |
) | |
) | |
i += step | |
return filenames | |
# Spielt einen Sound mit einer bestimmten Frequenz | |
def play(freq): | |
freq = float(freq) | |
# Wenn der Sound noch nicht im Soundbuffer ist, erstellen | |
wavePath = os.path.join(os.path.dirname(__file__), "{}hz.wav".format(freq)) | |
if not os.path.exists(wavePath): wavePath = createWavFile(freq=freq) | |
pygame.mixer.stop() | |
soundBuffer[freq].play(loops=3600, maxtime=0, fade_ms=0) # 3600 Wiederholungen = 1 Stunde | |
# Den Pygame Soundplayer initialisieren | |
pygame.mixer.pre_init(44100,-16,1,4096) | |
pygame.mixer.init() | |
############################################################################################################# | |
# Oberen und unteren Frequenzbereich festlegen | |
frequencySettings = { | |
"top": 80.0, | |
"bottom":5.0, | |
"step": 1, | |
} | |
currentFrequency = frequencySettings["bottom"] | |
currentPeriod = 1000 / currentFrequency | |
selectedFrequency = currentFrequency | |
selectedPeriod = currentPeriod | |
totalFrequencies = int((frequencySettings["top"]-frequencySettings["bottom"])/frequencySettings["step"]) | |
# Genreiere einen Orddner, in dem alle .wav Dateien gespeichert werden, sofern nicht vorhanden | |
if not os.path.exists(os.path.join(os.path.dirname(__file__),"wav/")): | |
os.mkdir(os.path.join(os.path.dirname(__file__),"wav/")) | |
# Generiere alle .wav Dateien, sofern noch nicht vorhanden | |
if not os.path.exists(os.path.join(os.path.dirname(__file__),"wav/","{}hz.wav".format(float(frequencySettings["bottom"])))): | |
generateWavFiles(start=frequencySettings["bottom"],end=frequencySettings["top"],step=frequencySettings["step"]) | |
############################################################################################################# | |
def apply(freq): | |
global currentFrequency | |
global currentPeriod | |
freq = float(freq) | |
# Wenn die Frequenz = -1 ist, dann die ausgewählte Frequnz nehmen | |
if freq == -1.0: freq = selectedFrequency | |
# Wenn die Frequenz größer als das Maximum ist, setzte sie zurrück | |
if freq > frequencySettings["top"]: freq = frequencySettings["top"] | |
# Wenn die Frequenz kleiner als das Minimum ist, setzte sie zurück | |
if freq < frequencySettings["bottom"]: freq = frequencySettings["bottom"] | |
print("Wende die Frequenz {}Hz an...".format(freq)) | |
currentFrequency = freq | |
currentPeriod = 1000 / currentFrequency | |
updateFreqencyLabel() | |
############################################################################################################# | |
# Das Fenster erstellen | |
root = tkinter.Tk() | |
root.title("Sound Generator") | |
root.geometry("640x480") | |
# Ein Label erstellen, auf dem die aktuelle, die ausgewählte und die maximal mögliche Frequenz angezeigt wird | |
def updateFreqencyLabel(): | |
text = """ | |
Aktuelle Frequenz: {}hz | |
Aktuelle Periodenlänge: {}ms | |
Ausgewählte Frequenz: {}hz | |
Ausgewählte Periodenlänge: {}ms | |
Maximal mögliche Frequenz: {}hz | |
Maximal mögliche Periodenlänge: {}ms | |
Minimal mögliche Frequenz: {}hz | |
Minimal mögliche Periodenlänge: {}ms | |
""".format( | |
currentFrequency, | |
round(currentPeriod, 1), | |
selectedFrequency, | |
round(selectedPeriod, 1), | |
frequencySettings["top"], | |
round(1000 / frequencySettings["top"], 1), | |
frequencySettings["bottom"], | |
round(1000 / frequencySettings["bottom"], 1) | |
) | |
rootLabelFreqency.config(text=text) | |
rootLabelFreqency = tkinter.Label( | |
root, | |
text="" | |
) | |
rootLabelFreqency.pack() | |
updateFreqencyLabel() | |
# Einen Slider erstellen, auf dem die Frequenz eingestellt werden kann | |
def onSliderChange(val): | |
global selectedFrequency | |
global selectedPeriod | |
# Berechne die ausgewählte Frequenz | |
selectedFrequency = float(val) | |
selectedPeriod = 1000 / selectedFrequency | |
updateFreqencyLabel() | |
rootSliderFrequency = tkinter.Scale(root, | |
from_=frequencySettings["bottom"], | |
to=frequencySettings["top"], | |
orient=tkinter.HORIZONTAL, | |
command = onSliderChange, | |
tickinterval=10, | |
length=640 | |
) | |
rootSliderFrequency.pack() | |
# Einen Knopf mit dem die ausgewählte Frequenz angeweendet werden kann, ein Knopf mit dem 50 Hz angeweendet werden kann, ein Knopf mit dem die Frequenz auf 60hz zurückgesetzt werden kann | |
rootButtonApply = tkinter.Button( | |
root, | |
text="Ausgewählte Frequenz anwenden", | |
command=lambda: apply(-1.0) | |
) | |
rootButton50hz = tkinter.Button( | |
root, | |
text="50 Hz anwenden", | |
command=lambda: apply(50.0) | |
) | |
rootButtonReset = tkinter.Button( | |
root, | |
text="60 Hz anwenden (Zurrücksetzen)", | |
command=lambda: apply(60.0) | |
) | |
rootButtonApply.pack() | |
rootButton50hz.pack() | |
rootButtonReset.pack() | |
# Das Fenster anzeigen und auf den Benutzer warten | |
tkinter.mainloop() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment