Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

sine wave that exponentialy changes between frequencies f1 and f2 at given time/amount of samples

I'm trying to implement Python method that generates sine wave, which ramps up between two freq exponentially. Linear change was solved in [this question] with following Python code:

from math import pi, sin

def sweep(f_start, f_end, interval, n_steps):    
    for i in range(n_steps):
        delta = i / float(n_steps)
        t = interval * delta
        phase = 2 * pi * t * (f_start + (f_end - f_start) * delta / 2)
        print t, phase * 180 / pi, 3 * sin(phase)

sweep(1, 10, 5, 1000)

How to change this linear accumulative phase/delta approach to expotential frequency sweep and be smooth to human ear.

like image 713
Ethan Smith Avatar asked Nov 04 '13 15:11

Ethan Smith


People also ask

How does frequency affect sine wave?

The number of times the sine wave goes through a complete cycle in the space of 1 second is called the frequency. Indeed the unit used to be cycles per second, but now the unit of measurement is hertz (Hz). A frequency of 1000Hz, or 1 kHz, means that the sine wave goes through 1000 complete cycles in 1 s.

What is the equation for a sine wave?

In its most general form, the sine wave can be described using the function y=a*sin⁡(bx), where: a is known as the amplitude of the sine wave. b is known as the periodicity.

What determines the frequency of a sine wave?

The frequency of a sine wave is the number of complete cycles that happen every second. (A cycle is the same as the period, see below.) In the bouncing weight above, the frequency is about one cycle per second. In this formula the frequency is w.


1 Answers

The trick in this sort of problems is to understand the relation between frequency modulation and phase modulation, these two are closely related. A sine with a constant frequency f and amplitude A can be described as (formulas, not python code):

x(t) = A sin(2 * pi * f * t)

but a different way to write this is by first defining a phase phi as a function of time:

phi(t) = 2 * pi * f * t
x(t) = A sin(phi(t))

The thing to note here is that frequency f is the derivative of the phase, divided by 2*pi: f = d/dt(phi(t)) / (2*pi).

For a signal which has a frequency that is varying in time, you can similarly define an instantaneous frequency f_inst:

x(t) = A sin(phi(t))
f_inst = d/dt(phi(t)) / (2*pi)

What you want to do is the opposite of this, you have a given instantaneous frequency (your logarithmic sweep), which you need to convert into a phase. Since the opposite of derivation is integration, you can calculate the appropriate phase like this (still formulas):

phi(t) = 2 * pi * Integral_0_to_t {f_inst(t) dt}
x(t) = A sin(phi(t))

What you are doing here is some sort of phase modulation of a signal (with zero frequency) to obtain the required instantaneous frequency. This is pretty easy to do in numpy:

from pylab import *
n = 1000 # number of points
f1, f2 = 10, 30 # frequency sweep range in Hertz

t = linspace(0,1,1000)
dt = t[1] - t[0] # needed for integration

# define desired logarithmic frequency sweep
f_inst = logspace(log10(f1), log10(f2), n)
phi = 2 * pi * cumsum(f_inst) * dt # integrate to get phase

# make plot
plot(t, sin(phi))
xlabel('Time (s)')
ylim([-1.2, 1.2])
grid()
show()

Resulting image:

Logarithmic frequency sweep

But (as also noted in the dupe mentioned by Dave), you probably don't want a logarithmic sweep, but an exponential one. Your ear has a logarithmic perception of frequency, so a smooth/linear musical scale (think the keys on a piano) are therefore spaced exponentially. This can be achieved by simply redefining your instantaneous frequency f_inst(t) = f1 * exp(k * t), where k is chosen such that f_inst(t2) = f2.

If you want to use amplitude modulation at the same time, you can simply change A to a time dependent A(t) in the formulas.

like image 75
Bas Swinckels Avatar answered Sep 29 '22 18:09

Bas Swinckels