Table of Contents

Download this file moon.wav 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__': data = snd_io.read_wav_file('moon.wav') snd_utils.view_wav(data, 0, 500)

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

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.

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