Saturday, May 17, 2014

21. Frequency Modulation


Frequency Modulation results in audio with very different kinds of sounds.




The definition of frequency modulation is that a signal is frequency modulated, that is, we find a cosine of a sine. The signal to be modulated has some maximum modulating frequency, fm. So we have to analyze the signal y, given here.




There is a lot of math involved, involving imaginary numbers and expanding the sines to their Taylor Series. The term Jn(B) is a Bessel series. The term series means a number just like the exponent e, cosine of an angle, sine of an angle, or pi. We usually round to some decimal place as computers have finite precision. There is a Bessel series, that is, rounded to a number, for each integer n. The most important result, is that, now many frequencies result, with the form, fc plus n times fm, with n, being either a positive, or negative integer. This results in more frequencies, in our resulting signal, centered at the carrier frequency.




The most important csound FM opcode is foscil. Note, there are 6 required parameters and 1 optional parameter. The optional parameter should be left out so it defaults to 0. Also the kcps term should always be 1, so that, the inputs xcar and xmod, will refer to fc and fm. The input, xamp, is the amplitude and usually an envelope. The input, kndx, is the value, B, in the FM definition. B is called the modulating index and the larger the index, the more frequencies should be in the resulting signal. One of the important things to note, in FM synthesis, is that the resulting frequencies, should not hit the Nyquist frequency of 22,050 Hz so all frequencies are correctly mapped and not shifted down. This artifact is called aliasing. Here, we assumed the sampling frequency is the usual 44,100 Hz and thus the Nyquist is half of that.




There are two examples that we will go into. The first uses a carrier frequency of 2200 Hz, modulating frequency of 10 Hz, and an index of 10. The envelope goes from 0.1 to 0.3 with fade-in and fade-out, at either end.


# Main1.py

from moduleCsound import *
add(startSyn,startOpt,stopOpt,startIns)
header(ksmps=1,nch=2)

# *** Instrument String ***
FMStr="""
kenv linseg 0,0.1,0.1,p3-.2,0.3,0.1,0
aosc foscil kenv, 1, 2200, 10, 10, 1
out aosc, aosc
"""

instrument('',1,FMStr)

add(stopIns,startSco)

# *** Table ***
table('1. Sine wave',1,0,8192,10,1)

# *** Score ***
rem('Example for FM synthesis')
score(1,0,2)

add(stopSco,stopSyn)
writeRun('Tut21a')



In the next example, a String Template is created. There are three placeholders representing the carrier frequency, modulating frequency and modulating index.




Now, 150 different, but similar, instruments are created. The carrier frequency is always 2200 Hz, and the modulating index is always 10. Only the modulating frequency changes from 400 Hz to 251 Hz. Note, in the instrument call an empty String is passed so extra comment are not included on each line in the csound file. Now, the comment has been moved outside, in a rem() function call.




Finally, a score line is entered for each instrument. Each score line lasts for 0.4 seconds and are called in succession.


# Main2.py

from moduleCsound import *
add(startSyn,startOpt,stopOpt,startIns)
header(ksmps=1,nch=2)

# *** Instrument String Template ***
FMStr="""
kenv linseg 0,0.1,0.1,p3-.2,0.3,0.1,0
aosc foscil kenv, 1, %s, %s, %s, 1
out aosc, aosc
"""

# 150 Instrument Strings
FMString=[FMStr % (2200,400-i,10) for i in range(150)]

rem('150 FM Instrument Definitions')
for i in range(150): instrument('',i+1,FMString[i])

add(stopIns,startSco)

# *** Table ***
table('1. Sine wave',1,0,8192,10,1)

# *** Score ***
rem('Example for FM synthesis')
for i in range(150): score(i+1,i*.4,.4)

add(stopSco,stopSyn)
writeRun('Tut21b')



If you were to look at the csound file, it will be over 900 lines. The Python program is only 30 lines. We can make the Python program smaller by removing empty lines, etc. But this results in more confusing code. We only have to type the Python lines correctly, rather than typing everything correctly in the csound file. This would result in less debugging time.




This is the output wav file for a small time duration. The 150 different instruments, have output sounds, in very different sound color, that is, timbre.




You will find additional information at pythonaudio.blogspot.com, including the source code.



This is the video of Tutorial 21:


3 comments:

About Me

I have used Python for the last 10+ years. I have a PhD in Electrical Engineering. I have taught Assembly Language programming of Intel-compatible chips as well as PC hardware interfacing. In my research, I have used Python to automate my calculations in physics and chemistry. I also use C++ and Java, often with Python.