Write a 440 Hz Sine Wave to .wav-File using Python and SciPy [closed]

This is my first post on DSP.SE! I'm a student in Computer Sciences and am just getting started with Signals and Systems, thus getting in touch with discrete signals and analyzing them.

I wanted to explore this world a little further and so my first goal is to create a Sine Wave that has a Frequency of 440 Hz and write it to a .wav-File. Of course i have all the calculus in mind, but i can't seem to figure out the problem myself!

So far, i have this:

#!/usr/bin/env python3

import numpy as np
from scipy.io import wavfile

sampleRate = 44100

t = np.linspace(0, 20, sampleRate * 5)  #  Produces a 5 second Audio-File
y = np.sin(440 * t)  #  Should have frequency of 440Hz

wavfile.write('Sine.wav', sampleRate, y)

I understand why this code always creates a File, that is 5 seconds long, but i can't figure out, how to get the frequency right!

Have i even gotten the rest of the code right, Dsp-Guy-wise?

closed as off-topic by robert bristow-johnson, lennon310, Marcus Müller, A_A, Matt L.Nov 8 '18 at 14:17

This question appears to be off-topic. The users who voted to close gave this specific reason:

• "General programming questions are off-topic here, but can be asked on Stack Overflow." – robert bristow-johnson, lennon310, Marcus Müller, A_A, Matt L.
If this question can be reworded to fit the rules in the help center, please edit the question.

• should maybe be t = np.linspace(0, 5, sampleRate*5 + 1). – robert bristow-johnson Nov 6 '18 at 22:24
• oh, and welcome to dsp.se . this might be a better question for Stack Overflow, but i dunno. – robert bristow-johnson Nov 6 '18 at 22:26
• Thanks for your comment! I already figured the solution out myself, see my answer! – Tim Hilt Nov 6 '18 at 22:32
• Actually, maybe math.se would also have been a good fit! I hope i haven't posted absolutely the wrong way – Tim Hilt Nov 6 '18 at 22:34

After some experimenting i came up with the following:

#!/usr/bin/env python3

import numpy as np
from scipy.io import wavfile

sampleRate = 44100
frequency = 440
length = 5

t = np.linspace(0, length, sampleRate * length)  #  Produces a 5 second Audio-File
y = np.sin(frequency * 2 * np.pi * t)  #  Has frequency of 440Hz

wavfile.write('Sine.wav', sampleRate, y)

I pulled out one of my math-books and figured out how to write the sine-function:

Since sin(x) has a period of 2*pi, sin(2*pi*x) has a period of 1/Frequency of 1Hz. Thus, sin(440*2*pi*x) has a Frequency of 440Hz.

The last thing that was unclear to me was how to get the array-length and element-count right!

Opting for a File that has a sample rate of 5 seconds at 44.1 kHz Sample Rate, i need 5 * 44.1k samples, so that was already ok. But since sin(440*2*pi*x) performs 440 periods until t == 1, the array simply has to have a duration of 5 (5 seconds in my case to be precise). enlarging the array boundaries would have squished the array-values together, resulting in a higher pitched sound.

Sorry to anyone that has already scratched their head, i probably should have thought for a little bit longer!

• Good to see you figured it out. I'd suggest using duration instead of length to avoid confusion -- length usually means "number of elements". – MBaz Nov 6 '18 at 23:31
• how many actual number of elements are produced by linspace()? i think the length of the vector is the last argument to the function (if it's anything like MATLAB's linspace()). in that case, i am pretty sure you want  t = np.linspace(0, length, sampleRate*length+1)  otherwise you will be slightly detuned. this is a "fencepost" or "off-by-one" sorta problem. – robert bristow-johnson Nov 6 '18 at 23:38
• No, it creates exactly as much elements, as the third Argument specified. When i do len(t) i get 220500. 220500/5 = 44100 => SampleRate – Tim Hilt Nov 7 '18 at 6:04
• But the Index of the elements is always len() - 1. So if i want to edit the last element of t, i would have to write t[len(t) - 1] = value, at least if i'm not mistaken – Tim Hilt Nov 7 '18 at 6:09
• I investigated a little bit: you can set behavior yourself, according to docs.scipy.org/doc/numpy-1.15.0/reference/generated/… in linspace, setting endpoint=False, the last wouldn't bei included in the array, Default is True. – Tim Hilt Nov 7 '18 at 6:52