music.frequency_modulation

music.frequency_modulation(carrier_freq=200.0, modulation_freq=10.0, frequency_deviation=20.0, duration=2.0, waveform_table=array([0., 0.0003835, 0.00076699, ..., -0.00115049, -0.00076699, -0.0003835], shape=(16384,)), modulation_waveform_table=array([0., 0.0003835, 0.00076699, ..., -0.00115049, -0.00076699, -0.0003835], shape=(16384,)), number_of_samples=0, sample_rate=44100)[source]

Sweep a carrier’s pitch: sstim-v:techFrequencyModulation.

A tone whose pitch sweeps over time. SSTIM types this as a generic technique because its status depends on rate: fast modulation can evoke frequency-following responses, while slow, breathing-rate modulation engages autonomic rather than entrainment pathways [2].

Parameters:
carrier_freqscalar

The centre frequency of the carrier, in Hertz.

modulation_freqscalar

The rate at which the pitch sweeps, in Hertz.

frequency_deviationscalar

The peak departure from carrier_freq, in Hertz. Stated in Hertz rather than in semitones, which is the convention this literature uses; music.note_with_vibrato() takes the musical form of the same idea in semitones.

durationscalar

The duration in seconds.

waveform_tablearray_like

The table the carrier is looked up in.

modulation_waveform_tablearray_like

The table the modulator is looked up in.

number_of_samplesinteger

The number of samples of the sound, taken instead of duration when it is given.

sample_rateinteger

The sampling frequency in Hertz.

Returns:
ndarray

A mono sequence of PCM samples.

Parameters:
  • carrier_freq (float)

  • modulation_freq (float)

  • frequency_deviation (float)

  • duration (float)

  • waveform_table (ArrayLike)

  • modulation_waveform_table (ArrayLike)

  • number_of_samples (int)

  • sample_rate (int)

Return type:

NDArray[float64]

See also

music.note_with_vibrato

the same modulation expressed musically, in semitones.

music.note_with_fm

FM synthesis, where the modulator is at audio rate and the point is timbre.

Notes

The modulation is physically present.

The instantaneous frequency is computed per sample and integrated into the lookup index, rather than the modulation being applied to an already-rendered tone. This is the package’s model throughout, and it is why the rendered sound matches the mathematics that describes it rather than approximating it.

References

[1]

Fabbri, Renato, et al. “Musical elements in the discrete-time representation of sound.” arXiv preprint arXiv:abs/1412.6853 (2017)

[2]

SSTIM, techFrequencyModulation. https://w3id.org/sstim/vocab#techFrequencyModulation

Examples

>>> stimulus = frequency_modulation(carrier_freq=200,
...                                 modulation_freq=0.1)
>>> stimulus.ndim
1