{"id":548,"date":"2024-06-26T12:16:13","date_gmt":"2024-06-26T12:16:13","guid":{"rendered":"http:\/\/landing.anderskisling.dk\/?page_id=548"},"modified":"2024-06-27T01:21:18","modified_gmt":"2024-06-27T01:21:18","slug":"akisynth","status":"publish","type":"page","link":"https:\/\/landing.anderskisling.dk\/index.php\/akisynth\/","title":{"rendered":"akisynth"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"548\" class=\"elementor elementor-548\">\n\t\t\t\t<div class=\"elementor-element elementor-element-65a0313 e-flex e-con-boxed e-con e-parent\" data-id=\"65a0313\" data-element_type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;gradient&quot;}\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t<div class=\"elementor-element elementor-element-99adccd e-con-full e-flex e-con e-child\" data-id=\"99adccd\" data-element_type=\"container\">\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-a47ad0c e-con-full e-flex e-con e-child\" data-id=\"a47ad0c\" data-element_type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-a511cf6 elementor-widget__width-inherit elementor-widget elementor-widget-html\" data-id=\"a511cf6\" data-element_type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <title>Akisynth med ADSR<\/title>\n    <style>\n        @import url('https:\/\/fonts.googleapis.com\/css2?family=Sarina&display=swap');\n\n        #akisynth {\n            font-family: Arial, sans-serif;\n            text-align: center;\n        }\n        #akisynth h2 {\n            font-family: 'Sarina', cursive;\n            color: white;\n        }\n        #keyboard {\n            display: flex;\n            justify-content: center;\n            margin-top: 20px;\n            user-select: none;\n        }\n        .key {\n            width: 40px;\n            height: 120px;\n            margin: 0;\n            background-color: white;\n            border: 1px solid black;\n            cursor: pointer;\n            transition: background-color 0.1s;\n        }\n        .key:hover {\n            background-color: #d0d0d0;\n        }\n        .key.black {\n            background-color: black;\n            height: 80px;\n            width: 30px;\n            margin-left: -15px;\n            margin-right: -15px;\n            z-index: 1;\n        }\n        .key.black:hover {\n            background-color: #222;\n        }\n        .key.active {\n            background-color: #b0b0b0;\n        }\n        .key.black.active {\n            background-color: #444;\n        }\n        #controls {\n            display: flex;\n            justify-content: center;\n            margin-top: 20px;\n            flex-wrap: wrap;\n        }\n        .control {\n            margin: 0 20px;\n            display: flex;\n            flex-direction: column;\n            align-items: center;\n        }\n        .control label {\n            user-select: none;\n            -webkit-user-select: none;\n            -moz-user-select: none;\n            -ms-user-select: none;\n        }\n        .knob-container {\n            width: 60px;\n            height: 60px;\n            position: relative;\n            margin-top: 10px;\n        }\n        .knob {\n            width: 100%;\n            height: 100%;\n            border-radius: 50%;\n            background-color: black;\n            position: relative;\n            cursor: pointer;\n            box-shadow: 0 8px 16px rgba(0, 0, 0, 0.4); \/* Kraftigere skyggeeffekt *\/\n        }\n        .indicator {\n            position: absolute;\n            width: 3px;\n            height: 50%;\n            background-color: white;\n            left: 50%;\n            transform-origin: bottom;\n        }\n        #oscillator-type {\n            margin-top: 10px;\n        }\n        .adsr-controls {\n            display: flex;\n            justify-content: space-between;\n            width: 300px;\n        }\n    <\/style>\n<\/head>\n<body>\n    <div id=\"akisynth\">\n        <h2>Akisynth<\/h2>\n        <div id=\"keyboard\"><\/div>\n        <div id=\"controls\">\n            <div class=\"control\">\n                <label>Rumklang:<\/label>\n                <div class=\"knob-container\">\n                    <div class=\"knob\" id=\"reverb-knob\">\n                        <div class=\"indicator\"><\/div>\n                    <\/div>\n                <\/div>\n            <\/div>\n            <div class=\"control\">\n                <label>Oscillator Type:<\/label>\n                <select id=\"oscillator-type\">\n                    <option value=\"sine\">Sine<\/option>\n                    <option value=\"sawtooth\">Sawtooth<\/option>\n                    <option value=\"square\">Square<\/option>\n                <\/select>\n            <\/div>\n            <div class=\"control\">\n                <label>Cutoff:<\/label>\n                <div class=\"knob-container\">\n                    <div class=\"knob\" id=\"cutoff-knob\">\n                        <div class=\"indicator\"><\/div>\n                    <\/div>\n                <\/div>\n            <\/div>\n            <div class=\"control\">\n                <label>Resonance:<\/label>\n                <div class=\"knob-container\">\n                    <div class=\"knob\" id=\"resonance-knob\">\n                        <div class=\"indicator\"><\/div>\n                    <\/div>\n                <\/div>\n            <\/div>\n            <div class=\"control\">\n                <label>ADSR<\/label>\n                <div class=\"adsr-controls\">\n                    <div class=\"control\">\n                        <label>A<\/label>\n                        <div class=\"knob-container\">\n                            <div class=\"knob\" id=\"attack-knob\">\n                                <div class=\"indicator\"><\/div>\n                            <\/div>\n                        <\/div>\n                    <\/div>\n                    <div class=\"control\">\n                        <label>D<\/label>\n                        <div class=\"knob-container\">\n                            <div class=\"knob\" id=\"decay-knob\">\n                                <div class=\"indicator\"><\/div>\n                            <\/div>\n                        <\/div>\n                    <\/div>\n                    <div class=\"control\">\n                        <label>S<\/label>\n                        <div class=\"knob-container\">\n                            <div class=\"knob\" id=\"sustain-knob\">\n                                <div class=\"indicator\"><\/div>\n                            <\/div>\n                        <\/div>\n                    <\/div>\n                    <div class=\"control\">\n                        <label>R<\/label>\n                        <div class=\"knob-container\">\n                            <div class=\"knob\" id=\"release-knob\">\n                                <div class=\"indicator\"><\/div>\n                            <\/div>\n                        <\/div>\n                    <\/div>\n                <\/div>\n            <\/div>\n        <\/div>\n    <\/div>\n\n    <script>\n        const audioContext = new (window.AudioContext || window.webkitAudioContext)();\n        const keys = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B',\n                      'C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B'];\n        const frequencies = [261.63, 277.18, 293.66, 311.13, 329.63, 349.23, 369.99, 392.00, 415.30, 440.00, 466.16, 493.88,\n                             523.25, 554.37, 587.33, 622.25, 659.25, 698.46, 739.99, 783.99, 830.61, 880.00, 932.33, 987.77];\n\n        let convolver = audioContext.createConvolver();\n        let reverbGain = audioContext.createGain();\n        reverbGain.gain.value = 0;\n\n        let filter = audioContext.createBiquadFilter();\n        filter.type = 'lowpass';\n        filter.frequency.value = 1000;\n        filter.Q.value = 0;\n\n        let dryGain = audioContext.createGain();\n        dryGain.gain.value = 1;\n\n        convolver.connect(reverbGain);\n        reverbGain.connect(audioContext.destination);\n        dryGain.connect(audioContext.destination);\n\n        let attackTime = 0.1, decayTime = 0.1, sustainLevel = 0.5, releaseTime = 0.1;\n\n        function generateImpulseResponse() {\n            const sampleRate = audioContext.sampleRate;\n            const length = sampleRate * 2;\n            const impulse = audioContext.createBuffer(2, length, sampleRate);\n            const left = impulse.getChannelData(0);\n            const right = impulse.getChannelData(1);\n\n            for (let i = 0; i < length; i++) {\n                left[i] = (Math.random() * 2 - 1) * Math.pow(1 - i \/ length, 2);\n                right[i] = (Math.random() * 2 - 1) * Math.pow(1 - i \/ length, 2);\n            }\n\n            convolver.buffer = impulse;\n        }\n\n        generateImpulseResponse();\n\n        function createOscillator(freq) {\n            const oscillator = audioContext.createOscillator();\n            const gainNode = audioContext.createGain();\n            oscillator.type = document.getElementById('oscillator-type').value;\n            oscillator.frequency.setValueAtTime(freq, audioContext.currentTime);\n            oscillator.connect(gainNode);\n            gainNode.connect(filter);\n            filter.connect(dryGain);\n            filter.connect(convolver);\n            return { oscillator, gainNode };\n        }\n\n        const activeNotes = new Map();\n\n        function startNote(note, freq) {\n            if (!activeNotes.has(note)) {\n                const sound = createOscillator(freq);\n                sound.oscillator.start();\n                \n                \/\/ ADSR envelope\n                const now = audioContext.currentTime;\n                sound.gainNode.gain.setValueAtTime(0, now);\n                sound.gainNode.gain.linearRampToValueAtTime(1, now + attackTime);\n                sound.gainNode.gain.linearRampToValueAtTime(sustainLevel, now + attackTime + decayTime);\n                \n                activeNotes.set(note, sound);\n                return sound;\n            }\n            return null;\n        }\n\n        function stopNote(note) {\n            if (activeNotes.has(note)) {\n                const sound = activeNotes.get(note);\n                const now = audioContext.currentTime;\n                sound.gainNode.gain.cancelScheduledValues(now);\n                sound.gainNode.gain.setValueAtTime(sound.gainNode.gain.value, now);\n                sound.gainNode.gain.linearRampToValueAtTime(0, now + releaseTime);\n                sound.oscillator.stop(now + releaseTime);\n                activeNotes.delete(note);\n            }\n        }\n\n        function createKey(note, freq, index) {\n            const key = document.createElement('div');\n            key.className = 'key' + (note.includes('#') ? ' black' : '');\n            key.dataset.note = note;\n            key.dataset.freq = freq;\n\n            key.addEventListener('mousedown', (e) => {\n                e.preventDefault();\n                startNote(note, freq);\n                key.classList.add('active');\n            });\n\n            key.addEventListener('mouseenter', (e) => {\n                if (e.buttons === 1) {\n                    startNote(note, freq);\n                    key.classList.add('active');\n                }\n            });\n\n            key.addEventListener('mouseleave', () => {\n                stopNote(note);\n                key.classList.remove('active');\n            });\n\n            return key;\n        }\n\n        const keyboard = document.getElementById('keyboard');\n        keys.forEach((note, index) => {\n            const key = createKey(note, frequencies[index], index);\n            keyboard.appendChild(key);\n        });\n\n        document.addEventListener('mouseup', () => {\n            activeNotes.forEach((sound, note) => {\n                stopNote(note);\n            });\n            document.querySelectorAll('.key').forEach(key => key.classList.remove('active'));\n        });\n\n        function createKnob(elementId, param, min, max, initial, curve = 1) {\n            const knob = document.getElementById(elementId);\n            const indicator = knob.querySelector('.indicator');\n            let isDragging = false;\n            let startAngle, currentAngle = 0;\n\n            function setKnobValue(angle) {\n                currentAngle = angle;\n                const normalized = (currentAngle + 150) \/ 300;\n                const value = min + Math.pow(normalized, curve) * (max - min);\n                if (typeof param === 'function') {\n                    param(value);\n                } else {\n                    param.setValueAtTime(value, audioContext.currentTime);\n                }\n                indicator.style.transform = `rotate(${currentAngle}deg)`;\n            }\n\n            knob.addEventListener('mousedown', (e) => {\n                isDragging = true;\n                startAngle = Math.atan2(e.clientY - knob.offsetTop - knob.offsetHeight \/ 2,\n                                        e.clientX - knob.offsetLeft - knob.offsetWidth \/ 2) * 180 \/ Math.PI;\n            });\n\n            document.addEventListener('mousemove', (e) => {\n                if (isDragging) {\n                    const angle = Math.atan2(e.clientY - knob.offsetTop - knob.offsetHeight \/ 2,\n                                             e.clientX - knob.offsetLeft - knob.offsetWidth \/ 2) * 180 \/ Math.PI;\n                    let newAngle = currentAngle - (angle - startAngle) * 12;\n                    newAngle = Math.max(-150, Math.min(150, newAngle));\n                    setKnobValue(newAngle);\n                    startAngle = angle;\n                }\n            });\n\n            document.addEventListener('mouseup', () => {\n                isDragging = false;\n            });\n\n            setKnobValue(initial);\n        }\n\n        createKnob('reverb-knob', reverbGain.gain, 0, 1, -150);\n        createKnob('cutoff-knob', filter.frequency, 50, 15000, 0, 2);\n        createKnob('resonance-knob', filter.Q, 0, 20, -150);\n        createKnob('attack-knob', value => attackTime = value, 0.01, 2, -75);\n        createKnob('decay-knob', value => decayTime = value, 0.01, 2, -75);\n        createKnob('sustain-knob', value => sustainLevel = value, 0, 1, 0);\n        createKnob('release-knob', value => releaseTime = value, 0.01, 2, -75);\n\n        \/\/ Keyboard controls\n        document.addEventListener('keydown', (e) => {\n            const key = keyboard.querySelector(`[data-note=\"${e.key.toUpperCase()}\"]`);\n            if (key && !activeNotes.has(key.dataset.note)) {\n                startNote(key.dataset.note, parseFloat(key.dataset.freq));\n                key.classList.add('active');\n            }\n        });\n\n        document.addEventListener('keyup', (e) => {\n            const key = keyboard.querySelector(`[data-note=\"${e.key.toUpperCase()}\"]`);\n            if (key && activeNotes.has(key.dataset.note)) {\n                stopNote(key.dataset.note);\n                key.classList.remove('active');\n            }\n        });\n    <\/script>\n<\/body>\n<\/html>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-c967bdd e-con-full e-flex e-con e-child\" data-id=\"c967bdd\" data-element_type=\"container\">\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>Akisynth med ADSR Akisynth Rumklang: Oscillator Type: SineSawtoothSquare Cutoff: Resonance: ADSR A D S R<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"inline_featured_image":false,"_kad_post_transparent":"","_kad_post_title":"hide","_kad_post_layout":"fullwidth","_kad_post_sidebar_id":"","_kad_post_content_style":"unboxed","_kad_post_vertical_padding":"hide","_kad_post_feature":"hide","_kad_post_feature_position":"","_kad_post_header":false,"_kad_post_footer":false,"footnotes":""},"class_list":["post-548","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/landing.anderskisling.dk\/index.php\/wp-json\/wp\/v2\/pages\/548","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/landing.anderskisling.dk\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/landing.anderskisling.dk\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/landing.anderskisling.dk\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/landing.anderskisling.dk\/index.php\/wp-json\/wp\/v2\/comments?post=548"}],"version-history":[{"count":15,"href":"https:\/\/landing.anderskisling.dk\/index.php\/wp-json\/wp\/v2\/pages\/548\/revisions"}],"predecessor-version":[{"id":1090,"href":"https:\/\/landing.anderskisling.dk\/index.php\/wp-json\/wp\/v2\/pages\/548\/revisions\/1090"}],"wp:attachment":[{"href":"https:\/\/landing.anderskisling.dk\/index.php\/wp-json\/wp\/v2\/media?parent=548"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}