#---------------------------------------------------------------------- # Generation of pure sine tones # # Copyright (C) April 18, 2017 -- Dr. William T. Verts #---------------------------------------------------------------------- # From page 330 of the Companion. # # There are three questions that must be answered when processing # or generating sounds digitally: # # Question #1: How many independent channels? # (1 for mono or 2 for stereo, JES defaults to 1) # # Question #2: How good is each sample? # (1 or 2 bytes/sample, JES defaults to 2) # # 1 byte/sample: Values range from -128...+127 # (256 levels, OK for voice) # # 2 bytes/sample: Values range from -32768...+32767 # (65536 levels, OK for music) # # Question #3: How many samples/second/channel do we need? # # 3A: What is the highest frequency humans can hear? # 22000 Hz (cycles/second) or 22KHz # # 3B: How does frequency relate to samples/second? # Nyquist's Sampling Theorem: # to reproduce a signal, sample > 2X # the highest desired frequency. # # For CDs: # (2 channels) * (2 bytes/sample) * (44100 samples/second/channel) = # 176400 bytes/second # # We will then use 44100 as our default sampling rate. We could make # it smaller if we chose. # # JES function makeEmptySoundBySeconds requires an integer number # of seconds. To make this a float, we have to manually compute the # number of needed samples using the number of seconds, the sampling # rate, and JES function makeEmptySound. #---------------------------------------------------------------------- def SineWave (Frequency, Seconds, Volume=32767.0, SamplingRate=44100): # MySound = makeEmptySoundBySeconds(int(Seconds), SamplingRate) MySound = makeEmptySound(int(Seconds*SamplingRate), SamplingRate) TotalSamples = getNumSamples(MySound) RadiansPerSample = (2.0 * pi) * Frequency / SamplingRate for MySample in range(TotalSamples): Angle = MySample * RadiansPerSample setSampleValueAt(MySound, MySample, int(Volume * sin(Angle))) return MySound #---------------------------------------------------------------------- # Play the 5-tone sequence from "Close Encounters of the Third Kind". # JES function blockingPlay will only play one sound at a time. # If we used the JES play function instead, all sounds would play # simultaneously. #---------------------------------------------------------------------- def CloseEncounters (): for F in [882, 990, 786, 393, 588]: blockingPlay(SineWave(F, 0.5)) return