Tempest shore DSP with Qwen 3.8 Max

You’re coding in the night or enjoying a relaxing week-end, and you want to listen to some rain. That’s what the classic Rainy Mood site was offering — though the experience has become less appealing with the advertisements.

Nasqueron had such a rain page implementation but it needs to be refreshed for modern browsers.

That’s when I’ve asked to Qwen 3.8 Max, the new model released this week, to generate me a rain sound. It does a lot of thinking passes, during it becomes clear it’s trying to write it as a procedurally generated digital signal processing (DSP) system.

I can’t attach a binary WAV/MP3 directly in this text interface, but below is a self-contained generator that renders the exact requested rain loop and saves it as a downloadable local file: rain_loop_48k.wav.

And here we are: a Python script using NumPy to generate 75 seconds of sound in around 5 seconds.

From speed optimization to a new sound effect

Five seconds is perhaps a little slow, especially with a Ryzen 9 7900X CPU, so can we speed it up if we rewrite it in Rust (RIIR)?

Not immediately. The Rust time and the Python time were on the same range. Still 5 seconds1. Not surprising, as the NumPy library is pretty well optimized.

That’s when Qwen decided to introduce Rayon in the mix, a library for parallel computation. We went from 5.1 seconds to 1.32 seconds, a 4x speed-up. The `time` command shows it was using 6 core (553%). Parallizing millions of sine computations was a good call. The next optimization wouldn’t be as dramatic2: 720 ms in the end.

There was also a question of shaping the sound as a rain sound: the initial noise sounded more like an old CRT TV without a signal than gentle rain. The model suggested tweaking some values in the equation and explained what the changes would do3.

All in all, the Rust code is not bad, but there were some issues along the way, such as the breaking incompatibilities introduced by rand 0.10.x or an unused variable4.

That’s when the things became interesting. We now had a very interesting result: it wasn’t just rain, it’s a tempest near the sea, with waves crashing on the sand and the wind becoming stronger and then quieter. I really enjoy it; it works well. You can test it here.

I so asked a XeLaTeX paper explaining the equations behind the code. In a TeX document, the equations would be properly rendered, with fractions displayed as proper fraction bars, square roots as √ symbols, etc., making them much easier to read and understand. After spending a good part of my Saturday learning about filtering techniques such as the Butterworth filter, I asked GPT 5.6 Sol to review the code and the paper. Hu hu. The Rust-to-equations skill of Qwen can be improved.

GPT 5.6 Sol pointed out the contradictions, I passed them to Qwen3.8-Max… and that’s when Qwen noticed the “bug” (read bug as a feature) introduced during the parallelism code. Now we know why the sound suddenly became interesting.

The story of a sound

Some years ago, Lionel Scheepmans told me about an interesting work, le Solfège de l’objet sonore by Pierre Schaeffer. It helps to describe any sound . That work (in French) really helps to understand the properties of a sound, and to understand generated code variable names such as attack, decay, or grain5.

So now, after a back and forth between GPT 5.6 Sol and Qwen3.8-Max, we have high-level documentation in the README and correct equations in XeLaTeX.

Qwen reports that the key to creating the dramatic waves is the periodic gain:

G(t)=k=1K1ck0.85sin(2πcktT+ϕk)maxk=1K1ck0.85sin(2πcktT+ϕk)G(t) = \frac{\sum_{k=1}^{K} \frac{1}{c_k^{0.85}} \sin\left(2\pi c_k \frac{t}{T} + \phi_k\right)}{\max\left|\sum_{k=1}^{K} \frac{1}{c_k^{0.85}} \sin\left(2\pi c_k \frac{t}{T} + \phi_k\right)\right|}

  • When G(t) ≈ 1, the sound volume is maximized;
  • When G(t) ≈ 0, the sound volume is quasi-silence6;
  • When G(t) < 0, the sound is phase-inverted, which creates destructive cancellations and constructive reinforcement with the other layers.

According to Qwen’s generated text, this creates breathing cycles in which the sound increases and then decreases, quieter moments, and sound explosions, with complex interactions resulting from those phase inversions.

The final DSP pipeline, in brief, is:

[ Spectral noise shaping (FFT domain) ] -> [ Bipolar modulation (the “tempest effect”) ] -> [ Granular droplets with resonant filtering ] -> [ Mid/Side stereo encoding ].

Notes about benchmarks and CPU temperature

This DSP is heavy in computation. With 75 seconds and 48000 Hz, the program performs approximately 3.6 million samples of audio processing, involving 648 millions of trigonometric evaluations across multiple DSP layers7. It also needs to perform five inverse fast Fourier transforms (IFFTs), each with those 3.6M points8.

When benchmarking a software, it’s useful to gather statistics of several runs, instead of a unique run:

for i in {1..10}; do
    /usr/bin/time -f '%e %U %S %P' sh -c "./target/release/tempest-shore-dsp > /dev/null" 
done

You can so gather the following statistics:

  • real time: ~719 ms ± 41 ms — the average and the standard deviation
  • 1182%, indicating the program is using roughly 11.8 CPU cores on average. That’s all the physical cores of the CPU, confirming tempest-shore-dsp is heavily parallellized across the 7900X.

Another interesting thing to do is to check CPU temperature during the computation. On Linux, we can use lm-sensors:

sensors k10temp-pci-00c3 | awk '/Tctl:/ {print $2}'

The successive runs show a quick increase from ~46–47°C to a peak of ~81.6°C, a perfectly reasonable temperature during repeated heavy computations. The Ryzen 9 7900X has a specified thermal limit of 95°C.

It was pretty warm in my loft this week-end, with no air conditioning; my Logitech MX 5000 keyboard reported 28 °C. If accurate, the delta was 53.6 °C above ambient.

Immediately after the successive runs, the temperature decreases back to 46°C, confirming it’s well our software that requested the computation9.

Lessons learned

  • The Qwen3.8-Max model can generate video, but not sound.
  • Models have difficulties staying faithful to one format when “translating” to another format, such as source code ↔ equations
  • Parallelization of sinus computations is a MUST DO now we have threads in our CPUs.
  • Collaborative cross-review generations by GPT 5.6 Sol and Qwen3.8-Max work pretty well10.
  • LLM give us opportunities to learn instead of just generating artifacts, if we take time to ask questions and analyze what’ has been done.

Useful links

Notes

  1. Qwen3.8-Max generated a text stating it expected 150-300 ms, as rustfft optimizes code per sampling size (3 600 000 for us) and “massively” uses AVX2 vector instructions from the CPU. Raté, that wasn’t the bottleneck. ↩︎
  2. On older hardware, perhaps it’s useful: the final product uses 700 ms on my Ryzen workstation but 6 to 7 seconds on an Intel Xeon CPU E5-1650 v3 @ 3.50GHz. ↩︎
  3. When I’ve fixed the bug introduced, nothing, it was still a white noise generator. End of the gentle rain quest. ↩︎
  4. Retrospectively, I realized this variable depth_db was unused after the rayon loop, not after the sound improvement iteration. That’s what introduced the bug causing the final DSP behavior. ↩︎
  5. The variable names chosen by Qwen model don’t seem to exactly match the notions with the same words in Pierre Schaeffer’s work. ↩︎
  6. GPT 5.6 Sol was good at catching pedantic issues such as “silence” vs “quasi-silence” in the Qwen .tex draft, so if you need to review a paper, I recommend that model. ↩︎
  7. 3.6M samples * 36 sines per layer * 5 layers ↩︎
  8. As explained at the start of the Princeton Algorithms course, without the Fourrier transformations, we wouldn’t be able to listen to MP3 audio or save a JPEG photo immediately after we press a button. So, of course, CPUs have useful instructions to compute them. ↩︎
  9. It also confirms that the combination of the Lancool III case airflow and the Noctua NH-D15S is efficient. ↩︎
  10. In the other direction, configuration as code work suggested by Qwen3.7 and implemented by GPT 5.5 – using Codex from PyCharm – was correctly reviewed by Qwen too. ↩︎

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.