Team Ai
Apppublic

iamdjbones/ethervox-vocal-processor

sourceHugging Faceupdated 9mo agoView on Hugging Face
0likes
ether-plugin.js201 linesDownload Raw Back to components
1class EtherPlugin extends HTMLElement {2  constructor() {3    super();4    this.attachShadow({ mode: 'open' });5    this.shadowRoot.innerHTML = `6      <style>7        :host {8          display: block;9          max-width: 320px;10          background: linear-gradient(145deg, #083344, #0e7490);11          border-radius: 12px;12          padding: 20px;13          box-shadow: 0 10px 25px rgba(0, 0, 0, 0.3);14          font-family: 'Inter', sans-serif;15        }16        17        .plugin-container {18          display: flex;19          flex-direction: column;20          gap: 20px;21        }22        23        .title {24          color: #f97316;25          text-align: center;26          font-size: 24px;27          font-weight: 700;28          margin-bottom: 10px;29          text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);30        }31        32        .knob-container {33          display: flex;34          flex-direction: column;35          align-items: center;36        }37        38        .knob {39          width: 70px;40          height: 70px;41          border-radius: 50%;42          background: linear-gradient(145deg, #0f172a, #1e293b);43          position: relative;44          box-shadow: 0 4px 15px rgba(0, 0, 0, 0.4);45          margin-bottom: 10px;46        }47        48        .knob::after {49          content: '';50          position: absolute;51          top: 5px;52          left: 5px;53          right: 5px;54          bottom: 5px;55          background: linear-gradient(145deg, #1e293b, #0f172a);56          border-radius: 50%;57          box-shadow: inset 0 2px 5px rgba(0, 0, 0, 0.5);58        }59        60        .knob-indicator {61          position: absolute;62          top: 10%;63          left: 50%;64          width: 3px;65          height: 20%;66          background: #f97316;67          transform-origin: bottom center;68          transform: translateX(-50%) rotate(0deg);69          z-index: 1;70        }71        72        .knob-label {73          color: #f8fafc;74          font-size: 14px;75          font-weight: 500;76          text-transform: uppercase;77          letter-spacing: 1px;78        }79        80        .knob-value {81          color: #f97316;82          font-size: 12px;83          font-weight: 600;84          margin-top: 4px;85        }86      </style>87      88      <div class="plugin-container">89        <div class="title">ETHER</div>90        91        <div class="knob-container">92          <div class="knob" id="ether">93            <div class="knob-indicator" id="ether-indicator"></div>94          </div>95          <div class="knob-label">Compression</div>96          <div class="knob-value" id="ether-value">50%</div>97        </div>98        99        <div class="knob-container">100          <div class="knob" id="gas">101            <div class="knob-indicator" id="gas-indicator"></div>102          </div>103          <div class="knob-label">Brightness</div>104          <div class="knob-value" id="gas-value">50%</div>105        </div>106        107        <div class="knob-container">108          <div class="knob" id="fire">109            <div class="knob-indicator" id="fire-indicator"></div>110          </div>111          <div class="knob-label">Body</div>112          <div class="knob-value" id="fire-value">50%</div>113        </div>114      </div>115    `;116    117    this.etherValue = 50;118    this.gasValue = 50;119    this.fireValue = 50;120  }121  122  connectedCallback() {123    this.setupKnob('ether', 'ether-indicator', 'ether-value', value => {124      this.etherValue = value;125      this.updateAudioProcessing();126    });127    128    this.setupKnob('gas', 'gas-indicator', 'gas-value', value => {129      this.gasValue = value;130      this.updateAudioProcessing();131    });132    133    this.setupKnob('fire', 'fire-indicator', 'fire-value', value => {134      this.fireValue = value;135      this.updateAudioProcessing();136    });137  }138  139  setupKnob(knobId, indicatorId, valueId, callback) {140    const knob = this.shadowRoot.getElementById(knobId);141    const indicator = this.shadowRoot.getElementById(indicatorId);142    const valueDisplay = this.shadowRoot.getElementById(valueId);143    let isDragging = false;144    145    const rotateKnob = (e, centerX, centerY) => {146      if (!isDragging) return;147      148      const rect = knob.getBoundingClientRect();149      const center = {150        x: centerX || rect.left + rect.width / 2,151        y: centerY || rect.top + rect.height / 2152      };153      154      const angle = Math.atan2(e.clientY - center.y, e.clientX - center.x) * (180 / Math.PI) + 90;155      const normalizedAngle = (angle < 0 ? angle + 360 : angle) % 360;156      const value = Math.min(100, Math.max(0, Math.round(normalizedAngle / 3.6)));157      158      indicator.style.transform = `translateX(-50%) rotate(${normalizedAngle}deg)`;159      valueDisplay.textContent = `${value}%`;160      callback(value);161    };162    163    knob.addEventListener('mousedown', (e) => {164      isDragging = true;165      rotateKnob(e);166    });167    168    window.addEventListener('mousemove', rotateKnob);169    window.addEventListener('mouseup', () => {170      isDragging = false;171    });172    173    knob.addEventListener('touchstart', (e) => {174      isDragging = true;175      const touch = e.touches[0];176      const rect = knob.getBoundingClientRect();177      rotateKnob(touch, rect.left + rect.width / 2, rect.top + rect.height / 2);178      e.preventDefault();179    });180    181    window.addEventListener('touchmove', (e) => {182      if (isDragging) {183        const touch = e.touches[0];184        const rect = knob.getBoundingClientRect();185        rotateKnob(touch, rect.left + rect.width / 2, rect.top + rect.height / 2);186        e.preventDefault();187      }188    });189    190    window.addEventListener('touchend', () => {191      isDragging = false;192    });193  }194  195  updateAudioProcessing() {196    // In a real VST plugin, this would interface with the audio processing code197    console.log(`Processing audio with Ether: ${this.etherValue}%, Gas: ${this.gasValue}%, Fire: ${this.fireValue}%`);198  }199}200 201customElements.define('ether-plugin', EtherPlugin);