/ docs / developer-guide.html
developer-guide.html
  1  <!DOCTYPE html>
  2  <html lang="en">
  3  
  4  <head>
  5      <meta charset="UTF-8">
  6      <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7      <title>Developer Guide - BrowserEQ V2</title>
  8      <link rel="stylesheet" href="styles.css">
  9  </head>
 10  
 11  <body>
 12      <header>
 13          <div class="wave-decoration"></div>
 14          <div class="language-toggle">
 15              <button onclick="setLanguage('en')" class="active" id="en-btn">English</button>
 16              <button onclick="setLanguage('de')" id="de-btn">Deutsch</button>
 17          </div>
 18          <div class="container">
 19              <h1>BrowserEQ V2</h1>
 20              <p class="en">Developer Guide</p>
 21              <p class="de">Entwicklerhandbuch</p>
 22              <div class="github-buttons">
 23                  <a href="index.html">Home</a>
 24                  <a href="https://github.com/berraknil/BrowserEQ-V2" target="_blank">View on GitHub</a>
 25              </div>
 26          </div>
 27      </header>
 28  
 29      <nav>
 30          <ul>
 31              <li><a href="#architecture">Architecture</a></li>
 32              <li><a href="#data-flow">Data Flow</a></li>
 33              <li><a href="#audio-processing">Audio Processing</a></li>
 34              <li><a href="#presets">Presets</a></li>
 35              <li><a href="#adding-features">Adding Features</a></li>
 36          </ul>
 37      </nav>
 38  
 39      <main class="container">
 40          <section id="introduction">
 41              <div class="en">
 42                  <p>This guide provides detailed information for developers who want to understand, modify, or contribute
 43                      to the BrowserEQ project.</p>
 44              </div>
 45              <div class="de">
 46                  <p>Dieses Handbuch bietet detaillierte Informationen für Entwickler, die das BrowserEQ-Projekt
 47                      verstehen, modifizieren oder dazu beitragen möchten.</p>
 48              </div>
 49          </section>
 50  
 51          <section id="architecture">
 52              <h2 class="en">Architecture Overview</h2>
 53              <h2 class="de">Architekturübersicht</h2>
 54  
 55              <div class="en">
 56                  <p>BrowserEQ uses a Vue 3 frontend with the Composition API, combined with Web Audio API for audio
 57                      processing. The extension follows a component-based architecture:</p>
 58                  <div class="code-block">
 59                      <pre>UI Components (Vue) → Audio Logic (TypeScript) → Web Audio API → Browser Audio</pre>
 60                  </div>
 61  
 62                  <h3>Key Components</h3>
 63                  <ol>
 64                      <li><strong>Popup.vue</strong>: The main component that renders the user interface and orchestrates
 65                          the other components.</li>
 66                      <li><strong>PresetManager.vue</strong>: Handles preset selection and management.</li>
 67                      <li><strong>Strip.vue</strong>: Represents a single filter strip with its controls.</li>
 68                      <li><strong>Slider.vue & Toggle.vue</strong>: Reusable UI controls.</li>
 69                  </ol>
 70  
 71                  <h3>Core Logic Modules</h3>
 72                  <ol>
 73                      <li><strong>audioProcessing.ts</strong>: Contains the Web Audio API implementation.</li>
 74                      <li><strong>EQValues.ts</strong>: Defines the default presets.</li>
 75                      <li><strong>presetStorage.ts</strong>: Manages storing preferences in localStorage.</li>
 76                      <li><strong>recordingService.ts</strong>: Handles audio recording functionality.</li>
 77                  </ol>
 78              </div>
 79  
 80              <div class="de">
 81                  <p>BrowserEQ verwendet ein Vue 3 Frontend mit der Composition API, kombiniert mit der Web Audio API für
 82                      die Audioverarbeitung. Die Erweiterung folgt einer komponentenbasierten Architektur:</p>
 83                  <div class="code-block">
 84                      <pre>UI-Komponenten (Vue) → Audio-Logik (TypeScript) → Web Audio API → Browser-Audio</pre>
 85                  </div>
 86  
 87                  <h3>Hauptkomponenten</h3>
 88                  <ol>
 89                      <li><strong>Popup.vue</strong>: Die Hauptkomponente, die die Benutzeroberfläche rendert und die
 90                          anderen Komponenten orchestriert.</li>
 91                      <li><strong>PresetManager.vue</strong>: Verwaltet die Voreinstellungsauswahl und -verwaltung.</li>
 92                      <li><strong>Strip.vue</strong>: Repräsentiert einen einzelnen Filterstreifen mit seinen
 93                          Steuerelementen.</li>
 94                      <li><strong>Slider.vue & Toggle.vue</strong>: Wiederverwendbare UI-Steuerelemente.</li>
 95                  </ol>
 96  
 97                  <h3>Kern-Logikmodule</h3>
 98                  <ol>
 99                      <li><strong>audioProcessing.ts</strong>: Enthält die Web Audio API-Implementierung.</li>
100                      <li><strong>EQValues.ts</strong>: Definiert die Standardvoreinstellungen.</li>
101                      <li><strong>presetStorage.ts</strong>: Verwaltet die Speicherung von Einstellungen im localStorage.
102                      </li>
103                      <li><strong>recordingService.ts</strong>: Handhabt die Audio-Aufnahmefunktionalität.</li>
104                  </ol>
105              </div>
106          </section>
107  
108          <section id="data-flow">
109              <h2 class="en">Data Flow</h2>
110              <h2 class="de">Datenfluss</h2>
111  
112              <div class="en">
113                  <ol>
114                      <li>User interacts with UI components (sliders, toggles, buttons)</li>
115                      <li>Component emits events to parent (Popup.vue)</li>
116                      <li>Popup.vue updates the current preset state</li>
117                      <li>Audio processing logic applies changes to Web Audio nodes</li>
118                      <li>Preferences can be stored in localStorage</li>
119                  </ol>
120  
121                  <h3>Key Interfaces</h3>
122                  <p>The core data structures are defined in several places:</p>
123                  <div class="code-block">
124                      <pre>// EQ Preset structure
125  interface EQPreset {
126    mainOut: {
127      gain: number;
128      muted: boolean;
129    };
130    filters: {
131      [key: string]: EQFilter;
132    };
133  }
134  
135  // Individual filter structure
136  interface EQFilter {
137    name: string;
138    type: BiquadFilterType;  // Web Audio API filter type
139    enabled: boolean;
140    frequency: {
141      value: number;
142    };
143    Q?: {
144      name: string;
145      value: number;
146    };
147    gain?: {
148      value: number;
149    };
150  }</pre>
151                  </div>
152              </div>
153  
154              <div class="de">
155                  <ol>
156                      <li>Benutzer interagiert mit UI-Komponenten (Schieberegler, Umschalter, Buttons)</li>
157                      <li>Komponente sendet Ereignisse an übergeordnetes Element (Popup.vue)</li>
158                      <li>Popup.vue aktualisiert den aktuellen Voreinstellungsstatus</li>
159                      <li>Audio-Verarbeitungslogik wendet Änderungen auf Web Audio-Knoten an</li>
160                      <li>Einstellungen können im localStorage gespeichert werden</li>
161                  </ol>
162  
163                  <h3>Wichtige Schnittstellen</h3>
164                  <p>Die Kerndatenstrukturen sind an mehreren Stellen definiert:</p>
165                  <div class="code-block">
166                      <pre>// EQ-Voreinstellungsstruktur
167  interface EQPreset {
168    mainOut: {
169      gain: number;
170      muted: boolean;
171    };
172    filters: {
173      [key: string]: EQFilter;
174    };
175  }
176  
177  // Individuelle Filterstruktur
178  interface EQFilter {
179    name: string;
180    type: BiquadFilterType;  // Web Audio API Filtertyp
181    enabled: boolean;
182    frequency: {
183      value: number;
184    };
185    Q?: {
186      name: string;
187      value: number;
188    };
189    gain?: {
190      value: number;
191    };
192  }</pre>
193                  </div>
194              </div>
195          </section>
196  
197          <section id="audio-processing">
198              <h2 class="en">Audio Processing Pipeline</h2>
199              <h2 class="de">Audio-Verarbeitungspipeline</h2>
200  
201              <div class="en">
202                  <ol>
203                      <li><strong>Capture</strong>: The extension captures tab audio using <code>chrome.tabCapture</code>.
204                      </li>
205                      <li><strong>Source Creation</strong>: A MediaStreamAudioSourceNode is created from the capture.</li>
206                      <li><strong>Filter Chain</strong>: Audio is routed through various BiquadFilterNode instances based
207                          on user settings.</li>
208                      <li><strong>Gain Node</strong>: Final processing includes volume adjustment through a GainNode.</li>
209                      <li><strong>Output</strong>: Processed audio is sent to the AudioContext destination.</li>
210                  </ol>
211  
212                  <div class="code-block">
213                      <pre>MediaStreamSource → [Enabled Filters] → GainNode → AudioContext.destination</pre>
214                  </div>
215  
216                  <h3>Filter Connectivity Logic</h3>
217                  <p>The system dynamically connects and disconnects filters when users toggle them:</p>
218                  <ol>
219                      <li>When enabling a filter, it's inserted into the chain at the appropriate point.</li>
220                      <li>When disabling a filter, it's bypassed, and the chain is reconnected.</li>
221                      <li>The <code>lastFilter</code> reference always points to the last active filter in the chain.</li>
222                  </ol>
223              </div>
224  
225              <div class="de">
226                  <ol>
227                      <li><strong>Erfassung</strong>: Die Erweiterung erfasst Tab-Audio mit
228                          <code>chrome.tabCapture</code>.
229                      </li>
230                      <li><strong>Quellenerstellung</strong>: Ein MediaStreamAudioSourceNode wird aus der Erfassung
231                          erstellt.</li>
232                      <li><strong>Filterkette</strong>: Audio wird durch verschiedene BiquadFilterNode-Instanzen basierend
233                          auf Benutzereinstellungen geleitet.</li>
234                      <li><strong>Verstärkungsknoten</strong>: Abschließende Verarbeitung umfasst Lautstärkeanpassung
235                          durch einen GainNode.</li>
236                      <li><strong>Ausgabe</strong>: Verarbeitetes Audio wird an das AudioContext-Ziel gesendet.</li>
237                  </ol>
238  
239                  <div class="code-block">
240                      <pre>MediaStreamSource → [Aktivierte Filter] → GainNode → AudioContext.destination</pre>
241                  </div>
242  
243                  <h3>Filterverbindungslogik</h3>
244                  <p>Das System verbindet und trennt Filter dynamisch, wenn Benutzer sie umschalten:</p>
245                  <ol>
246                      <li>Beim Aktivieren eines Filters wird er an der entsprechenden Stelle in die Kette eingefügt.</li>
247                      <li>Beim Deaktivieren eines Filters wird er umgangen, und die Kette wird neu verbunden.</li>
248                      <li>Die <code>lastFilter</code>-Referenz zeigt immer auf den letzten aktiven Filter in der Kette.
249                      </li>
250                  </ol>
251              </div>
252          </section>
253  
254          <section id="presets">
255              <h2 class="en">Preset Management</h2>
256              <h2 class="de">Voreinstellungsverwaltung</h2>
257  
258              <div class="en">
259                  <p>The preset system works as follows:</p>
260                  <ol>
261                      <li>Default presets are defined in <code>EQValues.ts</code> and serve as the source of truth.</li>
262                      <li>User preferences may be stored in localStorage for persistence between sessions.</li>
263                  </ol>
264  
265                  <h3>Deep Copy Implementation</h3>
266                  <p>To avoid reference issues, presets are deep-copied using a custom function:</p>
267                  <div class="code-block">
268                      <pre>function deepCopyPreset(preset: EQPreset): EQPreset {
269    // Creates a new object with all nested properties copied
270    // This prevents issues with shared references
271  }</pre>
272                  </div>
273  
274                  <h3>Reactive State Management</h3>
275                  <p>The extension uses Vue 3's reactivity system:</p>
276                  <ol>
277                      <li><code>ref</code> and <code>computed</code> are used for reactive state.</li>
278                      <li>Watchers (<code>watch</code>) observe changes to critical values like sliders.</li>
279                      <li>Two-way binding with <code>v-model</code> connects UI elements to state.</li>
280                  </ol>
281  
282                  <h3>LocalStorage Schema</h3>
283                  <p>Preferences are stored in localStorage for persistence:</p>
284                  <div class="code-block">
285                      <pre>// Key format example
286  {
287    "selectedPreset": "Neutral",
288    // other settings...
289  }</pre>
290                  </div>
291              </div>
292  
293              <div class="de">
294                  <p>Das Voreinstellungssystem funktioniert wie folgt:</p>
295                  <ol>
296                      <li>Standardvoreinstellungen sind in <code>EQValues.ts</code> definiert und dienen als Quelle der
297                          Wahrheit.</li>
298                      <li>Benutzereinstellungen können im localStorage für die Persistenz zwischen Sitzungen gespeichert
299                          werden.</li>
300                  </ol>
301  
302                  <h3>Deep-Copy-Implementierung</h3>
303                  <p>Um Referenzprobleme zu vermeiden, werden Voreinstellungen mit einer benutzerdefinierten Funktion tief
304                      kopiert:</p>
305                  <div class="code-block">
306                      <pre>function deepCopyPreset(preset: EQPreset): EQPreset {
307    // Erstellt ein neues Objekt mit allen verschachtelten Eigenschaften kopiert
308    // Dies verhindert Probleme mit gemeinsam genutzten Referenzen
309  }</pre>
310                  </div>
311  
312                  <h3>Reaktive Zustandsverwaltung</h3>
313                  <p>Die Erweiterung verwendet das Reaktivitätssystem von Vue 3:</p>
314                  <ol>
315                      <li><code>ref</code> und <code>computed</code> werden für den reaktiven Zustand verwendet.</li>
316                      <li>Beobachter (<code>watch</code>) überwachen Änderungen an kritischen Werten wie Schiebereglern.
317                      </li>
318                      <li>Zwei-Wege-Bindung mit <code>v-model</code> verbindet UI-Elemente mit dem Zustand.</li>
319                  </ol>
320  
321                  <h3>LocalStorage-Schema</h3>
322                  <p>Einstellungen werden im localStorage für die Persistenz gespeichert:</p>
323                  <div class="code-block">
324                      <pre>// Schlüsselformat-Beispiel
325  {
326    "selectedPreset": "Neutral",
327    // andere Einstellungen...
328  }</pre>
329                  </div>
330              </div>
331          </section>
332  
333          <section id="adding-features">
334              <h2 class="en">Adding New Features</h2>
335              <h2 class="de">Neue Funktionen hinzufügen</h2>
336  
337              <div class="en">
338                  <h3>Adding a New Preset</h3>
339                  <ol>
340                      <li>Add the preset definition to <code>EQValues.ts</code>:
341                          <div class="code-block">
342                              <pre>NewPreset: {
343    mainOut: { gain: 1.0, muted: false },
344    filters: {
345      // Define filter settings
346    }
347  }</pre>
348                          </div>
349                      </li>
350                      <li>The UI will automatically include the new preset in the dropdown menu.</li>
351                  </ol>
352  
353                  <h3>Adding a New Filter Type</h3>
354                  <ol>
355                      <li>Add the filter to the base preset in <code>EQValues.ts</code>.</li>
356                      <li>Create UI elements in <code>Popup.vue</code> for the new filter.</li>
357                      <li>Update <code>audioProcessing.ts</code> to handle the new filter type.</li>
358                      <li>Update related logic as needed.</li>
359                  </ol>
360  
361                  <h3>Common Pitfalls</h3>
362                  <ol>
363                      <li><strong>Reference Issues</strong>: Always use deep copies when working with preset objects to
364                          avoid unintended changes.</li>
365                      <li><strong>Web Audio API Timing</strong>: Be aware that some audio operations must be carefully
366                          timed to avoid clicks and pops.</li>
367                      <li><strong>Chrome Extension Context</strong>: Remember that the extension runs in an isolated
368                          context with security restrictions.</li>
369                  </ol>
370              </div>
371  
372              <div class="de">
373                  <h3>Hinzufügen einer neuen Voreinstellung</h3>
374                  <ol>
375                      <li>Fügen Sie die Voreinstellungsdefinition zu <code>EQValues.ts</code> hinzu:
376                          <div class="code-block">
377                              <pre>NewPreset: {
378    mainOut: { gain: 1.0, muted: false },
379    filters: {
380      // Filtereinstellungen definieren
381    }
382  }</pre>
383                          </div>
384                      </li>
385                      <li>Die Benutzeroberfläche wird die neue Voreinstellung automatisch im Dropdown-Menü aufnehmen.</li>
386                  </ol>
387  
388                  <h3>Hinzufügen eines neuen Filtertyps</h3>
389                  <ol>
390                      <li>Füge den Filter zur Basisvoreinstellung in <code>EQValues.ts</code> hinzu.</li>
391                      <li>Erstelle UI-Elemente in <code>Popup.vue</code> für den neuen Filter.</li>
392                      <li>Aktualisiere <code>audioProcessing.ts</code>, um den neuen Filtertyp zu handhaben.</li>
393                      <li>Aktualisiere die zugehörige Logik nach Bedarf.</li>
394                  </ol>
395  
396                  <h3>Häufige Fallstricke</h3>
397                  <ol>
398                      <li><strong>Referenzprobleme</strong>: Verwenden Sie immer tiefe Kopien, wenn Sie mit
399                          Voreinstellungsobjekten arbeiten, um unbeabsichtigte Änderungen zu vermeiden.</li>
400                      <li><strong>Web Audio API Timing</strong>: Beachten Sie, dass einige Audiooperationen sorgfältig
401                          zeitlich abgestimmt werden müssen, um Klicks und Knackgeräusche zu vermeiden.</li>
402                      <li><strong>Chrome-Erweiterungskontext</strong>: Denken Sie daran, dass die Erweiterung in einem
403                          isolierten Kontext mit Sicherheitsbeschränkungen ausgeführt wird.</li>
404                  </ol>
405              </div>
406          </section>
407  
408          <section id="build-and-test">
409              <h2 class="en">Build Process</h2>
410              <h2 class="de">Build-Prozess</h2>
411  
412              <div class="en">
413                  <p>The project uses Vite for building:</p>
414                  <ol>
415                      <li><strong>Development</strong>: <code>npm run dev</code> - Builds in development mode with hot
416                          reloading.</li>
417                      <li><strong>Production</strong>: <code>npm run build</code> - Creates a production version in the
418                          <code>extension</code> folder.
419                      </li>
420                      <li><strong>Testing</strong>: Load the <code>extension</code> folder as an unpacked extension in
421                          Chrome.</li>
422                  </ol>
423  
424                  <h3>Testing</h3>
425                  <p>We recommend testing your changes in these scenarios:</p>
426                  <ol>
427                      <li><strong>Different Content Types</strong>: Test with music, voice calls, videos, etc.</li>
428                      <li><strong>Edge Cases</strong>: Test with extreme filter settings and combinations.</li>
429                      <li><strong>Performance</strong>: Ensure changes don't cause audio glitches or high CPU usage.</li>
430                  </ol>
431              </div>
432  
433              <div class="de">
434                  <p>Das Projekt verwendet Vite zum Erstellen:</p>
435                  <ol>
436                      <li><strong>Entwicklung</strong>: <code>npm run dev</code> - Erstellt im Entwicklungsmodus mit Hot
437                          Reloading.</li>
438                      <li><strong>Produktion</strong>: <code>npm run build</code> - Erstellt eine Produktionsversion im
439                          Ordner <code>extension</code>.</li>
440                      <li><strong>Tests</strong>: Laden Sie den Ordner <code>extension</code> als entpackte Erweiterung in
441                          Chrome.</li>
442                  </ol>
443  
444                  <h3>Testen</h3>
445                  <p>Wir empfehlen, Ihre Änderungen in diesen Szenarien zu testen:</p>
446                  <ol>
447                      <li><strong>Verschiedene Inhaltstypen</strong>: Testen Sie mit Musik, Sprachanrufen, Videos usw.
448                      </li>
449                      <li><strong>Randfälle</strong>: Testen Sie mit extremen Filtereinstellungen und Kombinationen.</li>
450                      <li><strong>Leistung</strong>: Stellen Sie sicher, dass Änderungen keine Audioprobleme oder hohe
451                          CPU-Auslastung verursachen.</li>
452                  </ol>
453              </div>
454          </section>
455  
456          <section id="resources">
457              <h2 class="en">Resources</h2>
458              <h2 class="de">Ressourcen</h2>
459  
460              <div class="en">
461                  <ul>
462                      <li><a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API" target="_blank">Web
463                              Audio API Documentation</a></li>
464                      <li><a href="https://v3.vuejs.org/" target="_blank">Vue 3 Documentation</a></li>
465                      <li><a href="https://developer.chrome.com/docs/extensions/reference/" target="_blank">Chrome
466                              Extension API</a></li>
467                  </ul>
468              </div>
469  
470              <div class="de">
471                  <ul>
472                      <li><a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API" target="_blank">Web
473                              Audio API Dokumentation</a></li>
474                      <li><a href="https://v3.vuejs.org/" target="_blank">Vue 3 Dokumentation</a></li>
475                      <li><a href="https://developer.chrome.com/docs/extensions/reference/" target="_blank">Chrome
476                              Extension API</a></li>
477                  </ul>
478              </div>
479          </section>
480      </main>
481  
482      <footer>
483          <div class="container">
484              <div class="en">
485                  <p>BrowserEQ V2 - <a href="https://github.com/berraknil/BrowserEQ-V2">GitHub Repository</a> | <a
486                          href="index.html">Home</a></p>
487              </div>
488              <div class="de">
489                  <p>BrowserEQ V2 - <a href="https://github.com/berraknil/BrowserEQ-V2">GitHub-Repository</a> | <a
490                          href="index.html">Startseite</a></p>
491              </div>
492          </div>
493      </footer>
494  
495      <script>
496          function setLanguage(lang) {
497              if (lang === 'de') {
498                  document.body.classList.add('german');
499                  document.getElementById('de-btn').classList.add('active');
500                  document.getElementById('en-btn').classList.remove('active');
501              } else {
502                  document.body.classList.remove('german');
503                  document.getElementById('en-btn').classList.add('active');
504                  document.getElementById('de-btn').classList.remove('active');
505              }
506          }
507      </script>
508  </body>
509  
510  </html>