parent
758ef64788
commit
a91798ed9f
@ -0,0 +1,65 @@ |
|||||||
|
#include <Audio.h> |
||||||
|
#include "synth_dexed.h" |
||||||
|
#include "banks.h" |
||||||
|
|
||||||
|
AudioSynthDexed dexed(4, SAMPLE_RATE); // 4 voices max
|
||||||
|
AudioOutputI2S i2s1; |
||||||
|
AudioControlSGTL5000 sgtl5000_1; |
||||||
|
AudioConnection patchCord1(dexed, 0, i2s1, 0); |
||||||
|
AudioConnection patchCord2(dexed, 0, i2s1, 1); |
||||||
|
|
||||||
|
void setup() |
||||||
|
{ |
||||||
|
Serial.begin(230400); |
||||||
|
|
||||||
|
AudioMemory(32); |
||||||
|
|
||||||
|
sgtl5000_1.enable(); |
||||||
|
sgtl5000_1.lineOutLevel(29); |
||||||
|
sgtl5000_1.dacVolumeRamp(); |
||||||
|
sgtl5000_1.dacVolume(1.0); |
||||||
|
sgtl5000_1.unmuteHeadphone(); |
||||||
|
sgtl5000_1.unmuteLineout(); |
||||||
|
sgtl5000_1.volume(0.8, 0.8); // Headphone volume
|
||||||
|
|
||||||
|
randomSeed(analogRead(0)); |
||||||
|
} |
||||||
|
|
||||||
|
void loop() |
||||||
|
{ |
||||||
|
uint8_t b = random(0, 10); |
||||||
|
uint8_t v = random(0, 32); |
||||||
|
uint8_t t = random(0, 36); |
||||||
|
char voice_name[11]; |
||||||
|
uint8_t decoded_voice[156]; |
||||||
|
|
||||||
|
memset(voice_name, 0, 11); |
||||||
|
memcpy(voice_name, &progmem_bank[b][v][117], 10); |
||||||
|
|
||||||
|
Serial.print("Voice: "); |
||||||
|
Serial.print(voice_name); |
||||||
|
Serial.print(" "); |
||||||
|
Serial.print("Transpose: "); |
||||||
|
Serial.println(t); |
||||||
|
|
||||||
|
dexed.decodeVoice(progmem_bank[b][v],decoded_voice);
|
||||||
|
dexed.loadVoiceParameters(decoded_voice); |
||||||
|
dexed.setTranspose(t); |
||||||
|
|
||||||
|
Serial.println("Key-Down"); |
||||||
|
dexed.keydown(48, 100); |
||||||
|
delay(100); |
||||||
|
dexed.keydown(52, 100); |
||||||
|
delay(100); |
||||||
|
dexed.keydown(55, 100); |
||||||
|
delay(100); |
||||||
|
dexed.keydown(60, 100); |
||||||
|
delay(2000); |
||||||
|
|
||||||
|
Serial.println("Key-Up"); |
||||||
|
dexed.keyup(48); |
||||||
|
dexed.keyup(52); |
||||||
|
dexed.keyup(55); |
||||||
|
dexed.keyup(60); |
||||||
|
delay(1000); |
||||||
|
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,148 @@ |
|||||||
|
#!/usr/bin/python3 |
||||||
|
|
||||||
|
import sys |
||||||
|
import os.path |
||||||
|
|
||||||
|
# From: https://github.com/bwhitman/learnfm/blob/master/dx7db.py |
||||||
|
def unpack_packed_patch(p): |
||||||
|
# Input is a 128 byte thing from compact.bin |
||||||
|
# Output is a 156 byte thing that the synth knows about |
||||||
|
o = [0]*156 |
||||||
|
for op in range(6): |
||||||
|
o[op*21:op*21 + 11] = p[op*17:op*17+11] |
||||||
|
leftrightcurves = p[op*17+11] |
||||||
|
o[op * 21 + 11] = leftrightcurves & 3 |
||||||
|
o[op * 21 + 12] = (leftrightcurves >> 2) & 3 |
||||||
|
detune_rs = p[op * 17 + 12] |
||||||
|
o[op * 21 + 13] = detune_rs & 7 |
||||||
|
o[op * 21 + 20] = detune_rs >> 3 |
||||||
|
kvs_ams = p[op * 17 + 13] |
||||||
|
o[op * 21 + 14] = kvs_ams & 3 |
||||||
|
o[op * 21 + 15] = kvs_ams >> 2 |
||||||
|
o[op * 21 + 16] = p[op * 17 + 14] |
||||||
|
fcoarse_mode = p[op * 17 + 15] |
||||||
|
o[op * 21 + 17] = fcoarse_mode & 1 |
||||||
|
o[op * 21 + 18] = fcoarse_mode >> 1 |
||||||
|
o[op * 21 + 19] = p[op * 17 + 16] |
||||||
|
|
||||||
|
o[126:126+9] = p[102:102+9] |
||||||
|
oks_fb = p[111] |
||||||
|
o[135] = oks_fb & 7 |
||||||
|
o[136] = oks_fb >> 3 |
||||||
|
o[137:137+4] = p[112:112+4] |
||||||
|
lpms_lfw_lks = p[116] |
||||||
|
o[141] = lpms_lfw_lks & 1 |
||||||
|
o[142] = (lpms_lfw_lks >> 1) & 7 |
||||||
|
o[143] = lpms_lfw_lks >> 4 |
||||||
|
o[144:144+11] = p[117:117+11] |
||||||
|
o[155] = 0x3f |
||||||
|
|
||||||
|
# Clamp the unpacked patches to a known max. |
||||||
|
maxes = [ |
||||||
|
99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, # osc6 |
||||||
|
3, 3, 7, 3, 7, 99, 1, 31, 99, 14, |
||||||
|
99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, # osc5 |
||||||
|
3, 3, 7, 3, 7, 99, 1, 31, 99, 14, |
||||||
|
99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, # osc4 |
||||||
|
3, 3, 7, 3, 7, 99, 1, 31, 99, 14, |
||||||
|
99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, # osc3 |
||||||
|
3, 3, 7, 3, 7, 99, 1, 31, 99, 14, |
||||||
|
99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, # osc2 |
||||||
|
3, 3, 7, 3, 7, 99, 1, 31, 99, 14, |
||||||
|
99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, # osc1 |
||||||
|
3, 3, 7, 3, 7, 99, 1, 31, 99, 14, |
||||||
|
99, 99, 99, 99, 99, 99, 99, 99, # pitch eg rate & level |
||||||
|
31, 7, 1, 99, 99, 99, 99, 1, 5, 7, 48, # algorithm etc |
||||||
|
126, 126, 126, 126, 126, 126, 126, 126, 126, 126, # name |
||||||
|
127 # operator on/off |
||||||
|
] |
||||||
|
for i in range(156): |
||||||
|
if(o[i] > maxes[i]): o[i] = maxes[i] |
||||||
|
if(o[i] < 0): o[i] = 0 |
||||||
|
return o |
||||||
|
|
||||||
|
def print_header_data(voice_data): |
||||||
|
print("\t\t\t",end="") |
||||||
|
for y in range(0,len(voice_data)): |
||||||
|
if(y!=len(voice_data)-1): |
||||||
|
print("%3d, " % voice_data[y],end="") |
||||||
|
else: |
||||||
|
print("%3d\n" % voice_data[y],end="") |
||||||
|
if((y+1)%8==0 and y!=len(voice_data)-1): |
||||||
|
print("\n\t\t\t",end="") |
||||||
|
|
||||||
|
def help_message(): |
||||||
|
print(progname+" [--decode] <sysex1> [<sysex2> ... <sysexn>]") |
||||||
|
|
||||||
|
#--------------------------------------------------------------------------- |
||||||
|
|
||||||
|
progname=sys.argv.pop(0) |
||||||
|
if(len(sys.argv)==0): |
||||||
|
help_message() |
||||||
|
exit(1) |
||||||
|
if(sys.argv[0]=="-h" or sys.argv[0]=="--help"): |
||||||
|
help_message() |
||||||
|
exit(1) |
||||||
|
if(sys.argv[0]=="--decode"): |
||||||
|
decode=True |
||||||
|
sys.argv.pop(0) |
||||||
|
else: |
||||||
|
decode=False |
||||||
|
|
||||||
|
print(""" |
||||||
|
// |
||||||
|
// File generated with sysex2c.py |
||||||
|
// |
||||||
|
""") |
||||||
|
if(decode==True): |
||||||
|
print("uint8_t progmem_bank[%d][32][156] PROGMEM =\n{" % int(len(sys.argv))) |
||||||
|
else: |
||||||
|
print("uint8_t progmem_bank[%d][32][128] PROGMEM =\n{" % int(len(sys.argv))) |
||||||
|
for sysex in sys.argv: |
||||||
|
if(not os.path.isfile(sysex)): |
||||||
|
print("* File "+sysex+" does not exists.") |
||||||
|
exit(10) |
||||||
|
if(not os.access(sysex,os.R_OK)): |
||||||
|
print("* File "+sysex+" does not readable.") |
||||||
|
exit(11) |
||||||
|
print("\t{\t// %s" % os.path.basename(sysex)) |
||||||
|
with open(sysex, "rb") as f: |
||||||
|
header = f.read(6) |
||||||
|
if(header[0]!=240): |
||||||
|
print("* %s: Start of sysex not found." % sysex) |
||||||
|
exit(200) |
||||||
|
if(header[1]!=67): |
||||||
|
print("* %s: Manufactorer-ID not Yamaha." % sysex) |
||||||
|
exit(201) |
||||||
|
if(header[3]!=9): |
||||||
|
print("* %s: Not a 32 voice sysex file." % sysex) |
||||||
|
exit(202) |
||||||
|
byte_count = header[4]*128+header[5] |
||||||
|
if(byte_count!=4096): |
||||||
|
print("* %s: Byte count mismatch." % sysex) |
||||||
|
exit(203) |
||||||
|
patch_data=f.read(4096) |
||||||
|
check = ~sum(patch_data) + 1 & 0x7F |
||||||
|
f.seek(4102) # Bulk checksum |
||||||
|
checksum=int.from_bytes(f.read(1),"little") |
||||||
|
if(check!=checksum): |
||||||
|
print("* %s: Checksum mismatch!" % sysex) |
||||||
|
exit(204) |
||||||
|
f.seek(6) |
||||||
|
|
||||||
|
for v in range(1,33): |
||||||
|
data=f.read(128) |
||||||
|
print("\t\t{\t// %d: %s" % (v, data[118:128].decode('ascii'))) |
||||||
|
if(decode==True): |
||||||
|
print_header_data(unpack_packed_patch(data)) |
||||||
|
else: |
||||||
|
print_header_data(data) |
||||||
|
if(v!=32): |
||||||
|
print("\t\t},") |
||||||
|
else: |
||||||
|
print("\t\t}") |
||||||
|
if(sys.argv[len(sys.argv)-1]==sysex): |
||||||
|
print("\t}") |
||||||
|
else: |
||||||
|
print("\t},") |
||||||
|
print("};") |
Loading…
Reference in new issue