tinnitus / app.py
vitorcalvi
first commit
ffc9ee0
raw
history blame
6.08 kB
import gradio as gr
import numpy as np
from scipy import signal
import soundfile as sf
import matplotlib.pyplot as plt
import io
def generate_test_tone(frequency, duration=1.0, sample_rate=44100):
t = np.linspace(0, duration, int(sample_rate * duration))
tone = np.sin(2 * np.pi * frequency * t)
return tone * np.hanning(len(tone))
def create_audiogram(left_ear_results, right_ear_results):
frequencies = [250, 500, 1000, 2000, 4000, 8000]
plt.figure(figsize=(10, 8))
plt.fill_between([125, 8000], -10, 25, color='#e6f3ff', alpha=0.3, label='Normal Hearing')
plt.fill_between([125, 8000], 25, 40, color='#b3d9ff', alpha=0.3, label='Mild Loss')
plt.fill_between([125, 8000], 40, 55, color='#80bfff', alpha=0.3, label='Moderate Loss')
plt.fill_between([125, 8000], 55, 70, color='#4da6ff', alpha=0.3, label='Moderate-Severe Loss')
plt.plot(frequencies, left_ear_results, 'x-', color='blue', label='Left Ear')
plt.plot(frequencies, right_ear_results, 'o-', color='red', label='Right Ear')
plt.xscale('log')
plt.xlim(125, 8000)
plt.ylim(70, -10)
plt.grid(True)
plt.xlabel('Frequency (Hz)')
plt.ylabel('Hearing Level (dB)')
plt.title('Audiogram Results')
plt.legend()
buf = io.BytesIO()
plt.savefig(buf, format='png')
plt.close()
return buf
def hearing_test(frequency, volume, ear_selection):
sample_rate = 44100
tone = generate_test_tone(float(frequency), 1.0, sample_rate)
volume_adjusted = tone * (10 ** (volume / 20))
stereo_tone = np.zeros((2, len(tone)))
if ear_selection == "Left":
stereo_tone[0] = volume_adjusted
elif ear_selection == "Right":
stereo_tone[1] = volume_adjusted
else:
stereo_tone[0] = stereo_tone[1] = volume_adjusted
output_path = f"test_tone_{frequency}Hz.wav"
sf.write(output_path, stereo_tone.T, sample_rate)
return output_path
def generate_audio(duration, selected_frequencies):
sample_rate = 44100
num_samples = int(float(duration) * sample_rate)
noise = np.random.normal(0, 1, num_samples)
if selected_frequencies:
frequencies = [int(f) for f in selected_frequencies]
for freq in frequencies:
depth = -40 if freq == 4000 else -30
width = freq / 10
nyquist = sample_rate / 2
freq_normalized = freq / nyquist
quality_factor = freq / width
b, a = signal.iirnotch(freq_normalized, quality_factor)
noise = signal.filtfilt(b, a, noise)
noise *= 10 ** (depth / 20)
noise = noise / np.max(np.abs(noise))
output_path = "notched_noise.wav"
sf.write(output_path, noise, sample_rate)
return output_path
def create_interface():
with gr.Blocks(title="Hearing Test & White Noise Generator") as app:
with gr.Tabs():
with gr.Tab("Hearing Test"):
gr.Markdown("## Hearing Test")
with gr.Row():
with gr.Column():
frequency = gr.Dropdown(
choices=["250", "500", "1000", "2000", "4000", "8000"],
value="1000",
label="Test Frequency (Hz)"
)
volume = gr.Slider(
minimum=-60,
maximum=0,
value=-20,
step=5,
label="Volume (dB)"
)
ear_select = gr.Radio(
choices=["Both", "Left", "Right"],
value="Both",
label="Ear Selection"
)
test_btn = gr.Button("Play Test Tone")
with gr.Column():
audio_output = gr.Audio(label="Test Tone")
with gr.Row():
with gr.Column():
left_thresholds = [gr.Number(value=0, label=f"{freq}Hz Left") for freq in [250, 500, 1000, 2000, 4000, 8000]]
with gr.Column():
right_thresholds = [gr.Number(value=0, label=f"{freq}Hz Right") for freq in [250, 500, 1000, 2000, 4000, 8000]]
generate_audiogram_btn = gr.Button("Generate Audiogram")
audiogram_output = gr.Image(label="Audiogram")
with gr.Tab("White Noise Generator"):
gr.Markdown("## Notched White Noise Generator")
with gr.Row():
with gr.Column():
duration = gr.Slider(
minimum=1,
maximum=30,
value=5,
step=1,
label="Duration (seconds)"
)
frequencies = gr.CheckboxGroup(
choices=["250", "500", "1000", "2000", "4000", "8000"],
label="Frequencies to Notch (Hz)",
value=["4000", "2000"]
)
generate_noise_btn = gr.Button("Generate Noise")
with gr.Column():
noise_output = gr.Audio(label="Generated Noise")
test_btn.click(
fn=hearing_test,
inputs=[frequency, volume, ear_select],
outputs=audio_output
)
generate_audiogram_btn.click(
fn=lambda *args: create_audiogram(args[:6], args[6:]).getvalue(),
inputs=left_thresholds + right_thresholds,
outputs=audiogram_output
)
generate_noise_btn.click(
fn=generate_audio,
inputs=[duration, frequencies],
outputs=noise_output
)
return app
if __name__ == "__main__":
app = create_interface()
app.launch(share=False)