## Spring 09, Project 1: Specification of Required Functions

This section gives the specifications for the functions you are required to implement. The name and parameters of each function should not be changed. While the specifications may look long, they will take a lot of code to implement. Be sure to understand and follow the conventions given next.

## Conventions

The conventions below are used to define the functions in the specification.

For functions that modify a single array of sample data, the data parameter is always passed first. Next any parameters that indicate quantities such as amplitude, duration, or frequency are listed. If a sampler function is required, it is always the last parameter and is optional (the default is to use a sine wave).

### Parameter Names

• data - Corresponds to an array of input data containing samples.
• amp - Corresponds to amplitude for waves. Amplitude should always be between 0 and 1, inclusive.
• dur - Duration in seconds.
• sampler - Function to be used to generate input samples.

In most cases, parameters that indicate a quantity are taken to be percentages, unless specifically noted otherwise or the parameter refers to a duration. For example, the amplitude refers to the percent of the maximum allowable amplitude.

### Constants

• WAVE_MAX - The maximum allowable value of a single sample. Set to 32767.
• WAVE_MIN - The minimum allowable value of a single sample. Set to -32768.
• SAMPLE_FREQUENCY - The sampling frequency, in Hertz. Set to 22050.

### Useful array and other functions

```zeros(n) - return an array of n zeros
empty(n) - create an empty (uninitialized) array
array(l) - construct an array from a list
append(a,b) - append array b to a and return the result
xrange(stop) - similar to range, but faster```
```max(a) # returns the largest element of a
min(a) # returns the smallest element of a
abs(x) # returns the absolute value of x```

### Function Specifications

scale_volume(data, factor)

This function takes digital audio in array data and scales it by the value factor. To accomplish this scaling, every element of the array data is multiplied by factor. This multiplication increases or decreases the volume of the wave (corresponding to factors greater than 1 or less than 1, respectively) and may result in values that are out of range. Values out of range need to be clipped:

• If a scaled sample is greater than WAVE_MAX, set it to WAVE_MAX
• If a scaled sample is less than WAVE_MIN, set it to WAVE_MIN

Note that that factor may have a floating point value (e.g. 0.5) and thus the resulting new value may not be an integer, as needed. Use the built-in `int` function, which converts a float to an int by truncating decimal places. For illustration:

```x = 3.5
print x,int(x)```

prints:

`3.5 3`

normalize(data)

This function maximizes the possible volume of the sound given in array data. This operation is similar to scale_volume() except that now the value of parameter factor is to be determined in such a way that the volume is maximized and no clipping is needed after scaling. You need to address the special case where all samples are 0.

sin_sample(freq, amp, dur)

This function returns a sine wave with frequency freq, amplitude amp, and duration dur (in seconds).

The amplitude should be specified with a range of 0 to 1 where 1 represents the maximum amplitude. To obtain the actual amplitude in the sample use the WAVE_MAX value to scale it to an appropriate value.

half_speed(data)

This function takes an array of sample data and returns a new array containing the same sound, but at half of the original speed. Naively, this is accomplished by duplicating each sample, effectively halving the sampling frequency at which the sound is played back.

That is, if the original sound is [x1,x2,x3,x4], then the half_speed sound would be [x1,x1,x2,x2,x3,x3,x4,x4].

echo(data, delay, level)

This function takes as parameters a sound array data, a delay in seconds, and an echo level and it returns a new sound array. The generated array will be longer than array data.

Remember that the delay given in seconds is to be translated into SAMPLE_FREQUENCY*delay samples (i.e., array locations). The level is a value between 0 and 1. The level indicates the intensity of the echo in proportion to the original sound; i.e., the original wave is scaled by a factor of (1 - level).

To create an echo effect, consider the original wave and a copy of the wave. Now, shift the second wave forward by the number of seconds specified in variable delay. The two waves are then combined using the following weighting:

`result = (1-level)*orig_sample + level*echo_sample`

The pieces of the waves that do not overlap are matched by silence (0-valued samples). This technique produces a wave that has the sound of both the wave and the wave shifted by some amount of time, an echo. Generally, the echo is quieter than the original sound (level < .5), but that's not required.

NOTE: Remember that delay may be a floating point number, so it is important to make sure that when calculating the number of samples in the delay that the result is an integer.

combine_mean(list_of_sounds)

This function takes a list consisting of sound files (i.e., a list of arrays) and combines them into a single sound. All sound files must have the same length. The function returns the created sound in a new array (same size).

To calculate the combined sound, take the sum of each wave sample divided by the number of wave samples (i.e., compute the mean).

combine_interleave(list_of_sounds)

This function takes a list of waves that may have different lengths. The resulting wave takes samples from the waves at identical positions and interleaves them. For example:

```  [[x1,x2,x3,x4], [y1,y2,y3], [z1,z2,z3,z4,z5]] =>
[x1,y1,z1,x2,y2,z2,x3,y3,z3]```

The resulting wave's length is equal to the length of the shortest wave multiplied by the number of waves. That is, the waves are only interleaved so long as there are more samples left in all waves.

silence(dur)

Return an array consisting of dur seconds of silence.        