Note: all mono → stereo functions should return a new array, rather than trying to work in-place.

**equal_scale(freq, amp, dur, sampler=sin_sample)**

Return an ascending chromatic scale starting on freq where each tone is dur seconds long. A short silence should be inserted between notes. The function sampler may optionally be passed into the function to determine which waveform should be used (if none is passed, sin_sample you wrote earlier is used).

A chromatic scale is a 12-tone scale. In equal temperament, each note is equally spaced up the octave. An octave is reached when the frequency doubles. It follows, then, that the i-th note of the scaled is

f(i) = freq*2^(i/12)

Note that, despite being a 12-tone scale, the last note is a repeat of the first, but an octave higher. So, in total there will be 13 tones.

**ring_modulate(s1, s2)**

This function takes two waves and computes their ring modulation. The ring modulation is the product of the two input waves.

In order to calculate the ring modulation of the given waves, each wave is first scaled so that the samples range from 0 to 1. Each pair of corresponding sample is multiplied, and then scaled back to the original range of values (hint: use WAVE_MAX).

** fade_out(data, amount=.1) **

This function takes in an array of samples and implements a fading out effect over the last “amount” percent of the samples. The scaling function may be any decreasing curve, however a straightforward approach is to use a linear function. It may also be interesting to try this with an exponential function.

**repeat(data, count, scale_func=None)**

This function takes a signal data and repeats it count times. Note that count is the actual number of times the sound plays, so if count == 2, then the resulting wave has the original in it twice.

Optionally, a scaling function may be provided. If scale_function is provided, it should be a function that takes a sample number and returns a constant factor by which to scale that sample. Be careful about clipping if the scaling factor is greater than 1. The scaling includes the first instance of the wave.

If no scaling function is provided (i.e. scaling_func == None), then no scaling is applied, repeating simply the original values.

Examples of scaling functions include linear (i.e. could be something similar to fade_out), or cyclical (based on trig functions).

**sweep(mono_data, start)**

This function takes a mono signal and “sweeps” it linearly across the stereo spectrum. If start is 0, it should move left to right, and if it is 1, then right to left.

The pan should move evenly throughout the sound, using the sin/cos pan calculations shown in the stereo description.

**splatter(mono_data, count, duration)**

This function takes as input a mono wave. The wave is repeated count times, creating a wave that is duration seconds in length.

The repetitions happen at random intervals and may overlap. Each repetition should have a random pan and a random scaling factor from 0 to 1. The results are combined into a single wave.

For example, a single frog croak as input could be made to sound like a scene from a pond with frogs all around croaking.

This is the most challenging primitive, but arguably also has the most interesting results.

Example: