{"id":15,"date":"2025-12-23T12:04:46","date_gmt":"2025-12-23T12:04:46","guid":{"rendered":"https:\/\/zestrogaming.com\/tools\/?page_id=15"},"modified":"2026-01-05T11:17:10","modified_gmt":"2026-01-05T11:17:10","slug":"sound-test","status":"publish","type":"page","link":"https:\/\/zestrogaming.com\/tools\/sound-test\/","title":{"rendered":"Sound  Test"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"15\" class=\"elementor elementor-15\">\n\t\t\t\t<div class=\"elementor-element elementor-element-a62242f e-flex e-con-boxed wpr-particle-no wpr-jarallax-no wpr-parallax-no wpr-sticky-section-no e-con e-parent\" data-id=\"a62242f\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-da8c9a2 elementor-widget elementor-widget-html\" data-id=\"da8c9a2\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t\t\r\n<p>&nbsp;<\/p>\r\n<p>&nbsp;<\/p>\r\n<!-- COPY EVERYTHING BELOW THIS LINE INTO A WORDPRESS CUSTOM HTML BLOCK -->\r\n<div id=\"sound-tester-wrapper\" class=\"font-sans antialiased text-slate-800\"><!-- Load Tailwind CSS (scoped handling for WordPress is recommended, but this is the CDN method) --> <script src=\"https:\/\/cdn.tailwindcss.com\"><\/script> <script>\r\n    tailwind.config = {\r\n      theme: {\r\n        extend: {\r\n          fontFamily: {\r\n            sans: ['Inter', 'sans-serif'],\r\n          },\r\n          animation: {\r\n            'pulse-fast': 'pulse 1s cubic-bezier(0.4, 0, 0.6, 1) infinite',\r\n          }\r\n        }\r\n      }\r\n    }\r\n  <\/script> <!-- Load Font --> <style>\r\n    \/* Custom styles to ensure isolation in WordPress *\/\r\n    #sound-tester-wrapper {\r\n      font-family: 'Inter', sans-serif;\r\n    }\r\n  <\/style>\r\n<div class=\"w-full max-w-4xl mx-auto bg-white rounded-3xl shadow-xl overflow-hidden border border-slate-100 my-8\"><!-- Header Section -->\r\n<div class=\"bg-slate-900 p-8 text-center\">\r\n<h2 class=\"text-3xl font-bold text-white mb-2\">Stereo Check<\/h2>\r\n<p class=\"text-slate-400\">Click the buttons below to test each speaker channel.<\/p>\r\n<\/div>\r\n<!-- Controls Section -->\r\n<div class=\"p-8 md:p-16\">\r\n<div class=\"grid grid-cols-1 md:grid-cols-2 gap-8 md:gap-16\"><!-- Left Channel Button --> <button class=\"group relative flex flex-col items-center justify-center p-10 rounded-2xl transition-all duration-300 transform hover:-translate-y-1 focus:outline-none focus:ring-4 focus:ring-blue-200 bg-slate-50 border-2 border-slate-200 hover:border-blue-300 hover:shadow-md\" aria-label=\"Test Left Speaker\"><\/button><button class=\"group relative flex flex-col items-center justify-center p-10 rounded-2xl transition-all duration-300 transform hover:-translate-y-1 focus:outline-none focus:ring-4 focus:ring-blue-200 bg-slate-50 border-2 border-slate-200 hover:border-blue-300 hover:shadow-md\" aria-label=\"Test Left Speaker\"> <!-- Icon Container --><\/button>\r\n<div id=\"icon-bg-left\" class=\"w-24 h-24 rounded-full flex items-center justify-center mb-6 transition-colors duration-300 bg-slate-200 text-slate-400 group-hover:bg-blue-100 group-hover:text-blue-500\"><!-- Speaker Icon --><\/div>\r\n<button class=\"group relative flex flex-col items-center justify-center p-10 rounded-2xl transition-all duration-300 transform hover:-translate-y-1 focus:outline-none focus:ring-4 focus:ring-blue-200 bg-slate-50 border-2 border-slate-200 hover:border-blue-300 hover:shadow-md\" aria-label=\"Test Left Speaker\"><\/button><button class=\"group relative flex flex-col items-center justify-center p-10 rounded-2xl transition-all duration-300 transform hover:-translate-y-1 focus:outline-none focus:ring-4 focus:ring-blue-200 bg-slate-50 border-2 border-slate-200 hover:border-blue-300 hover:shadow-md\" aria-label=\"Test Left Speaker\"><span id=\"text-left\" class=\"text-2xl font-bold text-slate-700\">LEFT<\/span> <span class=\"text-sm text-slate-500 mt-2\">Click to play<\/span> <!-- Animation Layer (Hidden by default) --><\/button>\r\n<div id=\"anim-left\" class=\"absolute inset-0 rounded-2xl overflow-hidden pointer-events-none hidden\">\r\n<div class=\"absolute inset-0 bg-blue-500 opacity-5 animate-ping\">\u00a0<\/div>\r\n<\/div>\r\n<!-- Right Channel Button --> <button class=\"group relative flex flex-col items-center justify-center p-10 rounded-2xl transition-all duration-300 transform hover:-translate-y-1 focus:outline-none focus:ring-4 focus:ring-red-200 bg-slate-50 border-2 border-slate-200 hover:border-red-300 hover:shadow-md\" aria-label=\"Test Right Speaker\"><\/button><button class=\"group relative flex flex-col items-center justify-center p-10 rounded-2xl transition-all duration-300 transform hover:-translate-y-1 focus:outline-none focus:ring-4 focus:ring-red-200 bg-slate-50 border-2 border-slate-200 hover:border-red-300 hover:shadow-md\" aria-label=\"Test Right Speaker\"> <!-- Icon Container --><\/button>\r\n<div id=\"icon-bg-right\" class=\"w-24 h-24 rounded-full flex items-center justify-center mb-6 transition-colors duration-300 bg-slate-200 text-slate-400 group-hover:bg-red-100 group-hover:text-red-500\"><!-- Speaker Icon --><\/div>\r\n<button class=\"group relative flex flex-col items-center justify-center p-10 rounded-2xl transition-all duration-300 transform hover:-translate-y-1 focus:outline-none focus:ring-4 focus:ring-red-200 bg-slate-50 border-2 border-slate-200 hover:border-red-300 hover:shadow-md\" aria-label=\"Test Right Speaker\"><\/button><button class=\"group relative flex flex-col items-center justify-center p-10 rounded-2xl transition-all duration-300 transform hover:-translate-y-1 focus:outline-none focus:ring-4 focus:ring-red-200 bg-slate-50 border-2 border-slate-200 hover:border-red-300 hover:shadow-md\" aria-label=\"Test Right Speaker\"><span id=\"text-right\" class=\"text-2xl font-bold text-slate-700\">RIGHT<\/span> <span class=\"text-sm text-slate-500 mt-2\">Click to play<\/span> <!-- Animation Layer (Hidden by default) --><\/button>\r\n<div id=\"anim-right\" class=\"absolute inset-0 rounded-2xl overflow-hidden pointer-events-none hidden\">\r\n<div class=\"absolute inset-0 bg-red-500 opacity-5 animate-ping\">\u00a0<\/div>\r\n<\/div>\r\n<\/div>\r\n<div class=\"mt-12 text-center\">\r\n<p class=\"text-slate-600 bg-yellow-50 inline-block px-4 py-2 rounded-lg border border-yellow-100\"><span class=\"font-semibold text-yellow-800\">Note:<\/span> If you are on a mobile device, stereo separation might not be audible on built-in speakers.<\/p>\r\n<\/div>\r\n<\/div>\r\n<\/div>\r\n<script>\r\n    (function() {\r\n      \/\/ Audio Context Variable\r\n      let audioCtx = null;\r\n      let timeoutId = null;\r\n\r\n      \/\/ Class Constants for UI states\r\n      const UI = {\r\n        left: {\r\n          btn: document.getElementById('btn-left'),\r\n          iconBg: document.getElementById('icon-bg-left'),\r\n          text: document.getElementById('text-left'),\r\n          anim: document.getElementById('anim-left'),\r\n          activeBtn: ['bg-blue-50', 'border-blue-500', 'shadow-lg', 'shadow-blue-100'],\r\n          inactiveBtn: ['bg-slate-50', 'border-slate-200', 'hover:border-blue-300', 'hover:shadow-md'],\r\n          activeIcon: ['bg-blue-500', 'text-white', 'animate-pulse-fast'],\r\n          inactiveIcon: ['bg-slate-200', 'text-slate-400', 'group-hover:bg-blue-100', 'group-hover:text-blue-500'],\r\n          activeText: 'text-blue-600',\r\n          inactiveText: 'text-slate-700'\r\n        },\r\n        right: {\r\n          btn: document.getElementById('btn-right'),\r\n          iconBg: document.getElementById('icon-bg-right'),\r\n          text: document.getElementById('text-right'),\r\n          anim: document.getElementById('anim-right'),\r\n          activeBtn: ['bg-red-50', 'border-red-500', 'shadow-lg', 'shadow-red-100'],\r\n          inactiveBtn: ['bg-slate-50', 'border-slate-200', 'hover:border-red-300', 'hover:shadow-md'],\r\n          activeIcon: ['bg-red-500', 'text-white', 'animate-pulse-fast'],\r\n          inactiveIcon: ['bg-slate-200', 'text-slate-400', 'group-hover:bg-red-100', 'group-hover:text-red-500'],\r\n          activeText: 'text-red-600',\r\n          inactiveText: 'text-slate-700'\r\n        }\r\n      };\r\n\r\n      \/\/ Helper to reset UI\r\n      function resetUI() {\r\n        ['left', 'right'].forEach(side => {\r\n          const els = UI[side];\r\n          \r\n          \/\/ Reset Button\r\n          els.btn.classList.remove(...els.activeBtn);\r\n          els.btn.classList.add(...els.inactiveBtn);\r\n          \r\n          \/\/ Reset Icon\r\n          els.iconBg.classList.remove(...els.activeIcon);\r\n          els.iconBg.classList.add(...els.inactiveIcon);\r\n          \r\n          \/\/ Reset Text\r\n          els.text.classList.remove(els.activeText);\r\n          els.text.classList.add(els.inactiveText);\r\n          \r\n          \/\/ Hide Animation\r\n          els.anim.classList.add('hidden');\r\n        });\r\n      }\r\n\r\n      \/\/ Helper to activate UI\r\n      function activateUI(side) {\r\n        resetUI(); \/\/ Clear others first\r\n        const els = UI[side];\r\n        \r\n        \/\/ Active Button\r\n        els.btn.classList.remove(...els.inactiveBtn);\r\n        els.btn.classList.add(...els.activeBtn);\r\n        \r\n        \/\/ Active Icon\r\n        els.iconBg.classList.remove(...els.inactiveIcon);\r\n        els.iconBg.classList.add(...els.activeIcon);\r\n        \r\n        \/\/ Active Text\r\n        els.text.classList.remove(els.inactiveText);\r\n        els.text.classList.add(els.activeText);\r\n        \r\n        \/\/ Show Animation\r\n        els.anim.classList.remove('hidden');\r\n      }\r\n\r\n      \/\/ Main Audio Function exposed to global scope for onclick events\r\n      window.playChannel = function(channel) {\r\n        const panValue = channel === 'left' ? -1 : 1;\r\n\r\n        \/\/ Initialize Audio Context on user interaction\r\n        if (!audioCtx) {\r\n          const AudioContextClass = window.AudioContext || window.webkitAudioContext;\r\n          if (AudioContextClass) {\r\n            audioCtx = new AudioContextClass();\r\n          } else {\r\n            alert(\"Your browser does not support Web Audio API.\");\r\n            return;\r\n          }\r\n        }\r\n        if (audioCtx.state === 'suspended') {\r\n          audioCtx.resume();\r\n        }\r\n\r\n        \/\/ Cleanup previous timer\r\n        if (timeoutId) {\r\n          clearTimeout(timeoutId);\r\n          timeoutId = null;\r\n        }\r\n\r\n        \/\/ Setup Nodes\r\n        const oscillator = audioCtx.createOscillator();\r\n        const gainNode = audioCtx.createGain();\r\n        const panner = audioCtx.createStereoPanner();\r\n\r\n        oscillator.type = 'sine';\r\n        oscillator.frequency.setValueAtTime(440, audioCtx.currentTime); \/\/ A4\r\n        panner.pan.setValueAtTime(panValue, audioCtx.currentTime);\r\n\r\n        \/\/ Connect\r\n        oscillator.connect(panner);\r\n        panner.connect(gainNode);\r\n        gainNode.connect(audioCtx.destination);\r\n\r\n        \/\/ Envelope\r\n        const now = audioCtx.currentTime;\r\n        const duration = 1.5;\r\n\r\n        gainNode.gain.setValueAtTime(0, now);\r\n        gainNode.gain.linearRampToValueAtTime(0.5, now + 0.1);\r\n        gainNode.gain.exponentialRampToValueAtTime(0.001, now + duration);\r\n\r\n        \/\/ Play\r\n        oscillator.start(now);\r\n        oscillator.stop(now + duration);\r\n\r\n        \/\/ Update UI\r\n        activateUI(channel);\r\n\r\n        \/\/ Reset UI after sound finishes\r\n        timeoutId = setTimeout(() => {\r\n          resetUI();\r\n        }, duration * 1000);\r\n      };\r\n    })();\r\n  <\/script><\/div>\r\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>&nbsp; &nbsp; Stereo Check Click the buttons below to test each speaker channel. LEFT Click to play \u00a0 RIGHT Click to play \u00a0 Note: If you are on a mobile device, stereo separation might not be audible on built-in speakers.<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"elementor_header_footer","meta":{"_eb_attr":"","site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"class_list":["post-15","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/zestrogaming.com\/tools\/wp-json\/wp\/v2\/pages\/15","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/zestrogaming.com\/tools\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/zestrogaming.com\/tools\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/zestrogaming.com\/tools\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/zestrogaming.com\/tools\/wp-json\/wp\/v2\/comments?post=15"}],"version-history":[{"count":11,"href":"https:\/\/zestrogaming.com\/tools\/wp-json\/wp\/v2\/pages\/15\/revisions"}],"predecessor-version":[{"id":232,"href":"https:\/\/zestrogaming.com\/tools\/wp-json\/wp\/v2\/pages\/15\/revisions\/232"}],"wp:attachment":[{"href":"https:\/\/zestrogaming.com\/tools\/wp-json\/wp\/v2\/media?parent=15"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}