# Generating a noisy sine wave in Python, efficiently

(Questions after code block.)

For now, I am generating the sinusoid and the noise separately and then normalising the amplitude so I can write the signal to a .wav file (16-bit, 16kHz).

def genSine(f0,fs,dur):
sinusoid = []
for t in range(dur):
sinusoid.append(math.sin(2*math.pi*t(*freq/fs)))
sinusoid = normalise(sinusoid)
return sinusoid

def genNoise(dur):
noise = np.random.normal(0,1,dur))
noise = normalise(noise)
return noise

def normalise(x,MAX_INT16):
maxamp = max(x)
amp = floor(MAX_INT16/maxamp)
norm = np.zeros(len(x))
for i in range(len(x)):
norm[i] = amp*x[i]
return norm

def writeWav(w):
# audiophilic magic

if __name__ == '__main__':
f0 = 440
fs = 16000
dur = 1*fs                      #seconds
MAX_INT16 = 32767
sinusoid = genSine(f0,fs,dur)
noise = genNoise(dur)
sum = x + y
sum = normalise(sum,MAX_INT16)
writeWav(sum)

1. Is there a more efficient way to sum the two signals (sine + noise), perhaps bypassing/incorporating the normalisation step (it is currently called three times, in genSine, genNoise and main)?

2. How can I ensure set the amplitude ratio between the sine and noise signals?

I'm new to Python and stackexchange so any help is appreciated!

The are some ways to improve your solution.

First, use numpy and vectorize your code:

def genSine(f0,fs,dur):
sinusoid = []
for t in range(dur):
sinusoid.append(math.sin(2*math.pi*t(*freq/fs)))
sinusoid = normalise(sinusoid)
return sinusoid


becomes

import numpy as np
def genSine(f0, fs, dur):
t = np.arange(dur)
sinusoid = np.sin(2*np.pi*t*(f0/fs))
sinusoid = normalise(sinusoid)
return sinusoid


You will see the biggest improvment in efficiency when vectorizing all your code like this.

Second, concerning the normalization, you should consider the mathematics of your problem instead of doing it 3 times. You have 3 pieces of signal, the sinusoid, the noise, the mix. The first is already normalized (between -1 and 1), the second also (hence the name normal distribution for describing the noise). So you should only normalize the third.

Hope this helps!

• Actually, the normal distribution leads to a signal with Gaussian distribution that has unit variance. The amplitude of the signal is not restricted to a maximum. – Brian Aug 14 '15 at 20:00
• I said normalized, not bounded - for clarity let's not confuse different norm definitions. I do not see how that desserves a down vote, anyway :-) – meduz Aug 28 '15 at 15:07
• Not my downvote :-) – Brian Aug 28 '15 at 19:07
• Thanks meduz! I had a feeling it was something essential like numpy... (Not my downvote either, btw) – yunque Sep 1 '15 at 10:12
• why isn't there something like awgn (mathworks.com/help/comm/ref/awgn.html) in python? – Charlie Parker Oct 12 '16 at 5:01