import struct
import subprocess
import wave

# Standard musical pitch reference frequencies (Hz)
NOTES = {
    'C4': 262,  # Do
    'D4': 294,  # Re
    'E4': 330,  # Mi
    'F4': 349,  # Fa
    'G4': 392,  # Sol
    'A4': 440,  # La
    'B4': 494,  # Si
    'C5': 523   # High Do
}

def play_square_wave(freq, duration=0.35, duty=0.5):
    """
    Computes 16-bit 44.1kHz PWM square-wave data in memory using standard libraries,
    generates a temporary WAV file, and streams it to the USB speaker via aplay.
    """
    sample_rate = 44100
    total_samples = int(sample_rate * duration)
    amplitude = 9000  # Amplitude level (max 32767 for 16-bit signed int; 9000 prevents clipping)
    tmp_wav = "/tmp/pwm_tone.wav"

    with wave.open(tmp_wav, 'wb') as f:
        f.setnchannels(1)                # Mono
        f.setsampwidth(2)                # 16-bit integer (2 bytes)
        f.setframerate(sample_rate)      # 44.1kHz sample rate

        frames = bytearray()
        for i in range(total_samples):
            t = i / sample_rate
            phase = (t * freq) % 1.0
            # Square-wave duty cycle logic (simulating hardware PWM)
            val = amplitude if phase < duty else -amplitude
            # Pack as 16-bit signed little-endian PCM sample
            frames += struct.pack('<h', int(val))

        f.writeframes(frames)

    # Invoke native Linux ALSA playback command
    subprocess.run(["aplay", "-q", tmp_wav])

def main():
    print("=== Uno Q Native Square-Wave PWM Scale Test ===")
    scale = ['C4', 'D4', 'E4', 'F4', 'G4', 'A4', 'B4', 'C5']
    for note in scale:
        print(f"Playing note: {note} ({NOTES[note]} Hz)")
        play_square_wave(NOTES[note], duration=0.3)
    print("Scale playback completed!")

if __name__ == "__main__":
    main()