<commit_before>import Client from './Client';

/**
 * WersiClient
 *
 * Implements a Wersi MK1 compatible Websocket client for sysexd.
 */
export default class WersiClient extends Client {
  /**
   * Block types
   */
  static BLOCK_TYPE = {
    REQUEST: 'r',     // Request block, used to request other blocks of data
    SWITCH: 's',      // Controls the instrument's switches (buttons)
    TRANSFORM: 't',   // Transform buffer
    ICB: 'i',         // Instrument control block
    VCF: 'v',         // VCF block
    FREQ: 'f',        // Frequency envelope block
    AMPL: 'a',        // Amplitude envelope block
    FIXWAVE: 'q',     // FIXWAVE wavetable block
    RELWAVE: 'w'      // RELWAVE wavetable block
  };
  
  /**
   * Wersi addresses
   *
   * [0:5]  Identifier (64)
   * [6]    RAM
   * [7]    Cartridge (unused)
   *
   * RAM (CV / Control Voice) address range is therefore [64:127].
   *
   * ICB addresses are layed out as follows, according to the technical manual:
   *
   * Instrument 65 (DRAWBAR):      special drawbar instrument. We ignore this instrument.
   * Instrument 66 (CV 1):         ICB 66 VCF 65 AMPL 65 FREQ 65 FIXWAVE 65 (Voice 1), 87, 86, 86, 86 (Voice 2).
   * ...
   * Instrument 75 (CV 10):        ICB 75 VCF 74 AMPL 74 FREQ 74 FIXWAVE 74 (Voice 1), 96, 95, 95, 95 (Voice 2).
   * Instrument 76 (CV 1 BANK 2):  ICB 76 VCF 75 AMPL 75 FREQ 75 FIXWAVE 75 (Voice 1), 97, 96, 96, 96 (Voice 2).
   * ...
   * Instrument 85 (CV 10 BANK 2): ICB 85 VCF 84 AMPL 84 FREQ 84 FIXWAVE 84 (Voice 1), 106, 105, 105, 105 (Voice 2).
   *
   * ICB address range: [66:85] (20).
   * RAM address range: [86:127] (42).
   */
  static ADDRESS = {
    // Maximum number of CVs
    maxCVs: 20,
    
    // Unique ICB address (range [0:19], includes BANK 2) and voice layer id (range [0:2])
    CV(id, voiceLayer) {
      const address = (!voiceLayer) ? (66 + id) : (87 + id + (voiceLayer - 1) * WersiClient.ADDRESS.maxCVs);
      return (id >= 0 && id < WersiClient.ADDRESS.maxCVs && address >= 64 && address < 128) ? address : null;
    },
    
    // Unique RAM address for VCF/AMPL/FREQ/FIXWAVE (range [0:19], includes BANK 2) and voice layer id (range [0:2])
    RAM(id, voiceLayer) {
      const address = (voiceLayer == 0) ? (65 + id) : (86 + id + (voiceLayer - 1) * WersiClient.ADDRESS.maxCVs);
      return (id >= 0 && id < WersiClient.ADDRESS.maxCVs && address >= 64 && address < 128) ? address : null;
    },
    
    // Reverse ICB to CV id mapping
    id(icbAddress) {
      return icbAddress - 66;
    },
    
    // Reverse ICB to layer id mapping
    layer(icbAddress) {
      return (icbAddress >= 66 && icbAddress < 87) ? 0 : ((icbAddress - 87) / WersiClient.ADDRESS.maxCVs) + 1;
    }
  };
  
  /**
   * Wersi instruction explanation for envelopes
   *
   * Instructions (reverse engineered so far):
   *
   *     FVVVVVVV | 0x0: delay V or infinite if F (0 to 5*127 = 635 ms)
   * VVVVVVVVVVVV | 0x1: set V
   * VVVVVVVVVVVV | 0x5: add V
   */
  static ENVELOPE = {
    TIMESTEP: 5,            // single instruction time step (5 ms)
    TIMESTEP7: 5 * 127,     // max time step for 7-bit values
    TIMESTEP12: 5 * 4095,  // max time step for 12-bit values
    
    delay: function(v, f) {
      return [
        0x00,
        v
      ];
    },
    set: function(v) {
      return [
        ((v & 0xF) << 4) | 0x1,
        (v >> 4) & 0xFF
      ];<commit_msg>Fixing rounding on layer number.<commit_after>import Client from './Client';

/**
 * WersiClient
 *
 * Implements a Wersi MK1 compatible Websocket client for sysexd.
 */
export default class WersiClient extends Client {
  /**
   * Block types
   */
  static BLOCK_TYPE = {
    REQUEST: 'r',     // Request block, used to request other blocks of data
    SWITCH: 's',      // Controls the instrument's switches (buttons)
    TRANSFORM: 't',   // Transform buffer
    ICB: 'i',         // Instrument control block
    VCF: 'v',         // VCF block
    FREQ: 'f',        // Frequency envelope block
    AMPL: 'a',        // Amplitude envelope block
    FIXWAVE: 'q',     // FIXWAVE wavetable block
    RELWAVE: 'w'      // RELWAVE wavetable block
  };
  
  /**
   * Wersi addresses
   *
   * [0:5]  Identifier (64)
   * [6]    RAM
   * [7]    Cartridge (unused)
   *
   * RAM (CV / Control Voice) address range is therefore [64:127].
   *
   * ICB addresses are layed out as follows, according to the technical manual:
   *
   * Instrument 65 (DRAWBAR):      special drawbar instrument. We ignore this instrument.
   * Instrument 66 (CV 1):         ICB 66 VCF 65 AMPL 65 FREQ 65 FIXWAVE 65 (Voice 1), 87, 86, 86, 86 (Voice 2).
   * ...
   * Instrument 75 (CV 10):        ICB 75 VCF 74 AMPL 74 FREQ 74 FIXWAVE 74 (Voice 1), 96, 95, 95, 95 (Voice 2).
   * Instrument 76 (CV 1 BANK 2):  ICB 76 VCF 75 AMPL 75 FREQ 75 FIXWAVE 75 (Voice 1), 97, 96, 96, 96 (Voice 2).
   * ...
   * Instrument 85 (CV 10 BANK 2): ICB 85 VCF 84 AMPL 84 FREQ 84 FIXWAVE 84 (Voice 1), 106, 105, 105, 105 (Voice 2).
   *
   * ICB address range: [66:85] (20).
   * RAM address range: [86:127] (42).
   */
  static ADDRESS = {
    // Maximum number of CVs
    maxCVs: 20,
    
    // Unique ICB address (range [0:19], includes BANK 2) and voice layer id (range [0:2])
    CV(id, voiceLayer) {
      const address = (!voiceLayer) ? (66 + id) : (87 + id + (voiceLayer - 1) * WersiClient.ADDRESS.maxCVs);
      return (id >= 0 && id < WersiClient.ADDRESS.maxCVs && address >= 64 && address < 128) ? address : null;
    },
    
    // Unique RAM address for VCF/AMPL/FREQ/FIXWAVE (range [0:19], includes BANK 2) and voice layer id (range [0:2])
    RAM(id, voiceLayer) {
      const address = (voiceLayer == 0) ? (65 + id) : (86 + id + (voiceLayer - 1) * WersiClient.ADDRESS.maxCVs);
      return (id >= 0 && id < WersiClient.ADDRESS.maxCVs && address >= 64 && address < 128) ? address : null;
    },
    
    // Reverse ICB to CV id mapping
    id(icbAddress) {
      return icbAddress - 66;
    },
    
    // Reverse ICB to layer id mapping
    layer(icbAddress) {
      return (icbAddress >= 66 && icbAddress < 87) ? 0 : Math.floor((icbAddress - 87) / WersiClient.ADDRESS.maxCVs) + 1;
    }
  };
  
  /**
   * Wersi instruction explanation for envelopes
   *
   * Instructions (reverse engineered so far):
   *
   *     FVVVVVVV | 0x0: delay V or infinite if F (0 to 5*127 = 635 ms)
   * VVVVVVVVVVVV | 0x1: set V
   * VVVVVVVVVVVV | 0x5: add V
   */
  static ENVELOPE = {
    TIMESTEP: 5,            // single instruction time step (5 ms)
    TIMESTEP7: 5 * 127,     // max time step for 7-bit values
    TIMESTEP12: 5 * 4095,  // max time step for 12-bit values
    
    delay: function(v, f) {
      return [
        0x00,
        v
      ];
    },
    set: function(v) {
      return [
        ((v & 0xF) << 4) | 0x1,
        (v >> 4) & 0xFF
      ];
{'fraction_non_alphanumeric': 0.13000733675715334, 'fraction_numerical': 0.0628026412325752, 'mean_word_length': 2.162877030162413, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 6, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2207814', 'n_tokens_mistral': 2812, 'n_tokens_neox': 2346, 'n_words': 814}