Hello fellow Python coders,
I'm trying to build a simple FM synthesizer in Python. As a beginner,
I take 'FM synthesizer' to
mean: "using a sine wave to control the frequency of another sine wave."
I tried to generate a tone of 1000 Hz that deviates 15 Hz six times a
second. The start of the
resulting wave file sounds right, i.e., a vibrato effect can be heard.
After a second or so, the
vibrato becomes more and more extreme, as if the modulating
oscillator's amplitude is rising
over time. I suspect that I am misunderstanding the math. I tried a
couple of things:
- removing the factor 2 * num.pi from either of the oscillators does
not fix it, besides, doing so is
even more wrong because numpy.sin works with radians
- using a higher sampling frequency makes no difference
- making t run from 0 to 1 each second (t %= 1) causes a clipping of
the sound, so this seems
wrong too
- the problem is not related to Numpy, because the effect also happens
in pure-Python
implementations of my bug
As you can see, I'm at a loss and am even trying incorrect bugfixes.
Any help would be
very welcome.
Thanks for your time,
Joost Molenaar
[I left out a writewavheader function to aid brevity]
-------------------------------------------------------------------
import numpy as num
def oscillator(x, freq=1, amp=1, base=0, phase=0):
return base + amp * num.sin(2 * num.pi * freq * x + phase)
def writewav(filename, data):
wave = open(filename, 'wb')
# .wav header: 30 s at 44100 Hz, 1 channel of 16 bit signed samples
wave.write('RIFF\x14`(\x00WAVEfmt \x10\x00\x00\x00\x01\x00\x01\x00D'
'\xac\x00\x00\x88X\x01\x00\x02\x00\x10\x00data\xf0 _(\x00')
# write float64 data as signed int16
(32767 * data).astype(num.int16).tofile(wave)
wave.close()
t = num.arange(0, 30, 1./44100)
freq = oscillator(t, freq=6, amp=15, base=1000)
tone = oscillator(t, freq=freq, amp=0.1)
writewav('spam.wav', tone)
------------------------------------------------------------------- |