Quick question. I think I want to make a few scales of my own for the ER101/2. What I was thinking of doing was creating a few that are in different keys so that effectively I could easily switch between say Pentatonic in E Minor to say, G Minor by simply changing the voltage table. I know I can do this using a precision adder outside of the ER101/2 but wanted to do as much as possible in the ER101/2.
So, am looking at the python script in the scales.zip file and see the following for Pentatonic Minor.
"Pentatonic Minor: 0, 0, 0, 3, 3, 5, 5, 7, 7, 7, 10, 10"
I think this creates the scale in C. I am guessing that if I add 4 to each number, subtract 12 when necessary and then rerun the script you’d get there. i.e.,
“Pentatonic E Minor: 2, 2, 4, 4, 4, 7, 7, 9, 9, 11, 11, 11”
Does this make sense?
Also, is there some logic to why some numbers are repeated twice, but others three times?
0 1 2 3 4 5 6 7 8 9 10 11
0 1 (2) 3 (4) 5 6 (7) 8 (9) 10 (11)
2 2 (2) 4 (4) 7 7 (7) 9 (9) 11 (11)
# This Python script converts the scales given in text format below
# to the ER-102's voltage table format.
import ctypes
# The following scales were provided by EAT@dnp-music
input_data = """
Chromatic: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
Major: 0, 0, 2, 2, 4, 5, 5, 7, 7, 9, 9, 11
Minor: 0, 0, 2, 3, 3, 5, 5, 7, 7, 8, 10, 10
Harmonic Minor: 0, 0, 2, 3, 3, 5, 5, 7, 7, 8, 11, 11
Melodic Minor: 0, 0, 2, 3, 3, 5, 5, 7, 7, 9, 11, 11
Pentatonic: 1, 1, 1, 3, 3, 6, 6, 6, 8, 8, 10, 10
Pentatonic Neutral: 0, 0, 2, 2, 2, 5, 5, 7, 7, 7, 10, 10
Pentatonic Minor: 0, 0, 0, 3, 3, 5, 5, 7, 7, 7, 10, 10
Pentatonic Major: 0, 0, 2, 2, 4, 4, 4, 7, 7, 9, 9, 9
Blues: 0, 0, 0, 3, 3, 5, 6, 7, 7, 7, 10, 10
Dorian: 0, 0, 2, 3, 3, 5, 5, 7, 7, 9, 10, 10
Mixolydian: 0, 0, 2, 2, 4, 5, 5, 7, 7, 9, 10, 10
Phrygian: 0, 1, 1, 3, 3, 5, 5, 7, 8, 8, 10, 10
Lydian: 0, 0, 2, 2, 4, 4, 6, 7, 7, 9, 9, 11
Locrian: 0, 1, 1, 3, 3, 5, 6, 6, 8, 8, 10, 10
Dim Half: 0, 1, 1, 3, 4, 4, 6, 7, 7, 9, 10, 10
Dim Whole: 0, 0, 2, 3, 3, 5, 6, 6, 8, 9, 9, 11
Augmented: 0, 0, 0, 3, 4, 4, 6, 6, 8, 8, 8, 11
Roumanian Minor: 0, 0, 2, 3, 3, 3, 6, 7, 7, 9, 10, 10
Spanish Gypsy: 0, 1, 1, 1, 4, 5, 5, 7, 8, 8, 10, 10
Diatonic: 0, 0, 2, 2, 4, 5, 5, 7, 7, 9, 9, 9
Double Harmonic: 0, 1, 1, 1, 4, 5, 5, 7, 8, 8, 8, 10
Eight Tone Spanish: 0, 1, 1, 3, 4, 5, 6, 6, 8, 8, 10, 10
Enigmatic: 0, 1, 1, 1, 4, 4, 6, 6, 8, 8, 10, 11
Algerian: 0, 0, 2, 3, 3, 5, 6, 7, 8, 8, 8, 11
Arabian A: 0, 0, 2, 3, 3, 5, 6, 6, 8, 9, 9, 11
Arabian B: 0, 0, 2, 2, 4, 5, 6, 6, 8, 8, 10, 10
Balinese: 0, 1, 1, 3, 3, 3, 7, 8, 8, 8, 8, 8
Byzantine: 0, 1, 1, 1, 4, 5, 5, 7, 8, 8, 8, 11
Chinese: 0, 0, 0, 0, 4, 4, 6, 7, 7, 7, 7, 11
Egyptian: 0, 0, 2, 2, 2, 5, 5, 7, 7, 7, 10, 10
Hindu: 0, 0, 2, 2, 4, 5, 5, 7, 8, 8, 10, 10
Hirajoshi: 0, 0, 2, 3, 3, 3, 3, 7, 8, 8, 8, 8
Hungarian Gypsy: 0, 0, 2, 3, 3, 3, 6, 7, 8, 8, 8, 11
H.Gypsy Persian: 0, 1, 1, 1, 4, 5, 5, 7, 8, 8, 8, 11
Japanese A: 0, 1, 1, 1, 1, 5, 5, 7, 8, 8, 8, 8
Japanese B: 0, 0, 2, 2, 2, 5, 5, 7, 8, 8, 8, 8
Persian: 0, 1, 1, 1, 4, 5, 6, 6, 8, 8, 8, 11
Prometheus: 0, 0, 2, 2, 4, 4, 6, 6, 6, 9, 10, 10
Six Tone Symetrical: 0, 1, 1, 1, 4, 5, 5, 5, 8, 9, 9, 9
Super Locrian: 0, 1, 1, 3, 4, 4, 6, 6, 8, 8, 10, 10
Wholetone: 0, 0, 2, 2, 4, 4, 6, 6, 8, 8, 10, 10
"""
def abbreviate(x):
"""
A small routine to automatically derive an abbreviation from the long name.
"""
try:
first,last = x.split(' ')
if len(last)>2:
return "%s%s"%(first[0],last[0:3])
elif len(last)==1:
return "%s%s"%(first[0:3],last[0])
else:
return first[0:4]
except:
return x[0:4]
def chromatic_to_voltage_table(degrees):
"""
Convert a list of chromatic scale degrees to a binary voltage table.
"""
# roll out the degrees to 100 entries
unrolled = [degrees[i%len(degrees)]+12*(i/12) for i in range(100)]
# create a list of codes for each semitone
codes = [int(round(x*8000/12.0)) for x in unrolled]
# do not exceed the max for unsigned shorts
codes = [x if x<(1<<16)-1 else (1<<16)-1 for x in codes]
# convert the python list to a binary array
table = (ctypes.c_uint16 * len(codes))(*codes)
return table
# parse the input data, line by line
for item in input_data.split('\n'):
if len(item)==0: continue
scale = item.split(':')
scale_name = scale[0]
scale_degrees = [int(x) for x in scale[1].split(',')]
scale_short_name = abbreviate(scale_name)
print scale_name, "-->", scale_short_name
print scale_degrees
table = chromatic_to_voltage_table(scale_degrees)
# Write the binary array out to a binary file.
# Note: The '-P' at the end of the filename indicates a pitched table and thus voltages
# will be shown as note values rather than numeric values.
with open(scale_short_name+"-P.BIN","wb") as f:
f.write(table)
f.close()
At the moment this seems to be a very manual process
Am wondering whether a bit of script could be used to take a CSV file that could be created in something like Excel and turn it into the binary array?
I found this code on GitHub that might do the trick
https://gist.github.com/jaywilliams/385876
Thoughts?
Sure I can write a quick python script that takes as input a CSV file and outputs a voltage table file (^_^)yMay I ask you to provide me with an example CSV file that shows how you would like to specifiy the voltage table contents?
--
You received this message because you are subscribed to a topic in the Google Groups "odevices" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/odevices/brTAp94g6OY/unsubscribe.
To unsubscribe from this group and all its topics, send an email to odevices+u...@googlegroups.com.
To post to this group, send email to odev...@googlegroups.com.
Visit this group at https://groups.google.com/group/odevices.
To view this discussion on the web visit https://groups.google.com/d/msgid/odevices/94007967-f788-477b-963f-6ac55847a2c3%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
This script converts a CSV file containing 2 columns (index and voltage) to the ER-102 voltage table format. Indices should extend from 0 to 99 and voltages should extend from 0 to 8.192. The output file name should follow the format XXXX-P.BIN for tables that should be displayed as pitches by default, otherwise use XXXX.BIN.
python csv-to-voltage-table.py -i <inputfile> -o <outputfile>
EXAMPLE:
python csv-to-voltage-table.py -i test.csv -o TEST-P.BIN
import ctypes
import csv
import sys
import getopt
def printHelp():
print "This script converts a CSV file containing 2 columns (index and voltage) to the ER-102 voltage table format. Indices should extend from 0 to 99 and voltages should extend from 0 to 8.192. The output file name should follow the format XXXX-P.BIN for tables that should be displayed as pitches by default, otherwise use XXXX.BIN."
print
print 'python csv-to-voltage-table.py -i <inputfile> -o <outputfile>'
print
print "EXAMPLE:"
print "python csv-to-voltage-table.py -i test.csv -o TEST-P.BIN"
print
def main(argv):
inputfile = None
outputfile = None
try:
opts, args = getopt.getopt(argv,"hi:o:",["ifile=","ofile="])
except getopt.GetoptError:
print 'csv-to-voltage-table.py -i <inputfile> -o <outputfile>'
sys.exit(2)
for opt, arg in opts:
if opt == '-h':
printHelp()
sys.exit()
elif opt in ("-i", "--ifile"):
inputfile = arg
elif opt in ("-o", "--ofile"):
outputfile = arg
if inputfile==None or outputfile==None:
print "Error: no input or output file specified."
print
printHelp()
sys.exit(2)
# default voltage table
voltages = [0]*100
# parse the CSV file
print "Reading:", inputfile
count = 0
with open(inputfile) as inputstream:
reader = csv.DictReader(inputstream)
for row in reader:
# change field names to lower case
row = {k.lower(): v for k, v in row.items()}
i = int(row["index"])
v = float(row["voltage"])
if i >= 0 and i < 100:
count = count + 1
voltages[i] = v
print "Parsed",count,"entries."
# output the voltage table as a flat binary array of unsigned shorts
codes = [int(round(x*8000)) for x in voltages]
# do not exceed the max for unsigned shorts
codes = [x if x<(1<<16)-1 else (1<<16)-1 for x in codes]
# convert the python list to a binary array
table = (ctypes.c_uint16 * len
(codes))(*codes)
print "Writing:", outputfile
with open(outputfile,"wb") as outputstream:
outputstream.write(table)
if __name__ == "__main__":
main(sys.argv[1:])
--
You received this message because you are subscribed to a topic in the Google Groups "odevices" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/odevices/brTAp94g6OY/unsubscribe.
To unsubscribe from this group and all its topics, send an email to odevices+u...@googlegroups.com.
To post to this group, send email to odev...@googlegroups.com.
Visit this group at https://groups.google.com/group/odevices.
To view this discussion on the web visit https://groups.google.com/d/msgid/odevices/b6f3bc70-2cd6-4f33-a664-611d3f091202%40googlegroups.com.
<csv-to-voltage-table.py>
<test.csv>