Skip to content

Commit 90f81a1

Browse files
committed
Revert theremin changes
1 parent 0226471 commit 90f81a1

File tree

2 files changed

+67
-72
lines changed

2 files changed

+67
-72
lines changed

examples/theremin/README.md

Lines changed: 67 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,96 +1,80 @@
11
# Theremin Simulator
22

3-
The **Theremin Simulator** example lets you create and control a virtual theremin instrument using an interactive web interface, producing synthesized audio output through a connected **USB** audio device with low latency.
3+
The **Theremin Simulator** example lets you create and control a virtual theremin instrument using an interactive web interface, producing synthesized audio output through a connected **USB** audio device with minimal latency.
44

55
> **Note**: This example must be run in **[Network Mode](learn/network-mode)** or **[SBC Mode](learn/single-board-computer)**, since it requires a **USB-C® hub** and a **USB speaker**.
66
77
![Theremin Simulator](assets/docs_assets/theremin-simulator.png)
88

9-
This example generates real-time audio by creating sine waves at varying frequencies and amplitudes based on user input from the web interface. The workflow involves receiving mouse/touch coordinates from the frontend and updating a **Wave Generator** Brick, which handles the audio synthesis, smoothing, and streaming to the USB device automatically.
9+
This example generates real-time audio by creating sine waves at varying frequencies and amplitudes based on user input from the web interface. The workflow involves receiving mouse/touch coordinates from the frontend, calculating the corresponding frequency and amplitude, generating audio blocks using a sine wave generator, and playing them through a **USB** audio device with minimal latency.
10+
1011

1112
## Bricks Used
1213

1314
- `web_ui`: Brick that provides the web interface and a WebSocket channel for real-time control of the theremin.
14-
- `wave_generator`: Brick that handles audio synthesis, envelope control (smoothing), and streaming to the USB audio device.
15+
- `wave_generator`: Brick that generates continuous audio waveforms and streams them to the USB speaker with smooth frequency and amplitude transitions.
16+
1517

1618
## Hardware and Software Requirements
1719

1820
### Hardware
1921

2022
- [Arduino UNO Q](https://store.arduino.cc/products/uno-q) (x1)
2123
- **USB-C® hub with external power (x1)**
22-
- A power supply (5 V, 3 A) for the USB hub (x1)
24+
- A power supply (5 V, 3 A) for the USB hub adapter with external power (x1)
2325
- A **USB audio device** (choose one):
24-
- **USB speaker** (cabled) ✅ *supported*
25-
- **USB wireless speaker receiver/dongle** (2.4 GHz, non-Bluetooth) ✅ *supported*
26-
- **USB‑C → 3.5 mm audio connector** + headphones/speakers ⚠️ *not tested* (may work)
26+
- **USB speaker** (cabled) (x1) *supported*
27+
- **USB wireless speaker receiver/dongle** (2.4 GHz) (x1) ✅ *supported*
28+
- **USB‑C → 3.5 mm audio connector** + headphones/speakers (x1) ⚠️ *not tested* (may work)
2729
- A **power supply** (5 V, 3 A) for the USB hub (e.g. a phone charger)
2830

29-
> **Not supported:** **HDMI audio** and **Bluetooth® Speakers** are not supported by this App.
31+
> **Not supported:** **HDMI audio and Bluetooth® Speakers** output is not supported by this App.
3032
3133
### Software
3234

3335
- Arduino App Lab
3436

35-
**Note:** A **USB-C® hub is mandatory** for this example. The UNO Q's single port must be used for the hub, which provides the necessary connections for both the power supply and the USB audio device. consequently, this example must be run in **[Network Mode](learn/network-mode)** or **[SBC Mode](learn/single-board-computer)**.
37+
**Note:** A **USB-C® hub is mandatory** for this example. The UNO Q's single port must be used for the hub, which provides the necessary connections for both the power supply and the USB audio device. Consequently, this example must be run in **[Network Mode](learn/network-mode)** or **[SBC Mode](learn/single-board-computer)**.
38+
3639

3740
## How to Use the Example
3841

39-
1. **Hardware Setup:** Connect your **USB audio device** (e.g., USB speaker, wireless USB receiver) to a powered **USB-C® hub** attached to the UNO Q.
42+
1. Connect your **USB audio device** (e.g., USB speaker, wireless USB receiver, or USB‑C→3.5 mm dongle) to a powered **USB-C® hub** attached to the UNO Q.
4043
![hardware-setup](assets/docs_assets/hardware-setup.png)
4144

42-
2. **Launch:** Launch the App by clicking the **Play** button in the top-right corner. Wait until the App has launched.
45+
2. Launch the App by clicking the **Play** button in the top-right corner. Wait until the App has launched.
4346
![Launching an App](assets/docs_assets/launch-app-theremin.png)
47+
3. Open the App in your browser at `<UNO-Q-IP-ADDRESS>:7000` *(typically 192.168.x.x, e.g., http://192.168.1.11:7000)*.
48+
4. Click and drag your mouse (or use touch) on the interactive area to play:
49+
- **Horizontal movement (X-axis)** controls the **pitch** (frequency).
50+
- **Vertical movement (Y-axis)** controls the **volume** (amplitude).
4451

45-
3. **Open Interface:** Open the App in your browser at `<UNO-Q-IP-ADDRESS>:7000` *(typically 192.168.x.x, e.g., http://192.168.1.11:7000)*.
46-
47-
### Interacting with the Interface
48-
49-
Once the web page loads, follow these steps to make sound:
50-
51-
1. **Turn on Power:** Locate the orange control panel at the bottom. Click the **POWER** switch to toggle it **ON** (the small LED indicator will light up).
52-
* *Note: No sound will be produced if this switch is OFF.*
53-
2. **Set Master Volume:** Adjust the **VOL** knob to a comfortable level (e.g., 70-80%). This sets the maximum output limit for the application.
54-
3. **Play the Instrument:** Drag your mouse (or use your finger on a touchscreen) inside the large gray background area:
55-
* **Horizontal (Left ↔ Right):** Controls **Pitch**. Moving right increases the frequency (higher notes).
56-
* **Vertical (Bottom ↕ Top):** Controls **Note Volume**. Moving up increases the amplitude (louder). Moving to the very bottom silences the note.
57-
4. **Waveform Display:** The screen in the center of the panel visualizes the real-time sine wave, frequency (Hz), and amplitude data.
58-
59-
#### Additional Controls
60-
* **GRID Switch:** Toggles a background grid overlay. Use this to visually reference specific pitch intervals or volume levels.
6152

6253
## How it Works
6354

64-
The application uses the `wave_generator` Brick to create a continuous audio stream. The Python backend receives user coordinates via WebSocket and updates the generator's frequency and amplitude. The Brick automatically handles **envelope smoothing** (attack, release, glide) to ensure the audio changes sound natural and analog-like, rather than robotic.
55+
The application creates a real-time audio synthesizer controlled by a web interface. User interactions on the webpage are sent to the Python backend via a WebSocket. The backend uses the `wave_generator` brick to continuously generate and stream audio to the connected **USB** audio device with smooth transitions.
6556

66-
- **User Interaction**: The frontend captures mouse/touch coordinates and sends them to the backend.
67-
- **Real-time Communication**: Input data is sent via the `web_ui` Brick's WebSocket channel.
68-
- **Audio Synthesis**: The `wave_generator` Brick runs in the background. It takes the target frequency and amplitude and applies a **glide algorithm** to transition smoothly between notes.
69-
- **Audio Output**: The Brick streams the generated sine wave directly to the **USB** audio device.
57+
- **User Interaction**: The frontend captures mouse or touch coordinates within a designated "play area".
58+
- **Real-time Communication**: These coordinates are sent to the Python backend in real-time using the `web_ui` Brick's WebSocket channel.
59+
- **Audio Synthesis**: The backend maps the X-coordinate to **frequency** and the Y-coordinate to **amplitude**, then updates the `wave_generator` brick's state. The brick handles smooth transitions using configurable envelope parameters (attack, release, glide).
60+
- **Audio Output**: The `wave_generator` brick runs continuously in a background thread, generating audio blocks and streaming them to the **USB** audio device with minimal latency.
7061

71-
**High-level data flow:**
62+
High-level data flow:
7263
```
73-
Web Browser Interaction ──► WebSocket ──► Python Backend
74-
▲ │
75-
│ ▼
76-
(Visual Updates) (Glide & Synthesis)
77-
│ │
78-
└─ WebSocket ◄── State ◄── Sine Wave Generation
79-
80-
81-
USB Audio Output
64+
Web Browser Interaction → WebSocket → Python Backend → WaveGenerator Brick → USB Audio Device Output
8265
```
8366

8467

8568
## Understanding the Code
8669

8770
### 🔧 Backend (`main.py`)
8871

89-
The Python code is simplified by using the `WaveGenerator` Brick, which encapsulates the audio logic.
72+
The Python code manages the web server, handles real-time user input, and controls the audio generation brick.
9073

91-
- `wave_gen = WaveGenerator(...)` – Initializes the audio engine. It configures the **wave type** (sine), **sample rate** (16kHz), and **envelope parameters** (attack, release, glide). This Brick automatically connects to the USB audio device and starts a background thread for streaming.
92-
- `ui.on_message('theremin:move', on_move)` – When the frontend sends new coordinates, this function calculates the target frequency and calls `wave_gen.set_frequency()` and `wave_gen.set_amplitude()`.
93-
- `App.run()` – Starts the application. Since the audio generation is handled by the Brick in the background, no custom loop is required here.
74+
- `ui = WebUI()` – Initializes the web server that serves the HTML interface and handles WebSocket communication.
75+
- `wave_gen = WaveGenerator(...)` – Creates the wave generator brick with configured envelope parameters (attack=0.01s, release=0.03s, glide=0.02s). The brick automatically manages the USB speaker connection and audio streaming in a background thread.
76+
- `ui.on_message('theremin:move', on_move)` – Registers a handler that fires whenever the frontend sends new coordinates. This function updates the wave generator's frequency and amplitude using `wave_gen.set_frequency()` and `wave_gen.set_amplitude()`.
77+
- The `wave_generator` brick handles all audio generation and streaming automatically, including smooth transitions between frequency and amplitude changes, continuous audio output with ~**30 ms** blocks, and non-blocking playback without cracks or pops.
9478

9579
### 💻 Frontend (`main.js`)
9680

@@ -100,52 +84,63 @@ The web interface provides the interactive play area and controls for the user.
10084
- **Event listeners** capture `mousedown`, `mousemove`, `mouseup` (and touch equivalents) to track user interaction in the play area.
10185
- `socket.emit('theremin:move', { x, y })` – Sends normalized (0.0–1.0) X and Y coordinates to the backend; emissions are **throttled to ~80 Hz (≈12 ms)** to avoid overload.
10286
- `socket.on('theremin:state', ...)` – Receives state updates from the backend (like the calculated frequency and amplitude) and updates the values displayed on the webpage.
103-
- **Visual Waveform Generation:** Using the amplitude and frequency data received from the backend, the frontend draws a real-time sine wave animation on the HTML Canvas, providing immediate visual feedback.
104-
- `socket.emit('theremin:set_volume', { volume })` – Sends a **0–100** master volume value.
105-
- `socket.emit('theremin:power', { on })` – Toggles synth power (**On/Off**).
87+
- `socket.emit('theremin:set_volume', { volume })` – Sends a **0-100** hardware volume value to control the USB speaker's output level.
88+
- `socket.emit('theremin:power', { on })` – Toggles synth power (**On/Off**). After turning **On**, move/tap in the play area to resume sound.
89+
90+
10691

10792
## Troubleshooting
10893

10994
### "No USB speaker found" error
11095

111-
If the application fails to start and you see an error regarding the speaker (e.g., inside the `WaveGenerator` initialization), it means the required audio hardware is missing.
112-
113-
**Fix:**
114-
1. Make sure a **powered USB-C® hub** is connected to the UNO Q and its **5 V / 3 A** power supply is plugged in.
115-
2. Verify the **USB audio device** (USB speaker or wireless USB receiver) is **connected to the hub** and, if it has a switch, **turned on**.
96+
If the application fails to start and you see the following error in the logs, it means the required audio hardware is missing or not detected.
97+
```
98+
arduino.app_peripherals.speaker.SpeakerException: No USB speaker found.
99+
```
100+
**Fix:**
101+
1. Make sure a **powered USB-C® hub** is connected to the UNO Q and its **5 V / 3 A** power supply is plugged in.
102+
2. Verify the **USB audio device** (USB speaker, wireless USB receiver, or USB-C→3.5 mm dongle) is **connected to the hub** and, if it has a switch, **turned on**.
116103
3. Restart the application.
117104

118105
### No Sound Output
119106

120-
- **Power Button:** Make sure the button in the web UI shows **On**.
121-
- **Volume Knob:** Check the visual knob on the web UI.
122-
- **Pointer Position:** Move your mouse/finger toward the top of the play area (the bottom corresponds to zero volume).
123-
- **Speaker/Headphone Volume:** Check the physical volume control and mute status on your speaker or headphones.
107+
- **Power Button:** Make sure the button in the web UI shows **On**.
108+
- **Volume Slider:** Increase the volume slider in the web UI.
109+
- **Pointer Position:** Move your mouse/finger toward the top of the play area (the bottom corresponds to zero volume).
110+
- **Speaker/Headphone Volume:** Check the physical volume control and mute status on your speaker or headphones.
124111
- **Output Path:** Remember that **HDMI audio** and **Bluetooth® speakers** are not supported; use a **USB** audio device.
125112

126113
### Choppy or Crackling Audio
127114

128-
- **CPU Load:** Close any other applications running on the Arduino UNO Q that may be consuming significant resources.
115+
- **CPU Load:** Close any other applications running on the Arduino UNO Q that may be consuming significant resources.
129116
- **Power Supply:** Ensure you are using a stable, adequate power supply (5 V, 3 A) for the USB-C® hub, as insufficient power can affect USB peripheral performance.
130117

118+
119+
131120
## Technical Details
132121

133-
- **Sample rate:** 16,000 Hz
134-
- **Audio format:** 32-bit float, little-endian
135-
- **Block duration:** ~30 ms
136-
- **Frequency range:** ~20 Hz to ~8,000 Hz
137-
- **Envelope:**
138-
- **Attack:** 0.01s (fast onset)
139-
- **Release:** 0.03s (quick fade out)
140-
- **Glide:** 0.02s (smooth pitch sliding)
122+
- **Sample rate:** 16,000 Hz
123+
- **Audio format:** 32-bit float, little-endian
124+
- **Block duration:** ~30 ms (≈480 samples per block)
125+
- **Frequency range:** ~20 Hz to ~8,000 Hz
126+
- **Update rate:** Frontend throttled to ~80 Hz (≈12 ms minimum between updates)
127+
128+
141129

142130
## Compatibility Notes
143131

144-
- **Works with:**
145-
- **USB speakers** (cabled)
132+
- **Works with:**
133+
- **USB speakers** (cabled)
146134
- **USB wireless speaker receivers** (2.4 GHz dongles)
147-
- **Untested (may work):**
135+
- **Untested (may work):**
148136
- **USB‑C → 3.5 mm audio dongles** feeding analog speakers/headphones
149-
- **Not supported:**
150-
- **HDMI audio** output
137+
- **Not supported:**
138+
- **HDMI audio** output
151139
- **Bluetooth® speakers**
140+
141+
142+
## License
143+
144+
This example is licensed under the Mozilla Public License 2.0 (MPL-2.0).
145+
146+
Copyright (C) 2025 ARDUINO SA <http://www.arduino.cc>
117 KB
Loading

0 commit comments

Comments
 (0)