{"id":4656,"date":"2025-05-04T21:05:17","date_gmt":"2025-05-04T21:05:17","guid":{"rendered":"https:\/\/diverse.anderskisling.dk\/?page_id=4656"},"modified":"2025-07-27T03:23:07","modified_gmt":"2025-07-27T03:23:07","slug":"rytme","status":"publish","type":"page","link":"https:\/\/diverse.anderskisling.dk\/index.php\/rytme\/","title":{"rendered":"rytme"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"4656\" class=\"elementor elementor-4656\">\n\t\t\t\t<div class=\"elementor-element elementor-element-d3d4f6f e-flex e-con-boxed e-con e-parent\" data-id=\"d3d4f6f\" data-element_type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t<div class=\"elementor-element elementor-element-c2cfc9a e-flex e-con-boxed e-con e-child\" data-id=\"c2cfc9a\" data-element_type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t<div class=\"elementor-element elementor-element-d4b3362 e-flex e-con-boxed e-con e-child\" data-id=\"d4b3362\" data-element_type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t<div class=\"elementor-element elementor-element-0fcf104 e-con-full e-flex e-con e-child\" data-id=\"0fcf104\" data-element_type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t<div class=\"elementor-element elementor-element-efb10a0 e-flex e-con-boxed e-con e-child\" data-id=\"efb10a0\" data-element_type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;,&quot;shape_divider_top&quot;:&quot;clouds&quot;}\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-shape elementor-shape-top\" aria-hidden=\"true\" data-negative=\"false\">\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 283.5 27.8\" preserveAspectRatio=\"xMidYMax slice\">\n  <path class=\"elementor-shape-fill\" d=\"M0 0v6.7c1.9-.8 4.7-1.4 8.5-1 9.5 1.1 11.1 6 11.1 6s2.1-.7 4.3-.2c2.1.5 2.8 2.6 2.8 2.6s.2-.5 1.4-.7c1.2-.2 1.7.2 1.7.2s0-2.1 1.9-2.8c1.9-.7 3.6.7 3.6.7s.7-2.9 3.1-4.1 4.7 0 4.7 0 1.2-.5 2.4 0 1.7 1.4 1.7 1.4h1.4c.7 0 1.2.7 1.2.7s.8-1.8 4-2.2c3.5-.4 5.3 2.4 6.2 4.4.4-.4 1-.7 1.8-.9 2.8-.7 4 .7 4 .7s1.7-5 11.1-6c9.5-1.1 12.3 3.9 12.3 3.9s1.2-4.8 5.7-5.7c4.5-.9 6.8 1.8 6.8 1.8s.6-.6 1.5-.9c.9-.2 1.9-.2 1.9-.2s5.2-6.4 12.6-3.3c7.3 3.1 4.7 9 4.7 9s1.9-.9 4 0 2.8 2.4 2.8 2.4 1.9-1.2 4.5-1.2 4.3 1.2 4.3 1.2.2-1 1.4-1.7 2.1-.7 2.1-.7-.5-3.1 2.1-5.5 5.7-1.4 5.7-1.4 1.5-2.3 4.2-1.1c2.7 1.2 1.7 5.2 1.7 5.2s.3-.1 1.3.5c.5.4.8.8.9 1.1.5-1.4 2.4-5.8 8.4-4 7.1 2.1 3.5 8.9 3.5 8.9s.8-.4 2 0 1.1 1.1 1.1 1.1 1.1-1.1 2.3-1.1 2.1.5 2.1.5 1.9-3.6 6.2-1.2 1.9 6.4 1.9 6.4 2.6-2.4 7.4 0c3.4 1.7 3.9 4.9 3.9 4.9s3.3-6.9 10.4-7.9 11.5 2.6 11.5 2.6.8 0 1.2.2c.4.2.9.9.9.9s4.4-3.1 8.3.2c1.9 1.7 1.5 5 1.5 5s.3-1.1 1.6-1.4c1.3-.3 2.3.2 2.3.2s-.1-1.2.5-1.9 1.9-.9 1.9-.9-4.7-9.3 4.4-13.4c5.6-2.5 9.2.9 9.2.9s5-6.2 15.9-6.2 16.1 8.1 16.1 8.1.7-.2 1.6-.4V0H0z\"\/>\n<\/svg>\n\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-cddb63e elementor-widget elementor-widget-spacer\" data-id=\"cddb63e\" data-element_type=\"widget\" data-widget_type=\"spacer.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-spacer\">\n\t\t\t<div class=\"elementor-spacer-inner\"><\/div>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-29f2073 e-grid e-con-full e-con e-child\" data-id=\"29f2073\" data-element_type=\"container\">\n\t\t<div class=\"elementor-element elementor-element-f4b02e2 e-con-full e-flex e-con e-child\" data-id=\"f4b02e2\" data-element_type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t\t\t<div class=\"elementor-element elementor-element-64fa744 elementor-widget elementor-widget-image\" data-id=\"64fa744\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img fetchpriority=\"high\" decoding=\"async\" width=\"1024\" height=\"1024\" src=\"https:\/\/diverse.anderskisling.dk\/wp-content\/uploads\/2025\/06\/ht-gitter2-1024x1024.png\" class=\"attachment-large size-large wp-image-9175\" alt=\"\" srcset=\"https:\/\/diverse.anderskisling.dk\/wp-content\/uploads\/2025\/06\/ht-gitter2-1024x1024.png 1024w, https:\/\/diverse.anderskisling.dk\/wp-content\/uploads\/2025\/06\/ht-gitter2-300x300.png 300w, https:\/\/diverse.anderskisling.dk\/wp-content\/uploads\/2025\/06\/ht-gitter2-150x150.png 150w, https:\/\/diverse.anderskisling.dk\/wp-content\/uploads\/2025\/06\/ht-gitter2-768x768.png 768w, https:\/\/diverse.anderskisling.dk\/wp-content\/uploads\/2025\/06\/ht-gitter2.png 1200w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-c2dd149 elementor-widget elementor-widget-spacer\" data-id=\"c2dd149\" data-element_type=\"widget\" data-widget_type=\"spacer.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-spacer\">\n\t\t\t<div class=\"elementor-spacer-inner\"><\/div>\n\t\t<\/div>\n\t\t\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-40832e7 e-con-full e-flex e-con e-child\" data-id=\"40832e7\" data-element_type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t\t\t<div class=\"elementor-element elementor-element-713334a elementor-widget elementor-widget-spacer\" data-id=\"713334a\" data-element_type=\"widget\" data-widget_type=\"spacer.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-spacer\">\n\t\t\t<div class=\"elementor-spacer-inner\"><\/div>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-6af83a1 elementor-widget elementor-widget-image\" data-id=\"6af83a1\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img decoding=\"async\" width=\"1024\" height=\"99\" src=\"https:\/\/diverse.anderskisling.dk\/wp-content\/uploads\/2025\/07\/algo-metallogo3-1024x99.png\" class=\"attachment-large size-large wp-image-18460\" alt=\"\" srcset=\"https:\/\/diverse.anderskisling.dk\/wp-content\/uploads\/2025\/07\/algo-metallogo3-1024x99.png 1024w, https:\/\/diverse.anderskisling.dk\/wp-content\/uploads\/2025\/07\/algo-metallogo3-300x29.png 300w, https:\/\/diverse.anderskisling.dk\/wp-content\/uploads\/2025\/07\/algo-metallogo3-768x74.png 768w, https:\/\/diverse.anderskisling.dk\/wp-content\/uploads\/2025\/07\/algo-metallogo3.png 1422w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-28c1bc7 elementor-widget elementor-widget-heading\" data-id=\"28c1bc7\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">VINTAGE TR-777<\/h2>\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-a47ce85 e-con-full e-flex e-con e-child\" data-id=\"a47ce85\" data-element_type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t\t\t<div class=\"elementor-element elementor-element-cbd4b55 elementor-widget elementor-widget-image\" data-id=\"cbd4b55\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img fetchpriority=\"high\" decoding=\"async\" width=\"1024\" height=\"1024\" src=\"https:\/\/diverse.anderskisling.dk\/wp-content\/uploads\/2025\/06\/ht-gitter2-1024x1024.png\" class=\"attachment-large size-large wp-image-9175\" alt=\"\" srcset=\"https:\/\/diverse.anderskisling.dk\/wp-content\/uploads\/2025\/06\/ht-gitter2-1024x1024.png 1024w, https:\/\/diverse.anderskisling.dk\/wp-content\/uploads\/2025\/06\/ht-gitter2-300x300.png 300w, https:\/\/diverse.anderskisling.dk\/wp-content\/uploads\/2025\/06\/ht-gitter2-150x150.png 150w, https:\/\/diverse.anderskisling.dk\/wp-content\/uploads\/2025\/06\/ht-gitter2-768x768.png 768w, https:\/\/diverse.anderskisling.dk\/wp-content\/uploads\/2025\/06\/ht-gitter2.png 1200w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-523f32b elementor-widget elementor-widget-spacer\" data-id=\"523f32b\" data-element_type=\"widget\" data-widget_type=\"spacer.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-spacer\">\n\t\t\t<div class=\"elementor-spacer-inner\"><\/div>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-c07f851 elementor-widget elementor-widget-spacer\" data-id=\"c07f851\" data-element_type=\"widget\" data-widget_type=\"spacer.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-spacer\">\n\t\t\t<div class=\"elementor-spacer-inner\"><\/div>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\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\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-2b9cf55b e-flex e-con-boxed e-con e-parent\" data-id=\"2b9cf55b\" data-element_type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-4d4194f3 elementor-widget elementor-widget-html\" data-id=\"4d4194f3\" 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=\"da\">\n<head>\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<title>Trommemaskine<\/title>\n\n<style>\n* {\nbox-sizing: border-box;\nfont-family: Arial, sans-serif;\n-webkit-user-select: none;\n-moz-user-select: none;\n-ms-user-select: none;\nuser-select: none;\n}\nbody {\nmargin: 0;\npadding: 20px;\nbackground-color: #ffffff00;\n}\n.drum-machine {\nbackground-image: url('http:\/\/diverse.anderskisling.dk\/wp-content\/uploads\/2025\/05\/black-metalx4.jpg');\nbackground-size: cover;\nbackground-position: center;\nbackground-repeat: no-repeat;\ncolor: #fff;\npadding: 20px;\nborder-radius: 10px;\nbox-shadow: inset 2px 2px 12px #000000B3, 0 0 6px #B8947499;\nmax-width: 900px;\nmargin: 0 auto;\n-webkit-touch-callout: none;\n-webkit-user-select: none;\n-khtml-user-select: none;\n-moz-user-select: none;\n-ms-user-select: none;\nuser-select: none;\n}\n.title {\ntext-align: center;\nmargin-bottom: 20px;\nfont-size: 20px;\ncolor: #fff;\n}\n.tracks {\ndisplay: flex;\nflex-direction: column;\ngap: 10px;\n}\n.track {\ndisplay: flex;\nalign-items: center;\npadding: 13px;\nbackground-color: #000000;\nbackground-image: url('http:\/\/diverse.anderskisling.dk\/wp-content\/uploads\/2025\/06\/tr77-ny-ch-strip1.png');\nbackground-size: cover;\nbackground-position: center;\nbackground-repeat: no-repeat;\nborder: 1px solid #0F0F0FFF;\nborder-radius: 12px;\nbox-shadow: inset 0 1px 1px #00000066;\n}\n.track-label {\nwidth: 80px;\nfont-size: 14px;\nfont-weight: bold;\ncolor: #e4effd;\nmargin-left: 1px;\nmargin-right: 0px;\ntext-shadow: 0 1px 0 #FFFFFF22, 0 -1px 0 #00000033;\n}\n.controls {\ndisplay: flex;\nalign-items: center;\ngap: 20px;\nmargin-left: 15px;\nwidth: 120px;\nflex-shrink: 0;\n}\n.knob-container {\nposition: relative;\nwidth: 34px;\nheight: 34px;\n}\n.knob {\nposition: absolute;\nbottom: 0px;\nwidth: 34px;\nheight: 34px;\nbackground-color: #111111;\nborder-radius: 50%;\ncursor: pointer;\ndisplay: flex;\njustify-content: center;\nalign-items: center;\ntransform-origin: center center;\n-webkit-tap-highlight-color: transparent;\n-webkit-user-select: none;\n-moz-user-select: none;\n-ms-user-select: none;\nuser-select: none;\n}\n.knob::after {\ncontent: '';\nposition: absolute;\nwidth: 2px;\nheight: 15px;\nbackground-color: #FF5E37;\ntop: 1px;\nborder-radius: 8px;\n}\n.knob-value {\nposition: absolute;\nbottom: 0px;\nleft: 0;\nright: 0;\ntext-align: center;\nfont-size: 0px;\ncolor: #000000ff;\n}\n.volume-knob .knob {\nbackground: radial-gradient(circle, #333333, #222222, #111111);\n}\n.pan-knob .knob {\nbackground: radial-gradient(circle, #333333, #222222, #111111);\n}\n.sequencer {\ndisplay: flex;\nflex-grow: 1;\ngap: 8px;\nmargin-right: 4px;\n}\n.step {\nwidth: 32px;\nheight: 32px;\nborder-radius: 5px;\nbackground-color: #ffffff00;\ncursor: pointer;\ntransition: background-color 0.3s;\n-webkit-tap-highlight-color: transparent;\n-webkit-user-select: none;\n-moz-user-select: none;\n-ms-user-select: none;\nuser-select: none;\n}\n.step.active {\nbackground: radial-gradient(circle, #ff9c00, #FF5E37, #D6282899);\nbox-shadow: 0 0 16px #D62828CC;\n\n}\n.step.current {\nborder: 1px solid #ab1802;\n}\n.control-panel {\ndisplay: flex;\njustify-content: space-between;\nalign-items: center;\nmargin-top: 20px;\npadding: 15px;\nbackground: linear-gradient(0deg, #1C1C1CD2, #101010FF);\nborder-radius: 20px;\nbox-shadow: inset 0 2px 4px #00000066, 0 2px 4px #00000033;\nborder: 1px solid #1D1D1DFF;\n}\n.transport {\ndisplay: flex;\ngap: 10px;\n}\n.custom-radio-input {\ndisplay: flex;\nalign-items: center;\ngap: 2px;\nbackground-color: black;\npadding: 4px;\nborder-radius: 10px;\nz-index: 1;\nwidth: fit-content;\nmargin: 0 auto;\n}\n\n.custom-radio-input input {\ndisplay: none;\n}\n\n.custom-radio-input .custom-label {\nwidth: 90px;\nheight: 52px;\nbackground: linear-gradient(to bottom, #333333, rgb(36, 35, 35));\ndisplay: flex;\nflex-direction: column;\nalign-items: center;\njustify-content: center;\npadding: 8px;\ntransition: all 0.1s linear;\nborder-top: 1px solid #4e4d4d;\nbackground-color: #333333;\nposition: relative;\ncursor: pointer;\nbox-shadow: 0px 17px 5px 1px rgba(0, 0, 0, 0.2);\n}\n\n.custom-radio-input .custom-label:has(input[type=\"radio\"]:checked) {\nbox-shadow: 0px 17px 5px 1px rgba(0, 0, 0, 0);\nbackground: linear-gradient(to bottom, #1d1d1d, #1d1d1d);\nborder-top: none;\n}\n\n.custom-radio-input .custom-label:first-child {\nborder-top-left-radius: 6px;\nborder-bottom-left-radius: 6px;\n}\n\n.custom-radio-input .custom-label:last-child {\nborder-top-right-radius: 6px;\nborder-bottom-right-radius: 6px;\n}\n\n.custom-radio-input .custom-label::before {\ncontent: \"\";\nposition: absolute;\ntop: 50%;\nleft: 50%;\ntransform: translate(-50%, -50%);\nwidth: 103%;\nheight: 100%;\nborder-radius: 10px;\nbackground: linear-gradient(\n    to bottom,\n    transparent 10%,\n    transparent,\n    transparent 90%\n);\ntransition: all 0.1s linear;\nz-index: -1;\n}\n\n.custom-radio-input .custom-label:has(input[type=\"radio\"]:checked)::before {\nbackground: linear-gradient(\n    to bottom,\n    transparent 10%,\n    #cae2fd63,\n    transparent 90%\n);\n}\n\n.custom-radio-input .custom-label .custom-text {\ncolor: black;\nfont-size: 15px;\nline-height: 12px;\npadding: 0px;\nfont-weight: 800;\ntext-transform: uppercase;\ntransition: all 0.1s linear;\ntext-shadow:\n    -1px -1px 1px rgb(224, 224, 224, 0.1),\n    0px 2px 3px rgb(0, 0, 0, 0.3);\n}\n\n.custom-radio-input .custom-label input[type=\"radio\"]:checked + .custom-text {\ncolor: rgb(202, 226, 253);\ntext-shadow: 0px 0px 12px #cae2fd;\n}\n\n.custom-radio-input .custom-label.checked {\nbox-shadow: 0px 17px 5px 1px rgba(0, 0, 0, 0);\nbackground: linear-gradient(to bottom, #1d1d1d, #1d1d1d);\nborder-top: none;\n}\n\n.custom-radio-input .custom-label.checked::before {\nbackground: linear-gradient(\n    to bottom,\n    transparent 10%,\n    #cae2fd63,\n    transparent 90%\n);\n}\n\n.custom-radio-input .custom-label.checked .custom-text {\ncolor: rgb(202, 226, 253);\ntext-shadow: 0px 0px 12px #cae2fd;\n}\n.tempo-control {\ndisplay: flex;\nalign-items: center;\nbackground: linear-gradient(0deg, #FFFFFF00, #171717);\npadding: 12px 20px;\nborder-radius: 10px;\nbox-shadow: inset 0 2px 4px #00000066, 0 1px 2px #0000001A;\nborder: 4px solid #000000;\ngap: 10px;\ncolor: #e4effd;\ntext-shadow: 0 1px 0 #FFFFFF11, 0 -1px 0 #00000066;\nfont-weight: bold;\ntext-transform: uppercase;\nmin-width: 434px;\nfont-size: 13px;\n}\n\n.preset-buttons {\ndisplay: flex;\njustify-content: space-between;\nmargin-top: 20px;\ngap: 1px;\nbackground: linear-gradient(to bottom, #000000, #495059, #000000);\npadding: 1px;\nborder: 4px solid #000000;\nborder-radius: 10px;\n}\n\n.preset-button {\nflex-grow: 1;\nheight: 40px;\nbackground: linear-gradient(to bottom, #333333, rgb(36, 35, 35));\ndisplay: flex;\nflex-direction: column;\nalign-items: center;\njustify-content: center;\npadding: 8px;\n\nborder-top: 1px solid #4e4d4d;\nbackground-color: #333333;\nposition: relative;\ncursor: pointer;\nbox-shadow: 0px 17px 5px 1px rgba(0, 0, 0, 0.2);\nborder: none;\nfont-size: 12px;\nfont-weight: 800;\ntext-transform: uppercase;\ncolor: #e4effd !important;\ntext-shadow:\n    -1px -1px 1px rgb(224, 224, 224, 0.1),\n    0px 2px 3px rgb(0, 0, 0, 0.3);\n\/* Remove focus outline *\/\noutline: none !important;\n}\n\n.preset-button:focus {\noutline: none !important;\nbox-shadow: 0px 17px 5px 1px rgba(0, 0, 0, 0.2) !important;\n}\n\n.preset-button:first-child {\nborder-top-left-radius: 6px;\nborder-bottom-left-radius: 6px;\n}\n\n.preset-button:last-child {\nborder-top-right-radius: 6px;\nborder-bottom-right-radius: 6px;\n}\n\n.preset-button::before {\ncontent: \"\";\nposition: absolute;\ntop: 50%;\nleft: 50%;\ntransform: translate(-50%, -50%);\nwidth: 103%;\nheight: 100%;\nborder-radius: 10px;\nbackground: linear-gradient(\n    to bottom,\n    transparent 10%,\n    transparent,\n    transparent 90%\n);\ntransition: all 0.1s linear;\nz-index: -1;\n}\n\n.preset-button.active {\nbox-shadow: 0px 17px 5px 1px rgba(0, 0, 0, 0);\nbackground: linear-gradient(to bottom, #1d1d1d, #1d1d1d);\nborder-top: none;\ncolor: #cae2fd63,\ntext-shadow: 0px 2px 10px #cae2fd;\n}\n\n.preset-button.active:focus {\nbox-shadow: 0px 17px 5px 1px rgba(0, 0, 0, 0) !important;\n}\n\n.preset-button.active::before {\nbackground: linear-gradient(\n    to bottom,\n    transparent 10%,\n    #cfe2fb;\n    transparent 90%\n);\n}\n\ninput[type=\"range\"] {\nwidth: 260px;\nheight: 18px;\n-webkit-appearance: none;\nbackground: linear-gradient(to top, #333, #1a1a1a);\nborder-radius: 10px;\nborder: 1px solid #000000;\noutline: none;\n}\n\ninput[type=\"range\"]::-webkit-slider-track {\nbackground: linear-gradient(to right, #333, #1a1a1a);\nborder-radius: 10px;\nheight: 16px;\nborder: 1px solid #555;\n}\n\ninput[type=\"range\"]::-webkit-slider-thumb {\n-webkit-appearance: none;\nwidth: 20px;\nheight: 20px;\nborder-radius: 50%;\nbackground: linear-gradient(145deg, #FF8A00, #FF5E37);\ncursor: pointer;\nborder: 2px solid #333;\nbox-shadow: 0 2px 4px #00000066;\n}\n\ninput[type=\"range\"]::-webkit-slider-thumb:hover {\nbackground: linear-gradient(145deg, #FF5E37, #d54a2a);\ntransform: scale(1.0);\n}\n\ninput[type=\"range\"]::-moz-range-track {\nbackground: linear-gradient(to right, #333, #1a1a1a);\nborder-radius: 10px;\nheight: 16px;\nborder: 1px solid #000000;\n}\ninput[type=\"range\"]::-moz-range-thumb {\nwidth: 20px;\nheight: 20px;\nborder-radius: 50%;\nbackground: linear-gradient(145deg, #dfdfdf, #FF5E37);\ncursor: pointer;\nborder: 2px solid #333;\nbox-shadow: 0 2px 4px #00000066;\n}\n\n.active.current {\nbackground-color: #ffcc00;\n}\n<\/style>\n\n<\/head>\n<body>\n\n<div class=\"drum-machine\">\n<div class=\"tracks\" id=\"tracks\">\n<\/div>\n<div class=\"control-panel\">\n<div class=\"transport\">\n<div class=\"custom-radio-input\">\n<label class=\"custom-label\" id=\"play-button\">\n<input type=\"radio\" name=\"transport\" value=\"play\">\n<span class=\"custom-text\">PLAY<\/span>\n<\/label>\n<label class=\"custom-label\" id=\"stop-button\">\n<input type=\"radio\" name=\"transport\" value=\"stop\" checked>\n<span class=\"custom-text\">STOP<\/span>\n<\/label>\n<\/div>\n<\/div>\n<div class=\"tempo-control\">\n<span>Tempo:<\/span>\n<input type=\"range\" id=\"tempo-slider\" min=\"60\" max=\"180\" value=\"120\">\n<span id=\"tempo-value\">120 BPM<\/span>\n<\/div>\n<\/div>\n<div class=\"preset-buttons\" id=\"preset-buttons\">\n<\/div>\n<\/div>\n<script>\nlet audioContext = null;\nlet isPlaying = false;\nlet currentStep = 0;\nlet nextNoteTime = 0.0;\nlet scheduleAheadTime = 0.0; \nlet lookahead = 10.0;         \nlet tempo = 120.0;            \nlet timerID = null;\nlet patternLength = 16;\nlet currentPreset = 0;\nconst buffers = {};\nconst tracks = [\n{ id: 'kick', name: 'KICK', url: 'https:\/\/diverse.anderskisling.dk\/wp-content\/uploads\/2025\/05\/bd-x1.wav', volume: 0.8, pan: 0, loaded: false },\n{ id: 'hihat1', name: 'HI HAT', url: 'https:\/\/diverse.anderskisling.dk\/wp-content\/uploads\/2025\/05\/pops-hihat.wav', volume: 0.1, pan: -0.3, loaded: false },\n{ id: 'hihat2', name: 'CONGA', url: 'https:\/\/diverse.anderskisling.dk\/wp-content\/uploads\/2025\/05\/conga-x1.wav', volume: 0.5, pan: -0.2, loaded: false },\n{ id: 'snare', name: 'SNARE', url: 'https:\/\/diverse.anderskisling.dk\/wp-content\/uploads\/2025\/05\/snarez-x1.wav', volume: 0.5, pan: 0.4, loaded: false },\n{ id: 'tambourin', name: 'CLAVE', url: 'https:\/\/diverse.anderskisling.dk\/wp-content\/uploads\/2025\/05\/clave.wav', volume: 0.6, pan: 0.5, loaded: false },\n{ id: 'clap', name: 'VIBRA', url: 'https:\/\/diverse.anderskisling.dk\/wp-content\/uploads\/2025\/05\/pops-snare.wav', volume: 0.3, pan: -0.3, loaded: false }\n        ];\nlet patterns = {};\nconst presets = [\n{ name: 'RUMBA', pattern: {}, tempo: 125 },\n{ name: 'SAMBA', pattern: {}, tempo: 110 },\n{ name: 'BOSSA', pattern: {}, tempo: 97 },\n{ name: 'SALSA', pattern: {}, tempo: 110 },\n{ name: 'MAMBO', pattern: {}, tempo: 144 },\n{ name: 'CALYPSO', pattern: {}, tempo: 114 },\n{ name: 'BOMBA', pattern: {}, tempo: 103 },\n{ name: 'EMPTY', pattern: {}, tempo: 120 }\n        ];\n\nfunction initializePatterns() {\ntracks.forEach(track => {\npatterns[track.id] = Array(patternLength).fill(false);\n});\n}\n\nfunction initializePresets() {\nconst preset1Pattern = {\n'kick': [0, 8],       \n'hihat1': [0, 2, 4, 6, 8, 10, 12, 14],          \n'hihat2': [2, 6, 12],     \n'snare': [6, 12],                   \n'tambourin': [2, 3, 4, 10, 14],          \n'clap': [2]             \n};\nconst preset2Pattern = {\n'kick': [0, 3, 4, 7, 8, 11,12, 15],       \n'hihat1': [2, 6, 10, 13, 14], \n'hihat2': [4, 6, 14], \n'snare': [0, 2, 5, 9, 11, 13],                    \n'tambourin': [0, 2, 5, 7, 9, 13],    \n'clap': []                  \n};\nconst preset3Pattern = {\n'kick': [0, 3, 4, 7, 8, 11, 12, 15],            \n'hihat1': [0, 2, 4, 5, 6, 8, 11, 10, 12, 14],\n'hihat2': [14, 15],           \n'snare': [0, 3, 6, 10, 13],                    \n'tambourin': [3, 6, 10, 12],\n'clap': [12]                     \n};\nconst preset4Pattern = {\n'kick': [3, 6, 11, 14],         \n'hihat1': [0, 2, 3, 4, 6, 7, 8, 10, 11, 12, 14, 15], \n'hihat2': [3, 10, 12], \n'snare': [0, 3, 7, 10, 12],            \n'tambourin': [0, 2, 3, 5, 9, 12, 14],     \n'clap': [12]            \n};\nconst preset5Pattern = {\n'kick': [0, 8, 14],             \n'hihat1': [0, 2, 3, 4, 6, 8, 12, 14], \n'hihat2': [4, 10],           \n'snare': [4, 10, 12],                   \n'tambourin': [0, 4, 6, 12, 14],        \n'clap': [0]                   \n};\nconst preset6Pattern = {\n'kick': [0, 3, 8, 11],           \n'hihat1': [0, 2, 3, 4, 6, 7, 8, 10, 11, 12, 14, 15], \n'hihat2': [6, 11, 14],           \n'snare': [1, 3, 6, 9, 11, 14],                    \n'tambourin': [3, 6, 11, 14],       \n'clap': [12]                  \n};\n\n\n\n\n\n\n\n\n\nconst preset7Pattern = {\n'kick': [0, 4, 8, 12],           \n'hihat1': [2, 3, 6, 7, 10, 11, 14, 15],\n'hihat2': [0, 3, 4, 9, 13, 14],       \n'snare': [0, 2, 5, 7, 9, 11, 13, 14],           \n'tambourin': [0, 2, 5, 6, 7, 8, 10, 11, 12],      \n'clap': [4, 12]          \n};\n\n\n\n\n\n\n\n\n\n\nconst preset8Pattern = {\n'kick': [],              \n'hihat1': [],\n'hihat2': [],            \n'snare': [],                \n'tambourin': [],        \n'clap': [] \n};\n\n\n\n\n\n\n\n\n\n\npresets[0].pattern = convertSinglePattern(preset1Pattern);\npresets[1].pattern = convertSinglePattern(preset2Pattern);\npresets[2].pattern = convertSinglePattern(preset3Pattern);\npresets[3].pattern = convertSinglePattern(preset4Pattern);\npresets[4].pattern = convertSinglePattern(preset5Pattern);\npresets[5].pattern = convertSinglePattern(preset6Pattern);\npresets[6].pattern = convertSinglePattern(preset7Pattern);\npresets[7].pattern = convertSinglePattern(preset8Pattern);\n}\n\nfunction convertSinglePattern(userPattern) {\nconst formattedPattern = {};\nfor (const trackId in userPattern) {\nconst trackPattern = Array(patternLength).fill(false);\nuserPattern[trackId].forEach(pos => {\ntrackPattern[pos] = true;\n});\nformattedPattern[trackId] = trackPattern;\n}\nreturn formattedPattern;\n}\n\nfunction updateTransportButtons() {\nconst playButton = document.querySelector('#play-button input');\nconst stopButton = document.querySelector('#stop-button input');\n\nif (isPlaying) {\nplayButton.checked = true;\nstopButton.checked = false;\n} else {\nplayButton.checked = false;\nstopButton.checked = true;\n}\n}\n\nfunction createUI() {\nconst tracksContainer = document.getElementById('tracks');\ntracks.forEach(track => {\nconst trackDiv = document.createElement('div');\ntrackDiv.className = 'track';\nconst trackLabel = document.createElement('div');\ntrackLabel.className = 'track-label';\ntrackLabel.textContent = track.name;\ntrackDiv.appendChild(trackLabel);\nconst controls = document.createElement('div');\ncontrols.className = 'controls';\nconst volumeKnobContainer = document.createElement('div');\nvolumeKnobContainer.className = 'knob-container volume-knob';\nconst volumeKnob = document.createElement('div');\nvolumeKnob.className = 'knob';\nvolumeKnob.id = `volume-knob-${track.id}`;\nvolumeKnob.style.transform = `rotate(${track.volume * 270 - 135}deg)`;\nconst volumeRing = document.createElement('div');\nvolumeRing.className = 'knob-ring';\nconst volumeValue = document.createElement('div');\nvolumeValue.className = 'knob-value';\nvolumeValue.id = `volume-value-${track.id}`;\nvolumeValue.textContent = 'Vol';\nvolumeKnobContainer.appendChild(volumeKnob);\nvolumeKnobContainer.appendChild(volumeRing);\nvolumeKnobContainer.appendChild(volumeValue);\ncontrols.appendChild(volumeKnobContainer);\nconst volumeInput = document.createElement('input');\nvolumeInput.type = 'hidden';\nvolumeInput.id = `volume-${track.id}`;\nvolumeInput.value = track.volume;\ncontrols.appendChild(volumeInput);\nconst panKnobContainer = document.createElement('div');\npanKnobContainer.className = 'knob-container pan-knob';\nconst panKnob = document.createElement('div');\npanKnob.className = 'knob';\npanKnob.id = `pan-knob-${track.id}`;\npanKnob.style.transform = `rotate(${track.pan * 135}deg)`;\nconst panRing = document.createElement('div');\npanRing.className = 'knob-ring';\nconst panValue = document.createElement('div');\npanValue.className = 'knob-value';\npanValue.id = `pan-value-${track.id}`;\npanValue.textContent = 'Pan';\npanKnobContainer.appendChild(panKnob);\npanKnobContainer.appendChild(panRing);\npanKnobContainer.appendChild(panValue);\ncontrols.appendChild(panKnobContainer);\nconst panInput = document.createElement('input');\npanInput.type = 'hidden';\npanInput.id = `pan-${track.id}`;\npanInput.value = track.pan;\ncontrols.appendChild(panInput);\ntrackDiv.appendChild(controls);\nconst sequencer = document.createElement('div');\nsequencer.className = 'sequencer';\nfor (let i = 0; i < patternLength; i++) {\nconst step = document.createElement('div');\nstep.className = 'step';\nstep.dataset.track = track.id;\nstep.dataset.step = i;\nstep.addEventListener('click', (e) => {\ne.preventDefault();\ne.stopPropagation();\nconst trackId = step.dataset.track;\nconst stepIndex = parseInt(step.dataset.step);\npatterns[trackId][stepIndex] = !patterns[trackId][stepIndex];\nstep.classList.toggle('active', patterns[trackId][stepIndex]);\n});\nsequencer.appendChild(step);\n}\ntrackDiv.appendChild(sequencer);\ntracksContainer.appendChild(trackDiv);\nsetupKnobEvents(volumeKnob, volumeInput, volumeValue, 0, 1, track.id, 'volume');\nsetupKnobEvents(panKnob, panInput, panValue, -1, 1, track.id, 'pan');\n});\ncreatePresetButtons();\ndocument.getElementById('play-button').addEventListener('click', startPlaying);\ndocument.getElementById('stop-button').addEventListener('click', stopPlaying);\nconst tempoSlider = document.getElementById('tempo-slider');\nconst tempoValue = document.getElementById('tempo-value');\ntempoSlider.addEventListener('input', (e) => {\ntempo = parseInt(e.target.value);\nconst formattedTempo = tempo.toString().padStart(3, '0');\ntempoValue.textContent = `${formattedTempo} BPM`;\n\/\/ Opdater det aktuelle preset med det nye tempo\npresets[currentPreset].tempo = tempo;\n});\n}\n\nfunction setupKnobEvents(knobElement, inputElement, valueElement, minVal, maxVal, trackId, paramType) {\nlet isDragging = false;\nlet startY = 0;\nlet startValue = 0;\nknobElement.addEventListener('mousedown', startDrag);\ndocument.addEventListener('mousemove', drag);\ndocument.addEventListener('mouseup', endDrag);\nknobElement.addEventListener('touchstart', handleTouchStart);\ndocument.addEventListener('touchmove', handleTouchMove);\ndocument.addEventListener('touchend', handleTouchEnd);\nfunction startDrag(e) {\ne.preventDefault();\ne.stopPropagation();\nisDragging = true;\nstartY = e.clientY;\nstartValue = parseFloat(inputElement.value);\nknobElement.style.cursor = 'grabbing';\n}\nfunction handleTouchStart(e) {\ne.preventDefault();\ne.stopPropagation();\nconst touch = e.touches[0];\nisDragging = true;\nstartY = touch.clientY;\nstartValue = parseFloat(inputElement.value);\n}\nfunction drag(e) {\nif (!isDragging) return;\nconst deltaY = startY - e.clientY;\nconst range = maxVal - minVal;\nconst valueChange = (deltaY \/ 100) * range;\nlet newValue = Math.min(maxVal, Math.max(minVal, startValue + valueChange));\ninputElement.value = newValue;\ntracks.find(t => t.id === trackId)[paramType] = newValue;\nlet angle;\nif (paramType === 'volume') {\nangle = (newValue - minVal) \/ (maxVal - minVal) * 270 - 135;\n} else {\nangle = newValue * 135;\n}\nknobElement.style.transform = `rotate(${angle}deg)`;\nif (paramType === 'volume') {\nvalueElement.textContent = 'Vol';\n} else {\nvalueElement.textContent = 'Pan';\n}\n}\nfunction handleTouchMove(e) {\nif (!isDragging) return;\nconst touch = e.touches[0];\nconst deltaY = startY - touch.clientY;\nconst range = maxVal - minVal;\nconst valueChange = (deltaY \/ 100) * range;\nlet newValue = Math.min(maxVal, Math.max(minVal, startValue + valueChange));\ninputElement.value = newValue;\ntracks.find(t => t.id === trackId)[paramType] = newValue;\nlet angle;\nif (paramType === 'volume') {\nangle = (newValue - minVal) \/ (maxVal - minVal) * 270 - 135;\n} else {\nangle = newValue * 135;\n}\n\n\nknobElement.style.transform = `rotate(${angle}deg)`;\nif (paramType === 'volume') {\nvalueElement.textContent = 'Vol';\n} else {\nvalueElement.textContent = 'Pan';\n}\n}\nfunction endDrag() {\nisDragging = false;\nknobElement.style.cursor = 'pointer';\n}\nfunction handleTouchEnd() {\nisDragging = false;\n}\n}\n\nfunction initAudio() {\nif (audioContext === null) {\ntry {\naudioContext = new (window.AudioContext || window.webkitAudioContext)();\nif (audioContext.state === 'suspended') {\naudioContext.resume();\n}\n\n\nconsole.log('Starting to load samples...');\ntracks.forEach(track => {\nloadSample(track.url, track.id)\n.then(() => {\nconsole.log(`Sample ${track.id} loaded successfully`);\n})\n.catch(error => {\nconsole.error(`Failed to load sample ${track.id}:`, error);\ntryFallbackLoading(track);\n});\n});\n} catch (e) {\nconsole.error('Error initializing audio:', e);\nshowError('fejl');\n}\n}\n}\n\nfunction tryFallbackLoading(track) {\nconsole.log(`Attempting fallback loading for ${track.id}...`);\nconst audio = new Audio();\naudio.crossOrigin = \"anonymous\";\naudio.addEventListener('canplaythrough', function() {\ntry {\nconst source = audioContext.createMediaElementSource(audio);\nbuffers[track.id] = {\naudioElement: audio,\nmediaSource: source\n};\ntrack.loaded = true;\ntrack.useFallback = true;\nupdateLoadingStatus(track.id, true);\nconsole.log(`Fallback loading successful for ${track.id}`);\n} catch (e) {\nconsole.error(`Fallback loading failed for ${track.id}:`, e);\nupdateLoadingStatus(track.id, false, \"Fallback fejl\");\n}\n}, { once: true });\naudio.addEventListener('error', function() {\nconsole.error(`Fallback loading error for ${track.id}: ${audio.error?.message || 'Unknown error'}`);\nupdateLoadingStatus(track.id, false, \"Kunne ikke indl\u00e6se\");\n});\naudio.src = track.url;\naudio.load();\n}\n\nfunction showError(message) {\nconst errorDiv = document.createElement('div');\nerrorDiv.style.padding = '10px';\nerrorDiv.style.margin = '10px 0';\nerrorDiv.style.backgroundColor = '#555';\nerrorDiv.style.color = '#ddd';\nerrorDiv.style.borderRadius = '5px';\nerrorDiv.textContent = message;\nconst controlPanel = document.querySelector('.control-panel');\ncontrolPanel.parentNode.insertBefore(errorDiv, controlPanel);\nsetTimeout(() => {\nerrorDiv.remove();\n}, 5000);\n}\n\nfunction loadSample(url, id) {\nreturn new Promise((resolve, reject) => {\nconst track = tracks.find(t => t.id === id);\nconst xhr = new XMLHttpRequest();\nxhr.open('GET', url, true);\nxhr.responseType = 'arraybuffer';\nxhr.onload = function() {\nif (xhr.status === 200) {\naudioContext.decodeAudioData(\nxhr.response,\nfunction(buffer) {\nbuffers[id] = buffer;\ntrack.loaded = true;\nconsole.log(`Successfully loaded sample: ${id}`);\nupdateLoadingStatus(id, true);\nresolve(buffer);\n},\nfunction(error) {\nconsole.error(`Error decoding audio data for ${id}:`, error);\nupdateLoadingStatus(id, false, \"audiofejl\");\nreject(error);\n}\n);\n} else {\nconst errorMsg = `Failed to load sample: ${url}, status: ${xhr.status}`;\nconsole.error(errorMsg);\nupdateLoadingStatus(id, false, `HTTP ${xhr.status}`);\nreject(new Error(errorMsg));\n}\n};\nxhr.onerror = function() {\nconst errorMsg = `Network error loading sample: ${url}`;\nconsole.error(errorMsg);\nupdateLoadingStatus(id, false, \"Netv\u00e6rksfejl\");\nreject(new Error(errorMsg));\n};\nxhr.onprogress = function(event) {\nif (event.lengthComputable) {\nconst percentComplete = Math.round((event.loaded \/ event.total) * 100);\nupdateLoadingProgress(id, percentComplete);\n}\n};\nxhr.send();\n});\n}\n\nfunction updateLoadingStatus(id, success, errorMsg = \"\") {\nconsole.log(`Sample ${id} loading status: ${success ? \"Ready\" : errorMsg}`);\n}\n\nfunction updateLoadingProgress(id, percent) {\nif (percent % 25 === 0) { \nconsole.log(`Sample ${id} loading: ${percent}%`);\n}\n}\n\nfunction playSound(buffer, time, trackId) {\nif (!buffer) {\nconsole.warn('Attempted to play undefined buffer');\nreturn;\n}\ntry {\nconst track = tracks.find(t => t.id === trackId);\nif (!track) {\nconsole.warn(`Track with ID ${trackId} not found`);\nreturn;\n}\nconst volumeValue = document.getElementById(`volume-${trackId}`).value;\nconst panValue = document.getElementById(`pan-${trackId}`).value;\nconst volume = parseFloat(volumeValue);\nconst pan = parseFloat(panValue);\nconsole.log(`Playing ${trackId} with volume ${volume} and pan ${pan}`);\nif (buffer.audioElement && buffer.mediaSource) {\nconst audioEl = buffer.audioElement;\nconst source = buffer.mediaSource;\ntry {\nsource.disconnect();\n} catch (e) {\n}\nconst gainNode = audioContext.createGain();\ngainNode.gain.value = volume;\nconst pannerNode = audioContext.createStereoPanner();\npannerNode.pan.value = pan;\nsource.connect(pannerNode);\npannerNode.connect(gainNode);\ngainNode.connect(audioContext.destination);\naudioEl.currentTime = 0;\naudioEl.play();\nreturn source;\n} else {\nconst source = audioContext.createBufferSource();\nsource.buffer = buffer;\nconst gainNode = audioContext.createGain();\ngainNode.gain.value = volume;\nconst pannerNode = audioContext.createStereoPanner();\npannerNode.pan.value = pan;\nsource.connect(pannerNode);\npannerNode.connect(gainNode);\ngainNode.connect(audioContext.destination);\nsource.start(time);\nreturn source;\n}\n} catch (e) {\nconsole.error('Error playing sound:', e);\n}\n}\n\nfunction nextNote() {\nconst secondsPerBeat = 60.0 \/ tempo;\nnextNoteTime += 0.25 * secondsPerBeat; \ncurrentStep = (currentStep + 1) % patternLength;\n}\n\nfunction scheduleNote(beatNumber, time) {\ntracks.forEach(track => {\nif (patterns[track.id][beatNumber] && buffers[track.id]) {\nconst actualTime = track.useFallback ? audioContext.currentTime : time;\nplaySound(buffers[track.id], actualTime, track.id);\n}\n});\nupdateStepUIForCurrentBeat(beatNumber);\n}\n\nfunction updateStepUIForCurrentBeat(beatNumber) {\ndocument.querySelectorAll('.step.current').forEach(el => {\nel.classList.remove('current');\n});\ndocument.querySelectorAll(`.step[data-step=\"${beatNumber}\"]`).forEach(el => {\nel.classList.add('current');\n});\n}\n\nfunction updateStepUI() {\ntracks.forEach(track => {\nconst trackId = track.id;\nconst trackPattern = patterns[trackId];\nfor (let i = 0; i < patternLength; i++) {\nconst stepEl = document.querySelector(`.step[data-track=\"${trackId}\"][data-step=\"${i}\"]`);\nif (stepEl) {\nstepEl.classList.toggle('active', trackPattern[i]);\n}\n}\n});\n}\n\nfunction scheduler() {\nwhile (nextNoteTime < audioContext.currentTime + scheduleAheadTime) {\nscheduleNote(currentStep, nextNoteTime);\nnextNote();\n}\ntimerID = setTimeout(scheduler, lookahead);\n}\n\nfunction startPlaying() {\nif (isPlaying) return;\ninitAudio();\nconst hasLoadedSamples = tracks.some(track => track.loaded);\nif (!hasLoadedSamples) {\nconsole.warn(\"Reloading\");\ntracks.forEach(track => {\nif (!track.loaded) {\ntryFallbackLoading(track);\n}\n});\nshowError(\"! Virker ikke i Safari - Brug Chrome for bedste resultat\");\nreturn;\n}\nisPlaying = true;\ncurrentStep = 0;\nnextNoteTime = audioContext.currentTime;\nscheduler(); \nif (audioContext.state === 'suspended') {\naudioContext.resume();\n}\nupdateTransportButtons();\n}\n\nfunction stopPlaying() {\nisPlaying = false;\nclearTimeout(timerID);\ndocument.querySelectorAll('.step.current').forEach(el => {\nel.classList.remove('current');\n});\nupdateTransportButtons();\n}\n\nfunction testSingleSound(trackId) {\nif (!audioContext) {\ninitAudio();\n}\nconst track = tracks.find(t => t.id === trackId);\nif (track && buffers[trackId]) {\nplaySound(buffers[trackId], audioContext.currentTime, trackId);\n} else {\nconsole.warn(`Cannot test sound ${trackId}: not loaded`);\n}\n}\n\nfunction updateTempoDisplay(newTempo) {\ntempo = newTempo;\nconst tempoSlider = document.getElementById('tempo-slider');\nconst tempoValue = document.getElementById('tempo-value');\n\n\/\/ Opdater slider position\ntempoSlider.value = newTempo;\nconst formattedTempo = newTempo.toString().padStart(3, '0');\ntempoValue.textContent = `${formattedTempo} BPM`;\n}\n\nfunction loadPreset(presetIndex) {\nconst preset = presets[presetIndex];\nif (!preset || !preset.pattern) {\nconsole.warn(`Preset ${presetIndex} not found or has no pattern`);\nreturn;\n}\n\n\/\/ Opdater currentPreset variablen\ncurrentPreset = presetIndex;\n\ntracks.forEach(track => {\nconst trackId = track.id;\npatterns[trackId] = Array(patternLength).fill(false);\nif (preset.pattern[trackId]) {\nfor (let i = 0; i < patternLength; i++) {\npatterns[trackId][i] = preset.pattern[trackId][i];\n}\n}\n});\n\n\/\/ Indl\u00e6s tempo for dette preset\nupdateTempoDisplay(preset.tempo);\n\nupdateStepUI();\nupdatePresetButtons(presetIndex);\nconsole.log(`Loaded preset: ${preset.name} with tempo: ${preset.tempo}`);\n}\n\nfunction updatePresetButtons(activeIndex) {\nconst buttons = document.querySelectorAll('.preset-button');\nbuttons.forEach((button, index) => {\nbutton.classList.toggle('active', index === activeIndex);\n});\n}\n\nfunction createPresetButtons() {\nconst presetContainer = document.getElementById('preset-buttons');\npresetContainer.innerHTML = ''; \npresets.forEach((preset, index) => {\nconst button = document.createElement('button');\nbutton.className = 'preset-button';\nbutton.textContent = preset.name;\nbutton.addEventListener('click', () => {\nloadPreset(index);\n});\npresetContainer.appendChild(button);\n});\n}\n\nfunction init() {\ninitializePatterns();\ninitializePresets();\ncreateUI();\ninitAudio();\nloadPreset(0);\ndocument.getElementById('play-button').addEventListener('click', initAudio);\n}\n\nwindow.addEventListener('DOMContentLoaded', init);\n\ndocument.addEventListener('keydown', function(event) {\n    if (event.code === 'Space' || event.key === ' ') {\n        event.preventDefault();\n        if (isPlaying) {\n            stopPlaying();\n            console.log('Paused with spacebar');\n        } else {\n            startPlaying();\n            console.log('Started with spacebar');\n        }\n    }\n});\n<\/script>\n<\/body>\n<\/html>\t\t\t\t<\/div>\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>VINTAGE TR-777 Trommemaskine PLAY STOP Tempo: 120 BPM<\/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-4656","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/diverse.anderskisling.dk\/index.php\/wp-json\/wp\/v2\/pages\/4656","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/diverse.anderskisling.dk\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/diverse.anderskisling.dk\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/diverse.anderskisling.dk\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/diverse.anderskisling.dk\/index.php\/wp-json\/wp\/v2\/comments?post=4656"}],"version-history":[{"count":15,"href":"https:\/\/diverse.anderskisling.dk\/index.php\/wp-json\/wp\/v2\/pages\/4656\/revisions"}],"predecessor-version":[{"id":18492,"href":"https:\/\/diverse.anderskisling.dk\/index.php\/wp-json\/wp\/v2\/pages\/4656\/revisions\/18492"}],"wp:attachment":[{"href":"https:\/\/diverse.anderskisling.dk\/index.php\/wp-json\/wp\/v2\/media?parent=4656"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}