22

I'm trying to generate a sine wave of a given frequency for a given duration and then write it into a .wav file. I'm using numpy's sin function and scipy's wavfile function. I'm getting a weird sound that is definitely not a sine wave.

import numpy as np
from scipy.io import wavfile

fs = 44100

f = int(raw_input("Enter fundamental frequency: "))
t = float(raw_input("Enter duration of signal (in seconds): "))

samples = np.arange(t * fs)

signal = np.sin(2 * np.pi * f * samples)

signal *= 32767

signal = np.int16(signal)

wavfile.write(str(raw_input("Name your audio: ")), fs, signal)

Any help would be appreciated. Have I made some fundamentally incorrect assumption about sine waves or something?

4 Answers4

15

Change

samples = np.arange(t * fs)

to

samples = np.linspace(0, t, int(fs*t), endpoint=False)

(This assumes that fs*t results in an integer value.)

Or, as Paul Panzer suggests in a comment,

samples = np.arange(t * fs) / fs

Your samples was just the sequence of integers 0, 1, 2, ... fs*t. Instead, you need the actual time values (in seconds) of the samples.

Warren Weckesser
  • 110,654
  • 19
  • 194
  • 214
7

A simplified approach:

cycles = 2 # how many sine cycles
resolution = 25 # how many datapoints to generate

length = np.pi * 2 * cycles
my_wave = np.sin(np.arange(0, length, length / resolution))

Generates:

[ 0.      0.4818  0.8443  0.998   0.9048  0.5878  0.1253 -0.3681 -0.7705
 -0.9823 -0.9511 -0.6845 -0.2487  0.2487  0.6845  0.9511  0.9823  0.7705
  0.3681 -0.1253 -0.5878 -0.9048 -0.998  -0.8443 -0.4818]

generated_sine_wave


Note: Leaving this answer here despite not addressing sine wave for audio generation, since I found that for my application it was more intuitive to only parameterise length of the wave and number of datapoints generated, as opposed to fundamental frequency and duration in seconds.

Voy
  • 5,286
  • 1
  • 49
  • 59
4

Use this and set the parameters as you want

start_time = 0
end_time = 1
sample_rate = 1000
time = np.arange(start_time, end_time, 1/sample_rate)
theta = 0
frequency = 100
amplitude = 1
sinewave = amplitude * np.sin(2 * np.pi * frequency * time + theta)
figure(figsize=(20, 6), dpi=80)
plt.plot(sinewave)
Shanks D Shiva
  • 197
  • 1
  • 3
3

You are mixing sample value and length! Try:

samples = np.linspace(0, t, t * fs)

Another detail: you don't need the str around raw_input.

grovina
  • 2,999
  • 19
  • 25