parent
82d67515fa
commit
433304ba7b
@ -0,0 +1,3 @@ |
|||||||
|
Hammond 1455Q1602BK |
||||||
|
|
||||||
|
https://www.conrad.de/de/p/hammond-electronics-1455q1602bk-1455q1602bk-profil-gehaeuse-163-x-120-5-x-51-5-aluminium-schwarz-1-st-443133.html?searchType=SearchRedirect |
@ -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,69 @@ |
|||||||
|
#include <Audio.h> |
||||||
|
#include "synth_dexed.h" |
||||||
|
|
||||||
|
uint8_t fmpiano_sysex[156] = { |
||||||
|
95, 29, 20, 50, 99, 95, 00, 00, 41, 00, 19, 00, 00, 03, 00, 06, 79, 00, 01, 00, 14, // OP6 eg_rate_1-4, level_1-4, kbd_lev_scl_brk_pt, kbd_lev_scl_lft_depth, kbd_lev_scl_rht_depth, kbd_lev_scl_lft_curve, kbd_lev_scl_rht_curve, kbd_rate_scaling, amp_mod_sensitivity, key_vel_sensitivity, operator_output_level, osc_mode, osc_freq_coarse, osc_freq_fine, osc_detune
|
||||||
|
95, 20, 20, 50, 99, 95, 00, 00, 00, 00, 00, 00, 00, 03, 00, 00, 99, 00, 01, 00, 00, // OP5
|
||||||
|
95, 29, 20, 50, 99, 95, 00, 00, 00, 00, 00, 00, 00, 03, 00, 06, 89, 00, 01, 00, 07, // OP4
|
||||||
|
95, 20, 20, 50, 99, 95, 00, 00, 00, 00, 00, 00, 00, 03, 00, 02, 99, 00, 01, 00, 07, // OP3
|
||||||
|
95, 50, 35, 78, 99, 75, 00, 00, 00, 00, 00, 00, 00, 03, 00, 07, 58, 00, 14, 00, 07, // OP2
|
||||||
|
96, 25, 25, 67, 99, 75, 00, 00, 00, 00, 00, 00, 00, 03, 00, 02, 99, 00, 01, 00, 10, // OP1
|
||||||
|
94, 67, 95, 60, 50, 50, 50, 50, // 4 * pitch EG rates, 4 * pitch EG level
|
||||||
|
04, 06, 00, // algorithm, feedback, osc sync
|
||||||
|
34, 33, 00, 00, 00, 04, // lfo speed, lfo delay, lfo pitch_mod_depth, lfo_amp_mod_depth, lfo_sync, lfo_waveform
|
||||||
|
03, 24, // pitch_mod_sensitivity, transpose
|
||||||
|
70, 77, 45, 80, 73, 65, 78, 79, 00, 00 // 10 * char for name ("DEFAULT ")
|
||||||
|
}; // FM-Piano
|
||||||
|
|
||||||
|
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() |
||||||
|
{ |
||||||
|
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
|
||||||
|
} |
||||||
|
|
||||||
|
void loop() |
||||||
|
{ |
||||||
|
static uint8_t count; |
||||||
|
|
||||||
|
if (count % 2 == 0) |
||||||
|
{ |
||||||
|
dexed.loadInitVoice(); |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
dexed.loadVoiceParameters(fmpiano_sysex); |
||||||
|
dexed.setTranspose(36); |
||||||
|
} |
||||||
|
|
||||||
|
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(2000); |
||||||
|
|
||||||
|
count++; |
||||||
|
} |
@ -0,0 +1,151 @@ |
|||||||
|
#!/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 |
||||||
|
// |
||||||
|
|
||||||
|
#pragma once |
||||||
|
""") |
||||||
|
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) |
||||||
|
patchname=str(data[118:128].decode('ascii')).upper().replace('\\','') |
||||||
|
print("\t\t{\t// %d: %s" % (v, patchname)) |
||||||
|
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