Jump to content

Azrael

Member
  • Posts

    558
  • Joined

  • Last visited

  • Country

    Germany
  • Donations

    0.00 USD 

Posts posted by Azrael

  1. @@TimeWalker75a

    Sorry it took so long for me to notice your post, but there you go:

    https://www.dropbox.com/s/96tsou813nt3o51/sketch_footswitch.ino?dl=1

     

     

     

    // #include <Mouse.h>
    // #include <Keyboard.h>
    #include "MIDIUSB.h" // Allows Arduino to act as a MIDI instrument
    
    #include <HID-Project.h>
    // The HID library which produces the multimedia keys
    //(Volume UP,DOWN and MUTE)  https://github.com/NicoHood/HID
    
    
    /* 
     Sketch for a USB-controlled guitar footswitch with five buttons and LEDs
      - for the use in Rocksmith 2014
        * via USB keyboard emulation
      - for the use with AmpliTube 4
        * via MIDI signals
      - for the use in Reaper (Digital Audio Workstation)
        * via USB keyboard emulation (shortcuts assigned within Reaper)
      - for the use as a regular GamePad
        * HID library makes Windows recognize it
    
      Please note: Enable the serial monitor in the Arduino program to
                   get feedback on the application modes and footswitch modes.
        
      Version 7:
        - Complete rework, added AmpliTube & Reaper support
      Version 8:
        - Used MIDIUSB for direct midi device emulation
        - Implemented media keys and GamePad with HID-Project
      Version 8.1: 
        - Added round() in map_exponential() for intended conversion from double to int
      Version 8.2:
        - Added more GamePad buttons
      Version 8.3:
        - Make Max Dynamic Difficulty last longer
      Version 8.4:
        - Added Reaper Mode 2 "Multitrack navigation"
     */
    
     
    /* 7-Pin connection used to connect 
    FAME 5-Button Footswitch with ERNIE BALL Volume Pedal:
    
    Connection Board: 1 to 10 
    Cable:            0 to 7
    
    Board  1 - Cable 0, 1 - 5V - Yellow
    Board  2 - Cable 0, 2 
    Board  3 - Cable 0, 3 - Analog POT1 - Red
    Board  4 - Cable 0, 2
    Board  5 - Cable 0, 4 - GND - Black
    Board  6 - Cable 0, 2
    Board  7 - Cable 0, 5
    Board  8 - Cable 0, 2
    Board  9 - Cable 0, 6 
    Board 10 - Cable 0, 2
    
    __________________________________________
    Arduino     - Wire   - Cable - Wire (Poti)
    ------------------------------------------
    5V          - Yellow - 1     - orange
    Analog POT1 - Red    - 3     - red
    GND         - Black  - 4     - brown
    
    */
     
    // --- Constants ---
    // Pedal's potentiometer analog input pin:
    #define POT1 0
    // Tolerance for detecting a change in 'pedalState'
    #define POT_tol 5 // 3 gives light flickering near position zero (4 is better)
    #define POT_max 1023 // minimum potentiometer value (fixed)
    #define POT_min 0    // maximum potentiometer value (fixed)
    
    // Pin connections for switches (pushbuttons) on the Leonardo board
    // Please note: Edit this part! Most likely you connected the buttons and LEDs 
    // to different pins ;-)
    #define BUTTON1 7
    #define BUTTON2 3
    #define BUTTON3 4
    #define BUTTON4 8
    #define BUTTON5 5
    // Pin connections for LEDs on the Leonardo board (use PWM pins to allow analogWrite)
    #define LED1 6
    #define LED2 9
    #define LED3 10
    #define LED4 11
    #define LED5 13
    // Default flash time in milliseconds
    #define FLASHDELAY 100
    
    // application modes
    #define Rocksmith 1
    #define AmpliTube 2
    #define Reaper 3
    #define GamePad 4
    
    // --- Variables ---
    // Reference array to the buttons and LEDs
    int buttons[5]     = {BUTTON1, BUTTON2, BUTTON3, BUTTON4, BUTTON5};
    int LEDs[5]        = {LED1, LED2, LED3, LED4, LED5};
    // Array for checking the state of a pushButton (HIGH or LOW)
    int buttonState[5] = {HIGH, HIGH, HIGH, HIGH, HIGH};
    
    // State of the pedal (0...1023)
    bool pedal_is_connected = true; // Is a pedal connected?
    int pedalState = 0;
    int analogLEDvalue = 0; //(0...255)
    
    // Counter for the number of times a button has been pressed
    int buttonCounter[5] = {0, 0, 0, 0, 0};
    
    // Generally, you shuould use "unsigned long" for variables that hold time
    // The value will quickly become too large for an int to store
    
    // interval during which the button counters can be increased (milliseconds)
    unsigned long buttonTimer[5] = {1500, 1500, 1500, 1500, 750};
    // will store last time LED was updated
    unsigned long previousMillis[5] = {0, 0, 0, 0, 0}; 
    
    // --- RS Mode 2: Riff Repeater ---
    const char* RS_mode_2_keys[4] = {"9", "0", "o", "p"}; // Rocksmith 2014
    // const char* RS_mode_2_keys[4] = {"[", "]", "-", "+"}; // Rocksmith 2014 Remastered
    
    // --- RS Mode 3: Menu Navigation ---
    KeyboardKeycode RS_mode_3_keys[4] = {KEY_UP_ARROW, KEY_DOWN_ARROW, KEY_LEFT_ARROW, KEY_RIGHT_ARROW};
    
    
    
    
    // Initial application mode:
    int previous_application_mode = -1;
    int application_mode = 0;
    // int application_mode = Rocksmith;
    // int application_mode = AmpliTube;
    // int application_mode = Reaper;
    // int application_mode = GamePad;
    
    
    
    // Footswitch mode (submodes within an application mode)
    int footswitch_mode = 0;
    int previous_footswitch_mode = -1;
    
    // Rocksmith:
    // * Mode 0: Initial State (to avoid output when connected and perform LED check)
    // * Mode 1: Tone Selection
    // * Mode 2: Riff Repeater
    // * Mode 3: Menu Navigation
    //
    // AmpliTube:
    // * Mode 0: Initial State + Setup (start AmpliTube)
    // * Mode 1: Looper
    // * Mode 2: Control Change (Stomp A)
    // * Mode 3: Program Change
    // * Mode 4: More Control Change
    // * Mode 5: Record, Play/Pause, Loop
    //
    // Reaper:
    // * Mode 0: Initial State
    // * Mode 1: Rewind, Play/Stop, Record, Metronome
    // * Mode 2: Go to previous marker, Play/Pause, Go to next marker, Metronome
    
    // GamePad:
    // * Mode 0: Initial State
    // * Mode 1: Send Windows GamePad button events 1 to 4
    //           and an analog signal when the pedal is used
    
    // Store the selected tone globally, so that it can be reused when switching back
    // to Rocksmith Mode 1
    int Rocksmith_tone_selection = 1; 
    
    // AmpliTube program selection, is also stored globally:
    int AmpliTube_program_selection = 0;
    int AmpliTube_recording = 0;
    int AmpliTube_playing = 0;
    
    // Reaper global variables
    int Reaper_recording = 0;
    int Reaper_playing = 0;
    int Reaper_metronome = 0;
    
    // Windows system variables
    int system_volume = 0;
    
    // ##################################################################################
    //                                       SETUP
    // ##################################################################################
    void setup() {
      // Setup Buttons and activation LEDs
      for(int currentButton = 0; currentButton < 5; currentButton++ ) {
        pinMode(buttons[currentButton], INPUT);          // Set pin for Button
        pinMode(LEDs[currentButton],   OUTPUT);          // Set pin for LED
        // Set every saved button state to its actual current state:
        buttonState[currentButton] = digitalRead(buttons[currentButton]);
      }
      
      Serial.begin(57600);    // Set MIDI baud rate
      Keyboard.begin();       // Initialize control over the keyboard  
      LEDs_perform_check();   // Run LED check  
      Consumer.begin();       // Initialize HID media buttons
      
      // Sends a clean report to the host. This is important on any Arduino type.
      Gamepad.begin();
      
      // Check if a pedal board is connected
      pedal_is_connected = Pedal_perform_check();
    }
    
    // ##################################################################################
    //                                    MAIN LOOP
    // ##################################################################################
    void loop() {
      if (application_mode == 0){
        run_application_selection();    
        LEDs_dim_analog(); // Control brightness of LEDs with potentiometer  
      }
      else if (application_mode == Rocksmith){
        run_application_Rocksmith();
      }
      else if (application_mode == AmpliTube){
        run_application_AmpliTube();
      }
      else if (application_mode == Reaper){
        run_application_Reaper();
      }
      else if (application_mode == GamePad){
        run_application_GamePad();
      }
      send_status(); // Send status information to PC via serial connection
      
      previous_application_mode = application_mode;
      previous_footswitch_mode  = footswitch_mode;
      
      delay(5); // Wait some milliseconds for the next loop to prevent double inputs...  
    }
    
    // ##################################################################################
    //                                     METHODS
    // ##################################################################################
    
    // ---------------------------------------------------------------------------------
    //            Application Selection: Switch between the different applications
    // ---------------------------------------------------------------------------------
    void run_application_selection(){
      for(int currentButton = 0; currentButton < 5; currentButton++) {          
        if (digitalRead(buttons[currentButton]) != buttonState[currentButton]){
          switch( currentButton ) {
            case 0: // Mode Rocksmith
              application_mode = Rocksmith;
              footswitch_mode = 0;
              break;
            case 1: // Mode AmpliTube
              application_mode = AmpliTube;
              footswitch_mode = 0;
              break;
            case 2: // Mode Reaper
              application_mode = Reaper;
              footswitch_mode = 0;
              break;
            case 3: 
              application_mode = GamePad;
              footswitch_mode = 0;
              break;
            case 4: break;
          }      
        }
        buttonState[currentButton] = digitalRead(buttons[currentButton]);
      }
    }
      
    // ---------------------------------------------------------------------------------
    //                        Application mode: ROCKSMITH
    // ---------------------------------------------------------------------------------
    void run_application_Rocksmith(){
      
      for(int currentButton = 0; currentButton < 5; currentButton++) {          
        if (digitalRead(buttons[currentButton]) != buttonState[currentButton]){
          
          switch ( footswitch_mode ) {
            case 1:{ // --- RS Mode 1: Tone Selection ---
              switch( currentButton ) {            
                case 4:
                  perform_mode_selection();
                  break;
                default:
                  Rocksmith_tone_selection = currentButton + 1;
                  Keyboard.print(Rocksmith_tone_selection);     // Keyboard output                
                  LED_light_single(currentButton);    // LED control
                  break;
              }
              break;
            }
            case 2:{ // --- RS Mode 2: Riff Repeater ---
              switch( currentButton ) {
                case 4:   perform_mode_selection(); break;
                default:
                  Keyboard.print(RS_mode_2_keys[currentButton]);
                  // Serial.print(RS_mode_2_keys[currentButton]); // debugging
                  break; // Keyboard output
              }
              break;
            }
            case 3:{ // --- RS Mode 3: Menu Navigation ---          
              switch( currentButton ) {   
                case 4:
                  perform_mode_selection();
                  break;
                default:
                  Keyboard.write(RS_mode_3_keys[currentButton]);   // Keyboard output
                  buttonCounter[currentButton]++;
                  button_hold_or_release(currentButton); // Initiate holding button   
                  break;
              }
              break;
            }
            case 6:{ // --- Mode 6: Special macros ---
              switch( currentButton ) {
                case 0:
                  Rocksmith_set_music_volume(0);
                  footswitch_mode = 3;
                  break;            
                case 1:
                  Rocksmith_set_music_volume(1);
                  footswitch_mode = 3;
                  break;
              }
              break;
            }
            case 9:{ // --- Mode 9: Application Selection ---
              application_mode = 0;
              break;
            }
          }
        }
        buttonState[currentButton] = digitalRead(buttons[currentButton]);    
      }
      execute_mode_selection();
      
      // Pedal section:
      // Only trigger an action if the pedalState has changed
      int pedalState_new = Pedal_read_state(); // Update pedalState
      if (pedalState_new != pedalState){
        switch ( footswitch_mode ) {
          case 3:{ // --- RS Mode 3: Menu Navigation --- 
            // Option 1: Use arrow keys
            // if (pedalState_new > pedalState){
              // Keyboard.write(KEY_UP_ARROW);
            // }
            // else{
              // Keyboard.write(KEY_DOWN_ARROW);
            // }
            
            // Option 2: Use GamePad joystick
            int axis_pos_int = map_exponential(pedalState_new, POT_min, POT_max, 0, 10000);
            int axis_pos     = map(axis_pos_int, 0, 10000, 32767, -32768);
            Gamepad.yAxis(axis_pos);
            Gamepad.write();
            break;
          }
          default:{
            control_volume(); // Control Windows system volume
          }
        }
        pedalState = pedalState_new; // Update pedalState
      }
    }
    
    
    
    // ---------------------------------------------------------------------------------
    //                        Application mode: AmpliTube
    // ---------------------------------------------------------------------------------
    void run_application_AmpliTube(){
      
      for(int currentButton = 0; currentButton < 5; currentButton++) {          
        if (digitalRead(buttons[currentButton]) != buttonState[currentButton]){
          
          switch ( footswitch_mode ) {
            case 1:{ // --- Mode 1: Looper ---
              switch( currentButton ) {
                case 0: AmpliTube_bypass_on_off(currentButton, 90); break;
                case 1: AmpliTube_bypass_on_off(currentButton, 91); break;
                case 2: AmpliTube_bypass_on_off(currentButton, 92); break;
                case 3: AmpliTube_bypass_on_off(currentButton, 93); break;
                case 4: perform_mode_selection(); break;
              }        
              break;
            }
            case 2:{ // --- Mode 2: Control Change (e.g. Stomp A) ---
              switch( currentButton ) {
                case 0: AmpliTube_bypass_on_off(currentButton, 26); break;
                case 1: AmpliTube_bypass_on_off(currentButton, 27); break;
                case 2: AmpliTube_bypass_on_off(currentButton, 28); break;
                case 3: AmpliTube_bypass_on_off(currentButton, 29); break;
                case 4: perform_mode_selection(); break;
              }
              break;
            }
            case 3:{ // --- Mode 3: Program Change ---
              switch( currentButton ) {
                case 0: 
                  midi_program_change(1);
                  AmpliTube_program_selection = currentButton;
                  LED_light_single(currentButton);
                  break;
                case 1: 
                  midi_program_change(2);
                  AmpliTube_program_selection = currentButton;
                  LED_light_single(currentButton);
                  break;
                case 2: 
                  midi_program_change(3);
                  AmpliTube_program_selection = currentButton;
                  LED_light_single(currentButton);
                  break;
                case 3: 
                  midi_program_change(4);
                  AmpliTube_program_selection = currentButton;
                  LED_light_single(currentButton);
                  break;
                case 4: perform_mode_selection(); break;
              }
              break;
            }
             case 4:{ // --- Mode 4: More Control Change ---
              switch( currentButton ) {
                case 0: 
                  // Must send "off" and "on" simultaneously for some reason
                  midi_control_change(74, 0);
                  midi_control_change(74, 127);
                  LED_flash(currentButton,FLASHDELAY);
                  break;
                case 1:
                  // Must send "off" and "on" simultaneously for some reason
                  midi_control_change(75, 0);
                  midi_control_change(75, 127);
                  LED_flash(currentButton,FLASHDELAY);
                  break;
                case 2: AmpliTube_bypass_on_off(currentButton, 33); break;
                case 3: AmpliTube_bypass_on_off(currentButton, 34); break;
                case 4: perform_mode_selection(); break;
              }
              break;
             }
             case 5:{ // --- Mode 5: Record, Play/Pause, Rewind ---
              switch( currentButton ) {
                case 0: // Record (starting recording starts playing, too)
                  AmpliTube_bypass_on_off(0, 42);
                  AmpliTube_recording = !AmpliTube_recording;
                  if (AmpliTube_playing == 0) AmpliTube_playing = 1;
                  break;
                case 1: // Play (Pause ends recording)
                  AmpliTube_bypass_on_off(1, 43);
                  AmpliTube_playing = !AmpliTube_playing;
                  if (AmpliTube_recording == 1) AmpliTube_recording = 0;
                  break;
                case 2: // Rewind (only, when not recording)
                  if (AmpliTube_recording == 0){
                    AmpliTube_bypass_on_off(2, 44);
                    LED_flash(2, 500);
                  }
                  break;
                case 3: AmpliTube_bypass_on_off(currentButton, 45); break;
                case 4: perform_mode_selection(); break;
              }
              break;
             }
            case 9:{ // --- Mode 9: Application Selection ---
              application_mode = 0;
              break;
            }
          }
        }
        buttonState[currentButton] = digitalRead(buttons[currentButton]);
        
      }
      execute_mode_selection();
      
      // This must only be done after the loop through all buttons:
      if (footswitch_mode == 5){ // --- Mode 5: Record, Play/Pause, Rewind ---
        digitalWrite(LEDs[0], AmpliTube_recording);
        digitalWrite(LEDs[1], AmpliTube_playing);
      }
      
      // Pedal section:
      // Only trigger an action if the pedalState has changed
      int pedalState_new = Pedal_read_state(); // Update pedalState
      if (pedalState_new != pedalState){
        switch ( footswitch_mode ) {
          case 1:{ // --- Mode 1: Looper ---                
            // int send_value = map(pedalState_new, POT_min, POT_max, 0, 127);
            int send_value = map_exponential(pedalState_new, POT_min, POT_max, 0, 127);
            midi_control_change(107, send_value);
            break;
          }
          case 2:{ // --- Mode 2: Control Change (e.g. Stomp A) ---
            // int send_value = map(pedalState_new, POT_min, POT_max, 0, 127);
            int send_value = map_exponential(pedalState_new, POT_min, POT_max, 0, 127);
            midi_control_change(107, send_value);
            break;
          }
          case 3:{ // --- Mode 3: Program Change ---
            control_volume(); // Control Windows system volume
            break;
          }
          case 4:{ // --- Mode 4: More Control Change ---
            control_volume(); // Control Windows system volume
            break;
          }
          case 5:{ // --- Mode 5: Record, Play/Pause, Rewind ---
            // int send_value = map(pedalState_new, POT_min, POT_max, 0, 127);
            int send_value = map_exponential(pedalState_new, POT_min, POT_max, 0, 127);
            midi_control_change(107, send_value);
            break;
          }
        }
        
        pedalState = pedalState_new; // Update pedalState
      }
      
      
    }
    
    
    
    // ---------------------------------------------------------------------------------
    //                        Application mode: Reaper
    // ---------------------------------------------------------------------------------
    void run_application_Reaper(){
      
      for(int currentButton = 0; currentButton < 5; currentButton++) {          
        if (digitalRead(buttons[currentButton]) != buttonState[currentButton]){
          
          switch ( footswitch_mode ) {
            case 1:{ // --- Mode 1: Rewind, Play/Pause, Record, Metronome ---
              switch( currentButton ) {
                case 0: // Rewind
                  Keyboard.write(KEY_HOME);
                  LED_flash(currentButton, 500);
                  break;
                case 1: // Play/Pause
                  if (Reaper_playing == 0){
                    Keyboard.press(KEY_LEFT_CTRL);
                    Keyboard.press(KEY_LEFT_SHIFT);
                    Keyboard.press('k'); // "Play" function
                    Keyboard.releaseAll();
                  }
                  else{
                    Keyboard.press(KEY_LEFT_CTRL);
                    Keyboard.press(KEY_LEFT_SHIFT);
                    // Keyboard.press('l'); // "Pause" function
                    Keyboard.press('i'); // "Stop" function
                    Keyboard.releaseAll();
                  }
                  Reaper_playing = !Reaper_playing;
                  break;
                case 2: // Record (starting recording starts playing, too)
                  if (Reaper_recording == 0){
                    Keyboard.press(KEY_LEFT_CTRL);
                    Keyboard.press('r');
                    Keyboard.releaseAll();
                  }
                  else{
                    Keyboard.press(KEY_LEFT_CTRL);
                    Keyboard.press(KEY_LEFT_SHIFT);
                    Keyboard.press('i');
                    Keyboard.releaseAll();
                  }
                  if ((Reaper_playing == 0) && (Reaper_recording == 0)){
                    Reaper_playing = 1;
                  }
                  else if ((Reaper_playing == 1) && (Reaper_recording == 1)){
                    Reaper_playing = 0;
                  }
                  Reaper_recording = !Reaper_recording;
                  break;
                case 3: // Metronome (enable / disable)
                  if (Reaper_metronome == 0){
                    Keyboard.press(KEY_LEFT_CTRL);
                    Keyboard.press(KEY_LEFT_SHIFT);
                    Keyboard.press('o');
                    Keyboard.releaseAll();
                  }
                  else{
                    Keyboard.press(KEY_LEFT_CTRL);
                    Keyboard.press(KEY_LEFT_SHIFT);
                    Keyboard.press('p');
                    Keyboard.releaseAll();
                  }
                  Reaper_metronome = !Reaper_metronome;
                  break;
                case 4:
                  perform_mode_selection();
                  break;
              }
              break;
            }
            case 2:{ // --- Mode 2: Multitrack navigation ---
              switch( currentButton ) {
                case 0: // Go to previous marker/project start
                  Keyboard.press(KEY_LEFT_CTRL);
                  Keyboard.press(KEY_LEFT_ALT);
                  Keyboard.press(KEY_LEFT_ARROW);
                  Keyboard.releaseAll();
                  LED_flash(currentButton, 50);
                  break;
                case 1: // Play/Pause
                  if (Reaper_playing == 0){
                    Keyboard.press(KEY_LEFT_CTRL);
                    Keyboard.press(KEY_LEFT_SHIFT);
                    Keyboard.press('k'); // "Play" function
                    Keyboard.releaseAll();
                  }
                  else{
                    Keyboard.press(KEY_LEFT_CTRL);
                    Keyboard.press(KEY_LEFT_SHIFT);
                    Keyboard.press('l'); // "Pause" function
                    // Keyboard.press('i'); // "Stop" function
                    Keyboard.releaseAll();
                  }
                  Reaper_playing = !Reaper_playing;
                  break;
                case 2: // Go to next marker/project end
                  Keyboard.press(KEY_LEFT_CTRL);
                  Keyboard.press(KEY_LEFT_ALT);
                  Keyboard.press(KEY_RIGHT_ARROW);
                  Keyboard.releaseAll();
                  LED_flash(currentButton, 50);
                  break;
                case 3: // Metronome (enable / disable)
                  if (Reaper_metronome == 0){
                    Keyboard.press(KEY_LEFT_CTRL);
                    Keyboard.press(KEY_LEFT_SHIFT);
                    Keyboard.press('o');
                    Keyboard.releaseAll();
                  }
                  else{
                    Keyboard.press(KEY_LEFT_CTRL);
                    Keyboard.press(KEY_LEFT_SHIFT);
                    Keyboard.press('p');
                    Keyboard.releaseAll();
                  }
                  Reaper_metronome = !Reaper_metronome;
                  break;
                case 4:
                  perform_mode_selection();
                  break;
              }
              break;
            }
            case 9:{ // --- Mode 9: Application Selection ---
              application_mode = 0;
              break;
            }
          }
        }
        buttonState[currentButton] = digitalRead(buttons[currentButton]);
        
      }
      execute_mode_selection();
      
      // This must only be done after the loop through all buttons:
      if (footswitch_mode == 1){ // --- Mode 1: Record, Play/Pause, Rewind ---
        digitalWrite(LEDs[1], Reaper_playing);
        digitalWrite(LEDs[2], Reaper_recording);
        digitalWrite(LEDs[3], Reaper_metronome);
      }
      if (footswitch_mode == 2){ // --- Mode 2: Multitrack navigation ---
        digitalWrite(LEDs[1], Reaper_playing);
        digitalWrite(LEDs[3], Reaper_metronome);
      }
      
      // Pedal section:
      // Only trigger an action if the pedalState has changed
      int pedalState_new = Pedal_read_state(); // Update pedalState
      if (pedalState_new != pedalState){
        switch ( footswitch_mode ) {
          case 1:{ // --- Mode 1 ---                
            int send_value = map_exponential(pedalState_new, POT_min, POT_max, 0, 127);
            midi_control_change(107, send_value);
            break;
          }
          case 2:{ // --- Mode 2 ---                
            int send_value = map_exponential(pedalState_new, POT_min, POT_max, 0, 127);
            midi_control_change(107, send_value);
            break;
          }      
        }
        
        pedalState = pedalState_new; // Update pedalState
      }
    }
    
    
    
    // ---------------------------------------------------------------------------------
    //                        Application mode: GamePad
    // ---------------------------------------------------------------------------------
    void run_application_GamePad(){
      
      if (footswitch_mode == 0){
        LEDs_perform_check();
        footswitch_mode = 1;
      }
      
      for(int currentButton = 0; currentButton < 5; currentButton++) {          
        if (digitalRead(buttons[currentButton]) != buttonState[currentButton]){
          
          switch( currentButton ) {
            case 4: {
              perform_mode_selection();
              break;
            }
            default: {
              GamePad_button_toggle(currentButton);
              break;
            }
          }        
        }
        buttonState[currentButton] = digitalRead(buttons[currentButton]);    
      }
      execute_mode_selection();
      
      
      // Pedal section:
      // Only trigger an action if the pedalState has changed
      int pedalState_new = Pedal_read_state(); // Update pedalState
      if (pedalState_new != pedalState){
        
        // My custom exponential mapping does not work with negatives, so we need two steps:
        // 65535 is the decimal of the hex value 0xFFFF
        int axis_pos_int = map_exponential(pedalState_new, POT_min, POT_max, 0, 10000);
        int axis_pos = 0;
        
        switch(footswitch_mode){
          case 1:  
            axis_pos = map(axis_pos_int, 0, 10000, 32767, -32768);
            Gamepad.yAxis(axis_pos); 
            break;
          case 2:  
            axis_pos = map(axis_pos_int, 0, 10000, 32767, -32768);
            Gamepad.xAxis(axis_pos); 
            break;
          case 3:  
            axis_pos = map(axis_pos_int, 0, 10000, -128, 127);
            Gamepad.zAxis(axis_pos); 
            break;
          default: Gamepad.yAxis(axis_pos); break;
        }    
        // Functions above only set the values. This writes the report to the host.
        Gamepad.write();
        
        pedalState = pedalState_new; // Update pedalState
        
        // Serial.print("pedalState_new = ");
        // Serial.print(pedalState_new);
        // Serial.print(" axis_pos_int = ");
        // Serial.print(axis_pos_int);
        Serial.print(" axis_pos = ");
        Serial.print(axis_pos);
        Serial.print("\n");
      }
      
      
    }
    
    
    
    // ---------------------------------------------------------------------------------
    //                           Small help functions
    // ---------------------------------------------------------------------------------
    
    // --- Button 5 is tapped fast enough: Increase counter ----------------------------
    void perform_mode_selection(){   
      if(millis() - previousMillis[4] < buttonTimer[4]) {
        // Save time of last tap on button 5  
        previousMillis[4] = millis();
        // increase the counter of button 5 by one    
        buttonCounter[4]++;
        // Send status information to PC via the serial port
        Serial.print("Performing mode selection... ");
        Serial.print(buttonCounter[4]);
        Serial.print("\n");
    //    LED_light_single(4);
        for (int i = 0; i < 5; i++){
          if (buttonCounter[4] <= 5){
            if (i+1 <= buttonCounter[4]) digitalWrite(LEDs[i], HIGH);
            else                         digitalWrite(LEDs[i], LOW);
          }
          else{
            LEDs_turn_all(HIGH);
            digitalWrite(LEDs[buttonCounter[4]-6], LOW);
          }
        }
        delay(100);
        LEDs_turn_all(LOW); // turn off all LEDs    
      }
    }
    
    // --- Tapping on button 5 has stopped: Execute command ----------------------------
    // Execute a different functionality, based on how often button 5 has been pressed
    // before (and depending on the current footswitch_mode):
    void execute_mode_selection(){  
      if(millis() - previousMillis[4] >= buttonTimer[4]) {
        switch (application_mode){
          // For application_mode "Rocksmith":
          // 1: Toggle between footswitch_modes 1 and 2 (Tone Selection and Riff Repeater)
          // 2: mode = 1: - ESC
          //              - mode -> 3
          //    mode = 2: - DELETE (Escapes Riff Repeater)
          //              - mode -> 1
          //    mode = 3: - ESC
          // 3: mode = 3: - SPACE (Opens Menu)
          //    else:     - mode -> 3
          // 4: mode = 1: - Macro: Maximize Dynamic Difficulty
          //    else:     - mode -> 2
          // 5:           - mode -> 1
          // 6-9:         - mode -> 6-9
          case Rocksmith: {        
            switch ( buttonCounter[4] ){
              case 0: break;
              case 1:{
                if (footswitch_mode == 1) {
                  Keyboard.print(" ");
                  footswitch_mode = 2;
                }
                else if (footswitch_mode == 2) {
                  Keyboard.print(" ");
                  footswitch_mode = 1;
                }
                else if (footswitch_mode == 3) Keyboard.write(KEY_RETURN);
                else footswitch_mode = 1;
                break;
              }
              case 2:{
                if (footswitch_mode == 1) {
                  Keyboard.write(KEY_ESC);
                  footswitch_mode = 3;
                }
                else if (footswitch_mode == 2) {
                  Keyboard.write(KEY_DELETE);
                  footswitch_mode = 1;
                }
                else if (footswitch_mode == 3) Keyboard.write(KEY_ESC);
                break;
              }
              case 3:{
                if (footswitch_mode == 3) Keyboard.print(" ");
                else footswitch_mode = 3;
                break;
              }
              case 4:{
                if (footswitch_mode == 1) Rocksmith_set_DynamicDifficulty_to_max();
                else footswitch_mode = 2;
                break;
              }
              case 5:  footswitch_mode = 1; break;
              case 6:  footswitch_mode = 6; break;
              // case 7:  footswitch_mode = 7; break;
              // case 8:  footswitch_mode = 8; break;
              case 9:  footswitch_mode = 9; break;
              default: footswitch_mode = 1;
            }    
          
            // --- Stuff we need to do at the end of each loop that did not increase
            // --- the counter of button 5 (regardless of what buttons were pressed)
            switch ( footswitch_mode ) {
              case 0: // --- Mode 0: Initialization ---
                LEDs_perform_check();
                footswitch_mode = 1;
                break;
              case 1: // --- Mode 1: Tone Selection ---
                LED_light_single(Rocksmith_tone_selection-1);
                break;
              case 2: // --- Mode 2: Riff Repeater ---
                digitalWrite(LEDs[0], HIGH);   
                digitalWrite(LEDs[1], HIGH);
                digitalWrite(LEDs[2], LOW); 
                digitalWrite(LEDs[3], LOW);   
                digitalWrite(LEDs[4], LOW);
                break;
              case 3: // --- Mode 3: Menu Navigation ---
                digitalWrite(LEDs[0], HIGH);   
                digitalWrite(LEDs[1], HIGH);
                digitalWrite(LEDs[2], HIGH); 
                digitalWrite(LEDs[3], LOW);   
                //digitalWrite(LEDs[4], LOW);
                break;
            }
          break;
          }
          
          // For the application_mode "AmpliTube", simply switch to the footswitch_mode
          // corresponding to the number of button 5 presses:
          case AmpliTube: {
            switch ( buttonCounter[4] ){
              case 0:  break;
              case 1:  footswitch_mode = 1; break;
              case 2:  footswitch_mode = 2; break;
              case 3:  footswitch_mode = 3; break;
              case 4:  footswitch_mode = 4; break;
              case 5:  footswitch_mode = 5; break;
              case 9:  footswitch_mode = 9; break;
              default: footswitch_mode = 1; break;
            }
            // --- Stuff we need to do at the end of each loop that did not increase
            // --- the counter of button 5 (regardless of what buttons were pressed)
            switch ( footswitch_mode ) {
              case 0: // --- Mode 0: Initialization ---
                LEDs_perform_check();
                // AmpliTube_run_setup(); // Setup was required for version 7
                footswitch_mode = 1;
                break;
              case 3: // --- Mode 3: Program Change ---
                LED_light_single(AmpliTube_program_selection);
                break;
            }
          break;
          }
          
          // For the application_mode "Reaper", simply switch to the footswitch_mode
          // corresponding to the number of button 5 presses:
          case Reaper: {
            switch ( buttonCounter[4] ){
              case 0:  break;
              case 1:  footswitch_mode = 1; break;
              case 2:  footswitch_mode = 2; break;
              // case 3:  footswitch_mode = 3; break;
              // case 4:  footswitch_mode = 4; break;
              case 9:  footswitch_mode = 9; break;
              default: footswitch_mode = 1; break;
            }
            // --- Stuff we need to do at the end of each loop that did not increase
            // --- the counter of button 5 (regardless of what buttons were pressed)
            switch ( footswitch_mode ) {
              case 0: // --- Mode 0: Initialization ---
                LEDs_perform_check();
                footswitch_mode = 1;
                break;
            }
          break;
          }
          
          // For the application_mode "GamePad", switch to the footswitch_mode
          // corresponding to the number of button 5 presses
          // AND also toggle the corresponding GamePad button:
          case GamePad: {
            switch ( buttonCounter[4] ){
              case 0:  break;          
              case 1:{
                if (footswitch_mode == 1){GamePad_button_toggle(4);}
                footswitch_mode = 1; 
                break;
              }
              case 2:{ 
                if (footswitch_mode == 2){GamePad_button_toggle(4);}
                footswitch_mode = 2; 
                break;
              }
              case 3:{ 
                if (footswitch_mode == 3){GamePad_button_toggle(4);}
                footswitch_mode = 3; 
                break;
              }
              case 4:{ 
                if (footswitch_mode == 4){GamePad_button_toggle(4);}
                footswitch_mode = 4; 
                break;
              }
              case 9:  footswitch_mode = 9; break;
              default: footswitch_mode = 1; break;
            }
            // --- Stuff we need to do at the end of each loop that did not increase
            // --- the counter of button 5 (regardless of what buttons were pressed)
            switch ( footswitch_mode ) {
              case 0: // --- Mode 0: Initialization ---
                LEDs_perform_check();
                footswitch_mode = 1;
                break;
            }
          break;
          }
          
          // If application mode was different than the above:
          default:{
            switch ( buttonCounter[4] ){
              case 9:  footswitch_mode = 9; break;
            }
          }
        }
        // --- Independent of the application_mode: ---
        // Reset counter of button 5
        buttonCounter[4] = 0;
        // Save time of last tap on button 5  
        previousMillis[4] = millis();
        
        
        // --- Reset application_mode if
        // footswitch_mode = "Mode 9: Application Selection" was selected ---
        if (footswitch_mode == 9){
          application_mode = 0;
          footswitch_mode = 0;
        }
    
      }
    }
    
    
    
    // --- Perform LED check, which includes blinking all LEDs -------------------------
    void LEDs_perform_check() {
      // Loop from first to last pin
      for (int LED = 0; LED < 5; LED++)  {LED_flash(LED, FLASHDELAY);}
      // loop from the last pin to the first:
      for (int LED = 4; LED >= 0; LED--) {LED_flash(LED, FLASHDELAY);}
      delay(200);
      LEDs_turn_all(HIGH);
      delay(500);
      LEDs_turn_all(LOW);
      delay(500);  
    }
    
    // --- Flash a single LED ----------------------------------------------------------
    void LED_flash (int LED, int flashDelay) {  
      digitalWrite(LEDs[LED], HIGH);  // turn the pin on
      delay(flashDelay);              // Wait for x milliseconds
      digitalWrite(LEDs[LED], LOW);   // turn the pin off
    }
    
    // --- Light a single LED, while turning all others off ----------------------------
    void LED_light_single(int LED_select){  
      for (int LED = 0; LED < 5; LED++) {
        if (LED == LED_select) {digitalWrite(LEDs[LED], HIGH);}
        else                   {digitalWrite(LEDs[LED], LOW); }
      }
    }
    
    // --- Turn all LEDs on or off by making the voltage LOW or HIGH -------------------
    void LEDs_turn_all(int HIGH_or_LOW){  
      for (int LED = 0; LED < 5; LED++) {    
        digitalWrite(LEDs[LED], HIGH_or_LOW);
      }
    }
    
    
    // --- Control brightness of LEDs with potentiometer -------------------------------
    void LEDs_dim_analog(){
      // Print status information to serial connection if value has changed:
      int pedalState_new = Pedal_read_state(); // Update pedalState
      if (pedalState_new != pedalState){
        // map it to the range of the analog out:
        analogLEDvalue = map(pedalState_new, POT_min, POT_max, 0, 255);
        // analogLEDvalue = map_exponential(pedalState_new, POT_min, POT_max, 0, 255);
        
        Serial.print("pedalState = ");
        Serial.print(pedalState_new);
        Serial.print("; analogLEDvalue = ");
        Serial.print(analogLEDvalue);
        Serial.print("\n");    
      }
      pedalState = pedalState_new; // Update pedalState    
      
      // change the analog out value:
      analogWrite(LED1, analogLEDvalue);
      analogWrite(LED2, analogLEDvalue);
      analogWrite(LED3, analogLEDvalue);
      analogWrite(LED4, analogLEDvalue);
      analogWrite(LED5, analogLEDvalue);
    }
    
    
    // --- Allow "holding" buttons if they are pressed often enough --------------------
    // A "held" button can be "released" by pressing any other button; The button
    // lights up while it is "held"
    void button_hold_or_release(int currentButton){
      // Pressed for the first time: Turn LED low
      if (buttonCounter[currentButton] == 1){
        previousMillis[currentButton] = millis();
        digitalWrite(LEDs[currentButton], LOW);
      }
      // Keyboard output: "press" holds the button, until "released"      
      if ((buttonCounter[currentButton] == 5)
      && (millis() - previousMillis[currentButton] < buttonTimer[currentButton])){    
        Keyboard.press(RS_mode_3_keys[currentButton]);   
        buttonCounter[currentButton]++;
        digitalWrite(LEDs[currentButton], HIGH);
        digitalWrite(LEDs[4], HIGH);
      }
      // "Release" all buttons
      if (buttonCounter[currentButton] > 6){
        Keyboard.releaseAll();
        // Reset button counter
        for (int i = 0; i<4; i++){
          buttonCounter[i] = 0;
        }
        digitalWrite(LEDs[currentButton], LOW);
        digitalWrite(LEDs[4], LOW);
      }
    }
    
    
    // --- Rocksmith 2014: Macro for setting Dynamic Difficulty to maximum -------------
    void Rocksmith_set_DynamicDifficulty_to_max(){
      Keyboard.print(" ");             delay(1000);
      for (int i=0; i<60;i++){
        Keyboard.print(RS_mode_2_keys[3]); delay(50);
      }
      for (int i=0; i<20;i++){
        Keyboard.print(RS_mode_2_keys[0]); delay(50);
      }
      // Keyboard.write(KEY_UP_ARROW);  delay(50);
      // Keyboard.write(KEY_DOWN_ARROW);  delay(50);
      Keyboard.write(KEY_DOWN_ARROW);  delay(50);
      Keyboard.press(KEY_RIGHT_ARROW); delay(4000);
      Keyboard.releaseAll();
      Keyboard.write(KEY_DELETE);
    }
    
    // --- Rocksmith 2014: Macro for making the music silent or loud -------------------
    // Navigates the menu and slides the volume-slider to the left or right, depending
    // on the input
    void Rocksmith_set_music_volume(int ON_or_OFF){
      Keyboard.print(" ");              delay(1000);
      Keyboard.write(KEY_UP_ARROW);     delay(50);
      Keyboard.write(KEY_UP_ARROW);     delay(50);
      Keyboard.write(KEY_UP_ARROW);     delay(50);
      Keyboard.write(KEY_UP_ARROW);     delay(50);
      Keyboard.write(KEY_DOWN_ARROW);   delay(50);
      Keyboard.write(KEY_DOWN_ARROW);   delay(500);
      Keyboard.write(KEY_RETURN);       delay(1500);
      Keyboard.write(KEY_RETURN);       delay(1500);
      if (ON_or_OFF == 0){
        for (int i=100; i>0;i--){
          Keyboard.write(KEY_LEFT_ARROW); delay(50);
        }
      }
      else if (ON_or_OFF == 1){
        for (int i=0; i<75;i++){
          Keyboard.write(KEY_RIGHT_ARROW); delay(50);
        }   
      }
      Keyboard.write(KEY_ESC);  delay(1500);
      Keyboard.write(KEY_ESC);  delay(3000);
      Keyboard.write(KEY_ESC);  delay(500);
      for (int i=0; i<7;i++){
        Keyboard.write(KEY_UP_ARROW); delay(50);
      }
    }
    
    // --- AmpliTube: Perform Setup -------
    void AmpliTube_run_setup(){ 
      // Start the program "Midi_to_Serial"
      Keyboard.press(KEY_LEFT_CTRL);
      Keyboard.press(KEY_LEFT_ALT);
      Keyboard.press('s');
      delay(100);
      Keyboard.releaseAll();   delay(4000);
      Keyboard.write('A');     delay(100);
      Keyboard.write('E');     delay(100);
      Keyboard.write('B');     delay(100);
      Keyboard.write('D');     delay(100);
      Keyboard.write('B');     delay(100);
      Keyboard.press(KEY_LEFT_GUI);
      Keyboard.press(KEY_DOWN_ARROW);
      Keyboard.releaseAll();   delay(100);
      
      Keyboard.write(KEY_LEFT_GUI); delay(500);
      Keyboard.print("AmpliTube");  delay(1000);
      Keyboard.write(KEY_RETURN);   delay(100);
    }
    
    // --- AmpliTube: Toggle a bypass between states on and off (including LED) --------
    // These are "control change" MIDI signals
    void AmpliTube_bypass_on_off(int currentButton, char controlChange){
      if( buttonState[currentButton] == LOW ) {
        midi_control_change(controlChange, 0 ); // bypass off
        digitalWrite(LEDs[currentButton], HIGH);
      }
      else {
        midi_control_change(controlChange, 127 ); // bypass on
        digitalWrite(LEDs[currentButton], LOW);
      }
    }
    
    
    
    void midi_program_change(byte program) {
    // First parameter is the event type (0x0C = program change).
    // Second parameter is the event type, combined with the channel.
    // Third parameter is the program number (0-127).
    // Fourth parameter is just a dummy (0).
      int channel = 0; // channel is always "1": (0-15)
      uint8_t event_channel = 0xC0 | channel;
      midiEventPacket_t program_change = {0x0C, event_channel, program, 0};
      MidiUSB.sendMIDI(program_change);
      MidiUSB.flush();
    }
    
    void midi_control_change(byte control, byte value) {
    // First parameter is the event type (0x0B = control change).
    // Second parameter is the event type, combined with the channel.
    // Third parameter is the control number number (0-119).
    // Fourth parameter is the control value (0-127).
      int channel = 0; // channel is always "1": (0-15)
      uint8_t event_channel = 0xB0 | channel;
      // midiEventPacket_t control_change = {0x0B, 0xB0 | channel, control, value};
      midiEventPacket_t control_change = {0x0B, event_channel, control, value};
      // midiEventPacket_t event = {0x0B, channel, control, value};
      MidiUSB.sendMIDI(control_change);
      MidiUSB.flush();
    }
    
    
    
    // --- Send status information to PC via serial connection ------------------------
    void send_status(){
      if ((previous_application_mode != application_mode) ||
      (previous_footswitch_mode  != footswitch_mode)){
        Serial.print("application_mode = ");
        Serial.print(application_mode);
        Serial.print(", ");
        Serial.print("footswitch_mode = ");
        Serial.print(footswitch_mode);
        Serial.print("\n");        
      }
    }
    
    // --- Check if a pedal board is connected -----------------------------------------
    // Is supposed to be run during setup.
    // Returns a boolean which can be used to set "pedal_is_connected"
    bool Pedal_perform_check(){
      #define TRIES 10  
      #define PEDAL_CONNECTED_THRESHOLD 5 // (maximum difference in range of 100)
      
      // Read pedal state and map it to a range of 0 ... 100:
      int pedalState_mapped = map_exponential(Pedal_read_state(), POT_min, POT_max, 0, 100);
      int pedalState_mapped_new = pedalState_mapped;
      
      for (int TRY = 1; TRY <= TRIES; TRY++){
        delay(10); // Wait for x milliseconds
        
        pedalState_mapped_new = map_exponential(Pedal_read_state(), POT_min, POT_max, 0, 100); 
        
        int pedalState_diff = pedalState_mapped_new - pedalState_mapped;    
        pedalState_mapped = pedalState_mapped_new; // Update pedalState
        
        if (pedalState_diff < 0){ // make positive if negative
          pedalState_diff = -pedalState_diff;
        }
        
        Serial.print("TRY = ");
        Serial.print(TRY);
        Serial.print("; pedalState_diff = ");
        Serial.print(pedalState_diff);
        Serial.print("\n");    
        
        if (pedalState_diff > PEDAL_CONNECTED_THRESHOLD){
          Serial.print("Pedal failed test and is not connected!\n");
          return false;  // pedal failed test and is not connected
        } 
      }
      
      Serial.print("Pedal passed test and is connected.\n");
      return true; // pedal passed test and is connected
    }
    
    // --- Read the pedal's potentiometer ----------------------------------------------
    int Pedal_read_state(){
      if (pedal_is_connected == false){
        // Abort function and return the last known state of the pedal:
        return pedalState;
      }
      
      int pedalState_old  = pedalState;
      // int pedalState_read = analogRead(POT1);    // read the value from the sensor
      int pedalState_new  = pedalState;
      
      // The analogRead() tends to 'flicker' (giving unstable values), so we take the 
      // mean of a couple of reads:
      #define SAMPLES 10
      double pedalState_read = 0;
      for (int i=0; i< SAMPLES ; i++) pedalState_read += analogRead(POT1);
      pedalState_read /= SAMPLES;
      pedalState_read = round(pedalState_read);
      
      // Serial.print("pedalState_read = ");
      // Serial.print(pedalState_read);
      // Serial.print("\n");
      
      
      if ((pedalState_read <= pedalState_old-POT_tol) || 
          (pedalState_read >= pedalState_old+POT_tol)){
        pedalState_new = pedalState_read;    
      }  
      if (pedalState_read <= POT_min+POT_tol){
        pedalState_new = POT_min; // Minimum potentiometer value
      }
      if (pedalState_read >= POT_max-POT_tol){
        pedalState_new = POT_max; // Maximum potentiometer value
      } 
      
      return pedalState_new;
    }
    
    // --- Exponential mapping from one interval to another ----------------------------
    int map_exponential(double value, double x, double y, double a, double b){
      int    ret_i = 0;
      double ret_d = 0.0;
      
      // linear:
      // ret = (value-x)/(y-x)*(b-a) + a;
      
      // logarithmus naturalis:
      // if (value != 0){
        // double ln = log(value-x);
        // double ln_ref = log(y-x);
        // ret = ln/ln_ref * (b-a);
      // }
      
      // square root:
      double sqrt     = pow(value, 0.5);
      double sqrt_ref = pow(y-x,   0.5);
      ret_d = sqrt/sqrt_ref * (b-a);
      ret_i = round(ret_d);
    
    
      
      return ret_i;
    }
    
    // --- Control the computer volume with the media keys -----------------------------
    void control_volume(){
      
      int pedalState_new = Pedal_read_state(); // Update pedalState
      if (pedalState_new != pedalState) {
        
        int system_volume_new = map_exponential(pedalState_new, POT_min, POT_max, 0, 100);
        
        while (system_volume < system_volume_new) {
          Consumer.write(MEDIA_VOLUME_UP);
          system_volume = system_volume + 2;
        }    
        while (system_volume > system_volume_new) {
          Consumer.write(MEDIA_VOLUME_DOWN);
          system_volume = system_volume - 2;
        }
        
        Serial.print("system_volume = ");
        Serial.print(system_volume);
        Serial.print("\n");
        
        pedalState = pedalState_new; // Update pedalState
      }
      
    }
    
    
    void GamePad_button_toggle(int currentButton){
      // "press" + "release" means we toggle the button
      // takes the footswitch mode into account to use buttons above 5
      Gamepad.press(currentButton + 1 + 5*(footswitch_mode-1));
      Gamepad.write();
      LED_flash(currentButton, FLASHDELAY/2);
      Gamepad.release(currentButton + 1 + 5*(footswitch_mode-1));
      Gamepad.write();
    }
     

     

     

  2. While Rocksmith did help me with guitar technique and playing existing songs, after more than a year it did not really help me with getting creative with my guitar. At first I was fine with that, but at some point I wanted to go beyond just replaying existing songs. Rocksmith's session mode helped me to get a start on improvising, but there is just some theory and knowledge that you need to know that goes beyond what session mode can offer.

     

    So I took weekly one-on-one lessons for about 10 months and it was a great thing. I just moved to a different city and haven't looked for a new teacher yet, but that time has helped me a lot. I can know come up with songs of my own - something I did not think could be possible one or two years ago. I am not the most creative person in general, which is part of way I am not yet satisfied with my songwriting. But learing more technique helps with that.

     

    All in all: Taking lessons helped me to go beyond where Rocksmith could ever take me. I still use Rocksmith on a daily basis to learn songs I like, and when I feel "lazy" (as in: just want to play without having to think much).

    Thus, I can recommend the combination of Rocksmith and a real teacher to anyone :-)

    • Like 3
  3. A friend of mine has some of those 2-line displays and once I toyed around with them to see if I could get them working. I did, and we even considered cutting the board up, but soon realized there was not enough space to fit it in...

    You could make an external case and/or stick it to the backside of the board... but in the end I considered that to much effort. I know all the modes of my program and use the LEDs to give me hints where possible, so a display is not really necessary for me.

    I did, however, integrate a lot of Serial.print() commands into the code. So you can pop up the serial printer and it shows you some of the stuff you would probably want to put on a display. Should help understand the functions ;-)

    • Like 1
  4. @@KingCobra

    Actually I'm glad someone asked :)

     

    Here is my latest .ino version:

    https://dl.dropboxusercontent.com/u/8722253/Arduino/sketch_footswitch_08.ino

    Edit: New link

    https://www.dropbox.com/s/96tsou813nt3o51/sketch_footswitch.ino?dl=0

     

    I have continued working on my program and now use it for other applications and games!
     

     

    Sketch for a USB-controlled guitar footswitch with five buttons and LEDs
      - for the use in Rocksmith 2014
        * via USB keyboard emulation
      - for the use with AmpliTube 4
        * via MIDI signals
      - for the use in Reaper (Digital Audio Workstation)
        * via USB keyboard emulation (shortcuts assigned within Reaper)
      - for the use as a regular GamePad
        * HID library makes Windows recognize it

     

     

    I also attached a volume pedal (by Ernie Ball) to the Arduino, specifically the pedal's potentiometer, to be able to send analog signals to the PC.

    I use this for Window's volume control and scrolling inside Rocksmith. But the main purpose was to enable the control of virtual pedal boards in AmpliTube 4.

     

    So... the program now has many more functions than you might need... or maybe you will like them, too! You can download a free trial version of AmpliTube 4, it works with the Rocksmith Cable.

     

    If you have questions or suggestions for improvement, please let me know!

    • Like 1
  5. "New parameter in the configuration file to adjust or not the density status of chords"

    "the ability to fix the chord density status in old CDLCs"

     

    @Chilipouni

    thanks for you hard work! Regarding those two quotes for version 3.2, is there anything we have to change in the configuration file to make the density fix work?

    • I downloaded 3.2 beta
    • replaced all the 3.1 files in the Rocksmitih Custom Song Toolkit ddc subfolder (and Toolkit now shows DDC's version as 3.2)
    • Imported an old custom into toolkit
    • changed version number
    • hit generate in the toolkit

    Result:

    • the 100% bug is fixed
    • repeated chords are shown full and not "ghosted" (= not fixed)

    Is the ddc beta supposed to fix that last issue, or does the "chord density status" mean something else?

     

    Cheers!

  6.  

    Stability increased -- random program freezes and crashes on multiple platforms should no longer occur.

    This is from the change log of the latest patch... so it is possible that ubisoft fixed it. But our bug appears to be quite random, so maybe Lacey just got lucky and they didn't fix it at all.

     

    Just for the record: I got to the point where I would prefer the "seperate metronome CLDC" idea over the current state ;-) (mainly because having the word metronome in the song title would allow sorting, creating lists and in general find metronome songs ingame faster)

  7. On the plus side, it is possible that the too many arrangements crashing issue has been fixed by Ubisoft in yesterday's update. 

     

    I had a few CDLCs that folks PM'ed me about saying that they crashed Remastered. They were the ones which had 6 arrangements (two each of lead, rhythm and bass). After receiving the update last night, I tried playing some of the ones that they specifically mentioned as party crashers. Every one of them played without crashing (there is still the issue of not being able to see the final arrangement - even though you can still select it - but that would be a major user interface "fix" and I don't see that happening as it only affects a small number of CDLCs). I will still update mine to only have DD arrangements, but this should be good news for TomSawyer2525 and Dredfoxx, and fans of their customs -- assuming it's true of their 6 arrangement customs as well.   :)

     

    Can anyone confirm or deny that the update fixed the crashes?

    • Like 1
  8. Metronome arrangement :

    I guess the toollkit could create a second CDLC with a different DLCID (and maybe a name that indicate which one is the original and which one have the metronome activated) to allow both CDLC to live together inside RS and still allow user to have access to every single arrangement without any issue.

     

    @@cozy1

    I was offline for quite a while, but now I would like to get back to topic concerning the metronome bonus arrangements:

    Would it be technically possible to change the tickbox "Create Metronome Bonus Arrangement" into "Create additional Metronome CDLC", as suggested by firekorn?

    The additional psarc could have "_M" in the name (just like "_DD" and "_NDD"), and the string "(Metronome)" added to the fields song title and song title sort.

     

    Cheers

  9. Well, now I had my first crash, with a version of my own custom generated by the remastered.exe I created for test purposes. Cannot tell if this is really linked, though.

     

    Now I am curious what the devs think about the "creating seperate metronome CDLCs" approach and whether it is technically possible. By the way: Wasn't there at some point the idea of packaging multiple songs into a single psarc file? This could remove another entry from my "cons" list :-)

  10. I guess I could live with seperate metronome DLCs... I see the following pros:

    • Potentially prevent crashes
    • Prevent bugged UI
    • With the word 'metronome' or similar in the song name, we can search them ingame easily
    • creating a dedicated metronome playlist and using it in non-stop play would become feasible
    • I already use seperate DLCs for official songs where I added the metronome

    ... and cons:

    • In an extreme case, our song lists become twice as long. This is visually more unpleasing to me than the bugged UI in the arrangement selection
    • Scrolling through the song list becomes more complicated (although this can be handled with playlists)
    • mastery progress info is seperated and becomes harder to track
    • When uploading, downloading and sharing we have to handle multiple files

     

    I will admit that the pros seem to outweight the cons. I am, however, not satisfied with the explanation that the arrangement number alone is the problem. I would instead assume that the problematic CDLC have some other unknown bug that might be worth finding.

     

     

     


    Even if RS doesn't necessarily crash as some seems to report (i still have to encounter a case like that myself...)

     

    Please try one of my customs and see if they work for you, just out of curiosity.

    https://www.dropbox.com/sh/dc9f5h8n0l8dkd0/AAB031VltmNa5vUnkVfbKJ3Fa?dl=0

    (Farin Urlaub and Jethro Tull are in E Standard, Devin Townsend is Open C)

     

    Can someone point me to a CDLC that is causing a crash?

     

     

     

    I believe the bonus arrangements above 5 can be reached with the mouse wheel, and selected with no problem.

    But the score attack vanishes down from the screen, and can't be selected

    Using the arrow key down and then 'enter', I can select score attack as well

    (did you edit your post in the meantime?^^)

    • Like 1
  11. @@firekorn

    I am still convinced that the metronome mode is the most feasible way to learn how to play music (in contrast to regular RS usage, where you only learn to play the notes of a song and remain ignorant about how your guitar actually sounds) inside of Rocksmith. So I think the metronome implementation in the toolkit was a major achievement and I see it somewhat under attack here. I could of course agree to not apply the metronome to e.g. bass and stick to 5 arrangements, but that is not an ideal solution.

    I think some further investigation is justified before condemning 5+ arrangement CDLCs in general. Since they work for me, I think there must be other/additional reasons for the crashes, not the fact of 5+ arrangements alone.

    • Like 3
  12. @@BluePotato Vocals don't count, only playable arrangement count and the maximum RS remaster tolerate is 5.

     

    All my CDLC have a total of 6 playable arrangements: Lead, Rhythm and Bass plus the same with enabled metronome. They play just fine ingame. But visually ingame only 5 are supported, because the "other arrangement" list can only show 4 entries. The last one is not displayed, but you can still select it with the arrow keys.

    • Like 2
  13. Hi and thanks for the hard work.

     

    1.

    Maybe I found a bug in version 2.7.1.0 (rev 93cf5e58):

    When I use "Load Package" in the CDLC Creator the first time after the program is started, everything is fine. But if I then load another package to generate the psarc of another song, the field "Album Sort" is not updated. Instead it shows the previous text. So I have to update it manually before I can generate the psarc. Can anyone confirm this issue?

     

    2.

    Is there any reason not to reupload my remastered CDLC with the current toolkit version? All my customs work fine but I am wondering if there are any bugs I might not see or things you would like to polish before people start publishing their CDLCs again...

     

     

    ----

    Also I have been wondering for a long time (but this is in no way a priority thing):

    Would it be possible to create an option in the "configuration" to always chain the CDLC Creator and DDC? So that I would only have to hit "Generate" on the Creator tab and DD is generated automatically with my default settings, giving me the final CDLC with one click? Now with RS Remastered there is no reason not to apply DDC anymore, thus we might as well make it default behaviour?

    • Like 1
  14. Here are my scores for Farin Urlaub - OK:

    Lead - 94.65 %

    Rhythm - 96.50 %

    Bass -  99.73 %

    I must say that I cannot agree with the difficulty 5 on Lead... the solo is too hard for an intermediate song, in my oppinion.

     

    ... to add to my own statement about the difficulty this week: I also feel like "Feel Good" Lead is much easier than "OK":

    Advanced Lead - 97.59 %

     

    This is my score after 9 tries and starting practicing after my last post 1h ago (I think I could go further, but the slides are killing my streaks...). So I would suggest:

    • "Feel Good" Lead - 5
    • "OK" Lead - 7

    ... with this I will stop rambling about the difficulty and go to sleep instead :D

    • Like 8
  15. Also, we still found several people linking to folders of their CDLC. We will be contacting users about this and give you a week to rectify it. After that we'll be updating the links our self's.

     

    If you have any questions feel free to ask them.

     

    Hi there,

     

    I always linked to folders to also make PC, MAC, XBox 360, PS3 versions available, and lots of people also host DD and non-DD versions of their customs... If we are supposed to directly link to a file, how should be provide the links for the other versions?

    Of course the easiest thing is to directly link to the PC version, and include links to all other platforms / DD versions in the description text.

    But in my oppinion the most logical thing would be to replace the four platform checkboxes from the edit dialog with input fields for download links. This could at least solve the platform issue

    • Like 2
  16. Hi everyone,

     

    maybe I searched the wrong way, but I couldn't find any threads on this topic, so here we go.

    Recently the desire came up to try and record my guitar playing and experiment with melodies that come out of my hands.

    I've owned Rocksmith now for more than 1.5 years, and never considered the possibility that the Rocksmith Cable would be good for more than Rocksmith itself - silly me!

    It works great with other guitar / recording software!

     

    So I started experimenting with different software and want to tell you about it - maybe you, too, have no clue about the potential of the hardware you already own. At the same time I would like to know if others already have experience in this field and would like to share some tips.

     

    Guitar Software

     

    The most important detail in the beginning: Its worth installing the free audio driver asio4all  to reduce the latency of the guitar audio signal - worked great for me!

     

    Rocksmith modifies the audio signal from your guitar to apply various effects, and it is by far not the only software to do that. There are lots of other options and all claim to be very authentic and highly sophisticated. They come with not-so-low price tags, but feature a wide range of simulated hardware.

     

    AmpliTube

    140 €

    It has a demo version with reduced features but without time limitations. It simulates pedals, amps, racks, cabinets and you can even adjust the microphone and its position in front of the amp. Feels like a less clunky version of Rocksmith's Tone Designer. You can also record your guitar with it. The free version has two recording tracks, the full version eigth. The full version also has a four-layer looper, which I am very tempted to try out. What I do not like is the fact that you cannot resize the window of the application. Especially in the recorder this is a shame, since I could see a lot more of the audio tracks in a full screen mode. But well.. its all about the tone, I guess.

    If you have something you can kick with your feet that sends out Midi signals (see my description) you can control many of AmpliTubes functions (start recording / looping / switching presets / enabling pedals) while playing your guitar - I love it!

    Finally, it also works as a VST plugin for most digital audio workstations (DAWs) - see below.

     

    Bias FX

    70 €

    Demo version is only for a limited time. Seems to basically have the same functionality as AmpliTube, minus the recorder and looper. Has a standalone application, but is primarily designed to be used as a DAW plugin. May be a bit cheaper than AmpliTube... but in both cases there is some much extra stuff you can purchase, that this is really hard to tell.

    Is featured heavily on quite a few YouTube channels I watch. I don't have the experience to tell weather it sounds better or worse than AmpliTube.

     

     

    DAW / recording software

     

    Digital audio workstations are programs that allow you all the fancy recording and mixing of you instruments and their tracks. You can apply FX plugins to your tracks to get the guitar sound that you are after.

     

    FL Studio 12

    90 €

    Demo version cannot open saved projects. Seems higly professional oriented, with fancy all-vectorized and scaleable interfaces (have a look here, AmpliTube). Had a quick look at it and couldn't get the AmpliTube plugin working - but that's just me, I guess.

     

    Reaper

    $ 60

    Not as fancy looking as FL Studio, but noticeably cheaper and packed with functionality. 60 day trial period. Plugins worked immediately, and recording my guitar, too! I really enjoy the "take" feature. If you record say your lead guitar on one track, but missed one note in your awesome solo, you can go there and record a few seconds again, on the same track. It adds a new take for the second recording, and you can choose the take with your best performance.

     

     

    Conclusions

    Currently I am using Reaper + AmpliTube to have fun experimenting with my first recording and didn't need to pay a dime up to this point - highly recommended!

     

    Now I want to know: What guitar sound software do you use? Do you like being completely digital, or do you record your amp with a real microphone?

    What software do you use to record your music? Do you have tips for useful freeware?

    Do you recommend paying about 200€ for Reaper + AmpliTube? Or should I invest in real hardware?

    Please note: I don't own an amp yet... all the time I have only been playing through Rocksmith... I figured I don't need an expensive amp when I play through cheapish headphones anyway.

     

    Thank for your time, and keep on rockin'! :)

    • Like 4
  17. Hi everyone,

     

    I'm coming back from quiet a long brake (seems like 97 had been my last week). While I was finishing my studies I couldn't keep up anymore :-) But now I'm done, and I'm looking forward to participating regulary, again!

     

    Having one go at Iron Maiden made me question whether I really was "advanced" before my brake, so instead I went with Intermediate... but it looks like next week will be Advanced, anyway^^

     

    Intermediate Lead: 99.11%

    http://steamcommunity.com/sharedfiles/filedetails/?id=596132451

     

    Cheers, and have a nice weekend!

    • Like 7
  18. Hi everyone, here are my scores for the week:

     

    Advanced:

     

    Lead: 97.75 %

    The solo is simply impossible for me, but I like the song :-)

    http://steamcommunity.com/sharedfiles/filedetails/?id=512275833

     

    Rhyhtm: 90 %

    http://steamcommunity.com/sharedfiles/filedetails/?id=512275675

     

    Bass: 98.3 %

    Such a funky song, but such a boring bass... Though I have to admit that I probably didn't get most of it right^^

    http://steamcommunity.com/sharedfiles/filedetails/?id=512275537

    • Like 7
×
×
  • Create New...

Important Information

By using this site, you agree to our Guidelines. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue. - Privacy Policy