Syntax Reference - Quefumas/gensound GitHub Wiki

Here we cover core syntactical features that are not specific to any Signal or Transform.

Time Durations

Whenever time is involved, use float to represent milliseconds, and int to represent number of samples. The following examples are very different:

Sine(frequency=440, duration=100) # first 100 samples of a 440Hz Sine wave - actual duration depends on sample rate
Sine(frequency=440, duration=100.0) # a 440Hz Sine wave lasting 0.1 seconds, regardless of sample rate

A convenient convention for specifying milliseconds is using Python's scientific notation, which always results in a float, and thus can't be misinterpreted as a number of samples. For example: 1e3 means 1*10**3 = 1000.0, which Gensound interprets as one second (=1000 milliseconds). Similarly 5e3 is 5 seconds, and 0.5e3 half a second.

Operations

All of the following expressions return a new Signal object:

  • Signal + Signal: mix two Signals together
  • Signal + number: adds DC to Signal (if you don't know what this means, you don't need it)
  • -Signal: phase inversion
  • Signal | Signal: concatenate two Signals (play one after the other)
  • Signal | number: concatenates silence (measured in samples or ms, depends on type of number)
  • Signal**int: repeat the Signal int times (TODO: implement floats as well?)
  • Signal*Transform: apply Transform to Signal
  • float*Signal: change Signal's amplitude (loudness) by a given factor float (private case of Transform application)
  • Transform*Transform: chaining Transforms so that they can be later applied to a Signal together
  • (Rare) Signal | BiTransform | Signal: this is for a specialized kind of Transform, that operates on two Signals. So far this is only used for Cross-Fades (TODO cover somewhere)

Slicing Channels and Time

Gensound uses syntax similar to the indexing system in NumPy. For a given Signal we may choose a certain set of channels, and a certain time span. Since time durations and time positions are interpreted differently according to whether they are int or float, some care needs to be taken.

  • Signal[start_channel:end_channel,start_ms:end_ms]: Signal sliced to a certain range of channels and time (in ms). The first slice expects integers; the second expects floats.
  • Signal[start_channel:end_channel,start_sample:end_sample]: When the second slice finds integers instead of floats, it is interpreted as a range over samples instead of milliseconds. Note that the duration of this Signal changes according to the sample rate.
  • Signal[start_channel:end_channel]: when a single slice of ints is given, it is taken to mean the channels.
  • Signal[start_ms:end_ms]: if the slice is made up of floats, it is interpreted as timestamps, i.e.: Signal[:,start_ms:end_ms].

In short, when indexing with floats, Gensound knows we are talking about time positions. When indexing with ints, we may mean either the channels or sample numbers (or both); sample numbers will always be preceded by the channels, as otherwise Gensound has no way to tell.