Python’s winsound module (Windows only) plays tones and WAV audio through the system sound driver. import winsound. Beep: winsound.Beep(frequency, duration) — plays a pure tone; frequency 37–32767 Hz, duration milliseconds; blocks until finished. WAV file: winsound.PlaySound("alert.wav", winsound.SND_FILENAME) — synchronous. Async: winsound.PlaySound("alert.wav", winsound.SND_FILENAME | winsound.SND_ASYNC) — returns immediately and plays in background. Memory: winsound.PlaySound(wav_bytes, winsound.SND_MEMORY) — play WAV from bytes object. Stop: winsound.PlaySound(None, winsound.SND_PURGE) — stop any currently playing sound. Loop: winsound.PlaySound("loop.wav", winsound.SND_FILENAME | winsound.SND_LOOP | winsound.SND_ASYNC). System sounds: winsound.MessageBeep(winsound.MB_OK) — play the system beep for a message box type; constants: MB_OK, MB_ICONWARNING, MB_ICONERROR, MB_ICONQUESTION, MB_ICONASTERISK. Claude Code generates Windows desktop alert systems, progress notifications, error sounds, installer audio feedback, and Windows application sound themes.
CLAUDE.md for winsound
## winsound Stack
- Stdlib: import winsound (Windows only)
- Beep: winsound.Beep(440, 500) # 440Hz for 500ms
- File: winsound.PlaySound("alert.wav", winsound.SND_FILENAME)
- Async: winsound.PlaySound("bg.wav", winsound.SND_FILENAME | winsound.SND_ASYNC)
- Stop: winsound.PlaySound(None, winsound.SND_PURGE)
- System: winsound.MessageBeep(winsound.MB_ICONERROR)
- Memory: winsound.PlaySound(wav_bytes, winsound.SND_MEMORY)
winsound Audio Pipeline
# app/winsoundutil.py — tones, alerts, WAV builder, notification system
from __future__ import annotations
import os
import struct
import time
import wave
from dataclasses import dataclass, field
from io import BytesIO
from pathlib import Path
from typing import Callable
# Only import winsound on Windows
_WINSOUND_AVAILABLE = False
if os.name == "nt":
try:
import winsound as _ws
_WINSOUND_AVAILABLE = True
except ImportError:
pass
# ─────────────────────────────────────────────────────────────────────────────
# 1. Tone generation helpers
# ─────────────────────────────────────────────────────────────────────────────
def beep(frequency: int, duration_ms: int) -> None:
"""
Play a beep at the given frequency (Hz) for duration_ms milliseconds.
No-op on non-Windows platforms.
Example:
beep(440, 500) # A4 note for half a second
beep(880, 200) # A5 note for 200ms
"""
if _WINSOUND_AVAILABLE:
_ws.Beep(max(37, min(32767, frequency)), max(1, duration_ms))
def beep_sequence(notes: "list[tuple[int, int]]", gap_ms: int = 50) -> None:
"""
Play a sequence of (frequency, duration_ms) notes.
Example:
# Play a rising arpeggio
beep_sequence([(262, 150), (330, 150), (392, 150), (523, 300)])
"""
for freq, dur in notes:
beep(freq, dur)
if gap_ms > 0:
time.sleep(gap_ms / 1000)
def alert_beep(kind: str = "info") -> None:
"""
Play a pre-defined alert beep pattern.
kind: 'info' | 'warning' | 'error' | 'success' | 'question'
Example:
alert_beep("error")
alert_beep("success")
"""
patterns: dict[str, list[tuple[int, int]]] = {
"info": [(880, 100), (1100, 100)],
"warning": [(600, 200), (500, 300)],
"error": [(400, 300), (300, 400)],
"success": [(523, 100), (659, 100), (784, 200)],
"question": [(880, 150), (1100, 150)],
}
notes = patterns.get(kind, patterns["info"])
beep_sequence(notes, gap_ms=30)
# ─────────────────────────────────────────────────────────────────────────────
# 2. System sound shortcuts
# ─────────────────────────────────────────────────────────────────────────────
def system_beep(level: str = "default") -> None:
"""
Play a Windows system message beep.
level: 'default' | 'info' | 'warning' | 'error' | 'question'
Example:
system_beep("error")
"""
if not _WINSOUND_AVAILABLE:
return
mapping = {
"default": _ws.MB_OK,
"info": _ws.MB_ICONASTERISK,
"warning": _ws.MB_ICONEXCLAMATION,
"error": _ws.MB_ICONHAND,
"question": _ws.MB_ICONQUESTION,
}
_ws.MessageBeep(mapping.get(level, _ws.MB_OK))
# ─────────────────────────────────────────────────────────────────────────────
# 3. WAV file playback helpers
# ─────────────────────────────────────────────────────────────────────────────
def play_wav(path: "str | Path", async_: bool = False) -> None:
"""
Play a WAV file synchronously (default) or asynchronously.
Example:
play_wav("notification.wav")
play_wav("background.wav", async_=True) # non-blocking
"""
if not _WINSOUND_AVAILABLE:
return
flags = _ws.SND_FILENAME
if async_:
flags |= _ws.SND_ASYNC
_ws.PlaySound(str(path), flags)
def play_wav_bytes(wav_data: bytes, async_: bool = False) -> None:
"""
Play WAV audio from a bytes object in memory.
Example:
wav_data = Path("alert.wav").read_bytes()
play_wav_bytes(wav_data)
"""
if not _WINSOUND_AVAILABLE:
return
flags = _ws.SND_MEMORY
if async_:
flags |= _ws.SND_ASYNC
_ws.PlaySound(wav_data, flags)
def stop_sound() -> None:
"""Stop any currently playing sound."""
if _WINSOUND_AVAILABLE:
_ws.PlaySound(None, _ws.SND_PURGE)
# ─────────────────────────────────────────────────────────────────────────────
# 4. Minimal WAV generator (no third-party deps)
# ─────────────────────────────────────────────────────────────────────────────
import math
def generate_sine_wav(
frequency: float,
duration_s: float,
sample_rate: int = 44100,
amplitude: float = 0.5,
) -> bytes:
"""
Generate a simple sine-wave WAV as bytes (PCM 16-bit mono).
Example:
data = generate_sine_wav(440.0, 0.5)
play_wav_bytes(data)
"""
n_samples = int(sample_rate * duration_s)
buf = BytesIO()
with wave.open(buf, "wb") as wf:
wf.setnchannels(1)
wf.setsampwidth(2) # 16-bit
wf.setframerate(sample_rate)
frames: list[bytes] = []
max_amp = int(32767 * amplitude)
# Fade-in/out ramp to avoid clicks (5ms each)
fade_samples = min(int(sample_rate * 0.005), n_samples // 4)
for i in range(n_samples):
sample = max_amp * math.sin(2 * math.pi * frequency * i / sample_rate)
if i < fade_samples:
sample *= i / fade_samples
elif i >= n_samples - fade_samples:
sample *= (n_samples - i) / fade_samples
frames.append(struct.pack("<h", int(sample)))
wf.writeframes(b"".join(frames))
return buf.getvalue()
# ─────────────────────────────────────────────────────────────────────────────
# 5. Notification helper
# ─────────────────────────────────────────────────────────────────────────────
@dataclass
class SoundNotifier:
"""
Play audio notifications for application events.
Falls back gracefully on non-Windows platforms.
Example:
notifier = SoundNotifier()
notifier.on_start()
# ... do work ...
notifier.on_complete()
notifier.on_error()
"""
use_system_sounds: bool = True
volume: float = 0.5 # 0.0–1.0 for generated beeps
def on_start(self) -> None:
"""Notify that a task has started."""
if self.use_system_sounds:
system_beep("info")
else:
beep_sequence([(523, 80), (659, 80)], gap_ms=20)
def on_complete(self) -> None:
"""Notify that a task completed successfully."""
if self.use_system_sounds:
system_beep("default")
else:
beep_sequence([(523, 80), (659, 80), (784, 200)], gap_ms=20)
def on_error(self) -> None:
"""Notify that a task failed."""
if self.use_system_sounds:
system_beep("error")
else:
alert_beep("error")
def on_warning(self) -> None:
"""Notify that a warning occurred."""
if self.use_system_sounds:
system_beep("warning")
else:
alert_beep("warning")
# ─────────────────────────────────────────────────────────────────────────────
# Demo
# ─────────────────────────────────────────────────────────────────────────────
if __name__ == "__main__":
print("=== winsound demo ===")
print(f" Windows available: {_WINSOUND_AVAILABLE}")
if _WINSOUND_AVAILABLE:
print("\n--- beep (880Hz, 200ms) ---")
beep(880, 200)
print("\n--- beep_sequence (rising arpeggio) ---")
beep_sequence([(262, 100), (330, 100), (392, 100), (523, 200)], gap_ms=30)
print("\n--- alert_beep ---")
for kind in ["info", "success", "warning", "error"]:
print(f" {kind}...")
alert_beep(kind)
time.sleep(0.3)
print("\n--- system_beep ---")
system_beep("info")
time.sleep(0.2)
system_beep("error")
# ── generate_sine_wav (works on all platforms) ────────────────────────────
print("\n--- generate_sine_wav ---")
for freq, dur, name in [(440, 0.3, "A4"), (880, 0.3, "A5"), (1320, 0.3, "E6")]:
data = generate_sine_wav(freq, dur)
print(f" {name} ({freq}Hz, {dur}s): {len(data)} bytes WAV")
if _WINSOUND_AVAILABLE:
play_wav_bytes(data)
time.sleep(dur + 0.1)
print("\n=== done ===")
For the playsound / simpleaudio (PyPI) alternatives — playsound("alert.mp3") supports MP3 and WAV on Windows/macOS/Linux; simpleaudio.WaveObject.from_wave_file("alert.wav").play() offers non-blocking WAV playback on all platforms — use playsound or simpleaudio for cross-platform audio in end-user applications; use winsound when you need zero dependencies on Windows and only need beeps or WAV playback. For the pygame.mixer (PyPI) alternative — pygame.mixer.Sound("alert.ogg").play() supports OGG, WAV, and MP3 with volume control, channel mixing, and precise timing — use pygame.mixer when your application already uses pygame (games, multimedia tools) or needs fine-grained audio control; use winsound for simple Windows notifications with no install overhead. The Claude Skills 360 bundle includes winsound skill sets covering beep()/beep_sequence()/alert_beep() tone helpers, system_beep() MessageBeep wrapper, play_wav()/play_wav_bytes()/stop_sound() playback utilities, generate_sine_wav() minimal PCM generator, and SoundNotifier event-driven notification system. Start with the free tier to try Windows audio patterns and winsound pipeline code generation.