import numpy as np import sounddevice as sd from kivy.app import App from kivy.uix.widget import Widget from kivy.uix.boxlayout import BoxLayout from kivy.uix.button import Button from kivy.graphics import Rectangle, RenderContext, Color from kivy.clock import Clock class ShaderWidget(Widget): def __init__(self, **kwargs): super().__init__(**kwargs) # Use RenderContext for shaders self.canvas = RenderContext() self.shader_code = ''' #ifdef GL_ES precision mediump float; #endif varying vec2 v_texcoord; uniform float time; void main() { vec2 uv = v_texcoord * 2.0 - 1.0; float color = 0.5 + 0.5 * sin(10.0 * length(uv) - time); gl_FragColor = vec4(color, color * 0.5, color * 0.8, 1.0); } ''' self.canvas.shader.fs = self.shader_code self.time = 0.0 with self.canvas: Color(1, 1, 1, 1) self.rect = Rectangle(pos=self.pos, size=self.size) self.bind(pos=self.update_rect, size=self.update_rect) Clock.schedule_interval(self.update_shader_time, 1 / 60) def update_rect(self, *args): self.rect.pos = self.pos self.rect.size = self.size def update_shader_time(self, dt): self.time += dt self.canvas['time'] = self.time def generate_sine_wave(frequency, duration, sample_rate=44100): """Generate a sine wave signal.""" t = np.linspace(0, duration, int(sample_rate * duration), endpoint=False) wave = 0.5 * np.sin(2 * np.pi * frequency * t) # Amplitude scaled to 0.5 return wave class ShaderSoundApp(App): def build(self): layout = BoxLayout(orientation='vertical') shader_widget = ShaderWidget(size_hint=(1, 0.9)) button = Button(text="Play Sound", size_hint=(1, 0.1)) button.bind(on_press=self.play_sound) layout.add_widget(shader_widget) layout.add_widget(button) return layout def play_sound(self, instance): # Generate a sine wave of 440 Hz for 2 seconds frequency = 440 # A4 note duration = 2.0 # seconds sample_rate = 44100 # Hz wave = generate_sine_wave(frequency, duration, sample_rate) sd.play(wave, samplerate=sample_rate) if __name__ == "__main__": ShaderSoundApp().run()