<p>An alternative would be to draw the pitch over time —as you did it in your example picture— and generate the associated sound. This can be straight-forward sometimes, depending of your constraints.</p>
<p>You can do this easily if you are familiar with <a href="https://cycling74.com/downloads" rel="noreferrer">Max</a> or <a href="https://puredata.info/" rel="noreferrer">Pure Data</a> programming languages (draw the pitch, select the speed it should be read, link the drawing to the frequency of the sinusoidal generator).</p>
<p>You could also use a more-friendly-interface software such as <a href="https://www.klingbeil.com/spear/" rel="noreferrer">Spear</a>; it says &quot;Features include: pencil tool for drawing&quot;:</p>
<p><a href="https://i.sstatic.net/ruHPD.png" rel="noreferrer"><img src="https://i.sstatic.net/ruHPD.png" alt="enter image description here" /></a>
(picture from <a href="https://www.semanticscholar.org/paper/Software-for-spectral-Analysis%2C-Editing%2C-and-Klingbeil/505d336033e290066c8cf114194a5c530f1895e4" rel="noreferrer">Klingbeil 2005</a>)</p>

CC BY-SA 4.0
2022-07-22T15:57:15.297Z
This is a great answer. As well as Max & Pure Data, I would recommend to add **SuperCollider** (my favourite). I would expect there to be a good Python library too, but no - there are a few options but none of them very mature/dependable
Dan Stowell
CC BY-SA 4.0
2022-07-21T10:07:03.557Z
2022-07-21T12:31:44.440Z
2022-07-21T12:31:44.440Z
Noil
<p>Edited 2022-8-9: the bug is fixed in the new release published yesterday August 8, 2022, version 39.</p>
<p>Edited 2022-7-27: a bug discovered after posting this answer prevents a newly created whistle to not be stored properly in the persistent database and therefore the new whistle frequencies are lost when the app is closed; the bug is getting fixed and in the mean time please use the editor while taking this into consideration; a new version will be released when the bug is fixed.</p>
<p>Original post:
Here's an open source tool to generate such sounds, the source code is in gitlab: DC Dolphin Communicator, free for Android, from <a href="https://play.google.com/store/apps/details?id=sm.app.dc" rel="nofollow noreferrer">https://play.google.com/store/apps/details?id=sm.app.dc</a> - I wrote it. It may do what you need, although the app is also designed for whistle recognition. It is best used on a tablet instead of a phone.</p>
<p>It has an editor that lets you build whistles within a ~0.5 kHz to 11 kHz range. You need to defined the frequency values in Hz at each 40th of a second. You give the whistle a name. The app can emit the whistle by entering the name in the Emit entry field in the main screen; it will interpolate between the given frequency values when it generates the voltage samples to emit (voltage sampling is 48000 per second for most tablets). Your whistle will be kept in a database which will be reloaded the next time you use the app and which can be exported to a file that can be sent remotely.</p>
<p>To use the editor in DC and emit a new whistle:</p>
<ol>
<li>open the app (the first time, you need to allow a few permissions required by Android);</li>
<li>select the WHISTLES top menu item;</li>
<li>select a whistle in the list, such as the whistle named &quot;caret&quot; shown in the image;</li>
<li>select the NEW button;</li>
<li>enter the frequencies in this format &quot;[1]2000;&quot; where &quot;[1]&quot; is the rank of a value at a 40th of a second, &quot;2000&quot; is the frequency in Hz, and &quot;;&quot; is a separator, you can use approximate values at first and then edit them later;</li>
<li>select the DRAW button to show the contour, a red line indicates a change in frequency which may be too steep; the voltages graph is drawn in the screen accessed with the VOLTAGES... button;</li>
<li>enter a name, such as &quot;atest1&quot; (the &quot;a&quot; will have it listed at the top of the whistles list for easy access), no double-quotes;</li>
<li>Back out of the editor to the whistles list screen;</li>
<li>Back out of the whistles list to the main screen;</li>
<li>Type &quot;atest1&quot; in the emit field, no double-quotes;</li>
<li>Select the EMIT button to emit the whistle on the tablet speaker or a connected speaker if any.</li>
</ol>
<p><a href="https://i.sstatic.net/2GWKZ.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/2GWKZ.png" alt="enter image description here" /></a></p>

CC BY-SA 4.0
2022-07-22T15:41:30.527Z
2022-08-09T12:48:50.127Z
2022-08-09T12:48:50.127Z
sm1
<p>If you consider that for a signal</p>
<p>s(t) = sin(phi(t))</p>
<p>the frequency is</p>
<p>f(t) = 1/(2pi) d/dt phi(t)</p>
<p>then given a desired frequency function f(t),
you construct first a phase function</p>
<p>phi(t) = 2pi \int_0 ^t f(x) dx</p>
<p>which you use in your phasor: sin(x), cos(x), exp(ix)</p>
<p>Example:</p>
<p>f(t) = f0 + (f1-f0) * t # linear FM</p>
<p>phi(t) = 2pi * (f0 * t +(f1-f0) * t^2) = 2pi * (f0+(f1-f0)/2 * t) * t)</p>
<p>Note: the integration explains the factor 2 in (f1-f0)/2</p>
<p>Edit: I did a small Matlab script to visualize better what the answer is about.</p>
<pre><code>    %signal generation
    %
    % sketch frequency
    u=[0.1,1000
    0.2,4000
    0.3,1500
    0.4,5000];
    %
    % interpolate
    fs=24000;
    T=(0:1/fs:0.5)';
    v=interp1(u(:,1),u(:,2),T,'pchip');
    %
    % truncate if necessary
    isel=(u(1,1)&lt;=T) &amp; (T&lt;= u(end,1));
    v=v(isel);
    t=T(isel);
    %
    % integrate to obtain phase
    om=2*pi*cumtrapz(v)/fs;
    %
    % generate amplitude function (here attenuate initial/final 
    % transient
    aa=ones(size(t)); 
    i1=(1:0.1*fs)';
    aa(i1)=aa(i1).*exp(-1/2*((i1-i1(end))/(0.03*fs)).^2);
    i2=length(t)+1-fliplr(1:0.1*fs)';
    aa(i2)=aa(i2).*exp(-1/2*((i2-i2(1))/(0.03*fs)).^2);
    %
    % generate signal
    s=aa.*sin(om);
    %
    % for visualisation add leading and trailing zeroes
    s=[zeros(0.1*fs,1);s;zeros(0.1*fs,1)];
    %
    % for visualization add noise
    s=s+0.01*randn(size(s));
    %%
    %visualize
    figure(1)
    subplot(211)
    plot(u(:,1),u(:,2),'o',t,v)
    subplot(212)
    spectrogram(s,hann(256),128,1024,fs,'yaxis');
    line(t*1000,v/1000,'color','k')
</code></pre>
<p>which generates
<a href="https://i.sstatic.net/9VkMD.jpg" rel="nofollow noreferrer"><img src="https://i.sstatic.net/9VkMD.jpg" alt="enter image description here" /></a></p>
<p>To address one of Dan Stowell concerns I added a amplitude weighting function that removes initial and final transients.</p>
<p>Edit: to understand if simulated signal shows unwanted effects, it is best to inspect spectrogram. I did this in example to detect and remove initial and final transients. Readers with access to Matlab are invited to experiment with script.</p>

CC BY-SA 4.0
2022-07-22T15:50:07.917Z
Please do **not** generate your own sinusiods using simple trig like this. It will very likely lead to problems such as aliasing, frequency/phase drift, etc. A particularly common problem is the lack of windowing (tapering) at the beginning/end of sinusoids, which can lead to broadband artefacts in both analysis experiments and experiments with animals. Use a well-designed software tool instead, as in @Noil's answer
Dan Stowell
CC BY-SA 4.0
2022-07-22T19:17:20.207Z
I can NOT agree with Dan's comment on aliasing, frequency shift/phase drifts. I would advice to add an amplitude function that attenuates initial and final transients. It is really irrelevant how you synthesize your phasor, you always mast make sure that your transmitter  is not saturating.
WMXZ
CC BY-SA 4.0
2022-07-23T10:43:45.697Z
We can agree to disagree, that's fine. However, implementation is not irrelevant when it can lead to artefacts. I emphasise that I've seen these problems actually happen, both in published papers and live software.
Dan Stowell
CC BY-SA 4.0
2022-07-23T19:05:49.683Z
I added Matlab code and picture to show the process
WMXZ
CC BY-SA 4.0
2022-07-27T14:02:46.043Z
Would be enough to check the spectrogram to make sure the simulation does not generate unexpected artefacts?
Marcelo Araya-Salas
CC BY-SA 4.0
2022-07-27T15:03:23.420Z
@Marcelo, yes, I edited my answer accordingly.
WMXZ
CC BY-SA 4.0
2022-07-21T08:00:43.187Z
2022-07-27T15:02:34.790Z
2022-07-27T15:02:34.790Z
WMXZ
<p>I'd like to synthesise a series of bat social-call like sounds (that look 'wavy' on the spectrogram, (see schematic below). I'm looking to test my acoustic analyses with synthetic audio
, and being able to generate sounds with arbitrary frequency modulations is important.</p>
<p><a href="https://i.sstatic.net/8AlXz.png" rel="noreferrer"><img src="https://i.sstatic.net/8AlXz.png" alt="enter image description here" /></a></p>
<p>I know how to make other synthetic sounds like pure tones, and various sweeps (linear, hyperbolic, log) using <code>scipy.signal.chirp</code> in python, and its analogs in MATLAB. Essentially, the input needs to be the frequency at a given time/sample, and the output needs to be a waveform that results in that 'frequency-profile'.</p>
<p>Can someone point me to a formula to generate arbitrary frequency modulated sounds, or even an open-source tool to generate such sounds?</p>

<analysis><modelling>
How do I synthesise an arbitrary frequency-modulated sound?
# How do I synthesise an arbitrary frequency-modulated sound?

(Asked by: username_0 on 2022-07-21)

I'd like to synthesise a series of bat social-call like sounds (that look 'wavy' on the spectrogram, (see schematic below). I'm looking to test my acoustic analyses with synthetic audio
, and being able to generate sounds with arbitrary frequency modulations is important.

[![enter image description here](https://i.sstatic.net/8AlXz.png)](https://i.sstatic.net/8AlXz.png)

I know how to make other synthetic sounds like pure tones, and various sweeps (linear, hyperbolic, log) using `scipy.signal.chirp` in python, and its analogs in MATLAB. Essentially, the input needs to be the frequency at a given time/sample, and the output needs to be a waveform that results in that 'frequency-profile'.

Can someone point me to a formula to generate arbitrary frequency modulated sounds, or even an open-source tool to generate such sounds?

**Tags:** analysis, modelling


---

## 3 answers

### Answer by username_4 on 2022-07-21. Score: 7 | Accepted answer

If you consider that for a signal

s(t) = sin(phi(t))

the frequency is

f(t) = 1/(2pi) d/dt phi(t)

then given a desired frequency function f(t),
you construct first a phase function

phi(t) = 2pi \int\_0 ^t f(x) dx

which you use in your phasor: sin(x), cos(x), exp(ix)

Example:

f(t) = f0 + (f1-f0) \* t # linear FM

phi(t) = 2pi \* (f0 \* t +(f1-f0) \* t^2) = 2pi \* (f0+(f1-f0)/2 \* t) \* t)

Note: the integration explains the factor 2 in (f1-f0)/2

Edit: I did a small Matlab script to visualize better what the answer is about.

```
    %signal generation
    %
    % sketch frequency
    u=[0.1,1000
    0.2,4000
    0.3,1500
    0.4,5000];
    %
    % interpolate
    fs=24000;
    T=(0:1/fs:0.5)';
    v=interp1(u(:,1),u(:,2),T,'pchip');
    %
    % truncate if necessary
    isel=(u(1,1)<=T) & (T<= u(end,1));
    v=v(isel);
    t=T(isel);
    %
    % integrate to obtain phase
    om=2*pi*cumtrapz(v)/fs;
    %
    % generate amplitude function (here attenuate initial/final 
    % transient
    aa=ones(size(t)); 
    i1=(1:0.1*fs)';
    aa(i1)=aa(i1).*exp(-1/2*((i1-i1(end))/(0.03*fs)).^2);
    i2=length(t)+1-fliplr(1:0.1*fs)';
    aa(i2)=aa(i2).*exp(-1/2*((i2-i2(1))/(0.03*fs)).^2);
    %
    % generate signal
    s=aa.*sin(om);
    %
    % for visualisation add leading and trailing zeroes
    s=[zeros(0.1*fs,1);s;zeros(0.1*fs,1)];
    %
    % for visualization add noise
    s=s+0.01*randn(size(s));
    %%
    %visualize
    figure(1)
    subplot(211)
    plot(u(:,1),u(:,2),'o',t,v)
    subplot(212)
    spectrogram(s,hann(256),128,1024,fs,'yaxis');
    line(t*1000,v/1000,'color','k')

```

which generates
[![enter image description here](https://i.sstatic.net/9VkMD.jpg)](https://i.sstatic.net/9VkMD.jpg)

To address one of username_2 concerns I added a amplitude weighting function that removes initial and final transients.

Edit: to understand if simulated signal shows unwanted effects, it is best to inspect spectrogram. I did this in example to detect and remove initial and final transients. Readers with access to Matlab are invited to experiment with script.

> **Comments:**
> **username_2**: Please do **not** generate your own sinusiods using simple trig like this. It will very likely lead to problems such as aliasing, frequency/phase drift, etc. A particularly common problem is the lack of windowing (tapering) at the beginning/end of sinusoids, which can lead to broadband artefacts in both analysis experiments and experiments with animals. Use a well-designed software tool instead, as in @username_1's answer  
> **username_4**: I can NOT agree with Dan's comment on aliasing, frequency shift/phase drifts. I would advice to add an amplitude function that attenuates initial and final transients. It is really irrelevant how you synthesize your phasor, you always mast make sure that your transmitter  is not saturating.  
> **username_2**: We can agree to disagree, that's fine. However, implementation is not irrelevant when it can lead to artefacts. I emphasise that I've seen these problems actually happen, both in published papers and live software.  
> **username_4**: I added Matlab code and picture to show the process  
> **username_5**: Would be enough to check the spectrogram to make sure the simulation does not generate unexpected artefacts?  
> **username_4**: @username_5, yes, I edited my answer accordingly.  

---

### Answer by username_1 on 2022-07-21. Score: 7

An alternative would be to draw the pitch over time —as you did it in your example picture— and generate the associated sound. This can be straight-forward sometimes, depending of your constraints.

You can do this easily if you are familiar with [Max](https://cycling74.com/downloads) or [Pure Data](https://puredata.info/) programming languages (draw the pitch, select the speed it should be read, link the drawing to the frequency of the sinusoidal generator).

You could also use a more-friendly-interface software such as [Spear](https://www.klingbeil.com/spear/); it says "Features include: pencil tool for drawing":

[![enter image description here](https://i.sstatic.net/ruHPD.png)](https://i.sstatic.net/ruHPD.png)
(picture from [Klingbeil 2005](https://www.semanticscholar.org/paper/Software-for-spectral-Analysis%2C-Editing%2C-and-Klingbeil/505d336033e290066c8cf114194a5c530f1895e4))

> **Comments:**
> **username_2**: This is a great answer. As well as Max & Pure Data, I would recommend to add **SuperCollider** (my favourite). I would expect there to be a good Python library too, but no - there are a few options but none of them very mature/dependable  

---

### Answer by username_3 on 2022-07-22. Score: 3

Edited 2022-8-9: the bug is fixed in the new release published yesterday August 8, 2022, version 39.

Edited 2022-7-27: a bug discovered after posting this answer prevents a newly created whistle to not be stored properly in the persistent database and therefore the new whistle frequencies are lost when the app is closed; the bug is getting fixed and in the mean time please use the editor while taking this into consideration; a new version will be released when the bug is fixed.

Original post:
Here's an open source tool to generate such sounds, the source code is in gitlab: DC Dolphin Communicator, free for Android, from <https://play.google.com/store/apps/details?id=sm.app.dc> - I wrote it. It may do what you need, although the app is also designed for whistle recognition. It is best used on a tablet instead of a phone.

It has an editor that lets you build whistles within a ~0.5 kHz to 11 kHz range. You need to defined the frequency values in Hz at each 40th of a second. You give the whistle a name. The app can emit the whistle by entering the name in the Emit entry field in the main screen; it will interpolate between the given frequency values when it generates the voltage samples to emit (voltage sampling is 48000 per second for most tablets). Your whistle will be kept in a database which will be reloaded the next time you use the app and which can be exported to a file that can be sent remotely.

To use the editor in DC and emit a new whistle:

1. open the app (the first time, you need to allow a few permissions required by Android);
2. select the WHISTLES top menu item;
3. select a whistle in the list, such as the whistle named "caret" shown in the image;
4. select the NEW button;
5. enter the frequencies in this format "[1]2000;" where "[1]" is the rank of a value at a 40th of a second, "2000" is the frequency in Hz, and ";" is a separator, you can use approximate values at first and then edit them later;
6. select the DRAW button to show the contour, a red line indicates a change in frequency which may be too steep; the voltages graph is drawn in the screen accessed with the VOLTAGES... button;
7. enter a name, such as "atest1" (the "a" will have it listed at the top of the whistles list for easy access), no double-quotes;
8. Back out of the editor to the whistles list screen;
9. Back out of the whistles list to the main screen;
10. Type "atest1" in the emit field, no double-quotes;
11. Select the EMIT button to emit the whistle on the tablet speaker or a connected speaker if any.

[![enter image description here](https://i.sstatic.net/2GWKZ.png)](https://i.sstatic.net/2GWKZ.png)


---

