From bd9afc78632bf63a7f705548e3a09148a1f860f8 Mon Sep 17 00:00:00 2001 From: gornvan Date: Wed, 9 Oct 2024 21:21:10 +0200 Subject: [PATCH 1/8] Define and implement mic-tester tool --- src/tools/mic-tester/index.ts | 12 +++ src/tools/mic-tester/mic-tester.vue | 121 ++++++++++++++++++++++++++++ 2 files changed, 133 insertions(+) create mode 100644 src/tools/mic-tester/index.ts create mode 100644 src/tools/mic-tester/mic-tester.vue diff --git a/src/tools/mic-tester/index.ts b/src/tools/mic-tester/index.ts new file mode 100644 index 000000000..725e9f2c8 --- /dev/null +++ b/src/tools/mic-tester/index.ts @@ -0,0 +1,12 @@ +import { Microphone } from '@vicons/tabler'; +import { defineTool } from '../tool'; +import { translate } from '@/plugins/i18n.plugin'; + +export const tool = defineTool({ + name: translate('tools.mic-tester.title'), + path: '/mic-tester', + description: translate('tools.mic-tester.description'), + keywords: ['mic', 'microphone', 'test', 'check', 'troubleshoot', 'sound'], + component: () => import('./mic-tester.vue'), + icon: Microphone, +}); diff --git a/src/tools/mic-tester/mic-tester.vue b/src/tools/mic-tester/mic-tester.vue new file mode 100644 index 000000000..6bbda911c --- /dev/null +++ b/src/tools/mic-tester/mic-tester.vue @@ -0,0 +1,121 @@ + + + + + + From cd96bf63177d07d19f900f5238766199f0f57898 Mon Sep 17 00:00:00 2001 From: gornvan Date: Wed, 9 Oct 2024 21:25:49 +0200 Subject: [PATCH 2/8] Create localizations for mic-tester component in de, en and pl (also initialize the pl localization, adding it to the dropdown selector at the top of the page) --- locales/de.yml | 5 ++ locales/en.yml | 6 ++ locales/pl.yml | 87 +++++++++++++++++++ .../i18n/components/locale-selector.vue | 1 + 4 files changed, 99 insertions(+) create mode 100644 locales/pl.yml diff --git a/locales/de.yml b/locales/de.yml index e59ca1144..d6a8ac0a3 100644 --- a/locales/de.yml +++ b/locales/de.yml @@ -281,6 +281,11 @@ tools: mime-types: title: MIME-Typen description: Konvertiere MIME-Typen in Erweiterungen und umgekehrt. + start-button-text: Mikrofon-Wiedergabe Starten + stop-button-text: Mikrofon-Wiedergabe Stoppen + mic-tester: + title: Mikrofonprufung + description: Wiedergabe und Visualisierung des Tons von Ihrem Mikrofon, mit einer Sekunde Verzögerung hinzugefügt toml-to-json: title: TOML zu JSON description: Parse und konvertiere TOML zu JSON. diff --git a/locales/en.yml b/locales/en.yml index d1cd21c47..4f3139f85 100644 --- a/locales/en.yml +++ b/locales/en.yml @@ -240,6 +240,12 @@ tools: title: MIME types description: Convert MIME types to file extensions and vice-versa. + mic-tester: + title: Microphone Tester + description: Replay and Visualize sound from Your microphone, with added one second of delay + start-button-text: Start replaying microphone + stop-button-text: Stop replaying microphone + toml-to-json: title: TOML to JSON description: Parse and convert TOML to JSON. diff --git a/locales/pl.yml b/locales/pl.yml new file mode 100644 index 000000000..e09128b96 --- /dev/null +++ b/locales/pl.yml @@ -0,0 +1,87 @@ +home: + categories: + newestTools: 'Najnowsze narzędzia' + favoriteTools: 'Twoje ulubione narzędzia' + allTools: 'Wszystkie narzędzia' + subtitle: 'Narzędzia dla programistów' + toggleMenu: 'Menu' + home: Strona główna + uiLib: 'UI Lib' + buyMeACoffee: 'Wesprzyj IT-Tools' + follow: + title: 'Podoba Ci się it-tools?' + p1: 'Wesprzyj nas gwiazdką na' + githubRepository: "repozytorium GitHub IT-Tools" + p2: 'lub śledź nas na' + twitterAccount: "koncie Twitter IT-Tools" + thankYou: 'Dziękujemy!' + nav: + github: 'Repozytorium GitHub' + githubRepository: "Repozytorium GitHub IT-Tools" + twitter: 'Konto Twitter' + twitterAccount: "Konto Twitter IT-Tools" + about: "O IT-Tools" + aboutLabel: 'O nas' + darkMode: 'Tryb ciemny' + lightMode: 'Tryb jasny' + mode: 'Przełącz tryb ciemny/jasny' +about: + content: > + # O IT-Tools + + Ta wspaniała strona, stworzona z ❤ przez [Corentina Thomasseta](https://corentin.tech?utm_source=it-tools&utm_medium=about), zbiera przydatne narzędzia dla programistów i osób pracujących w IT. Jeśli uznasz ją za pomocną, nie zapomnij się nią podzielić i dodać do ulubionych! + + IT Tools jest open-source (na licencji MIT) i darmowe, i takie pozostanie, ale koszty związane z jego hostingiem i odnawianiem domeny spoczywają na mnie. Jeśli chcesz wesprzeć moją pracę i zmotywować mnie do dodania kolejnych narzędzi, zachęcam do [wsparcia](https://www.buymeacoffee.com/cthmsst). + + ## Technologie + + IT Tools zostało stworzone w Vue.js (Vue 3) z wykorzystaniem biblioteki komponentów Naive UI i jest hostowane oraz ciągle wdrażane przez Vercel. Niektóre narzędzia korzystają z zewnętrznych bibliotek open-source, pełną listę znajdziesz w pliku [package.json](https://github.com/CorentinTh/it-tools/blob/main/package.json) repozytorium. + + ## Znalazłeś błąd? Brakuje jakiegoś narzędzia? + + Jeśli potrzebujesz narzędzia, które nie jest jeszcze dostępne, a uważasz, że mogłoby być przydatne, zapraszam do zgłoszenia propozycji funkcji w [sekcji issue](https://github.com/CorentinTh/it-tools/issues/new/choose) repozytorium GitHub. + +404: + notFound: '404 Nie znaleziono' + sorry: "Przepraszamy, ta strona nie istnieje" + maybe: 'Może to problem z cachem, spróbuj wymusić odświeżenie?' + backHome: "Powrót na stronę główną" +toolCard: + new: Nowe +search: + label: Szukaj +tools: + categories: + favorite-tools: 'Twoje ulubione narzędzia' + crypto: Kryptografia + converter: Konwerter + web: Web + images and videos: 'Obrazy i wideo' + development: Programowanie + network: Sieć + math: Matematyka + measurement: Pomiary + text: Tekst + data: Dane + + token-generator: + title: Generator tokenów + description: >- + Generuje losowy ciąg znaków z wybranych przez Ciebie znaków: wielkie + lub małe litery, cyfry i/lub symbole. + uppercase: Wielkie litery (ABC...) + lowercase: Małe litery (abc...) + numbers: Cyfry (123...) + symbols: Symbole (!-;...) + button: + copy: Kopiuj + refresh: Odśwież + copied: Token został skopiowany + length: Długość + tokenPlaceholder: Token... + + mic-tester: + title: Tester mikrofonu + description: Odtwórz i wizualizuj dźwięk z Twojego mikrofonu, z dodaną jedną sekundą opóźnienia + start-button-text: Odtwarzaj mikrofonu + stop-button-text: Zatrzymaj odtwarzanie mikrofonu diff --git a/src/modules/i18n/components/locale-selector.vue b/src/modules/i18n/components/locale-selector.vue index 45732bf93..713141572 100644 --- a/src/modules/i18n/components/locale-selector.vue +++ b/src/modules/i18n/components/locale-selector.vue @@ -6,6 +6,7 @@ const localesLong: Record = { de: 'Deutsch', es: 'Español', fr: 'Français', + pl: 'Polski', pt: 'Português', ru: 'Русский', uk: 'Українська', From 78b62246481f6ee282384e288407506d3f243770 Mon Sep 17 00:00:00 2001 From: gornvan Date: Wed, 9 Oct 2024 21:28:07 +0200 Subject: [PATCH 3/8] register mic-tester component in the Web category --- src/tools/index.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/tools/index.ts b/src/tools/index.ts index 388cfaf49..8e93f8111 100644 --- a/src/tools/index.ts +++ b/src/tools/index.ts @@ -87,6 +87,7 @@ import { tool as uuidGenerator } from './uuid-generator'; import { tool as macAddressLookup } from './mac-address-lookup'; import { tool as xmlFormatter } from './xml-formatter'; import { tool as yamlViewer } from './yaml-viewer'; +import { tool as micTester } from './mic-tester'; export const toolsByCategory: ToolCategory[] = [ { @@ -137,6 +138,7 @@ export const toolsByCategory: ToolCategory[] = [ httpStatusCodes, jsonDiff, safelinkDecoder, + micTester, ], }, { From e8f17667b0e29dff82259b357d9af27ef98c8d3f Mon Sep 17 00:00:00 2001 From: gornvan Date: Wed, 9 Oct 2024 21:29:48 +0200 Subject: [PATCH 4/8] The compilation toolset seems to have deleted some unused types and added the new for mic-tester --- components.d.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/components.d.ts b/components.d.ts index 3e65c3cc5..8041c4387 100644 --- a/components.d.ts +++ b/components.d.ts @@ -128,12 +128,11 @@ declare module '@vue/runtime-core' { MenuIconItem: typeof import('./src/components/MenuIconItem.vue')['default'] MenuLayout: typeof import('./src/components/MenuLayout.vue')['default'] MetaTagGenerator: typeof import('./src/tools/meta-tag-generator/meta-tag-generator.vue')['default'] + MicTester: typeof import('./src/tools/mic-tester/mic-tester.vue')['default'] MimeTypes: typeof import('./src/tools/mime-types/mime-types.vue')['default'] NavbarButtons: typeof import('./src/components/NavbarButtons.vue')['default'] - NCheckbox: typeof import('naive-ui')['NCheckbox'] NCollapseTransition: typeof import('naive-ui')['NCollapseTransition'] NConfigProvider: typeof import('naive-ui')['NConfigProvider'] - NDivider: typeof import('naive-ui')['NDivider'] NEllipsis: typeof import('naive-ui')['NEllipsis'] NH1: typeof import('naive-ui')['NH1'] NH3: typeof import('naive-ui')['NH3'] @@ -141,8 +140,6 @@ declare module '@vue/runtime-core' { NLayout: typeof import('naive-ui')['NLayout'] NLayoutSider: typeof import('naive-ui')['NLayoutSider'] NMenu: typeof import('naive-ui')['NMenu'] - NSpace: typeof import('naive-ui')['NSpace'] - NTable: typeof import('naive-ui')['NTable'] NumeronymGenerator: typeof import('./src/tools/numeronym-generator/numeronym-generator.vue')['default'] OtpCodeGeneratorAndValidator: typeof import('./src/tools/otp-code-generator-and-validator/otp-code-generator-and-validator.vue')['default'] PasswordStrengthAnalyser: typeof import('./src/tools/password-strength-analyser/password-strength-analyser.vue')['default'] From c7d8ea4de4bb1e9cad836ceecae85529340e672c Mon Sep 17 00:00:00 2001 From: gornvan Date: Wed, 9 Oct 2024 21:52:56 +0200 Subject: [PATCH 5/8] mic-tester: pull the media api stuff into a service. --- src/tools/mic-tester/mic-tester.service.ts | 87 ++++++++++++++++ src/tools/mic-tester/mic-tester.vue | 115 ++++----------------- 2 files changed, 106 insertions(+), 96 deletions(-) create mode 100644 src/tools/mic-tester/mic-tester.service.ts diff --git a/src/tools/mic-tester/mic-tester.service.ts b/src/tools/mic-tester/mic-tester.service.ts new file mode 100644 index 000000000..412b0a943 --- /dev/null +++ b/src/tools/mic-tester/mic-tester.service.ts @@ -0,0 +1,87 @@ +import { ref, onBeforeUnmount } from 'vue'; + +export function useMicrophoneService() { + let audioContext: AudioContext | null = null; + let delayNode: DelayNode | null = null; + let sourceNode: MediaStreamAudioSourceNode | null = null; + let analyserNode: AnalyserNode | null = null; + let stream: MediaStream | null = null; + + const isPlaying = ref(false); + const loudnessLevel = ref(0); // Observable for loudness + + const startMicReplay = async () => { + if (!audioContext) { + audioContext = new (window.AudioContext || window.webkitAudioContext)(); + } + + try { + stream = await navigator.mediaDevices.getUserMedia({ audio: true }); + } catch (err) { + console.error('Microphone access denied:', err); + alert('Microphone access denied (the error is also in the console):', err); + return; + } + + sourceNode = audioContext.createMediaStreamSource(stream); + delayNode = audioContext.createDelay(1.0); + delayNode.delayTime.value = 1.0; + + analyserNode = audioContext.createAnalyser(); + analyserNode.fftSize = 256; + + // Connect nodes: mic -> delay -> speakers + sourceNode.connect(delayNode); + delayNode.connect(audioContext.destination); + sourceNode.connect(analyserNode); + + isPlaying.value = true; + measureLoudness(); + }; + + const stopMicReplay = () => { + if (audioContext && stream) { + const tracks = stream.getTracks(); + tracks.forEach(track => track.stop()); + audioContext.close(); + audioContext = null; + isPlaying.value = false; + loudnessLevel.value = 0; + } + }; + + // Measure loudness and update loudness bar + const measureLoudness = () => { + const dataArray = new Uint8Array(analyserNode!.frequencyBinCount); + + const updateLoudness = () => { + analyserNode!.getByteFrequencyData(dataArray); + + // Calculate average loudness + let sum = 0; + dataArray.forEach(value => sum += value); + const average = sum / dataArray.length; + + // Update the observable loudness level + loudnessLevel.value = average; + + if (isPlaying.value) { + requestAnimationFrame(updateLoudness); + } + }; + + updateLoudness(); + }; + + // Cleanup on service destruction + onBeforeUnmount(() => { + stopMicReplay(); + }); + + return { + startMicReplay, + stopMicReplay, + loudnessLevel, + isPlaying + }; +} diff --git a/src/tools/mic-tester/mic-tester.vue b/src/tools/mic-tester/mic-tester.vue index 6bbda911c..fc0addad5 100644 --- a/src/tools/mic-tester/mic-tester.vue +++ b/src/tools/mic-tester/mic-tester.vue @@ -1,99 +1,23 @@