Hi,
I am new to Arduino and programming and I am trying to modify a sketch that initially required a short data type array. The modification I want to make to the sketch I believe, requires a long data type array.
The modification I need is to add an additional two channels to the sketch. Currently the sketch has 15 (1 for an accent track, 14 for drum keys).
I would need to make it 17 (1 for an accent track, 16 for drum keys). Making it 17 requires a larger data type, i.e. going from 16bit(short) to 32bit(long).
How would I modify this sketch to accommodate the additional two channels?
So far I have updated the following:
#define EUCL_TRACKS from 15 to 17
added two additional drum keys as needed
byte dkeys[]={0,36,37,38,39,42,45,46,48,49,50,51,54,56,69};
added two additional CCs as needed
byte dcontrol[]={96,97,102,103,104,105,106,107,108,109,110,111,112,113,114};
I believe the array that needs to be a long data type:
short drumloop[]={0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 };
Since 0-15 = 16bits, I have hit the max for this short datatype array.
What do I need to do to accommodate the 18bits (0-17) in the above array?
Currently when I run the sketch all the drum tracks respond EXCEPT the last one, meaning it is out of range. I really appreciate any support on figuring this out.
The sketch is below:
#include <RK002.h>
#define APP_NAME "16CH Euclidean Drums"
#define APP_AUTHOR "mmryspace"
#define APP_VERSION "0.1"
#define APP_GUID "78183b0f-f95a-45c8-9fc1-2d547664d541"
#define EUCL_TRACKS 17
/*
*
* This sketch plays a set of keys (preset to GM keys) via the Euclidean calculations.
*
* Euclidean rhythms are controllable in external play with CCs:
* 96,97,102,103,104,105,106,107,108,109,110,111,112,113,114
* CC 96 will control the euclidean velocity accent instead of triggering a key
*
* keynumbers triggered are: 36,37,38,39,42,45,46,48,49,50,51,54,56,69
*
* By default, if the sequencer is running, pressing a drum key will mute/unmute the pattern for that sound.
*
* ONLINE PARAMETERS:
* CHANNEL = MIDI channel on which the Euclid is operating
* LOOP = loop length of the euclid pattern.
* TEMPOTHRU = forward tempo/transport messages from RK002 in to out (def = on)
*
*/
RK002_DECLARE_INFO(APP_NAME,APP_AUTHOR,APP_VERSION,APP_GUID)
RK002_DECLARE_PARAM(CHANNEL,1,1,16,10)
RK002_DECLARE_PARAM(LOOP,1,1,32,16) // default value of 16 can be adjusted, e.g. to 32
RK002_DECLARE_PARAM(TEMPOTHRU,1,0,1,1)
// Keys for each channel, matched to the drum machine
// 0 -> not a drum key but is an accent track
byte dkeys[]={0,36,37,38,39,42,45,46,48,49,50,51,54,56,69};
// Euclid CCs for each channel, first one (96) is for the accent track
byte dcontrol[]={96,97,102,103,104,105,106,107,108,109,110,111,112,113,114};
// a series of 16bit numbers to hold the triggers
short drumloop[]={0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 };
short drum_active=0;
short muteChannel=0xffff;
short isPatterned=0;
byte dChannel=9;
byte seq_position=0;
bool drum_run=false;
byte ppqn=0;
//handler triggered on note on message:
bool RK002_onStop(){
drum_run=false;
if(RK002_paramGet(TEMPOTHRU)) return true;
return false;
}
bool RK002_onClock(){
advanceDrum();
ppqn++;
ppqn=ppqn%6;
if(RK002_paramGet(TEMPOTHRU)) return true;
return false;
}
bool RK002_onStart(){
ppqn=0;
seq_position=0;
drum_run=true;
if(RK002_paramGet(TEMPOTHRU)) return true;
return false;
}
bool RK002_onContinue(){
drum_run=!drum_run;
if(RK002_paramGet(TEMPOTHRU)) return true;
return false;
}
bool RK002_onControlChange(byte channel,byte number,byte val){
bool retval=true;
if(channel==dChannel){ // are we in euclidean set channel?
for (byte i=0;i<EUCL_TRACKS;i++){ // traverse the CC's
// euclid control
if(number==dcontrol[i]){ // match the cc
if(val>0){ // is there activity
bitSet(isPatterned,i); // euclidean pattern controls this
}else{
bitSet(muteChannel,i); // pattern is cleared: note key can just control the sound
bitClear(isPatterned,i); // reset trig flag for this one
}
Euclid(i,int((val+1)/8)); // make the pattern based on CC val
retval=false;
}
}
}
return retval;
}
// key to mute (NOTE: comment out this function to disable muting)
bool RK002_onNoteOn(byte channel,byte number,byte value){
bool retval=true;
// euclid
if(channel==dChannel){ // in designated MIDI channel?
for (byte i=0 ; i<EUCL_TRACKS ; i++){
if(dkeys[i] == number){
if(drum_run){
// key is in programmed range and sequencer is running
if(bitRead(isPatterned,i)){ // is a defined key and patterned?
if(bitRead(muteChannel,i)){ // is it not muted?
bitClear(muteChannel,i); // mute (0 = muted)
}else{
//RK002_sendNoteOff(channel,number,value);
bitSet(muteChannel,i); // unmute
}
retval=false;
}
}
}
}
}
return retval;
}
bool RK002_onNoteOff(byte channel,byte number,byte value){
bool retval=true;
if(channel==dChannel){ // in designated MIDI channel?
for (byte i=0 ; i<EUCL_TRACKS ; i++){
if(dkeys[i]==number){
if(drum_run){
// key is in programmed range and sequencer is running
if(bitRead(isPatterned,i)){ // is a defined key and patterned?
if(!bitRead(muteChannel,i)) retval=false; // muted: do not play off
}
}
}
}
}
return retval;
}
void advanceDrum(){
byte n;
bool drum_trigger;
if(ppqn==0){
// skip n = 0 - this is an accent track
for(n=1;n<EUCL_TRACKS;n++){
drum_trigger=bitRead(drumloop[seq_position],n);
if(drum_trigger && drum_run && bitRead(muteChannel,n)){
// bit 15 = velocity seq
RK002_sendNoteOn(dChannel, dkeys[n], 99+bitRead(drumloop[seq_position],0)*28);//veloLoop[seq_position]);
bitSet(drum_active,n);
}
}
seq_position++;
seq_position=seq_position % RK002_paramGet(LOOP);//sizeof(drumloop);
}else if (ppqn==1){
for(n=1;n<EUCL_TRACKS;n++){
drum_trigger=bitRead(drum_active,n);
if(drum_trigger){
RK002_sendNoteOff(dChannel, dkeys[n], 100);
bitClear(drum_active,n);
}
}
}
}
void Euclid(byte drumBit, byte trigs) {
byte cur = RK002_paramGet(LOOP);
for (byte i=0; i<RK002_paramGet(LOOP); i++) {
if (cur >= RK002_paramGet(LOOP)) {
cur -= RK002_paramGet(LOOP);
bitSet(drumloop[i],drumBit);
}
else {
bitClear(drumloop[i],drumBit);
}
if ((trigs==0) && (drumBit<RK002_paramGet(LOOP))) bitClear(drumloop[i],drumBit);
cur += trigs;
}
}
void updateParams()
{
// convert readable channels 1-16 to internal 0-15
dChannel = RK002_paramGet(CHANNEL) - 1;
}
void RK002_onParamChange(unsigned param_nr, int val){
updateParams();
}
// initialize
void setup()
{
//RK002_clockSetTempo(1200);
RK002_clockSetMode(0); // auto clock mode (will be clock slaved)
updateParams();
}
// the main loop
void loop()
{
}