I'll try to upload the audio later... for now, the code below will generate diatonic scales in alternate third patterns (in tune) for several keys (as long as you keep the frequencies low on the keyboard!
The setup is straight-forward, just follow the pic... be careful to make sure the little negative stripe on the electrolytic cap goes to ground!
To run the code use:
Code: Select all
./concert_scale.sh 4 1 .2 .1
For some reason I don't understand yet, the PWM oscillators are noisy (irritatingly dirty) and at upper frequencies they aren't very precise... but down lower they're not bad for experimenting with sound; even with this unfiltered non amplified setup pictured.... a truly inexpensive and fun experiment !
edit: When I have used PWM in the past on the PI, I thought I would see small 'glitches' from time to time in the LEDs, or in the motors... well, they're there! You can hear them very clearly ... don't know what's going on, but I'm sure its the reason for the dirty sound quality in the stereo output of the composite video (if its based on the pwm, and I think it must be).
concert_scale.sh
Code: Select all
#!/usr/bin/python
#
# concert_scale.sh
#
# Mark H. Harris
# v.01.b
# 06-02-2016
#
## Import the necessary header modules
from time import sleep
from sys import argv
import RPi.GPIO as GPIO
## Setup the GPIO for PWM on pin12 {GPIO18}
GPIO.setmode(GPIO.BOARD)
GPIO.setup(12, GPIO.OUT)
p = GPIO.PWM(12, 220)
p.stop()
## Determine the intervals of the chromatic scale
chromatic=[]
ss = 2.0 ** (1.0 / 12)
ssc = 1
for n in range(36):
ssc*=ss
chromatic.append(ssc)
## Build list of diatonic intervals for chromatic indexing
base_offset=int(argv[1])
diatonic=[]
dia_index=[0,2,4,5,7,9,10,12,14,16,17,19,21,22,24]
for ndx in dia_index:
diatonic.append(ndx+base_offset)
## Build the concert diatonic scale 164.8=E
S_diatonic=[]
for note in diatonic:
S_diatonic.append(chromatic[note]*164.8)
## Build tune note index codex
h_tune = [3,5,4,6,5,7,6,4,5,3,4,2,3,3,3]
yankee = [3,3,4,5,3,5,4,0,3,3,4,5,3,3,2,2,3,3,4,5,6,5,4,3,2,0,1,2,3,3,3,3]
## Build tune3 ... up and down the half-scale in alternate thirds
tune3 = []
for xnote in h_tune:
tune3.append(S_diatonic[xnote])
## Build yankee doodle ...
doodle = []
for xnote in yankee:
doodle.append(S_diatonic[xnote])
## Define the 'scale playing' function
def scale(tune, register, duty, on_delay, rel_delay):
for note in tune:
p.ChangeFrequency(note*register)
p.start(duty)
sleep(on_delay)
p.stop()
sleep(rel_delay)
## Play the concert scale : scale(tune, 2, 1, 50, .2 .1 )
# command line: ./concert_scale.sh 2 1 .2 .1
#
scale(doodle, int(argv[2]), 50, float(argv[3]), float(argv[4]))
sleep(.7)
scale(tune3, int(argv[2]), 50, float(argv[3]), float(argv[4]))
sleep(.7)
## Cleanup the GPIO stuff...
GPIO.cleanup()