# Rust Audio Programming: Oscillator – Build a sine wave [PART 1]

Hey there 👋!

Whether you’re a seasoned rustacean, a curious audio hacker, or just someone who thinks synths are cool — **welcome aboard!**

This is the **Rust Audio Programming** series, and today we’re diving into the **basics of audio programming** by building our very first **sine wave** — the audio equivalent of “hello, world”.

> ⚙️ *This tutorial assumes you already have the Rust toolchain installed (via* [*rustup*](https://rustup.rs)). If not, check out the official install guide — setting it up is out of scope for this post.

## So what digital sound is?

**Sound**, at its core, is a **vibration in the air** — pressure **waves** that travel to our ears. Inside, these vibrations are turned into signals that our brains understand as sound.

In the digital world, we sample these continuous waves at **discrete intervals** — usually thousands of times per second — and store the values as numbers.

This is known as **digital audio**. For example, CD-quality audio samples the waveform 44,100 times per second (44.1 kHz), capturing its shape with enough detail that it sounds smooth and natural to the human ear.

## Enter the waveform

Every sound you hear — a piano note, a bird chirp, a voice — has a unique **waveform**. The shape of this waveform determines the character or **timbre** of the sound.

Waves are building blocks of synthetic sound, and they’re what we’ll be working with in this series.

## What’s a note, really?

When we talk about a musical **note**, we're really talking about **a specific frequency of vibration** — how fast the air is wiggling back and forth. Each full wiggle is called a **cycle**.

That frequency is measured in **hertz (Hz)**, or **cycles per second**. So if a sound wave vibrates 440 times in one second, it has a frequency of **440 Hz** — which just happens to be the pitch of the musical note **A4**.

![The Science of Music — Kaitlin Bove Music](https://images.squarespace-cdn.com/content/v1/5d0434f328d8d9000101f755/1585620613365-X8HXP8D6S9MNEE04CL8W/Screen+Shot+2020-03-30+at+6.32.27+PM.png align="left")

Different notes are just **different frequencies**:

* A lower note? Slower vibrations (lower Hz).
    
* A higher note? Faster vibrations (higher Hz).
    

So when we generate sound in code, we’re not saying **“*play A4*”** we’re saying ***“generate a waveform that cycles at 440 Hz.”***.

## Let’s try it out!

First, let’s set up a fresh Rust project for our experiment. Open your terminal and run:

```bash
cargo new sine_wave && cd sine_wave
```

> 💡 *These examples use Unix-style commands (Linux/macOS). If you’re on Windows… well, you know the drill — adjust accordingly*.

Before jumping into code, let’s take a second to understand **what we’re actually generating**.

We’re going to produce a **2-second sine wave** that plays the musical note **A4** — which has a frequency of **440 Hz**. That means the waveform will complete **440 full cycles every second**.

To represent that wave digitally, we’ll **sample it** — break it down into thousands of tiny values we can save to a file.

We’ll use a **sample rate of 44100 Hz** (standard CD quality), meaning we’ll capture **44100 samples per second**. For 2 seconds of audio: `44100 samples/sec × 2 sec = 88200 samples.`

To generate each sample, we’ll use the classic sine wave equation: `sample = amplitude × sin(2π × frequency × time)`, where:

* frequency is **440.0 (A4)**
    
* time is the current time in seconds for each sample (t / sample\_rate)
    
* amplitude controls the volume — we’ll use the max for 16-bit audio
    

> 🧠 **Isn’t the sine formula usually written differently?**
> 
> In math you’ll often see it as A × sin(2πft + φ), where φ is the **phase offset**.
> 
> In our case, we’re starting the wave right at the beginning of its cycle, so we just set phase to zero — and skip it entirely.

Now let’s generate our very first **sine wave** and save it as a .wav file we can actually play and analyze.

To do that, we’ll use a single dependency: [hound](https://crates.io/crates/hound).

Run this in your terminal:

```bash
cargo add hound@3.5
```

> hound is a simple Rust library for reading and writing WAV files.

Open `src/main.rs` and replace everything with this:

```rust
use std::f32::consts::PI;

fn main() {
    // WAV file settings
    let spec = hound::WavSpec {
        channels: 1,        // mono
        sample_rate: 44100, // samples per second
        bits_per_sample: 16,
        sample_format: hound::SampleFormat::Int,
    };
    // Create a WAV writer
    let mut writer = hound::WavWriter::create("sine.wav", spec).expect("Failed to create WAV file");
    // Sine wave parameters
    let freq_hz = 440.0; // frequency (A4)
    let duration_secs = 2.0; // 2 seconds
    let amplitude = i16::MAX as f32; // max volume

    let sample_rate = spec.sample_rate as f32;
    let total_samples = (sample_rate * duration_secs) as usize;

    for t in 0..total_samples {
        let time = t as f32 / sample_rate;
        let sample = (amplitude * (2.0 * PI * freq_hz * time).sin()) as i16;
        writer.write_sample(sample).unwrap();
    }

    writer.finalize().unwrap();
    println!("✅ Sine wave written to 'sine.wav'");
}
```

### **What’s happening in the code?**

Let’s break down the essential parts:

**1. WAV file setup**

```rust
let spec = hound::WavSpec {
    channels: 1,
    sample_rate: 44100,
    bits_per_sample: 16,
    sample_format: hound::SampleFormat::Int,
};
```

We configure the .wav file to be:

* **Mono** audio (channels: 1)
    
* **44.1 kHz** sample rate (standard quality)
    
* **16-bit samples** (i.e., each sample is stored as a signed 16-bit integer)
    

**2. Main parameters**

```rust
let freq_hz = 440.0;
let duration_secs = 2.0;
let amplitude = i16::MAX as f32;
```

We want a **440 Hz sine wave** (A4 note) that lasts **2 seconds**, at **maximum volume**.

**3. Generate samples**

```rust
for t in 0..total_samples {
    let time = t as f32 / sample_rate;
    let sample = (amplitude * (2.0 * PI * freq_hz * time).sin()) as i16;
    writer.write_sample(sample).unwrap();
}

writer.finalize().unwrap();
```

We:

* **Loop through each sample**
    
* **Use the sine wave formula to calculate its value**
    
* **Write the value to the WAV writer’s internal buffer**
    

Then, in the next step:

* **Call .finalize() to flush the buffer and write everything to the file**
    

Now let’s actually **run the code** and hear what we’ve created:

```bash
cargo run
```

You should see:

> ✅ Sine wave written to 'sine.wav'

That means your .wav file was successfully generated! Now go ahead and **play** `sine.wav` using your favourite audio player.

If everything worked, you should hear a **clean, steady tone** — no clicks, no weird noise. That’s a **pure 440 Hz sine wave**, also known as **concert A**.

## **Let’s see the sound**

To visualize the waveform, open `sine.wav` in [**Audacity**](https://www.audacityteam.org/) — a free, open-source audio editor that makes it easy to zoom in and inspect waveforms.

You should see a **smooth, repeating sine wave** — but heads up, it might not look like much at first.

Audacity will probably show it as a solid block by default. **Zoom in horizontally** until you can see the individual wave cycles — that’s your sine wave in action!

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1749388654941/361e09a5-5c0f-44a2-8a35-4b1a3e07899f.png align="center")

## **🏁 That’s a wrap for \[PART 1\]**

Congrats — you just generated your first sine wave **from scratch** using Rust. 🎉

You now understand:

* What digital sound is
    
* How sampling works
    
* How to generate individual audio samples using math
    

Not bad for one article, huh?

## **🔜 What’s next?**

In the next part of this series, we’ll build on what we’ve made by **changing the note over time** — like playing a simple melody with just a sine wave.

It sounds straightforward… but we’ll run into some interesting behavior that’s worth a closer look 👀

Along the way, we’ll improve the math behind our **waveform generation** and start shaping the code into something more flexible and reusable.

▶️ **Continue to Part 2:**

[*Rust Audio Programming: Oscillator – Handle frequency changes smoothly \[PART 2\]*](https://blog.paramako.com/rust-audio-programming-oscillator-handle-frequency-changes-smoothly-part-2)

💾 **Source code from this article:**

[View on GitHub →](https://github.com/paramako-blog/oscillator/blob/main/examples/part1_sine_wave.rs)
