# CS 190C LAB 4: Friday, February 6, 2009

## Demo Problems

### Visualizing an Audio File

Download this file and make sure it's called moon.wav instead of cs190c_moon.wav or anything else. Then, save the below code in a .py file in the same location you saved the moon.wav and run it.

```import snd_io
import snd_utils

if __name__ == '__main__':
snd_utils.view_wav(data, 0, 500)```

### Generating Audio Data

```def square_sample(freq, amp, dur):
"""
square_sample(freq, amp, dur)

This function returns a square wave with frequency freq, amplitude amp,
and duration dur (in seconds). The smplitude should be specified
with a range of 0 to 1 where 1 represents the maximal amplitude.

To obtain the actual amplitude in the sample use the WAVE_MAX value
to scale it to an appropriate value.

A square sample looks like this:
____      ____      __   amp*WAVE_MAX
|    |    |    |    |
0 --|----|----|----|----|--
__|    |____|    |____|    -amp*WAVE_MAX
"""
output = empty(dur*SAMPLE_FREQUENCY, dtype=numpy.int16)
factor = WAVE_MAX*amp
period = int(SAMPLE_FREQUENCY/freq)

for t in xrange(0,len(output)):
if t%period < (period/2):
output[t] = factor
else:
output[t] = -factor

return output```

## A Word of Warning with NumPy Arithmetic

When dealing with arrays, the numbers stored inside will have a bound on the maximum and minimum numbers it can hold. If you attempt to store a number in an array that is bigger than the maximum or smaller than the minimum, then it will “overflow” and generate a number that looks essentially like nonsense. This can be overcome by extracting the values you want to work with from the array, converting them back to Python's int type, and doing operations on those numbers instead.

```>>> import numpy
>>> a1 = numpy.array([200], dtype=numpy.int16)
>>> a2 = numpy.array([200], dtype=numpy.int16)
>>> n1, n2 = a1[0], a2[0]
>>> n1
200
>>> n2
200
>>> n1*n2
Warning: overflow encountered in short_scalars
-25536```

As you can see, we try to multiply 200 by 200 and store it in an array. The resulting number is -25536, which is clearly not the result of 200 * 200. This is because the maximum value of a 16-bit integer is `2**16 - 1 = 32767`. Instead, when dealing with values that might exceed the maximum allowed value, you could do something like this:

```>>> n1, n2 = int(n1), int(n2)
>>> n1
200
>>> n2
200
>>> n1*n2
40000```

At this point, since you know the product of the numbers exceeds 32767, you can perform the necessary operations to make it a logical value (like using 32767, the maximum), rather than allowing a “random” value of -25536 to be stored instead.

## In-Lab Problem

Write the required `sin_sample` function for the project. Work in pairs, but turn in your own code on Blackboard (don't have just your partner turn it in). The only file you need to submit is primitives.py.

```def sin_sample(freq, amp, dur):
"""
sin_sample(freq, amp, dur)

This function returns a sine wave with frequencey freq, amplitude amp,
and duration dur (in seconds). The smplitude should be specified
with a range of 0 to 1 where 1 represents the maximal amplitude.

To obtain the actual amplitude in the sample use the WAVE_MAX value
to scale it to an appropriate value.
"""
output = empty(int(dur*SAMPLE_FREQUENCY), dtype=numpy.int16)
factor = WAVE_MAX*amp

for t in xrange(0,len(output)):
output[t] = factor*math.sin(2*math.pi/SAMPLE_FREQUENCY*freq*t)

return output```

cs190c/lab4_09.txt · Last modified: 2009/02/11 10:00 by seh