Page 1 of 1

Yamaha DM1000 odd variable ranges

Posted: 14 Apr 2012 12:49
by pngaudioguy
So I've got a script that's working great to send sysex to my DM1000 to control various things. Items that fall within the range of 0-127 are relatively simple. Once the word becomes too large for one bit, I just can't wrap my head around it. They've used a bunch of odd ranges for parameters. Here's the one I'm struggling with. If I can grasp this, I'm pretty sure I can figure the other ranges out.

The component being controlled is the channel compressor threshold. Value range is -540 to 0, correlating to -54dB to 0dB.
This is what I've come up with based on posts here to others' questions and digging through templates that gets it really, really close:

Code: Select all

decl val,dd1,dd2;
if(Threshold.msg_rcvd==0) {
  val=round(range(Threshold.x,0,540));
  if(val<=539){
    dd1={0x7F}; dd2={0x7F};
  } else if(val==540) {
    dd1={0x00}; dd2={0x00};
  }
  send_sysex({sys_comp_hdr,sys_comp_thresh,sysex_channel,dd1,dd2,(floor(Threshold.x*512)>>7)+124&0X7F, floor(Threshold.x*512) & 0x7F});
} else {
  Threshold.msg_rcvd=0; 
}
The problem there, is that it never reaches 540 (in sysex land {0x7F, 0x7F}.) The other problem is that it starts at {0x7C, 0x00} when I actually need it to start at {0x7B, 0x63} since it's a range of 540 decimal digits down from {0x7F, 0x7F} as opposed to up.

Anybody feel like helping guide me through this oddity? I'm intentionally rolling all the values over to 0x00 when x=1, because that's what the mixer sends back when I scroll through the values and watch the sysex coming in. I'm guessing this is some kind of internal "off" signal it sends to itself.

Thanks in advance!

Re: Yamaha DM1000 odd variable ranges

Posted: 16 Apr 2012 17:58
by pngaudioguy
I figured out some code that produces perfect results, but is far from clean! I'd love to find a much more efficient mathematical method as opposed to a table of ifs.

Code: Select all

decl val;
decl last=sizeof(sys_msg)-1;
sys_msg=fill(1,{0x7F},last);

if(Threshold.msg_rcvd==0) {
  val=round(range(Threshold.x,0,540));
  if(val<=28) {
    sys_msg[last-1]=123; sys_msg[last]=val+99;
  }
else if(val>=29 && val<=156) {
    sys_msg[last-1]=124; sys_msg[last]=val-29;
  }
else if(val>=157 && val<=284) {
    sys_msg[last-1]=125; sys_msg[last]=val-157;
  }
else if(val>=285 && val<=412) {
    sys_msg[last-1]=126; sys_msg[last]=val-285;
  }
else if(val>=413 && val<=539) {
    sys_msg[last-1]=127; sys_msg[last]=val-413;
  } else if(val==540) {
    sys_msg=fill(1,{0x00},last+1);
  }
send_sysex({sys_comp_hdr,sys_comp_thresh,sys_channel,sys_msg});
} else {
  Threshold.msg_rcvd=0;
}
The more I think about it, I'm pretty sure it has to do with subtracting the value from 1024, as opposed to adding to the base. I'll rework it from that angle and see what I can arrive at.

Re: Yamaha DM1000 odd variable ranges

Posted: 16 Apr 2012 20:32
by pngaudioguy
Found a working solution that I'm much happier with. Still would prefer to eliminate the if's at the top and go straight to the formula, but this is far better than the last solution!
I'm building my template to work with two different consoles which have different message lengths for the data, hence the extra bits about sizeof and all that.

Code: Select all

decl val,tmp;
if(x<1) sys_msg=fill(1,{0x7F},sizeof(sys_msg)-2);
if(x==1) sys_msg=fill(1,{0x00},sizeof(sys_msg)-2);

if(Threshold.msg_rcvd==0) {
  val=pow(2,14)+round(range(Threshold.x,-540,0));
  sys_msg={{sys_msg},floor(val)>>7&0x7F,floor(val)&0x7F};
  send_sysex({sys_comp_hdr,sys_comp_thresh,sys_channel,sys_msg});
} else {
  Threshold.msg_rcvd=0;
}

Re: Yamaha DM1000 odd variable ranges

Posted: 17 Apr 2012 03:10
by Macciza
Hi
I did have a bit of look at the DM1000 manual on the net though it does not really provide the necessary info that I could see.
I am guessing you have the parameter number data etc to form your messages
They really should have some info somewhere about how they are formatting the individual data ranges.
Some synths use 14bit signed 2's complement numbers for negative values and nibble-the values which is what your doing there by the looks of it so you've probably nailed it there.
It is always difficult when one does not have all the tech data available.
Cheers
MM

Re: Yamaha DM1000 odd variable ranges

Posted: 18 Apr 2012 13:09
by pngaudioguy
So here's the code I finally settled on. I wasn't happy with the first few bytes rolling over at a different time than the rest of the numbers, so moved the if's. I'm sure this isn't kosher in some book somewhere, but it spits out exactly the string I need to move the parameter. If you've found this thread via a search, the following code will work to control a DM1000 and LS9 threshold. You also have to define the variables, and actually send the data through a user defined send_sysex script, but the sys_msg data string portion is what I'm referring to working here.

Code: Select all

decl val=pow(2,21)+round(range(x,-540,0));

if(Threshold.msg_rcvd==0) {
  if(sizeof(sys_msg)==4) {
    sys_msg={floor(val)>>14&0x7F,floor(val)>>14&0x7F,floor(val)>>7&0x7F,floor(val)&0x7F};
  } else if(sizeof(sys_msg)==5) {
    sys_msg={floor(val)>>14&0x7F,floor(val)>>14&0x7F,floor(val)>>14&0x7F,floor(val)>>7&0x7F,floor(val)&0x7F};
  }
  send_sysex({sys_comp_hdr,sys_comp_thresh,sys_channel,sys_msg});
} else {
  Threshold.msg_rcvd=0;
}
I suspect I can just ignore all the preceding digits when I bring it back from the console with my sysexin script, but need to figure out how to reverse the bitwise operations now. If anyone feels like saving me from several days of formula agony, I'd be much obliged. I'm discovering that this whole bitwise thing takes awhile to grasp.

Re: Yamaha DM1000 odd variable ranges

Posted: 18 Apr 2012 15:02
by pngaudioguy
I set up a little test window with a fader (providing x), a text box (Text), and a monitor (return), and started to fiddle. This is the on expression, x, any script for the fader which seems to convert back to the correct number right up until it hits 0, at which point I'm subtracting 16384 from 0 and so instead of stepping -2,-1,0, it steps -2,-1,-16384.

I worked around this by setting a simple if statement to find out if the value exists, subtracting 16384 if it does, and setting to 0 if it does not. Naturally, to make this useful to the knob on my interface, I'll have to add 540 to make a positive range, and divide by 540 to create a 0-1 range. Is this right, or is there a better way to solve the zero transition?

Code: Select all

decl val, msg, test;
val=pow(2,21)+round(range(x,-540,0));
msg={floor(val)>>14&0x7F,floor(val)>>7&0x7F,floor(val)&0x7F};
setattribute(Text,'content',lemur_tools.arraytohex(msg));
test=(128*msg[1]+msg[2]);
if(test) return.value=test-16384;
else return.value=0;

Final Followup from me - send and receive scripts

Posted: 14 May 2012 12:49
by pngaudioguy
Just realized that a month has gone by and I never got around to posting a follow up on here. Here are the final scripts that work great.

Code for the knob to send data to the console.
msg_rcvd is set to 0 on load at the object level (Threshold).
sys_msg is a global variable, empty until defined.
sys_comp_hdr and sys_comp_thresh are defined globally to match the board's string.
sys_channel is defined by selecting a channel on the interface.
send_sysex is a script that appends header and EOF info, then sends it to midiout 0.

Code: Select all

if(Threshold.msg_rcvd==0) {
  decl val=pow(2,21)+round(range(x,-540,0));
  sys_msg={floor(val)>>14&0x7F,floor(val)>>14&0x7F,floor(val)>>7&0x7F,floor(val)&0x7F};
  send_sysex({sys_comp_hdr,sys_comp_thresh,sys_channel,sys_msg});
} else {
  Threshold.msg_rcvd=0;
}
The following makes it so that when you move the control on the console, the appropriate control on the Lemur interface tracks it. Naturally, this is a script with an On MIDI action, F0 (sysex), and the MIDI channel in use. This is just an excerpt from the script to control the compression focusing on the difficult portion.

I borrowed the lemur_tools container from user bxsj's project here: http://liine.net/forum/viewtopic.php?f= ... ynth#p5122. Very useful arraycomp and arraytohex functions. Thank you.

Code: Select all

if(MIDI_ARGS[7]=={sys_channel}) {
if(lemur_tools.arraycomp(subarray(MIDI_ARGS,0,6),{{sysexhdr},{sys_comp_hdr}})) { 
    decl msb=sizeof(MIDI_ARGS)-2;
    decl tmp={MIDI_ARGS[msb-1],MIDI_ARGS[msb]};
    if(MIDI_ARGS[6]==sys_comp_thresh) {
      decl n=((128*tmp[0]+tmp[1])-15844)/540;
      Threshold.x=clamp(n,0,1);
      Threshold.msg_rcvd=1;
    }
  }
}