How to create and add a new function to the LXR

From Sonic Potions Wiki
Revision as of 17:33, 9 May 2014 by Rstephane (talk | contribs)
Jump to: navigation, search

This is a DRAFT !!!! I will correct it during the next days :-)

  • GOAL, we will implement a function that change the length of all the tracks at once. A sort of loop/divide (like on the arturia spark machine). We will add a special knob in the PERF menu, when this knob is turned, the length of the tracks changes from 1 to 16 making the whole pattern ROLL :-)

- We start by adding a new knob 'LEN' (for Length) in the PERF menu on the LCD display.

  • Open the file 'Parameters.h', we first declare our parameter and its type.

add in the section: 'enum ParamEnums' ... your new parameter. In our case we wil add the parameter : PAR_LOOP

you have to add all the new parameters right after a dedicated section in the code declaration (otherwise you want link later the knob with the function you want to execute):

enum ParamEnums ...

       PAR_MIDI_NOTE1,
       PAR_MIDI_NOTE2,
       PAR_MIDI_NOTE3,
       PAR_MIDI_NOTE4,
       PAR_MIDI_NOTE5,
       PAR_MIDI_NOTE6,
       PAR_MIDI_NOTE7,
       // YOUR parameters comes right after thoses lines...
                  
       // rstephane MY VALUES ADDED FOR LOOP FUNCTION
       PAR_LOOP,     

--

Now, let's go the the menu text, we want that our knob display a name 'FILTER' or in our case 'RANDOM' .. well we will set it to 'RND' to make it short on the LCD screen.

We need to open the menu.c file.

menu.c //--------------------------------------------------------------- // Parameter types. These correspond with ParamEnums and entries in parameter_values const enum Datatypes PROGMEM parameter_dtypes[NUM_PARAMS] = {

           /*PAR_NONE*/                         DTYPE_0B127,                                                        // 0
           /*PAR_OSC_WAVE_DRUM1*/         DTYPE_MENU | (MENU_WAVEFORM<<4),
           /*PAR_OSC_WAVE_DRUM2*/         DTYPE_MENU | (MENU_WAVEFORM<<4),
           /*PAR_OSC_WAVE_DRUM3*/         DTYPE_MENU | (MENU_WAVEFORM<<4),
           /*PAR_OSC_WAVE_SNARE*/  DTYPE_MENU | (MENU_WAVEFORM<<4),

....

Again, place your parameter at a special place, right after the section: /*PAR_MIDI_NOTE1*/ DTYPE_NOTE_NAME,

           /*PAR_MIDI_NOTE2*/                DTYPE_NOTE_NAME,
           /*PAR_MIDI_NOTE3*/                DTYPE_NOTE_NAME,
           /*PAR_MIDI_NOTE4*/                DTYPE_NOTE_NAME,
           /*PAR_MIDI_NOTE5*/                DTYPE_NOTE_NAME,
           /*PAR_MIDI_NOTE6*/                DTYPE_NOTE_NAME,
           /*PAR_MIDI_NOTE7*/                DTYPE_NOTE_NAME,
           // YOUR PARAMETER comes right here and not elsewhere!!!!!
           
           // rstephane MY VALUES ADDED FOR RANDOM FUNCTION
           /*PAR_RND_VOICE1*/        DTYPE_ON_OFF,  // choose the type of your parameter, a definition of the parameter type is shown right after....
           
           /*PAR_ROLL*/                         DTYPE_MENU | (MENU_ROLL_RATES<<4),
           /*PAR_MORPH*/                         DTYPE_0B255,
               ....
               

Type of parameters: //----------------------------------------------------------------- enum Datatypes {

       DTYPE_0B255,        //0:255
       DTYPE_0B127,        //0-127
       DTYPE_PM100,        //-100:100
       DTYPE_MENU,                //text type outputs 
       DTYPE_PM63,                //-63 <-> 63
       DTYPE_1B16,                //1-16
       DTYPE_ON_OFF,        //0-1
       DTYPE_MIX_FM,        //0-1
       DTYPE_TARGET_SELECTION_LFO,
       DTYPE_TARGET_SELECTION_VELO,        
       DTYPE_VOICE_LFO,
       DTYPE_AUTOM_TARGET,
       DTYPE_0b1,
       DTYPE_NOTE_NAME, // --AS eg C#0, D 1 for note name
       DTYPE_0B15,                //0-15
       /*15*/
       /*16*/
       // --AS warning, we can only have 16 on this list the way things are laid out

};


oki, once this done, we need to fill other infformation in the code

Open the* menuPages.h

/** This array hold the whole menu structure. each voice has different pages. The pages hold the top and bottom enums to indicate which values and desriptors to show

  • /

in the section: const Page menuPages[NUM_PAGES][NUM_SUB_PAGES] PROGMEM =

               ....

add your MENU !

in our case: we want to create an random knob for its voice. this new button/parameter will appear when we have selected the 'OSC' menu

so we have:

const Page menuPages[NUM_PAGES][NUM_SUB_PAGES] PROGMEM = {

       //page 1 - Voice 1
       {
               //sub page 1 - Oscillator
               {
                       TEXT_COARSE,        TEXT_FINE,        TEXT_WAVEFORM,                TEXT_RND_VOICE,TEXT_EMPTY,TEXT_EMPTY,TEXT_EMPTY,TEXT_EMPTY,
                       PAR_COARSE1,        PAR_FINE1,        PAR_OSC_WAVE_DRUM1,        PAR_RND_VOICE1,PAR_NONE,PAR_NONE,PAR_NONE,PAR_NONE
               },
               

you will noticed two parameters: TEXT_RND_VOICE and PAR_RND_VOICE1

those parameter are important as the program will display on the LCD the menu names that appears in this section, so if we want to show a new menu or function, we need to add it in this section/file.

but we need now to declare the TEXT_RND_VOICE1 and PAR_RND_VOICE1 in other files :-)

Open file menu.h go to section

enum NamesEnum {

       TEXT_EMPTY = 0,                                        //0
       TEXT_COARSE,
       TEXT_FINE,
       TEXT_ATTACK,
       TEXT_DECAY,
       TEXT_PITCH_DECAY,
       TEXT_MOD_AMOUNT,                
       ....

add at the end, the text 'TEXT_RND_VOICE1" :

       ....
       TEXT_BAR_RESET_MODE,
       TEXT_MIDI_CHAN_GLOBAL,
       TEXT_RND_VOICE,        // rstephane: random text 
       NUM_NAMES

};

+

Open Cc2Text.c

//Voice 1 - Drum 1 // 1 Oscillator {TEXT_COARSE, PAR_COARSE1}, //2 {TEXT_FINE, PAR_FINE1}, {TEXT_WAVEFORM, PAR_OSC_WAVE_DRUM1}, {TEXT_RND_VOICE, PAR_RND_VOICE1}, // rstephane : added random button

Now, Open the menu.c file go to section valueNames:

const Name valueNames[NUM_NAMES] PROGMEM = {

               {SHORT_EMPTY,CAT_EMPTY,LONG_EMPTY},
               ....

add the following information:

               ....
               {SHORT_BAR_RESET_MODE, CAT_SEQUENCER, LONG_BAR_RESET_MODE}, // TEXT_BAR_RESET_MODE
               {SHORT_CHANNEL, CAT_MIDI, LONG_MIDI_CHANNEL}, // TEXT_MIDI_CHAN_GLOBAL
               {SHORT_RND, CAT_OSC, LONG_RND_VOICE}, // rstephane: TEXT_RND_VOICE

};

we declare it at the end of the section :-)

now, open the * MenuText.h file to declare the short and long version of the TEXT (TEXT_RND_VOICE1) go to section

const char longNames[][16] PROGMEM = 
et const char shortNames[][4] PROGMEM  = 

add the parameters:

const char shortNames[][4] PROGMEM = {

       {""},
       {"coa"},
       {"fin"},
       {"atk"},
       {"dec"},
       {"eg2"},
       ....
       
       {"co2"},  // trigger clock out2 ppq
       {"pcr"}, // pattern change resets bar counter
       {"RND"}, // rstephane: RND VOice
       

};

const char longNames[][16] PROGMEM = {

       {""},
       //01234567
       {"Coarse"},
       {"Fine"},
       {"Attack"},
       {"Decay"},
       {"Amount"},
       ....
       {"Out2 PPQ"},
       {"Gate Mode"},
       {"PCReset" }, // reset bar counter on manual pattern change
       {"Random"}, // rstephane: RND VOice LONG text

};


Now, we will create our function and will add a link between this function and our knob.

If you want you can already compile and see the results under the menu OSC of the VOICE1, normally right after COARSE, FINE, WAV, should appear RND.


/////

call the function relative to the encoder:

open midimessage.h


//for all parameters above 127 <- our case enum {

       ....
       // Again, place your parameter at a special place, right after the section:
       CC2_MIDI_NOTE1,
       CC2_MIDI_NOTE2,
       CC2_MIDI_NOTE3,
       CC2_MIDI_NOTE4,
       CC2_MIDI_NOTE5,
       CC2_MIDI_NOTE6,
       CC2_MIDI_NOTE7, // s/b 111 i think
       
       // YOUR PARAMETER comes right here and not elsewhere!!!!!
       // rstephane MY VALUES ADDED FOR RANDOM FUNCTION
       // rstephane : RND button :-) for CASE switch in MidiParser.C
       CC2_RND_VOICE1,
       ....

}Param2Enums;

open

  • MidiParser.c

//----------------------------------------------------------- /** handle all incoming CCs and invoke action*/ void midiParser_ccHandler(MidiMsg msg, uint8_t updateOriginalValue) {

       ...
       
       else //MIDI_CC2
       {
               const uint16_t paramNr = msg.data1+1 + 127;
               if(updateOriginalValue) {
                       midiParser_originalCcValues[paramNr] = msg.data2;
               }
               switch(msg.data1)
               {
                       case CC2_TRANS1_WAVE:
                                       voiceArray[0].transGen.waveform = msg.data2;
                               break;
                       case CC2_TRANS1_VOL:
                               voiceArray[0].transGen.volume = msg.data2/127.f;
                               break;
       ...
       case CC2_MUTE_1:
                       case CC2_MUTE_2:
                       case CC2_MUTE_3:
                       case CC2_MUTE_4:
                       case CC2_MUTE_5:
                       case CC2_MUTE_6:
                       case CC2_MUTE_7:
                       {
                               const uint8_t voiceNr = msg.data1 - CC2_MUTE_1;
                               if(msg.data2 == 0)
                               {
                                       seq_setMute(voiceNr,0);
                               }
                               else
                               {
                                       seq_setMute(voiceNr,1);
                               }
                       }
                               break;
                       // rstephane MY FUNCTIONS
                       // rstephane : Handle the RND button
                       case CC2_RND_VOICE1:
                               if(msg.data2 == 1)
                               {
                                       // RND is ON
                                       randomDrumVoice123(0); //voice1 = 0, voice2 = 1 etc...
                               }
                               break;        
                                                       
                       default:
                               break;
                               
                       ....
                       
                       

+ open drumvoice.h


// rstephane : my functions //random all the parameters for voice 1 2 and 3 void randomDrumVoice123(const uint8_t voiceNr);


+ open drumvoice.c


// rstephane : pour random functions

  1. include "valueShaper.h"

+

//--------------------------------------------------- // rstephane : my functions //random all the parameters for voice 1 2 and 3 //--------------------------------------------------- void randomDrumVoice123(const uint8_t voiceNr) {

               uint8_t rndData; // , new_min, new_max;
               // uint32_t rndDataTemp, old_min, old_max;
               // COARSE
               rndData = (uint8_t) GetRngValue();
               //clear upper nibble
               voiceArray[voiceNr].osc.midiFreq &= 0x00ff;
               //set upper nibble
               voiceArray[voiceNr].osc.midiFreq |= rndData << 8;
               osc_recalcFreq(&voiceArray[voiceNr].osc);
               //OSC1_DIST:
               rndData = (uint8_t) GetRngValue();
  1. if USE_FILTER_DRIVE
               voiceArray[voiceNr].filter.drive = 0.5f + (rndData/127.f) *6;
  1. else
               setDistortionShape(&voiceArray[voiceNr].distortion,rndData);
  1. endif

}