Merging, concatenating, and repeating objects#
thebeat contains a number of functions for manipulating existing objects. These are useful when combining different types of sequences, or when creating complex sound stimuli.
Before we begin, we import the used object classes:
[27]:
from thebeat.core import Sequence, SoundStimulus, SoundSequence
from thebeat.music import Rhythm
Concatenating objects#
We can elongate and combine Sequence
, Rhythm
, SoundStimulus
and SoundSequence
objects, simply by using an asterisk to multiply, or a plus-sign to concatenate.
Note that Sequence
and SoundSequence
objects must end with an interval. Otherwise, we do not know what interval to place between the offset of the final event in the first sequence and the onset of the first event in the next sequence. Consider the example below in which we multiply a Sequence
object 10 times.
Sequence
#
[29]:
# Initial sequence
seq = Sequence.generate_random_normal(n_events=10,
mu=500,
sigma=50,
end_with_interval=True)
seq.plot_sequence();
# Repeat sequence 10 times and plot
seq_longrepeats = seq * 10
seq_longrepeats.plot_sequence();
Rhythm
#
For Rhythm
objects we can do the exact same manipulations. But let’s now try to add two together instead of multiplying them by a number.
[30]:
rhythm1 = Rhythm.from_integer_ratios([1, 1, 2])
rhythm2 = Rhythm.from_integer_ratios([2, 1, 1])
rhythm = rhythm1 + rhythm2
rhythm.plot_rhythm(dpi=600, staff_type="percussion");
SoundStimulus
#
SoundStimulus
objects can be concatenated in much the same way:
[31]:
sound1 = SoundStimulus.generate(freq=100, duration_ms=100)
sound2 = SoundStimulus.generate(freq=400, duration_ms=100)
sound = sound1 + sound2
sound.plot_waveform();
SoundSequence
#
As a final example, we will combine two SoundSequence objects:
[32]:
stim = SoundStimulus.generate()
seq1 = Sequence.generate_random_normal(n_events=5, mu=500, sigma=20, end_with_interval=True)
seq2 = Sequence.generate_random_normal(n_events=5, mu=500, sigma=20, end_with_interval=True)
stimseq1 = SoundSequence(stim, seq1)
stimseq2 = SoundSequence(stim, seq2)
trial = stimseq1 + stimseq2
trial.plot_waveform();
Merging objects#
Rather than concatenating objects, we can also merge (overlay) them. There are two ways of doing this. Either we use an object’s .merge()
method, and pass another object as the first argument. Alternatively, we can use the ‘merge’ functions from thebeat.utils
.
Sequence
#
When we merge two Sequence
objects we get a combination between the two. Consider the following code:
[33]:
seq1 = Sequence.from_onsets([0, 500, 1000, 1500])
seq2 = Sequence.from_onsets([250, 750, 1250, 1750])
# Method 1
seq = seq1.merge(seq2)
# Method 2
from thebeat.utils import merge_sequences
seq = merge_sequences([seq1, seq2])
# Plot
seq.plot_sequence();
SoundStimulus
: complex sounds#
We can merge multiple SoundStimulus
objects to create complex sounds. When we merge, the sounds are overlaid and normalized. Below, we combine a sine wave sound of 440Hz, and its first harmonic, which is 880Hz.
[34]:
stim_f0 = SoundStimulus.generate(freq=440, duration_ms=100)
stim_f1 = SoundStimulus.generate(freq=880, duration_ms=100)
# Method 1
stim = stim_f0.merge(stim_f1)
# Method 2
from thebeat.utils import merge_soundstimuli
stim = merge_soundstimuli([stim_f0, stim_f1])
# Plot
stim.plot_waveform();
SoundSequence
#
Finally, we can merge SoundSequence
objects as well:
[35]:
ss1 = SoundSequence(stim_f0, seq1)
ss2 = SoundSequence(stim_f1, seq2)
# Method 1
ss = ss1.merge(ss2)
# Method 2
from thebeat.utils import merge_soundsequences
ss = merge_soundsequences([ss1, ss2])
#ss.play()
You can listen to the merged SoundSequence
below. In your IDE simply execute ss.play()
.