{"id":3347,"date":"2026-09-08T14:52:10","date_gmt":"2026-09-08T12:52:10","guid":{"rendered":"https:\/\/lucasgoret.com\/?page_id=3347"},"modified":"2026-09-23T10:28:58","modified_gmt":"2026-09-23T08:28:58","slug":"audition-forme-donde","status":"publish","type":"page","link":"https:\/\/lucasgoret.com\/index.php\/audition-forme-donde\/","title":{"rendered":"3 COURS &#8211; Audition Forme d&#8217;Onde"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"3347\" class=\"elementor elementor-3347\">\n\t\t\t\t<div class=\"elementor-element elementor-element-50463e3 e-flex e-con-boxed e-con e-parent\" data-id=\"50463e3\" 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-ecde2eb elementor-widget elementor-widget-html\" data-id=\"ecde2eb\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<!--\nPAGE 02 \u2014 AUDITION \/ FORME D'ONDE\nHTML complet pr\u00eat \u00e0 coller dans un widget HTML Elementor.\n-->\n<style>\n#au26{\n  --bg:#09090b;--surface:#14151a;--surface2:#101116;--line:#2b2d35;\n  --text:#f4f4f6;--muted:#a3a5ad;--accent:#918bff;--accent2:#b8b4ff;\n  --max:1380px;\n  background:var(--bg)!important;color:var(--text)!important;\n  font-family:Inter,Arial,sans-serif;overflow:hidden;\n}\n#au26 *{box-sizing:border-box}\n#au26 a{color:inherit}\n#au26 .shell{width:min(var(--max),calc(100% - 48px));margin:auto}\n#au26 .course-nav{border-bottom:1px solid var(--line);background:#09090b}\n#au26 .course-nav .inner{display:grid;grid-template-columns:repeat(7,1fr);gap:10px;padding:26px 0 20px}\n#au26 .course-nav a{text-decoration:none;text-align:center;padding:12px 8px 16px;color:#c5c5c9!important;border-bottom:2px solid transparent}\n#au26 .course-nav strong{display:block;color:#f4f4f6!important;font-size:13px;letter-spacing:.02em}\n#au26 .course-nav span{display:block;margin-top:6px;font-size:12px}\n#au26 .course-nav a.active{border-bottom-color:var(--accent)}\n#au26 .topbar{position:sticky;top:10px;z-index:30;margin-top:16px}\n#au26 .topbar-inner{display:flex;justify-content:space-between;align-items:center;gap:20px;padding:14px 18px;border:1px solid var(--line);border-radius:22px;background:rgba(20,21,26,.88);backdrop-filter:blur(16px)}\n#au26 .brand{display:flex;gap:12px;align-items:center}\n#au26 .dot{width:10px;height:10px;border-radius:50%;background:var(--accent);box-shadow:0 0 0 7px rgba(145,139,255,.12)}\n#au26 .brand b{font-size:14px}\n#au26 .brand small{display:block;margin-top:3px;color:#7f818a!important;font-size:10px;letter-spacing:.13em;text-transform:uppercase}\n#au26 .theme{border:1px solid var(--line);background:transparent;color:var(--text);border-radius:14px;width:42px;height:42px;cursor:pointer}\n#au26 .hero{padding:clamp(90px,11vw,155px) 0 clamp(80px,9vw,125px)}\n#au26 .hero-grid{display:grid;grid-template-columns:minmax(0,1.55fr) minmax(260px,.45fr);gap:70px;align-items:end}\n#au26 .kicker{display:flex;gap:12px;align-items:center;margin-bottom:28px;color:#aaa!important;font-size:11px;letter-spacing:.16em;text-transform:uppercase;font-weight:800}\n#au26 .kicker:before{content:\"\";width:38px;height:1px;background:var(--accent)}\n#au26 h1,#au26 h2,#au26 h3{color:var(--text)!important}\n#au26 .hero h1{margin:0!important;font-size:clamp(64px,9.8vw,136px)!important;line-height:.83!important;letter-spacing:-.074em!important;font-weight:760!important}\n#au26 .hero h1 span{display:inline-block}\n#au26 .hero h1 .hero-main{color:var(--text)!important}\n#au26 .hero h1 .hero-accent{color:var(--accent)!important}\n#au26 .lead{max-width:820px;margin:42px 0 0!important;color:var(--muted)!important;font-size:clamp(18px,2vw,24px)!important;line-height:1.55!important}\n#au26 .meta{display:grid;gap:12px}\n#au26 .meta div{padding:18px;border:1px solid var(--line);border-radius:18px;background:var(--surface)}\n#au26 .meta small{display:block;color:#7b7d86!important;font-size:10px;letter-spacing:.15em;text-transform:uppercase;font-weight:800}\n#au26 .meta b{display:block;margin-top:8px;font-size:14px}\n#au26 .local-nav{position:sticky;top:84px;z-index:25;padding:0 0 28px}\n#au26 .local-nav .links{display:flex;gap:4px;overflow:auto;padding:6px;border:1px solid var(--line);border-radius:999px;background:rgba(20,21,26,.92);backdrop-filter:blur(14px)}\n#au26 .local-nav a{white-space:nowrap;text-decoration:none;padding:10px 14px;border-radius:999px;color:#a9abb3!important;font-size:12px;font-weight:700}\n#au26 .local-nav a:hover{background:#202128;color:#fff!important}\n#au26 .section{padding:clamp(78px,8vw,122px) 0;border-top:1px solid #18191e}\n#au26 .head{display:grid;grid-template-columns:190px minmax(0,1fr);gap:52px;margin-bottom:52px}\n#au26 .index{color:var(--accent)!important;font-size:11px;font-weight:800;letter-spacing:.16em;text-transform:uppercase;padding-top:9px}\n#au26 .head h2{margin:0!important;font-size:clamp(45px,6vw,84px)!important;line-height:.94!important;letter-spacing:-.055em!important;font-weight:740!important}\n#au26 .intro{max-width:880px;margin:20px 0 0!important;color:var(--muted)!important;font-size:18px!important;line-height:1.65!important}\n#au26 p,#au26 li{color:#c6c7cc!important;font-size:15px!important;line-height:1.75!important}\n#au26 strong{color:#f4f4f6!important}\n#au26 .grid2{display:grid;grid-template-columns:1fr 1fr;gap:16px}\n#au26 .grid3{display:grid;grid-template-columns:repeat(3,1fr);gap:16px}\n#au26 .card{padding:22px;border:1px solid var(--line);border-radius:20px;background:var(--surface)}\n#au26 .card h3{margin:0 0 12px!important;font-size:22px!important;letter-spacing:-.025em!important}\n#au26 .card p:first-child{margin-top:0!important}\n#au26 .card p:last-child{margin-bottom:0!important}\n#au26 .media{overflow:hidden;border:1px solid var(--line);border-radius:22px;background:#0d0e12}\n#au26 .media img{display:block;width:100%;height:auto}\n#au26 .media-caption{padding:13px 16px;color:#90929b!important;font-size:11px;line-height:1.5}\n#au26 .video{aspect-ratio:16\/9;border:1px solid var(--line);border-radius:20px;overflow:hidden;background:#000}\n#au26 .video iframe{width:100%;height:100%;border:0}\n#au26 .warning{padding:20px 22px;border-left:3px solid var(--accent);border-radius:0 18px 18px 0;background:#15151b}\n#au26 .principle-row{\n  display:grid;\n  grid-template-columns:minmax(240px,.72fr) minmax(0,1.28fr);\n  gap:34px;\n  align-items:center;\n  margin:24px 0 34px;\n}\n#au26 .principle{\n  padding:clamp(26px,4vw,46px);\n  border:1px solid rgba(145,139,255,.42);\n  border-radius:24px;\n  background:#1b1b2b!important;\n}\n#au26 .principle p{\n  margin:0!important;\n  color:#f4f4f6!important;\n  font-size:clamp(27px,3vw,44px)!important;\n  line-height:1.05!important;\n  letter-spacing:-.045em!important;\n  font-weight:700!important;\n}\n#au26 .principle-wide{\n  margin:24px 0 34px;\n  padding:clamp(30px,5vw,58px);\n  border:1px solid rgba(145,139,255,.40);\n  border-radius:26px;\n  background:#1b1b2b!important;\n}\n#au26 .principle-wide p{\n  max-width:980px;\n  margin:0!important;\n  color:#f4f4f6!important;\n  font-size:clamp(30px,4.2vw,58px)!important;\n  line-height:1.02!important;\n  letter-spacing:-.05em!important;\n  font-weight:700!important;\n}\n#au26 .accent-line{\n  margin:24px 0 34px;\n  padding:18px 0 18px 22px;\n  border-left:2px solid var(--accent);\n}\n#au26 .accent-line p{\n  max-width:980px;\n  margin:0!important;\n  color:#e7e7eb!important;\n  font-size:clamp(20px,2.2vw,28px)!important;\n  line-height:1.35!important;\n  letter-spacing:-.025em!important;\n  font-weight:650!important;\n}\n#au26 .footer-index{\n  margin-top:24px;\n  padding:clamp(28px,4vw,46px);\n  border:1px solid var(--line);\n  border-radius:26px;\n  background:var(--surface)!important;\n}\n#au26 .footer-index-head{\n  display:grid;\n  grid-template-columns:180px minmax(0,1fr);\n  gap:36px;\n  align-items:start;\n  margin-bottom:30px;\n  padding-bottom:24px;\n  border-bottom:1px solid var(--line);\n}\n#au26 .footer-index-head .eyebrow{\n  color:var(--accent)!important;\n  font-size:10px;\n  line-height:1.3;\n  letter-spacing:.17em;\n  text-transform:uppercase;\n  font-weight:800;\n  padding-top:8px;\n}\n#au26 .footer-index-head h2{\n  margin:0!important;\n  font-size:clamp(40px,5vw,68px)!important;\n  line-height:.96!important;\n  letter-spacing:-.05em!important;\n  font-weight:720!important;\n}\n#au26 .footer-groups{\n  display:grid;\n  grid-template-columns:repeat(3,minmax(0,1fr));\n  gap:14px;\n}\n#au26 .footer-group{\n  padding:18px;\n  border:1px solid var(--line);\n  border-radius:16px;\n  background:var(--surface2)!important;\n}\n#au26 .footer-group h3{\n  margin:0 0 12px!important;\n  font-size:17px!important;\n}\n#au26 .footer-group a{\n  display:block;\n  padding:8px 0;\n  border-top:1px solid var(--line-soft);\n  text-decoration:none;\n  color:#d8d9de!important;\n  font-size:13px;\n}\n#au26 .footer-group a:first-of-type{border-top:0}\n#au26 .footer-note{\n  margin-top:14px;\n  padding:16px 18px;\n  border:1px solid var(--line);\n  border-radius:14px;\n  background:var(--surface2)!important;\n}\n#au26 .footer-note p{margin:0 0 8px!important}\n#au26 .footer-note p:last-child{margin-bottom:0!important}\n#au26 .final-card{\n  margin:72px 0 34px;\n  padding:clamp(34px,5vw,62px);\n  border:1px solid var(--line);\n  border-radius:27px;\n  background:var(--surface)!important;\n}\n#au26 .final-card h2{\n  max-width:760px;\n  margin:0!important;\n  font-size:clamp(38px,5.5vw,64px)!important;\n  line-height:1!important;\n  letter-spacing:-.05em!important;\n  font-weight:650!important;\n}\n#au26 .site-footer{\n  display:flex;\n  justify-content:space-between;\n  gap:20px;\n  padding:26px 0 45px;\n  border-top:1px solid var(--line);\n  color:#777982!important;\n  font-size:11px;\n}\n@media(max-width:900px){\n  #au26 .principle-row{grid-template-columns:1fr}\n  #au26 .footer-index-head{grid-template-columns:1fr;gap:12px}\n  #au26 .footer-groups{grid-template-columns:1fr 1fr}\n}\n@media(max-width:620px){\n  #au26 .footer-groups{grid-template-columns:1fr}\n  #au26 .principle p{font-size:clamp(25px,8vw,36px)!important}\n}\n\n#au26 .steps{display:grid;grid-template-columns:repeat(3,1fr);gap:12px}\n#au26 .step{padding:18px;border:1px solid var(--line);border-radius:16px;background:var(--surface2)}\n#au26 .step b{display:block;margin-bottom:7px}\n#au26 .tool-wrap{margin-top:28px;border:1px solid var(--line);border-radius:26px;overflow:hidden;background:#09090b}\n#au26 iframe.tool{display:block;width:100%;border:0;background:#09090b}\n#au26 .facts{display:grid;grid-template-columns:repeat(2,1fr);gap:14px}\n#au26 .facts .card{min-height:160px}\n#au26 ul{padding-left:20px}\n#au26 .effects{display:grid;grid-template-columns:repeat(2,1fr);gap:16px}\n\n#au26 .basics-hero{\n  display:grid;\n  grid-template-columns:minmax(270px,.72fr) minmax(0,1.28fr);\n  gap:18px;\n  align-items:stretch;\n  margin:24px 0 20px;\n}\n#au26 .basics-hero .principle{\n  margin:0;\n  min-height:100%;\n  display:flex;\n  align-items:center;\n}\n#au26 .basics-screen{\n  overflow:hidden;\n  border:1px solid var(--line);\n  border-radius:24px;\n  background:#0d0e12;\n}\n#au26 .basics-screen img{\n  display:block;\n  width:100%;\n  height:100%;\n  object-fit:cover;\n}\n#au26 .basics-screen .media-caption{border-top:1px solid var(--line)}\n#au26 .basics-note{\n  margin:0 0 34px;\n  padding:16px 18px 16px 20px;\n  border-left:2px solid var(--accent);\n  border-radius:0 14px 14px 0;\n  background:#14151a;\n}\n#au26 .basics-note p{\n  margin:0!important;\n  color:#c9cad0!important;\n  font-size:14px!important;\n  line-height:1.6!important;\n}\n\n#au26 .compact-subhead{\n  margin:46px 0 24px!important;\n  color:var(--text)!important;\n  font-size:clamp(30px,3.5vw,46px)!important;\n  line-height:1.02!important;\n  letter-spacing:-.04em!important;\n  font-weight:670!important;\n}\n\n#au26 .tools-row{\n  grid-template-columns:repeat(4,minmax(0,1fr))!important;\n  gap:12px!important;\n}\n#au26 .tools-row .tool-card{\n  min-height:205px;\n}\n@media(max-width:1050px){\n  #au26 .tools-row{grid-template-columns:repeat(2,minmax(0,1fr))!important}\n}\n@media(max-width:620px){\n  #au26 .tools-row{grid-template-columns:1fr!important}\n}\n\n#au26 .tool-card{\n  position:relative;\n  padding-top:72px!important;\n}\n#au26 .tool-icon{\n  position:absolute;\n  left:18px;\n  top:17px;\n  width:40px;\n  height:40px;\n  display:grid;\n  place-items:center;\n  border:1px solid var(--line);\n  border-radius:11px;\n  background:#0d0e12;\n  color:var(--accent);\n}\n#au26 .tool-icon svg{\n  width:23px;\n  height:23px;\n  display:block;\n  stroke:currentColor;\n  fill:none;\n  stroke-width:1.7;\n  stroke-linecap:round;\n  stroke-linejoin:round;\n}\n\n#au26 .utility-panel{\n  display:grid;\n  grid-template-columns:1fr 1fr;\n  margin-top:42px;\n  border-top:1px solid var(--line);\n  border-bottom:1px solid var(--line);\n}\n#au26 .utility-col{\n  padding:30px 30px 30px 0;\n}\n#au26 .utility-col + .utility-col{\n  padding-left:30px;\n  padding-right:0;\n  border-left:1px solid var(--line);\n}\n#au26 .utility-col h3{\n  margin:0 0 22px!important;\n  font-size:clamp(25px,2.4vw,34px)!important;\n  line-height:1.1!important;\n  letter-spacing:-.035em!important;\n  font-weight:630!important;\n}\n#au26 .utility-list{\n  display:grid;\n  gap:0;\n}\n#au26 .utility-item{\n  padding:15px 0;\n  border-top:1px solid var(--line-soft);\n}\n#au26 .utility-item:first-child{border-top:0;padding-top:0}\n#au26 .utility-item p{\n  margin:0!important;\n  color:#bfc1c8!important;\n  font-size:14px!important;\n  line-height:1.6!important;\n}\n#au26 .utility-item strong{\n  display:inline;\n}\n#au26 .utility-details{\n  margin-top:10px;\n  border-top:1px solid var(--line-soft);\n}\n#au26 .utility-details summary{\n  list-style:none;\n  display:flex;\n  align-items:center;\n  justify-content:space-between;\n  gap:14px;\n  padding:14px 0 4px;\n  cursor:pointer;\n  color:#e5e5e9!important;\n  font-size:13px;\n  font-weight:700;\n}\n#au26 .utility-details summary::-webkit-details-marker{display:none}\n#au26 .utility-details summary:after{\n  content:\"+\";\n  width:24px;height:24px;\n  display:grid;place-items:center;\n  border:1px solid var(--line);\n  border-radius:50%;\n  color:var(--accent);\n  transition:transform .18s ease;\n}\n#au26 .utility-details[open] summary:after{transform:rotate(45deg)}\n#au26 .utility-details ul{\n  margin:8px 0 0;\n  padding:0 0 0 18px;\n}\n#au26 .utility-details li{\n  margin:5px 0;\n  color:#aeb0b8!important;\n  font-size:13px!important;\n  line-height:1.5!important;\n}\n@media(max-width:850px){\n  #au26 .utility-panel{grid-template-columns:1fr}\n  #au26 .utility-col{padding:26px 0}\n  #au26 .utility-col + .utility-col{\n    padding-left:0;\n    border-left:0;\n    border-top:1px solid var(--line);\n  }\n}\n\n#au26 .fx-explainer{\n  display:grid;\n  gap:16px;\n}\n#au26 .fx-legend{\n  display:grid;\n  grid-template-columns:repeat(2,minmax(0,1fr));\n  gap:8px;\n  margin-top:16px;\n}\n#au26 .fx-item{\n  display:grid;\n  grid-template-columns:24px minmax(0,1fr);\n  gap:8px;\n  align-items:start;\n  padding:9px 0;\n  border-top:1px solid var(--line-soft);\n}\n#au26 .fx-num{\n  color:var(--accent)!important;\n  font-size:10px;\n  font-weight:800;\n  letter-spacing:.12em;\n  padding-top:2px;\n}\n#au26 .fx-text{\n  color:#bfc1c8!important;\n  font-size:12px;\n  line-height:1.45;\n}\n@media(max-width:620px){\n  #au26 .fx-legend{grid-template-columns:1fr}\n}\n\n#au26 .gesture-intro{\n  display:grid;\n  grid-template-columns:180px minmax(0,1fr);\n  gap:36px;\n  align-items:start;\n  margin:46px 0 24px;\n}\n#au26 .gesture-intro .eyebrow{\n  color:var(--accent)!important;\n  font-size:10px;\n  line-height:1.3;\n  letter-spacing:.16em;\n  text-transform:uppercase;\n  font-weight:800;\n  padding-top:7px;\n}\n#au26 .gesture-intro h3{\n  margin:0!important;\n  font-size:clamp(30px,3.5vw,46px)!important;\n  line-height:1.02!important;\n  letter-spacing:-.04em!important;\n  font-weight:670!important;\n}\n#au26 .gesture-intro p{\n  max-width:760px;\n  margin:12px 0 0!important;\n  color:var(--muted)!important;\n  font-size:14px!important;\n}\n#au26 .gesture-grid{\n  display:grid;\n  grid-template-columns:1fr 1fr;\n  gap:12px;\n}\n#au26 .gesture-grid details{\n  overflow:hidden;\n  border:1px solid var(--line);\n  border-radius:17px;\n  background:var(--surface);\n  transition:border-color .18s ease, background .18s ease;\n}\n#au26 .gesture-grid details[open]{\n  border-color:rgba(145,139,255,.5);\n  background:#161720;\n}\n#au26 .gesture-grid summary{\n  list-style:none;\n  display:grid;\n  grid-template-columns:36px minmax(0,1fr) auto;\n  gap:12px;\n  align-items:center;\n  min-height:86px;\n  padding:15px 16px;\n  cursor:pointer;\n}\n#au26 .gesture-grid summary::-webkit-details-marker{display:none}\n#au26 .gesture-num{\n  color:var(--accent)!important;\n  font-size:10px;\n  font-weight:800;\n  letter-spacing:.14em;\n}\n#au26 .gesture-title{\n  color:var(--text)!important;\n  font-size:17px;\n  line-height:1.15;\n  font-weight:700;\n  letter-spacing:-.02em;\n}\n#au26 .gesture-desc{\n  margin-top:4px;\n  color:var(--muted)!important;\n  font-size:12px;\n  line-height:1.45;\n}\n#au26 .gesture-end{display:flex;align-items:center;gap:8px}\n#au26 .gesture-key{\n  padding:6px 9px;\n  border:1px solid var(--line);\n  border-radius:999px;\n  background:#0d0e12;\n  color:#c8c9cf!important;\n  font-size:10px;\n  font-weight:750;\n  white-space:nowrap;\n}\n#au26 .gesture-plus{\n  width:26px;height:26px;\n  display:grid;place-items:center;\n  border:1px solid var(--line);\n  border-radius:50%;\n  color:var(--accent)!important;\n  font-size:15px;\n  line-height:1;\n  transition:transform .18s ease;\n}\n#au26 .gesture-grid details[open] .gesture-plus{transform:rotate(45deg)}\n#au26 .gesture-media{\n  padding:0 12px 12px;\n  animation:auGestureIn .18s ease both;\n}\n#au26 .gesture-frame{\n  overflow:hidden;\n  border:1px solid var(--line);\n  border-radius:13px;\n  background:#07080b;\n}\n#au26 .gesture-frame img{\n  display:block;\n  width:100%;\n  height:auto;\n}\n@keyframes auGestureIn{\n  from{opacity:0;transform:translateY(-4px)}\n  to{opacity:1;transform:none}\n}\n@media(max-width:900px){\n  #au26 .basics-hero{grid-template-columns:1fr}\n  #au26 .gesture-intro{grid-template-columns:1fr;gap:10px}\n  #au26 .gesture-grid{grid-template-columns:1fr}\n}\n@media(max-width:560px){\n  #au26 .gesture-grid summary{grid-template-columns:30px minmax(0,1fr)}\n  #au26 .gesture-end{grid-column:2;justify-content:flex-start}\n}\n\n#au26 .subsection-title{\n  margin:52px 0 24px!important;\n  font-size:clamp(30px,3.2vw,44px)!important;\n  line-height:1.05!important;\n  letter-spacing:-.035em!important;\n  font-weight:650!important;\n}\n#au26 .links-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:14px}\n#au26 .links-grid a{display:block;text-decoration:none;padding:16px 18px;border:1px solid var(--line);border-radius:14px;background:var(--surface);color:#e9e9ec!important}\n#au26 .links-grid a:hover{border-color:var(--accent)}\n#au26 .final{padding:110px 0 130px;text-align:center;border-top:1px solid #18191e}\n#au26 .final h2{margin:0!important;font-size:clamp(52px,8vw,110px)!important;line-height:.92!important;letter-spacing:-.065em!important}\n#au26 [data-parallax]{will-change:transform;transform:translate3d(0,0,0)}\n#au26 .hero-word{display:inline-block}\n#au26.light{--bg:#f2f2f4;--surface:#fff;--surface2:#f7f7f8;--line:#d9dae0;--text:#101114;--muted:#656873}\n#au26.light .course-nav{background:#f2f2f4}\n#au26.light .topbar-inner,#au26.light .local-nav .links{background:rgba(255,255,255,.88)}\n#au26.light p,#au26.light li{color:#4c4f58!important}\n@media(max-width:900px){\n  #au26 .course-nav .inner{grid-template-columns:repeat(4,1fr)}\n  #au26 .hero-grid,#au26 .head{grid-template-columns:1fr}\n  #au26 .hero-grid{gap:40px}\n  #au26 .grid3,#au26 .steps{grid-template-columns:1fr 1fr}\n}\n@media(max-width:620px){\n  #au26 .shell{width:min(100% - 24px,var(--max))}\n  #au26 .course-nav .inner{display:flex;overflow:auto}\n  #au26 .course-nav a{min-width:130px}\n  #au26 .hero{padding:70px 0 60px}\n  #au26 .hero h1{font-size:clamp(56px,18vw,84px)!important}\n  #au26 .grid2,#au26 .grid3,#au26 .steps,#au26 .facts,#au26 .effects,#au26 .links-grid{grid-template-columns:1fr}\n  #au26 .head{gap:18px}\n  #au26 .local-nav{top:74px}\n}\n@media(prefers-reduced-motion:reduce){#au26 [data-parallax]{transform:none!important}}\n<\/style>\n\n\n\n<!-- CONFORMIT\u00c9 GLOBALE \u2014 navigation + barre de cours uniquement -->\n<style id=\"au26-global-bars-conformity\">\n\/* H\u00d4TE ELEMENTOR \u2014 neutralise uniquement les contraintes qui emp\u00eachent le plein \u00e9cran et le sticky. *\/\nbody .e-con:has(#au26),\nbody .e-con:has(#au26) > .e-con-inner,\nbody .elementor-widget-html:has(#au26),\nbody .elementor-widget-html:has(#au26) > .elementor-widget-container{\n  overflow:visible!important;\n}\nbody .elementor-widget-html:has(#au26),\nbody .elementor-widget-html:has(#au26) > .elementor-widget-container{\n  margin:0!important;\n  padding:0!important;\n}\n\n\/* La racine doit laisser fonctionner position:sticky et occuper toute la largeur disponible. *\/\n#au26{\n  overflow:visible!important;\n  width:100%!important;\n  max-width:none!important;\n  margin:0!important;\n  padding:0!important;\n}\n\n\/* NAVIGATION G\u00c9N\u00c9RALE \u2014 g\u00e9om\u00e9trie identique \u00e0 la Page 01. *\/\n#au26 .course-nav{\n  width:100%!important;\n  margin:0!important;\n  padding:0!important;\n  overflow-x:auto!important;\n  background:#050505!important;\n  border-bottom:1px solid rgba(255,255,255,.09)!important;\n  scrollbar-width:none!important;\n}\n#au26 .course-nav::-webkit-scrollbar{display:none!important}\n#au26 .course-nav .inner{\n  width:min(1500px,calc(100% - 40px))!important;\n  min-width:1050px!important;\n  margin:0 auto!important;\n  padding:0!important;\n  gap:0!important;\n  display:grid!important;\n  grid-template-columns:repeat(7,1fr)!important;\n  overflow:visible!important;\n}\n#au26 .course-nav a{\n  position:relative!important;\n  min-width:0!important;\n  min-height:108px!important;\n  padding:20px 12px!important;\n  display:flex!important;\n  flex-direction:column!important;\n  align-items:center!important;\n  justify-content:center!important;\n  text-align:center!important;\n  text-decoration:none!important;\n  border:0!important;\n  color:#fff!important;\n  line-height:1.25!important;\n}\n#au26 .course-nav strong{\n  display:block!important;\n  color:#fff!important;\n  font-size:13px!important;\n  font-weight:800!important;\n  letter-spacing:normal!important;\n}\n#au26 .course-nav span{\n  display:block!important;\n  margin-top:4px!important;\n  color:#fff!important;\n  font-size:13px!important;\n  font-weight:400!important;\n}\n#au26 .course-nav a:after{\n  content:\"\";\n  position:absolute;\n  bottom:15px;\n  left:50%;\n  width:0;\n  height:2px;\n  background:var(--accent)!important;\n  transform:translateX(-50%);\n  transition:width .25s ease;\n}\n#au26 .course-nav a:hover:after,\n#au26 .course-nav a.active:after{width:42px}\n#au26.light .course-nav{background:#050505!important}\n\n\/* BARRE DU COURS \u2014 native sticky, comme la Page 01. *\/\n#au26 .topbar{\n  position:sticky!important;\n  top:12px!important;\n  z-index:10000!important;\n  width:100%!important;\n  max-width:none!important;\n  margin:0!important;\n  padding-top:12px!important;\n}\n#au26 .topbar-inner{\n  position:relative!important;\n  width:min(1160px,calc(100% - 64px))!important;\n  min-height:62px!important;\n  margin:0 auto!important;\n  padding:9px 11px 9px 17px!important;\n  display:flex!important;\n  align-items:center!important;\n  justify-content:space-between!important;\n  gap:20px!important;\n  border:1px solid var(--line)!important;\n  border-radius:19px!important;\n  background:var(--surface)!important;\n  -webkit-backdrop-filter:none!important;\n  backdrop-filter:none!important;\n  box-shadow:0 8px 30px rgba(0,0,0,.05)!important;\n  opacity:.97!important;\n}\n#au26 .brand{display:flex!important;align-items:center!important;gap:12px!important}\n#au26 .dot{width:10px!important;height:10px!important;border-radius:99px!important;background:var(--accent)!important;box-shadow:0 0 0 6px rgba(145,139,255,.12)!important}\n#au26 .brand b{display:block!important;font-size:13px!important;font-weight:750!important}\n#au26 .brand small{display:block!important;margin-top:5px!important;color:#7f818a!important;font-size:10px!important;text-transform:uppercase!important;letter-spacing:.12em!important}\n#au26 .theme{\n  width:42px!important;min-width:42px!important;height:42px!important;min-height:42px!important;\n  margin:0!important;padding:0!important;display:grid!important;place-items:center!important;\n  border:1px solid var(--line)!important;border-radius:13px!important;background:transparent!important;\n  color:var(--text)!important;cursor:pointer!important;font-size:18px!important;line-height:1!important;\n  appearance:none!important;-webkit-appearance:none!important;\n}\n\n\/* Le sommaire des chapitres ne suit JAMAIS le scroll. *\/\n#au26 .local-nav{\n  position:relative!important;\n  top:auto!important;\n  z-index:auto!important;\n  padding:0 0 28px!important;\n}\n\n\/* Bouton retour haut, centr\u00e9 ind\u00e9pendamment du contenu gauche\/droite. *\/\n#au26 .to-top{\n  position:absolute!important;\n  left:50%!important;\n  top:50%!important;\n  transform:translate(-50%,-50%)!important;\n  width:40px!important;height:40px!important;min-width:40px!important;min-height:40px!important;\n  margin:0!important;padding:0!important;display:grid!important;place-items:center!important;\n  border:1px solid var(--line)!important;border-radius:50%!important;\n  background:var(--surface2)!important;color:var(--text)!important;box-shadow:none!important;\n  cursor:pointer!important;appearance:none!important;-webkit-appearance:none!important;z-index:2!important;\n}\n#au26 .to-top:hover{background:rgba(145,139,255,.12)!important}\n#au26 .to-top:focus-visible{outline:2px solid var(--accent)!important;outline-offset:3px!important}\n#au26 .to-top svg{width:18px!important;height:18px!important;display:block!important;fill:none!important;stroke:currentColor!important;stroke-width:2!important;stroke-linecap:round!important;stroke-linejoin:round!important}\n\n@media(max-width:650px){\n  #au26 .topbar-inner{width:calc(100% - 20px)!important}\n  #au26 .brand small{display:none!important}\n}\n<\/style>\n\n<div id=\"au26\">\n  <nav class=\"course-nav\" aria-label=\"Navigation de la formation\">\n    <div class=\"shell inner\">\n      <a href=\"https:\/\/lucasgoret.com\/index.php\/initiation-sound-design\/\"><strong>INITIATION<\/strong><span>Sound Design<\/span><\/a>\n      <a href=\"https:\/\/lucasgoret.com\/index.php\/audition-forme-donde\/\" class=\"active\" aria-current=\"page\"><strong>AUDITION<\/strong><span>Forme d'onde<\/span><\/a>\n      <a href=\"https:\/\/lucasgoret.com\/index.php\/audition-multipiste\/\"><strong>AUDITION<\/strong><span>Multipiste<\/span><\/a>\n      <a href=\"https:\/\/lucasgoret.com\/index.php\/premiere-pro-mixage\/\"><strong>PREMI\u00c8RE PRO<\/strong><span>Mixage<\/span><\/a>\n      <a href=\"https:\/\/lucasgoret.com\/index.php\/lenregistrement-prise-de-son\/\"><strong>L\u2019ENREGISTREMENT<\/strong><span>Prise de son<\/span><\/a>\n      <a href=\"https:\/\/lucasgoret.com\/index.php\/audio-branding\/\"><strong>AUDIO<\/strong><span>BRANDING<\/span><\/a>\n      <a href=\"https:\/\/lucasgoret.com\/index.php\/cours-exercices\/\"><strong>EXERCICES<\/strong><span>Astuces<\/span><\/a>\n    <\/div>\n  <\/nav>\n\n  <div class=\"topbar\">\n    <div class=\"topbar-inner\">\n      <div class=\"brand\"><span class=\"dot\"><\/span><div><b>Audition \u00b7 Forme d\u2019onde<\/b><small>Cours 02 \u00b7 Fondamentaux<\/small><\/div><\/div>\n      <button class=\"to-top\" id=\"au26-to-top\" type=\"button\" aria-label=\"Retour en haut de page\" title=\"Retour en haut\">\n        <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\" focusable=\"false\"><path d=\"M6 15l6-6 6 6\"\/><\/svg>\n      <\/button>\n      <button class=\"theme\" id=\"auTheme\" type=\"button\" aria-label=\"Changer le th\u00e8me\">\u263c<\/button>\n    <\/div>\n  <\/div>\n\n  <header class=\"shell hero\">\n    <div class=\"hero-grid\">\n      <div>\n        <div class=\"kicker\" data-parallax=\"-0.026\">Formation \u00b7 Chapitre 02<\/div>\n        <h1 class=\"hero-title\"><span class=\"hero-word hero-accent\" data-parallax=\"-0.082\">Audition<\/span><br><span class=\"hero-word hero-main\" data-parallax=\"0.068\">Forme d\u2019onde.<\/span><\/h1>\n        <p class=\"lead\" data-parallax=\"0.014\">Comprendre le son, apprendre \u00e0 le lire et ma\u00eetriser les op\u00e9rations essentielles dans Adobe Audition.<\/p>\n      <\/div>\n      <div class=\"meta\">\n        <div><small>Cours<\/small><b>02 \u2014 Audition<\/b><\/div>\n        <div><small>Logiciel<\/small><b>Adobe Audition<\/b><\/div>\n        <div><small>Objectif<\/small><b>Voir \u00b7 Comprendre \u00b7 \u00c9diter<\/b><\/div>\n      <\/div>\n    <\/div>\n  <\/header>\n\n  <div class=\"shell local-nav\">\n    <div class=\"links\">\n      <a href=\"#physique\">Physique du son<\/a><a href=\"#analyse\">Analyse<\/a><a href=\"#laboratoire\">Laboratoire<\/a>\n      <a href=\"#bases\">Fonctions de base<\/a><a href=\"#representations\">Repr\u00e9sentations<\/a><a href=\"#effets\">Effets<\/a>\n      <a href=\"#egalisation\">\u00c9galisation<\/a><a href=\"#voix\">Voix<\/a><a href=\"#liens\">Liens utiles<\/a>\n    <\/div>\n  <\/div>\n\n  <main class=\"shell\">\n    <section class=\"section\" id=\"physique\">\n      <div class=\"head\">\n        <div class=\"index\">01 \u2014 Pr\u00e9ambule<\/div>\n        <div><h2 data-parallax=\"-0.02\">La physique<br>du son<\/h2><\/div>\n      <\/div>\n      <div class=\"video\"><iframe src=\"https:\/\/www.youtube-nocookie.com\/embed\/uw5xK0mCeYE?rel=0\" title=\"La physique du son\" allowfullscreen><\/iframe><\/div>\n    <\/section>\n\n    <section class=\"section\" id=\"analyse\">\n      <div class=\"head\">\n        <div class=\"index\">02 \u2014 Analyse<\/div>\n        <div><h2 data-parallax=\"-0.02\">Outil<br>d\u2019analyse<\/h2><p class=\"intro\">Physique du son \u00b7 fr\u00e9quence \u00b7 harmoniques \u00b7 FFT \u00b7 filtrage<\/p><\/div>\n      <\/div>\n      <div class=\"tool-wrap\"><iframe class=\"tool autoheight\" title=\"Outil d'analyse interactif\" srcdoc=\"&lt;!DOCTYPE html&gt;\n&lt;html lang=&quot;fr&quot;&gt;\n&lt;head&gt;\n&lt;meta charset=&quot;UTF-8&quot;&gt;\n&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width,initial-scale=1.0&quot;&gt;\n\n&lt;title&gt;Outil d&#x27;analyse&lt;\/title&gt;\n\n&lt;style&gt;\n\n:root{\n  --bg:#09090b;\n  --panel:#121318;\n  --panel2:#17181e;\n  --border:#2b2d35;\n  --text:#f4f4f6;\n  --muted:#a2a4ad;\n  --cyan:#918bff;\n  --green:#b8b4ff;\n  --yellow:#c8c5ff;\n  --orange:#aaa6ff;\n  --red:#918bff;\n}\n\n*{\n  box-sizing:border-box;\n}\n\nhtml,\nbody{\n  margin:0;\n  min-height:100%;\n  background:var(--bg) !important;\n  font-family:\n    Inter,\n    system-ui,\n    -apple-system,\n    BlinkMacSystemFont,\n    &quot;Segoe UI&quot;,\n    sans-serif;\n}\n\nbody{\n  padding:0;\n  background:var(--bg) !important;\n  color:var(--text) !important;\n}\n\n.lab{\n  width:100%;\n  max-width:1500px;\n  margin:auto;\n  padding:24px;\n  background:var(--bg) !important;\n  color:var(--text) !important;\n}\n\nheader{\n  display:flex;\n  justify-content:flex-end;\n  align-items:flex-end;\n  margin-bottom:18px;\n}\nheader&gt;div:first-child{\n  display:none!important;\n}\n\nh1{\n  margin:0;\n  font-size:25px;\n  letter-spacing:-.04em;\n}\n\n.subtitle{\n  font-size:12px;\n  margin-top:5px;\n}\n\n.status{\n  display:flex;\n  align-items:center;\n  gap:8px;\n  font-size:11px;\n}\n\n.statusDot{\n  width:9px;\n  height:9px;\n  border-radius:50%;\n  background:var(--red);\n  box-shadow:\n    0 0 10px rgba(255,77,94,.35);\n  transition:\n    background .15s ease,\n    box-shadow .15s ease;\n}\n\n.statusDot.active{\n  background:var(--green);\n  box-shadow:\n    0 0 12px var(--green);\n}\n\n.layout{\n  display:grid;\n  grid-template-columns:\n    360px\n    minmax(0,1fr);\n  gap:16px;\n}\n\n.panel{\n  background:var(--panel);\n  border:1px solid var(--border);\n  border-radius:16px;\n  padding:16px;\n}\n\n.controls{\n  display:flex;\n  flex-direction:column;\n  gap:18px;\n}\n\n.section{\n  border-top:1px solid var(--border);\n  padding-top:16px;\n}\n\n.section:first-child{\n  border-top:0;\n  padding-top:0;\n}\n\n.sectionTitle{\n  font-size:10px;\n  text-transform:uppercase;\n  letter-spacing:.13em;\n  margin-bottom:11px;\n}\n\nlabel{\n  display:flex;\n  justify-content:space-between;\n  align-items:center;\n  font-size:12px;\n  margin-bottom:6px;\n}\n\n.value{\n  font-variant-numeric:tabular-nums;\n}\n\nselect,\nbutton,\n.fileButton{\n  width:100%;\n  border:1px solid var(--border);\n  background:var(--panel2);\n  border-radius:10px;\n  padding:9px;\n  font:inherit;\n  font-size:12px;\n  cursor:pointer;\n}\n\nselect:hover,\nbutton:hover,\n.fileButton:hover{\n  border-color:var(--cyan);\n}\n\nbutton.primary{\n  background:var(--cyan);\n  border-color:var(--cyan);\n  font-weight:700;\n}\n\ninput[type=&quot;range&quot;]{\n  width:100%;\n  accent-color:var(--cyan);\n}\n\n.harmonics{\n  display:flex;\n  flex-direction:column;\n  gap:8px;\n}\n\n.harmonic{\n  display:grid;\n  grid-template-columns:\n    32px\n    1fr\n    45px;\n  gap:8px;\n  align-items:center;\n  font-size:11px;\n}\n\n.harmonicName{\n  font-weight:600;\n}\n\n.harmonicValue{\n  text-align:right;\n}\n\n.samples{\n  display:flex;\n  flex-direction:column;\n  gap:5px;\n  max-height:330px;\n  overflow:auto;\n}\n\n.sample{\n  border:1px solid var(--border);\n  background:var(--panel2);\n  border-radius:6px;\n  padding:8px 9px;\n  cursor:pointer;\n  display:flex;\n  justify-content:space-between;\n  align-items:center;\n  font-size:11px;\n}\n\n.sample:hover{\n  border-color:var(--cyan);\n}\n\n.sample.active{\n  border-color:var(--green);\n}\n\n.sample small{\n  color:var(--muted);\n}\n\n.fileInput{\n  display:none;\n}\n\n.explanation{\n  border-left:2px solid var(--cyan);\n  padding-left:10px;\n  color:var(--muted);\n  font-size:11px;\n  line-height:1.55;\n}\n\n.visuals{\n  display:flex;\n  flex-direction:column;\n  gap:14px;\n  min-width:0;\n}\n\n.visual{\n  background:#05080d;\n  border:1px solid var(--border);\n  border-radius:10px;\n  overflow:hidden;\n}\n\n.visualHead{\n  height:38px;\n  display:flex;\n  justify-content:space-between;\n  align-items:center;\n  padding:0 12px;\n  border-bottom:1px solid var(--border);\n  font-size:10px;\n  letter-spacing:.08em;\n}\n\n.visualHead .right{\n  color:var(--muted);\n  letter-spacing:0;\n}\n\ncanvas{\n  display:block;\n  width:100% !important;\n  height:230px;\n}\n\n.smallCanvas canvas{\n  height:185px;\n}\n\n.spectrogramWrapper{\n  display:grid;\n  grid-template-columns:\n    58px\n    minmax(0,1fr);\n  background:#020509;\n}\n\n.spectrogramYAxis{\n  position:relative;\n  height:380px;\n  border-right:1px solid #1a232d;\n  color:#718091;\n  font-size:9px;\n  user-select:none;\n}\n\n.spectrogramYAxis span{\n  position:absolute;\n  right:8px;\n  transform:translateY(-50%);\n  white-space:nowrap;\n}\n\n.spectrogramYAxis .top{\n  top:4px;\n  transform:none;\n}\n\n.spectrogramYAxis .bottom{\n  bottom:4px;\n  transform:none;\n}\n\n.spectrogramMain{\n  min-width:0;\n  overflow:hidden;\n}\n\n#spectrogram{\n  width:100% !important;\n  height:380px !important;\n}\n\n.spectrogramTime{\n  height:24px;\n  position:relative;\n  border-top:1px solid #1a232d;\n  color:#718091;\n  font-size:9px;\n}\n\n.spectrogramTime span{\n  position:absolute;\n  top:6px;\n  white-space:nowrap;\n}\n\n.lab,\n.lab *,\n.lab *::before,\n.lab *::after{\n  color:#ffffff !important;\n}\n\n.lab h1,\n.lab .subtitle{\n  color:#ffffff !important;\n}\n\n.lab .status,\n.lab .sectionTitle,\n.lab .harmonicValue,\n.lab .sample small,\n.lab .explanation,\n.lab .visualHead .right,\n.lab .spectrogramYAxis,\n.lab .spectrogramTime{\n  color:#a2a4ad !important;\n}\n\n.lab .value{\n  color:#918bff !important;\n}\n\n.lab .harmonicName{\n  color:#c8c5ff !important;\n}\n\n.lab .sample.active{\n  color:#b8b4ff !important;\n}\n\n.lab input,\n.lab select,\n.lab button,\n.lab option,\n.lab textarea{\n  color:#ffffff !important;\n}\n\n.lab button.primary{\n  color:#061018 !important;\n}\n\n.lab input::placeholder,\n.lab textarea::placeholder{\n  color:#ffffff !important;\n  opacity:.7;\n}\n\n@media(max-width:900px){\n\n  .lab{\n    padding:12px;\n  }\n\n  .layout{\n    grid-template-columns:1fr;\n  }\n\n}\n\n&lt;\/style&gt;\n&lt;\/head&gt;\n\n&lt;body data-rsssl=1&gt;\n\n&lt;div class=&quot;lab&quot;&gt;\n\n&lt;header&gt;\n\n  &lt;div&gt;\n\n    &lt;h1&gt;\n      Outil d&#x27;analyse\n    &lt;\/h1&gt;\n\n    &lt;div class=&quot;subtitle&quot;&gt;\n      Physique du son \u00b7 fr\u00e9quence \u00b7 harmoniques \u00b7 FFT \u00b7 filtrage\n    &lt;\/div&gt;\n\n  &lt;\/div&gt;\n\n  &lt;div class=&quot;status&quot;&gt;\n\n    &lt;span\n      class=&quot;statusDot&quot;\n      id=&quot;statusDot&quot;\n    &gt;&lt;\/span&gt;\n\n    &lt;span id=&quot;status&quot;&gt;\n      Audio arr\u00eat\u00e9\n    &lt;\/span&gt;\n\n  &lt;\/div&gt;\n\n&lt;\/header&gt;\n\n&lt;div class=&quot;layout&quot;&gt;\n\n&lt;aside class=&quot;panel controls&quot;&gt;\n\n&lt;div class=&quot;section&quot;&gt;\n\n  &lt;div class=&quot;sectionTitle&quot;&gt;\n    Source\n  &lt;\/div&gt;\n\n  &lt;label&gt;\n    Type\n  &lt;\/label&gt;\n\n  &lt;select id=&quot;sourceType&quot;&gt;\n\n    &lt;option value=&quot;oscillator&quot;&gt;\n      Oscillateur\n    &lt;\/option&gt;\n\n    &lt;option value=&quot;sample&quot;&gt;\n      Sample\n    &lt;\/option&gt;\n\n  &lt;\/select&gt;\n\n  &lt;div id=&quot;oscillatorPanel&quot;&gt;\n\n    &lt;br&gt;\n\n    &lt;label&gt;\n      Forme d&#x27;onde\n    &lt;\/label&gt;\n\n    &lt;select id=&quot;waveform&quot;&gt;\n\n      &lt;option value=&quot;sine&quot;&gt;\n        Sinuso\u00efde\n      &lt;\/option&gt;\n\n      &lt;option value=&quot;square&quot;&gt;\n        Carr\u00e9e\n      &lt;\/option&gt;\n\n      &lt;option value=&quot;triangle&quot;&gt;\n        Triangle\n      &lt;\/option&gt;\n\n      &lt;option value=&quot;sawtooth&quot;&gt;\n        Dent de scie\n      &lt;\/option&gt;\n\n    &lt;\/select&gt;\n\n    &lt;br&gt;\n\n    &lt;label&gt;\n\n      Fr\u00e9quence\n\n      &lt;span\n        class=&quot;value&quot;\n        id=&quot;frequencyValue&quot;\n      &gt;\n        440 Hz\n      &lt;\/span&gt;\n\n    &lt;\/label&gt;\n\n    &lt;input\n      id=&quot;frequency&quot;\n      type=&quot;range&quot;\n      min=&quot;20&quot;\n      max=&quot;20000&quot;\n      step=&quot;1&quot;\n      value=&quot;440&quot;\n    &gt;\n\n    &lt;br&gt;\n\n    &lt;label&gt;\n\n      Amplitude\n\n      &lt;span\n        class=&quot;value&quot;\n        id=&quot;amplitudeValue&quot;\n      &gt;\n        0.50\n      &lt;\/span&gt;\n\n    &lt;\/label&gt;\n\n    &lt;input\n      id=&quot;amplitude&quot;\n      type=&quot;range&quot;\n      min=&quot;0&quot;\n      max=&quot;1&quot;\n      step=&quot;0.01&quot;\n      value=&quot;0.5&quot;\n    &gt;\n\n  &lt;\/div&gt;\n\n  &lt;div\n    id=&quot;samplePanel&quot;\n    style=&quot;display:none&quot;\n  &gt;\n\n    &lt;br&gt;\n\n    &lt;label&gt;\n      Samples\n    &lt;\/label&gt;\n\n    &lt;div\n      class=&quot;samples&quot;\n      id=&quot;sampleList&quot;\n    &gt;&lt;\/div&gt;\n\n    &lt;br&gt;\n\n    &lt;label\n      class=&quot;fileButton&quot;\n      for=&quot;fileInput&quot;\n      style=&quot;\n        text-align:center;\n        justify-content:center;\n      &quot;\n    &gt;\n      + Charger un fichier audio\n    &lt;\/label&gt;\n\n    &lt;input\n      class=&quot;fileInput&quot;\n      id=&quot;fileInput&quot;\n      type=&quot;file&quot;\n      accept=&quot;audio\/*&quot;\n    &gt;\n\n  &lt;\/div&gt;\n\n  &lt;br&gt;\n\n  &lt;button\n    class=&quot;primary&quot;\n    id=&quot;playButton&quot;\n  &gt;\n    \u25b6 D\u00e9marrer\n  &lt;\/button&gt;\n\n&lt;\/div&gt;\n\n&lt;div class=&quot;section&quot;&gt;\n\n  &lt;div class=&quot;sectionTitle&quot;&gt;\n    Harmoniques \u2014 synth\u00e8se additive\n  &lt;\/div&gt;\n\n  &lt;div\n    class=&quot;harmonics&quot;\n    id=&quot;harmonics&quot;\n  &gt;&lt;\/div&gt;\n\n&lt;\/div&gt;\n\n&lt;div class=&quot;section&quot;&gt;\n\n  &lt;div class=&quot;sectionTitle&quot;&gt;\n    Filtre\n  &lt;\/div&gt;\n\n  &lt;label&gt;\n    Type\n  &lt;\/label&gt;\n\n  &lt;select id=&quot;filterType&quot;&gt;\n\n    &lt;option value=&quot;off&quot;&gt;\n      D\u00e9sactiv\u00e9\n    &lt;\/option&gt;\n\n    &lt;option value=&quot;lowpass&quot;&gt;\n      Passe-bas\n    &lt;\/option&gt;\n\n    &lt;option value=&quot;highpass&quot;&gt;\n      Passe-haut\n    &lt;\/option&gt;\n\n    &lt;option value=&quot;bandpass&quot;&gt;\n      Passe-bande\n    &lt;\/option&gt;\n\n    &lt;option value=&quot;notch&quot;&gt;\n      Coupe-bande\n    &lt;\/option&gt;\n\n  &lt;\/select&gt;\n\n  &lt;br&gt;\n\n  &lt;label&gt;\n\n    Fr\u00e9quence\n\n    &lt;span\n      class=&quot;value&quot;\n      id=&quot;cutoffValue&quot;\n    &gt;\n      1200 Hz\n    &lt;\/span&gt;\n\n  &lt;\/label&gt;\n\n  &lt;input\n    id=&quot;cutoff&quot;\n    type=&quot;range&quot;\n    min=&quot;20&quot;\n    max=&quot;20000&quot;\n    step=&quot;1&quot;\n    value=&quot;1200&quot;\n  &gt;\n\n  &lt;br&gt;\n\n  &lt;label&gt;\n\n    Gain\n\n    &lt;span\n      class=&quot;value&quot;\n      id=&quot;filterGainValue&quot;\n    &gt;\n      0 dB\n    &lt;\/span&gt;\n\n  &lt;\/label&gt;\n\n  &lt;input\n    id=&quot;filterGain&quot;\n    type=&quot;range&quot;\n    min=&quot;-24&quot;\n    max=&quot;24&quot;\n    step=&quot;0.1&quot;\n    value=&quot;0&quot;\n  &gt;\n\n  &lt;br&gt;\n\n  &lt;label&gt;\n\n    R\u00e9sonance\n\n    &lt;span\n      class=&quot;value&quot;\n      id=&quot;qValue&quot;\n    &gt;\n      1.0 Q\n    &lt;\/span&gt;\n\n  &lt;\/label&gt;\n\n  &lt;input\n    id=&quot;q&quot;\n    type=&quot;range&quot;\n    min=&quot;0.1&quot;\n    max=&quot;20&quot;\n    step=&quot;0.1&quot;\n    value=&quot;1&quot;\n  &gt;\n\n&lt;\/div&gt;\n\n&lt;div class=&quot;explanation&quot;&gt;\n\n  Le signal affich\u00e9 dans les analyseurs est le signal\n  r\u00e9ellement envoy\u00e9 aux haut-parleurs, apr\u00e8s le filtre.\n\n  Dans le spectrogramme :\n  horizontal = temps,\n  vertical = fr\u00e9quence,\n  couleur = amplitude.\n\n&lt;\/div&gt;\n\n&lt;\/aside&gt;\n\n&lt;main class=&quot;visuals&quot;&gt;\n\n&lt;div class=&quot;visual&quot;&gt;\n\n  &lt;div class=&quot;visualHead&quot;&gt;\n\n    &lt;span&gt;\n      OSCILLOSCOPE\n    &lt;\/span&gt;\n\n    &lt;span class=&quot;right&quot;&gt;\n      signal apr\u00e8s filtre\n    &lt;\/span&gt;\n\n  &lt;\/div&gt;\n\n  &lt;canvas id=&quot;scope&quot;&gt;&lt;\/canvas&gt;\n\n&lt;\/div&gt;\n\n&lt;div class=&quot;visual smallCanvas&quot;&gt;\n\n  &lt;div class=&quot;visualHead&quot;&gt;\n\n    &lt;span&gt;\n      SPECTRE \/ FFT\n    &lt;\/span&gt;\n\n    &lt;span class=&quot;right&quot;&gt;\n      amplitude \u2192 fr\u00e9quence\n    &lt;\/span&gt;\n\n  &lt;\/div&gt;\n\n  &lt;canvas id=&quot;spectrum&quot;&gt;&lt;\/canvas&gt;\n\n&lt;\/div&gt;\n\n&lt;div class=&quot;visual smallCanvas&quot;&gt;\n\n  &lt;div class=&quot;visualHead&quot;&gt;\n\n    &lt;span&gt;\n      R\u00c9PONSE DU FILTRE\n    &lt;\/span&gt;\n\n    &lt;span\n      class=&quot;right&quot;\n      id=&quot;filterInfo&quot;\n    &gt;\n      Filtre d\u00e9sactiv\u00e9\n    &lt;\/span&gt;\n\n  &lt;\/div&gt;\n\n  &lt;canvas id=&quot;filterCanvas&quot;&gt;&lt;\/canvas&gt;\n\n&lt;\/div&gt;\n\n&lt;div class=&quot;visual&quot;&gt;\n\n  &lt;div class=&quot;visualHead&quot;&gt;\n\n    &lt;span&gt;\n      SPECTROGRAMME\n    &lt;\/span&gt;\n\n    &lt;span class=&quot;right&quot;&gt;\n      temps \u2192\n    &lt;\/span&gt;\n\n  &lt;\/div&gt;\n\n  &lt;div class=&quot;spectrogramWrapper&quot;&gt;\n\n    &lt;div class=&quot;spectrogramYAxis&quot;&gt;\n\n      &lt;span class=&quot;top&quot;&gt;\n        20 kHz\n      &lt;\/span&gt;\n\n      &lt;span style=&quot;top:18%&quot;&gt;\n        10 kHz\n      &lt;\/span&gt;\n\n      &lt;span style=&quot;top:36%&quot;&gt;\n        5 kHz\n      &lt;\/span&gt;\n\n      &lt;span style=&quot;top:54%&quot;&gt;\n        2 kHz\n      &lt;\/span&gt;\n\n      &lt;span style=&quot;top:72%&quot;&gt;\n        500 Hz\n      &lt;\/span&gt;\n\n      &lt;span style=&quot;top:88%&quot;&gt;\n        100 Hz\n      &lt;\/span&gt;\n\n      &lt;span class=&quot;bottom&quot;&gt;\n        20 Hz\n      &lt;\/span&gt;\n\n    &lt;\/div&gt;\n\n    &lt;div class=&quot;spectrogramMain&quot;&gt;\n\n      &lt;canvas id=&quot;spectrogram&quot;&gt;&lt;\/canvas&gt;\n\n      &lt;div class=&quot;spectrogramTime&quot;&gt;\n\n        &lt;span style=&quot;left:0&quot;&gt;\n          0 s\n        &lt;\/span&gt;\n\n        &lt;span style=&quot;left:25%&quot;&gt;\n          2 s\n        &lt;\/span&gt;\n\n        &lt;span style=&quot;left:50%&quot;&gt;\n          4 s\n        &lt;\/span&gt;\n\n        &lt;span style=&quot;left:75%&quot;&gt;\n          6 s\n        &lt;\/span&gt;\n\n        &lt;span style=&quot;right:0&quot;&gt;\n          8 s\n        &lt;\/span&gt;\n\n      &lt;\/div&gt;\n\n    &lt;\/div&gt;\n\n  &lt;\/div&gt;\n\n&lt;\/div&gt;\n\n&lt;\/main&gt;\n\n&lt;\/div&gt;\n\n&lt;\/div&gt;\n\n&lt;script&gt;\n\n\/* =========================================================\n   SAMPLES\n   URLs EXACTES FOURNIES\n========================================================= *\/\n\nconst SAMPLE_FILES = {\n\n  ballon:{\n    name:&quot;Ballon&quot;,\n    file:&quot;https:\/\/lucasgoret.com\/wp-content\/uploads\/2026\/09\/Ballon.flac&quot;\n  },\n\n  voiture:{\n    name:&quot;Voiture&quot;,\n    file:&quot;https:\/\/lucasgoret.com\/wp-content\/uploads\/2026\/09\/Voiture.wav&quot;\n  },\n\n  cloche:{\n    name:&quot;Cloche&quot;,\n    file:&quot;https:\/\/lucasgoret.com\/wp-content\/uploads\/2026\/09\/Cloche.wav&quot;\n  },\n\n  voixFemme:{\n    name:&quot;Voix femme&quot;,\n    file:&quot;https:\/\/lucasgoret.com\/wp-content\/uploads\/2026\/09\/Voix-femme.mp3&quot;\n  },\n\n  voixHomme:{\n    name:&quot;Voix homme&quot;,\n    file:&quot;https:\/\/lucasgoret.com\/wp-content\/uploads\/2026\/09\/Voix-homme.wav&quot;\n  },\n\n  modem:{\n    name:&quot;Modem&quot;,\n    file:&quot;https:\/\/lucasgoret.com\/wp-content\/uploads\/2026\/09\/Modem.mp3&quot;\n  },\n\n  violon:{\n    name:&quot;Violon&quot;,\n    file:&quot;https:\/\/lucasgoret.com\/wp-content\/uploads\/2026\/09\/Violon.wav&quot;\n  },\n\n  guitare:{\n    name:&quot;Guitare&quot;,\n    file:&quot;https:\/\/lucasgoret.com\/wp-content\/uploads\/2026\/09\/Guitare.mp3&quot;\n  },\n\n  trombone:{\n    name:&quot;Trombone&quot;,\n    file:&quot;https:\/\/lucasgoret.com\/wp-content\/uploads\/2026\/09\/Trombone.wav&quot;\n  },\n\n  flute:{\n    name:&quot;Fl\u00fbte&quot;,\n    file:&quot;https:\/\/lucasgoret.com\/wp-content\/uploads\/2026\/09\/Flute.wav&quot;\n  },\n\n  vagues:{\n    name:&quot;Vagues&quot;,\n    file:&quot;https:\/\/lucasgoret.com\/wp-content\/uploads\/2026\/09\/Vagues.mp3&quot;\n  },\n\n  oiseaux:{\n    name:&quot;Oiseaux&quot;,\n    file:&quot;https:\/\/lucasgoret.com\/wp-content\/uploads\/2026\/09\/Oiseaux.mp3&quot;\n  }\n\n};\n\n\n\n\/* =========================================================\n   AUDIO\n========================================================= *\/\n\nlet audioContext=null;\n\nlet masterGain=null;\n\nlet filterNode=null;\n\nlet filterStage2=null;\n\nlet bandpassStage2=null;\n\nlet filterGainNode=null;\n\nlet analyser=null;\n\nlet oscillators=[];\n\nlet oscillatorGains=[];\n\nlet sampleSource=null;\n\nlet sampleBuffer=null;\n\nlet selectedSampleUrl=null;\n\nlet selectedSampleName=null;\n\nlet isPlaying=false;\n\n\n\n\/* =========================================================\n   VISUALISATION\n========================================================= *\/\n\nlet animationFrame=null;\n\nlet scopeData=null;\n\nlet spectrumData=null;\n\nlet spectrogramImage=null;\n\nlet spectrogramWidth=0;\n\nlet spectrogramHeight=0;\n\n\n\n\/* =========================================================\n   DOM\n========================================================= *\/\n\nconst sourceType=\n  document.getElementById(\n    &quot;sourceType&quot;\n  );\n\nconst oscillatorPanel=\n  document.getElementById(\n    &quot;oscillatorPanel&quot;\n  );\n\nconst samplePanel=\n  document.getElementById(\n    &quot;samplePanel&quot;\n  );\n\nconst waveform=\n  document.getElementById(\n    &quot;waveform&quot;\n  );\n\nconst frequency=\n  document.getElementById(\n    &quot;frequency&quot;\n  );\n\nconst amplitude=\n  document.getElementById(\n    &quot;amplitude&quot;\n  );\n\nconst filterType=\n  document.getElementById(\n    &quot;filterType&quot;\n  );\n\nconst cutoff=\n  document.getElementById(\n    &quot;cutoff&quot;\n  );\n\nconst filterGain=\n  document.getElementById(\n    &quot;filterGain&quot;\n  );\n\nconst q=\n  document.getElementById(\n    &quot;q&quot;\n  );\n\nconst playButton=\n  document.getElementById(\n    &quot;playButton&quot;\n  );\n\nconst status=\n  document.getElementById(\n    &quot;status&quot;\n  );\n\nconst statusDot=\n  document.getElementById(\n    &quot;statusDot&quot;\n  );\n\n\n\n\/* =========================================================\n   STATUS\n========================================================= *\/\n\nfunction setAudioStatus(\n  active,\n  text\n){\n\n  status.textContent=text;\n\n  if(active){\n\n    statusDot.classList.add(\n      &quot;active&quot;\n    );\n\n  }else{\n\n    statusDot.classList.remove(\n      &quot;active&quot;\n    );\n\n  }\n\n}\n\n\n\n\/* =========================================================\n   HARMONIQUES\n========================================================= *\/\n\nconst harmonicContainer=\n  document.getElementById(\n    &quot;harmonics&quot;\n  );\n\nconst harmonicSliders=[];\n\n\n\nfor(\n  let i=1;\n  i&lt;=8;\n  i++\n){\n\n  const row=\n    document.createElement(\n      &quot;div&quot;\n    );\n\n  row.className=\n    &quot;harmonic&quot;;\n\n\n\n  row.innerHTML=`\n\n    &lt;span class=&quot;harmonicName&quot;&gt;\n      H${i}\n    &lt;\/span&gt;\n\n    &lt;input\n      type=&quot;range&quot;\n      min=&quot;0&quot;\n      max=&quot;1&quot;\n      step=&quot;0.01&quot;\n      value=&quot;${i===1?1:0}&quot;\n    &gt;\n\n    &lt;span class=&quot;harmonicValue&quot;&gt;\n      ${i===1?&quot;100%&quot;:&quot;0%&quot;}\n    &lt;\/span&gt;\n\n  `;\n\n\n\n  harmonicContainer.appendChild(\n    row\n  );\n\n\n\n  const slider=\n    row.querySelector(\n      &quot;input&quot;\n    );\n\n  const value=\n    row.querySelector(\n      &quot;.harmonicValue&quot;\n    );\n\n\n\n  harmonicSliders.push(\n    slider\n  );\n\n\n\n  slider.addEventListener(\n    &quot;input&quot;,\n    ()=&gt;{\n\n      value.textContent=\n        Math.round(\n          Number(\n            slider.value\n          )*100\n        )+&quot;%&quot;;\n\n\n\n      updateOscillatorHarmonics();\n\n    }\n  );\n\n}\n\n\n\n\/* =========================================================\n   SAMPLES UI\n========================================================= *\/\n\nconst sampleList=\n  document.getElementById(\n    &quot;sampleList&quot;\n  );\n\n\n\nObject.entries(\n  SAMPLE_FILES\n).forEach(\n  ([id,sample])=&gt;{\n\n    const element=\n      document.createElement(\n        &quot;div&quot;\n      );\n\n\n\n    element.className=\n      &quot;sample&quot;;\n\n\n\n    element.innerHTML=`\n\n      &lt;span&gt;\n        ${sample.name}\n      &lt;\/span&gt;\n\n      &lt;small&gt;\n        sample\n      &lt;\/small&gt;\n\n    `;\n\n\n\n    element.addEventListener(\n      &quot;click&quot;,\n      async()=&gt;{\n\n        document\n          .querySelectorAll(\n            &quot;.sample&quot;\n          )\n          .forEach(\n            x=&gt;\n              x.classList.remove(\n                &quot;active&quot;\n              )\n          );\n\n\n\n        element.classList.add(\n          &quot;active&quot;\n        );\n\n\n\n        await loadSampleFile(\n          sample.file,\n          sample.name\n        );\n\n      }\n    );\n\n\n\n    sampleList.appendChild(\n      element\n    );\n\n  }\n);\n\n\n\n\/* =========================================================\n   SOURCE\n========================================================= *\/\n\nsourceType.addEventListener(\n  &quot;change&quot;,\n  ()=&gt;{\n\n    const isSample=\n      sourceType.value===&quot;sample&quot;;\n\n\n\n    oscillatorPanel.style.display=\n      isSample\n        ?&quot;none&quot;\n        :&quot;block&quot;;\n\n\n\n    samplePanel.style.display=\n      isSample\n        ?&quot;block&quot;\n        :&quot;none&quot;;\n\n  }\n);\n\n\n\n\/* =========================================================\n   AUDIO CONTEXT\n========================================================= *\/\n\nfunction createContext(){\n\n  if(!audioContext){\n\n    audioContext=\n      new(\n        window.AudioContext ||\n        window.webkitAudioContext\n      )();\n\n  }\n\n}\n\n\n\n\/* =========================================================\n   AUDIO GRAPH\n========================================================= *\/\n\nfunction createGraph(){\n\n  createContext();\n\n\n\n  masterGain=\n    audioContext.createGain();\n\n\n\n  masterGain.gain.value=\n    Number(\n      amplitude.value\n    );\n\n\n\n  filterNode=\n    audioContext.createBiquadFilter();\n\n\n\n  filterStage2=\n    audioContext.createBiquadFilter();\n\n\n\n  bandpassStage2=\n    audioContext.createBiquadFilter();\n\n\n\n  filterGainNode=\n    audioContext.createGain();\n\n\n\n  analyser=\n    audioContext.createAnalyser();\n\n\n\n  analyser.fftSize=\n    16384;\n\n\n\n  analyser.smoothingTimeConstant=\n    0.05;\n\n\n\n  updateFilter();\n\n}\n\n\n\n\/* =========================================================\n   FILTRE\n========================================================= *\/\n\nfunction updateFilter(){\n\n  if(!filterNode || !audioContext)\n    return;\n\n\n\n  const type=\n    filterType.value;\n\n\n\n  const f=\n    Number(\n      cutoff.value\n    );\n\n\n\n  const gain=\n    Number(\n      filterGain.value\n    );\n\n\n\n  const resonance=\n    Number(\n      q.value\n    );\n\n\n\n  document.getElementById(\n    &quot;cutoffValue&quot;\n  ).textContent=\n    f+&quot; Hz&quot;;\n\n\n\n  document.getElementById(\n    &quot;filterGainValue&quot;\n  ).textContent=\n    (gain&gt;=0?&quot;+&quot;:&quot;&quot;)+\n    gain.toFixed(1)+\n    &quot; dB&quot;;\n\n\n\n  document.getElementById(\n    &quot;qValue&quot;\n  ).textContent=\n    resonance.toFixed(1)+\n    &quot; Q&quot;;\n\n\n\n  try{\n    masterGain.disconnect();\n  }catch(e){}\n\n\n\n  try{\n    filterNode.disconnect();\n  }catch(e){}\n\n\n\n  try{\n    filterStage2.disconnect();\n  }catch(e){}\n\n\n\n  try{\n    bandpassStage2.disconnect();\n  }catch(e){}\n\n\n\n  try{\n    filterGainNode.disconnect();\n  }catch(e){}\n\n\n\n  const safeFrequency=\n    Math.min(\n      f,\n      audioContext.sampleRate\/2-1\n    );\n\n\n\n  if(type===&quot;off&quot;){\n\n    filterNode.type=\n      &quot;lowpass&quot;;\n\n\n\n    filterNode.frequency.value=\n      audioContext.sampleRate\/2-1;\n\n\n\n    filterNode.Q.value=\n      0.0001;\n\n\n\n    masterGain.connect(\n      filterNode\n    );\n\n\n\n    filterNode.connect(\n      filterGainNode\n    );\n\n\n\n    document.getElementById(\n      &quot;filterInfo&quot;\n    ).textContent=\n      &quot;Filtre d\u00e9sactiv\u00e9&quot;;\n\n  }\n\n\n\n  else if(type===&quot;bandpass&quot;){\n\n    filterNode.type=\n      &quot;bandpass&quot;;\n\n\n\n    filterNode.frequency.value=\n      safeFrequency;\n\n\n\n    filterNode.Q.value=\n      resonance;\n\n\n\n    bandpassStage2.type=\n      &quot;bandpass&quot;;\n\n\n\n    bandpassStage2.frequency.value=\n      safeFrequency;\n\n\n\n    bandpassStage2.Q.value=\n      resonance;\n\n\n\n    masterGain.connect(\n      filterNode\n    );\n\n\n\n    filterNode.connect(\n      bandpassStage2\n    );\n\n\n\n    bandpassStage2.connect(\n      filterGainNode\n    );\n\n\n\n    document.getElementById(\n      &quot;filterInfo&quot;\n    ).textContent=\n      &quot;Passe-bande raide \u00b7 &quot;+\n      f+\n      &quot; Hz \u00b7 Q &quot;+\n      resonance.toFixed(1);\n\n  }\n\n\n\n  else{\n\n    filterNode.type=\n      type;\n\n\n\n    filterNode.frequency.value=\n      safeFrequency;\n\n\n\n    filterNode.Q.value=\n      resonance;\n\n\n\n    filterStage2.type=\n      type;\n\n\n\n    filterStage2.frequency.value=\n      safeFrequency;\n\n\n\n    filterStage2.Q.value=\n      resonance;\n\n\n\n    masterGain.connect(\n      filterNode\n    );\n\n\n\n    filterNode.connect(\n      filterStage2\n    );\n\n\n\n    filterStage2.connect(\n      filterGainNode\n    );\n\n\n\n    const label=\n      filterType\n        .options[\n          filterType.selectedIndex\n        ]\n        .text;\n\n\n\n    document.getElementById(\n      &quot;filterInfo&quot;\n    ).textContent=\n      label+\n      &quot; \u00b7 pente 24 dB\/oct \u00b7 &quot;+\n      f+\n      &quot; Hz \u00b7 Q &quot;+\n      resonance.toFixed(1);\n\n  }\n\n\n\n  filterGainNode.gain.value=\n    Math.pow(\n      10,\n      gain\/20\n    );\n\n\n\n  filterGainNode.connect(\n    analyser\n  );\n\n\n\n  analyser.connect(\n    audioContext.destination\n  );\n\n\n\n  updateFilterVisual();\n\n}\n\n\n\n\/* =========================================================\n   OSCILLATEURS\n========================================================= *\/\n\nfunction createAdditiveOscillators(){\n\n  oscillators=[];\n\n  oscillatorGains=[];\n\n\n\n  for(\n    let i=1;\n    i&lt;=8;\n    i++\n  ){\n\n    const osc=\n      audioContext.createOscillator();\n\n\n\n    const gain=\n      audioContext.createGain();\n\n\n\n    osc.type=\n      waveform.value;\n\n\n\n    osc.frequency.value=\n      Math.min(\n        Number(\n          frequency.value\n        )*i,\n        audioContext.sampleRate\/2-1\n      );\n\n\n\n    gain.gain.value=\n      Number(\n        harmonicSliders[i-1].value\n      );\n\n\n\n    osc.connect(\n      gain\n    );\n\n\n\n    gain.connect(\n      masterGain\n    );\n\n\n\n    oscillators.push(\n      osc\n    );\n\n\n\n    oscillatorGains.push(\n      gain\n    );\n\n  }\n\n\n\n  oscillators.forEach(\n    osc=&gt;\n      osc.start()\n  );\n\n}\n\n\n\n\/* =========================================================\n   UPDATE HARMONIQUES\n========================================================= *\/\n\nfunction updateOscillatorHarmonics(){\n\n  if(!audioContext)\n    return;\n\n\n\n  if(\n    sourceType.value!==&quot;oscillator&quot;\n  )\n    return;\n\n\n\n  const now=\n    audioContext.currentTime;\n\n\n\n  for(\n    let i=0;\n    i&lt;8;\n    i++\n  ){\n\n    if(\n      oscillatorGains[i]\n    ){\n\n      oscillatorGains[i]\n        .gain\n        .setTargetAtTime(\n          Number(\n            harmonicSliders[i].value\n          ),\n          now,\n          0.01\n        );\n\n    }\n\n\n\n    if(\n      oscillators[i]\n    ){\n\n      oscillators[i]\n        .frequency\n        .setTargetAtTime(\n          Math.min(\n            Number(\n              frequency.value\n            )*(i+1),\n            audioContext.sampleRate\/2-1\n          ),\n          now,\n          0.01\n        );\n\n    }\n\n  }\n\n}\n\n\n\n\/* =========================================================\n   START\n========================================================= *\/\n\nasync function startAudio(){\n\n  createGraph();\n\n\n\n  await audioContext.resume();\n\n\n\n  if(\n    sourceType.value===&quot;oscillator&quot;\n  ){\n\n    createAdditiveOscillators();\n\n  }\n\n  else{\n\n    if(!sampleBuffer){\n\n      setAudioStatus(\n        false,\n        &quot;Choisis un sample&quot;\n      );\n\n      return;\n\n    }\n\n\n\n    sampleSource=\n      audioContext.createBufferSource();\n\n\n\n    sampleSource.buffer=\n      sampleBuffer;\n\n\n\n    sampleSource.loop=true;\n\n\n\n    sampleSource.connect(\n      masterGain\n    );\n\n\n\n    sampleSource.onended=()=&gt;{\n      if(isPlaying){\n        isPlaying=false;\n        playButton.textContent=&quot;\u25b6 D\u00e9marrer&quot;;\n        setAudioStatus(false,&quot;Audio arr\u00eat\u00e9&quot;);\n      }\n    };\n\n\n\n    sampleSource.start();\n\n  }\n\n\n\n  isPlaying=true;\n\n\n\n  playButton.textContent=\n    &quot;\u25a0 Arr\u00eater&quot;;\n\n\n\n  setAudioStatus(\n    true,\n    sourceType.value===&quot;sample&quot;\n      ?selectedSampleName+&quot; \u00b7 Audio actif&quot;\n      :&quot;Audio actif&quot;\n  );\n\n\n\n  startVisualisation();\n\n}\n\n\n\n\/* =========================================================\n   STOP\n========================================================= *\/\n\nasync function stopAudio(){\n\n  stopVisualisation();\n\n\n\n  oscillators.forEach(\n    osc=&gt;{\n\n      try{\n        osc.stop();\n      }\n      catch(e){}\n\n    }\n  );\n\n\n\n  oscillators=[];\n\n  oscillatorGains=[];\n\n\n\n  if(sampleSource){\n\n    try{\n      sampleSource.stop();\n    }\n    catch(e){}\n\n    sampleSource.disconnect();\n\n    sampleSource=null;\n\n  }\n\n\n\n  if(audioContext){\n\n    try{\n      await audioContext.close();\n    }\n    catch(e){}\n\n  }\n\n\n\n  audioContext=null;\n\n  masterGain=null;\n\n  filterNode=null;\n\n  filterStage2=null;\n\n  bandpassStage2=null;\n\n  filterGainNode=null;\n\n  analyser=null;\n\n  isPlaying=false;\n\n\n\n  playButton.textContent=\n    &quot;\u25b6 D\u00e9marrer&quot;;\n\n\n\n  setAudioStatus(\n    false,\n    &quot;Audio arr\u00eat\u00e9&quot;\n  );\n\n\n\n  clearSpectrogram();\n\n}\n\n\n\n\/* =========================================================\n   PLAY BUTTON\n========================================================= *\/\n\nplayButton.addEventListener(\n  &quot;click&quot;,\n  async()=&gt;{\n\n    if(isPlaying){\n\n      await stopAudio();\n\n    }\n\n    else{\n\n      await startAudio();\n\n    }\n\n  }\n);\n\n\n\n\/* =========================================================\n   FREQUENCE\n========================================================= *\/\n\nfrequency.addEventListener(\n  &quot;input&quot;,\n  ()=&gt;{\n\n    document.getElementById(\n      &quot;frequencyValue&quot;\n    ).textContent=\n      frequency.value+\n      &quot; Hz&quot;;\n\n\n\n    if(!audioContext)\n      return;\n\n\n\n    const now=\n      audioContext.currentTime;\n\n\n\n    oscillators.forEach(\n      (osc,i)=&gt;{\n\n        osc.frequency\n          .setTargetAtTime(\n            Math.min(\n              Number(\n                frequency.value\n              )*(i+1),\n              audioContext.sampleRate\/2-1\n            ),\n            now,\n            0.01\n          );\n\n      }\n\n    );\n\n  }\n);\n\n\n\n\/* =========================================================\n   WAVEFORM\n========================================================= *\/\n\nwaveform.addEventListener(\n  &quot;change&quot;,\n  ()=&gt;{\n\n    oscillators.forEach(\n      osc=&gt;\n        osc.type=\n          waveform.value\n    );\n\n  }\n);\n\n\n\n\/* =========================================================\n   AMPLITUDE\n========================================================= *\/\n\namplitude.addEventListener(\n  &quot;input&quot;,\n  ()=&gt;{\n\n    document.getElementById(\n      &quot;amplitudeValue&quot;\n    ).textContent=\n      Number(\n        amplitude.value\n      ).toFixed(2);\n\n\n\n    if(masterGain){\n\n      masterGain.gain.setTargetAtTime(\n        Number(\n          amplitude.value\n        ),\n        audioContext.currentTime,\n        0.01\n      );\n\n    }\n\n  }\n);\n\n\n\n\/* =========================================================\n   FILTRE EVENTS\n========================================================= *\/\n\nfilterType.addEventListener(\n  &quot;change&quot;,\n  updateFilter\n);\n\ncutoff.addEventListener(\n  &quot;input&quot;,\n  updateFilter\n);\n\nfilterGain.addEventListener(\n  &quot;input&quot;,\n  updateFilter\n);\n\nq.addEventListener(\n  &quot;input&quot;,\n  updateFilter\n);\n\n\n\n\/* =========================================================\n   FICHIER AUDIO LOCAL\n========================================================= *\/\n\ndocument\n  .getElementById(\n    &quot;fileInput&quot;\n  )\n  .addEventListener(\n    &quot;change&quot;,\n    async event=&gt;{\n\n      const file=\n        event.target.files[0];\n\n\n\n      if(!file)\n        return;\n\n\n\n      try{\n\n        createContext();\n\n\n\n        const arrayBuffer=\n          await file.arrayBuffer();\n\n\n\n        sampleBuffer=\n          await audioContext.decodeAudioData(\n            arrayBuffer\n          );\n\n\n\n        selectedSampleUrl=null;\n\n        selectedSampleName=\n          file.name;\n\n\n\n        sourceType.value=\n          &quot;sample&quot;;\n\n\n\n        oscillatorPanel.style.display=\n          &quot;none&quot;;\n\n\n\n        samplePanel.style.display=\n          &quot;block&quot;;\n\n\n\n        setAudioStatus(\n          false,\n          &quot;Sample charg\u00e9 : &quot;+\n          file.name\n        );\n\n\n\n        if(isPlaying){\n\n          await stopAudio();\n\n          await startAudio();\n\n        }\n\n      }\n\n      catch(error){\n\n        console.error(error);\n\n        setAudioStatus(\n          false,\n          &quot;Impossible de charger le fichier&quot;\n        );\n\n      }\n\n    }\n  );\n\n\n\n\/* =========================================================\n   SAMPLE DISTANT\n========================================================= *\/\n\nasync function loadSampleFile(\n  url,\n  name\n){\n\n  try{\n\n    \/*\n     * Si un audio tourne d\u00e9j\u00e0, on l&#x27;arr\u00eate proprement\n     * avant de recr\u00e9er le contexte.\n     *\/\n\n    if(isPlaying){\n\n      await stopAudio();\n\n    }\n\n\n\n    createContext();\n\n\n\n    setAudioStatus(\n      false,\n      &quot;Chargement : &quot;+name\n    );\n\n\n\n    const response=\n      await fetch(\n        url,\n        {\n          method:&quot;GET&quot;,\n          mode:&quot;cors&quot;,\n          cache:&quot;no-store&quot;\n        }\n      );\n\n\n\n    if(!response.ok){\n\n      throw new Error(\n        &quot;HTTP &quot;+\n        response.status+\n        &quot; \u2014 &quot;+\n        response.statusText\n      );\n\n    }\n\n\n\n    const data=\n      await response.arrayBuffer();\n\n\n\n    sampleBuffer=\n      await audioContext.decodeAudioData(\n        data\n      );\n\n\n\n    selectedSampleUrl=\n      url;\n\n\n\n    selectedSampleName=\n      name;\n\n\n\n    sourceType.value=\n      &quot;sample&quot;;\n\n\n\n    oscillatorPanel.style.display=\n      &quot;none&quot;;\n\n\n\n    samplePanel.style.display=\n      &quot;block&quot;;\n\n\n\n    setAudioStatus(\n      false,\n      name+&quot; charg\u00e9&quot;\n    );\n\n\n\n    \/*\n     * Le sample est seulement charg\u00e9 ici.\n     * Il sera ensuite envoy\u00e9 dans la m\u00eame cha\u00eene\n     * audio que l&#x27;oscillateur lorsqu&#x27;on clique\n     * sur D\u00e9marrer.\n     *\/\n\n  }\n\n  catch(error){\n\n    console.error(\n      &quot;Erreur de chargement du sample :&quot;,\n      error\n    );\n\n\n\n    sampleBuffer=null;\n\n\n\n    setAudioStatus(\n      false,\n      &quot;Impossible de charger le sample&quot;\n    );\n\n  }\n\n}\n\n\n\n\/* =========================================================\n   CANVAS\n========================================================= *\/\n\nconst scope=\n  document.getElementById(\n    &quot;scope&quot;\n  );\n\nconst scopeCtx=\n  scope.getContext(\n    &quot;2d&quot;\n  );\n\n\n\nconst spectrum=\n  document.getElementById(\n    &quot;spectrum&quot;\n  );\n\nconst spectrumCtx=\n  spectrum.getContext(\n    &quot;2d&quot;\n  );\n\n\n\nconst filterCanvas=\n  document.getElementById(\n    &quot;filterCanvas&quot;\n  );\n\nconst filterCtx=\n  filterCanvas.getContext(\n    &quot;2d&quot;\n  );\n\n\n\nconst spectrogram=\n  document.getElementById(\n    &quot;spectrogram&quot;\n  );\n\nconst spectrogramCtx=\n  spectrogram.getContext(\n    &quot;2d&quot;\n  );\n\n\n\nfunction setupCanvas(canvas){\n\n  const rect=\n    canvas.getBoundingClientRect();\n\n\n\n  const dpr=\n    window.devicePixelRatio ||\n    1;\n\n\n\n  canvas.width=\n    Math.max(\n      1,\n      Math.floor(\n        rect.width*dpr\n      )\n    );\n\n\n\n  canvas.height=\n    Math.max(\n      1,\n      Math.floor(\n        rect.height*dpr\n      )\n    );\n\n\n\n  const ctx=\n    canvas.getContext(\n      &quot;2d&quot;\n    );\n\n\n\n  ctx.setTransform(\n    dpr,\n    0,\n    0,\n    dpr,\n    0,\n    0\n  );\n\n}\n\n\n\nfunction setupAllCanvases(){\n\n  setupCanvas(scope);\n\n  setupCanvas(spectrum);\n\n  setupCanvas(filterCanvas);\n\n  setupCanvas(spectrogram);\n\n\n\n  spectrogramWidth=\n    spectrogram.clientWidth;\n\n\n\n  spectrogramHeight=\n    spectrogram.clientHeight;\n\n}\n\n\n\nwindow.addEventListener(\n  &quot;resize&quot;,\n  ()=&gt;{\n    setupAllCanvases();\n    clearSpectrogram();\n  }\n);\n\nwindow.addEventListener(\n  &quot;DOMContentLoaded&quot;,\n  setupAllCanvases\n);\n\nsetupAllCanvases();\n\n\n\n\/* =========================================================\n   VISUALISATION \u2014 OUTILS\n========================================================= *\/\n\nfunction drawGrid(\n  ctx,\n  width,\n  height,\n  horizontal=4,\n  vertical=8\n){\n\n  ctx.strokeStyle=\n    &quot;rgba(255,255,255,.07)&quot;;\n\n  ctx.lineWidth=1;\n\n\n\n  for(\n    let i=1;\n    i&lt;horizontal;\n    i++\n  ){\n\n    const y=\n      height*i\/horizontal;\n\n\n\n    ctx.beginPath();\n\n    ctx.moveTo(\n      0,\n      y\n    );\n\n    ctx.lineTo(\n      width,\n      y\n    );\n\n    ctx.stroke();\n\n  }\n\n\n\n  for(\n    let i=1;\n    i&lt;vertical;\n    i++\n  ){\n\n    const x=\n      width*i\/vertical;\n\n\n\n    ctx.beginPath();\n\n    ctx.moveTo(\n      x,\n      0\n    );\n\n    ctx.lineTo(\n      x,\n      height\n    );\n\n    ctx.stroke();\n\n  }\n\n}\n\n\n\n\/* =========================================================\n   OSCILLOSCOPE\n========================================================= *\/\n\nfunction drawScope(){\n\n  const width=\n    scope.clientWidth;\n\n  const height=\n    scope.clientHeight;\n\n\n\n  scopeCtx.clearRect(\n    0,\n    0,\n    width,\n    height\n  );\n\n\n\n  scopeCtx.fillStyle=\n    &quot;#05080d&quot;;\n\n  scopeCtx.fillRect(\n    0,\n    0,\n    width,\n    height\n  );\n\n\n\n  drawGrid(\n    scopeCtx,\n    width,\n    height,\n    4,\n    8\n  );\n\n\n\n  \/*\n   * Ligne centrale 0\n   *\/\n\n  scopeCtx.strokeStyle=\n    &quot;rgba(85,214,255,.25)&quot;;\n\n  scopeCtx.beginPath();\n\n  scopeCtx.moveTo(\n    0,\n    height\/2\n  );\n\n  scopeCtx.lineTo(\n    width,\n    height\/2\n  );\n\n  scopeCtx.stroke();\n\n\n\n  if(!analyser){\n\n    return;\n\n  }\n\n\n\n  if(!scopeData){\n\n    scopeData=\n      new Uint8Array(\n        analyser.fftSize\n      );\n\n  }\n\n\n\n  analyser.getByteTimeDomainData(\n    scopeData\n  );\n\n\n\n  scopeCtx.strokeStyle=\n    &quot;#918bff&quot;;\n\n  scopeCtx.lineWidth=1.5;\n\n  scopeCtx.beginPath();\n\n\n\n  const sliceWidth=\n    width\/\n    scopeData.length;\n\n\n\n  let x=0;\n\n\n\n  for(\n    let i=0;\n    i&lt;scopeData.length;\n    i++\n  ){\n\n    const v=\n      scopeData[i]\/\n      128.0;\n\n\n\n    const y=\n      v*\n      height\/2;\n\n\n\n    if(i===0){\n\n      scopeCtx.moveTo(\n        x,\n        y\n      );\n\n    }\n\n    else{\n\n      scopeCtx.lineTo(\n        x,\n        y\n      );\n\n    }\n\n\n\n    x+=sliceWidth;\n\n  }\n\n\n\n  scopeCtx.stroke();\n\n}\n\n\n\n\/* =========================================================\n   SPECTRE \/ FFT\n========================================================= *\/\n\nfunction drawSpectrum(){\n\n  const width=\n    spectrum.clientWidth;\n\n  const height=\n    spectrum.clientHeight;\n\n\n\n  spectrumCtx.clearRect(\n    0,\n    0,\n    width,\n    height\n  );\n\n\n\n  spectrumCtx.fillStyle=\n    &quot;#05080d&quot;;\n\n  spectrumCtx.fillRect(\n    0,\n    0,\n    width,\n    height\n  );\n\n\n\n  drawGrid(\n    spectrumCtx,\n    width,\n    height,\n    4,\n    10\n  );\n\n\n\n  if(!analyser){\n\n    return;\n\n  }\n\n\n\n  if(!spectrumData){\n\n    spectrumData=\n      new Uint8Array(\n        analyser.frequencyBinCount\n      );\n\n  }\n\n\n\n  analyser.getByteFrequencyData(\n    spectrumData\n  );\n\n\n\n  spectrumCtx.beginPath();\n\n\n\n  const gradient=\n    spectrumCtx.createLinearGradient(\n      0,\n      height,\n      0,\n      0\n    );\n\n\n\n  gradient.addColorStop(\n    0,\n    &quot;#918bff&quot;\n  );\n\n\n\n  gradient.addColorStop(\n    .55,\n    &quot;#b8b4ff&quot;\n  );\n\n\n\n  gradient.addColorStop(\n    1,\n    &quot;#c8c5ff&quot;\n  );\n\n\n\n  spectrumCtx.strokeStyle=\n    gradient;\n\n  spectrumCtx.lineWidth=1.5;\n\n\n\n  \/*\n   * \u00c9chelle logarithmique de fr\u00e9quence.\n   * C&#x27;est beaucoup plus lisible pour un analyseur\n   * audio r\u00e9el que l&#x27;\u00e9chelle lin\u00e9aire.\n   *\/\n\n  const nyquist=\n    audioContext.sampleRate\/2;\n\n\n\n  let started=false;\n\n\n\n  for(\n    let i=1;\n    i&lt;spectrumData.length;\n    i++\n  ){\n\n    const freq=\n      i\/\n      spectrumData.length*\n      nyquist;\n\n\n\n    if(freq&lt;20)\n      continue;\n\n\n\n    const logMin=\n      Math.log10(20);\n\n    const logMax=\n      Math.log10(\n        Math.min(\n          20000,\n          nyquist\n        )\n      );\n\n\n\n    const x=\n      (\n        Math.log10(freq)-\n        logMin\n      )\/\n      (\n        logMax-\n        logMin\n      )*\n      width;\n\n\n\n    const magnitude=\n      spectrumData[i]\/\n      255;\n\n\n\n    const y=\n      height-\n      magnitude*\n      (height-4);\n\n\n\n    if(!started){\n\n      spectrumCtx.moveTo(\n        x,\n        y\n      );\n\n      started=true;\n\n    }\n\n    else{\n\n      spectrumCtx.lineTo(\n        x,\n        y\n      );\n\n    }\n\n  }\n\n\n\n  spectrumCtx.stroke();\n\n\n\n  \/*\n   * Axe fr\u00e9quence minimal discret\n   *\/\n\n  spectrumCtx.fillStyle=\n    &quot;#718091&quot;;\n\n  spectrumCtx.font=\n    &quot;9px system-ui&quot;;\n\n  const labels=[\n    20,\n    100,\n    500,\n    1000,\n    2000,\n    5000,\n    10000,\n    20000\n  ];\n\n\n\n  labels.forEach(\n    f=&gt;{\n\n      if(f&gt;nyquist)\n        return;\n\n\n\n      const logMin=\n        Math.log10(20);\n\n      const logMax=\n        Math.log10(\n          Math.min(\n            20000,\n            nyquist\n          )\n        );\n\n\n\n      const x=\n        (\n          Math.log10(f)-\n          logMin\n        )\/\n        (\n          logMax-\n          logMin\n        )*\n        width;\n\n\n\n      spectrumCtx.fillText(\n        f&gt;=1000\n          ?(f\/1000)+&quot;k&quot;\n          :f+&quot;&quot;,\n        Math.max(\n          0,\n          Math.min(\n            width-25,\n            x-8\n          )\n        ),\n        height-5\n      );\n\n    }\n  );\n\n}\n\n\n\n\/* =========================================================\n   R\u00c9PONSE DU FILTRE\n========================================================= *\/\n\nfunction updateFilterVisual(){\n\n  const width=\n    filterCanvas.clientWidth;\n\n  const height=\n    filterCanvas.clientHeight;\n\n\n\n  filterCtx.clearRect(\n    0,\n    0,\n    width,\n    height\n  );\n\n\n\n  filterCtx.fillStyle=\n    &quot;#05080d&quot;;\n\n  filterCtx.fillRect(\n    0,\n    0,\n    width,\n    height\n  );\n\n\n\n  drawGrid(\n    filterCtx,\n    width,\n    height,\n    4,\n    10\n  );\n\n\n\n  if(!audioContext || !filterNode){\n\n    drawFlatFilterLine(\n      width,\n      height\n    );\n\n    return;\n\n  }\n\n\n\n  const frequencies=\n    new Float32Array(512);\n\n  const magnitudes=\n    new Float32Array(512);\n\n  const phases=\n    new Float32Array(512);\n\n\n\n  const nyquist=\n    audioContext.sampleRate\/2;\n\n\n\n  const maxFreq=\n    Math.min(\n      20000,\n      nyquist-1\n    );\n\n\n\n  const minFreq=20;\n\n\n\n  for(\n    let i=0;\n    i&lt;frequencies.length;\n    i++\n  ){\n\n    frequencies[i]=\n      minFreq*\n      Math.pow(\n        maxFreq\/minFreq,\n        i\/(frequencies.length-1)\n      );\n\n  }\n\n\n\n  try{\n\n    filterNode.getFrequencyResponse(\n      frequencies,\n      magnitudes,\n      phases\n    );\n\n  }\n\n  catch(e){\n\n    drawFlatFilterLine(\n      width,\n      height\n    );\n\n    return;\n\n  }\n\n\n\n  filterCtx.beginPath();\n\n  filterCtx.strokeStyle=\n    &quot;#aaa6ff&quot;;\n\n  filterCtx.lineWidth=1.5;\n\n\n\n  for(\n    let i=0;\n    i&lt;magnitudes.length;\n    i++\n  ){\n\n    const x=\n      i\/\n      (magnitudes.length-1)*\n      width;\n\n\n\n    const db=\n      20*\n      Math.log10(\n        Math.max(\n          magnitudes[i],\n          0.00001\n        )\n      );\n\n\n\n    \/*\n     * Affichage de +12 dB \u00e0 -60 dB.\n     *\/\n\n    const normalized=\n      (\n        db+60\n      )\/\n      72;\n\n\n\n    const y=\n      height-\n      Math.max(\n        0,\n        Math.min(\n          1,\n          normalized\n        )\n      )*\n      height;\n\n\n\n    if(i===0){\n\n      filterCtx.moveTo(\n        x,\n        y\n      );\n\n    }\n\n    else{\n\n      filterCtx.lineTo(\n        x,\n        y\n      );\n\n    }\n\n  }\n\n\n\n  filterCtx.stroke();\n\n\n\n  filterCtx.fillStyle=\n    &quot;#718091&quot;;\n\n  filterCtx.font=\n    &quot;9px system-ui&quot;;\n\n\n\n  filterCtx.fillText(\n    &quot;+12 dB&quot;,\n    5,\n    11\n  );\n\n\n\n  filterCtx.fillText(\n    &quot;0 dB&quot;,\n    5,\n    height\/2\n  );\n\n\n\n  filterCtx.fillText(\n    &quot;-60 dB&quot;,\n    5,\n    height-5\n  );\n\n\n\n  \/*\n   * Ligne verticale de fr\u00e9quence de coupure.\n   *\/\n\n  const f=\n    Number(\n      cutoff.value\n    );\n\n\n\n  const logMin=\n    Math.log10(20);\n\n  const logMax=\n    Math.log10(maxFreq);\n\n\n\n  const x=\n    (\n      Math.log10(\n        Math.max(\n          20,\n          Math.min(\n            maxFreq,\n            f\n          )\n        )\n      )-\n      logMin\n    )\/\n    (\n      logMax-logMin\n    )*\n    width;\n\n\n\n  filterCtx.strokeStyle=\n    &quot;rgba(85,214,255,.55)&quot;;\n\n  filterCtx.setLineDash(\n    [4,4]\n  );\n\n\n\n  filterCtx.beginPath();\n\n  filterCtx.moveTo(\n    x,\n    0\n  );\n\n  filterCtx.lineTo(\n    x,\n    height\n  );\n\n  filterCtx.stroke();\n\n  filterCtx.setLineDash([]);\n\n\n\n  filterCtx.fillStyle=\n    &quot;#918bff&quot;;\n\n  filterCtx.fillText(\n    f+&quot; Hz&quot;,\n    Math.min(\n      width-55,\n      Math.max(\n        3,\n        x+4\n      )\n    ),\n    12\n  );\n\n}\n\n\n\nfunction drawFlatFilterLine(\n  width,\n  height\n){\n\n  filterCtx.strokeStyle=\n    &quot;#b8b4ff&quot;;\n\n  filterCtx.lineWidth=1.5;\n\n  filterCtx.beginPath();\n\n  filterCtx.moveTo(\n    0,\n    height\/2\n  );\n\n  filterCtx.lineTo(\n    width,\n    height\/2\n  );\n\n  filterCtx.stroke();\n\n}\n\n\n\n\/* =========================================================\n   SPECTROGRAMME\n========================================================= *\/\n\nfunction clearSpectrogram(){\n\n  spectrogramCtx.clearRect(\n    0,\n    0,\n    spectrogram.clientWidth,\n    spectrogram.clientHeight\n  );\n\n}\n\n\n\nfunction drawSpectrogram(){\n\n  const width=\n    spectrogram.clientWidth;\n\n  const height=\n    spectrogram.clientHeight;\n\n\n\n  if(!analyser)\n    return;\n\n\n\n  if(!spectrumData){\n\n    spectrumData=\n      new Uint8Array(\n        analyser.frequencyBinCount\n      );\n\n  }\n\n\n\n  analyser.getByteFrequencyData(\n    spectrumData\n  );\n\n\n\n  \/*\n   * On d\u00e9cale l&#x27;image existante d&#x27;un pixel\n   * vers la gauche.\n   *\/\n\n  const dpr=\n    window.devicePixelRatio ||\n    1;\n\n\n\n  const pixelWidth=\n    spectrogram.width;\n\n  const pixelHeight=\n    spectrogram.height;\n\n\n\n  if(\n    pixelWidth&lt;=0 ||\n    pixelHeight&lt;=0\n  )\n    return;\n\n\n\n  \/*\n   * Le canvas utilise un transform DPR pour les\n   * autres dessins. Pour le spectrogramme, on\n   * travaille directement en pixels du canvas.\n   *\/\n\n  const oldTransform=\n    spectrogramCtx.getTransform();\n\n\n\n  spectrogramCtx.setTransform(\n    1,\n    0,\n    0,\n    1,\n    0,\n    0\n  );\n\n\n\n  try{\n\n    spectrogramCtx.drawImage(\n      spectrogram,\n      1,\n      0,\n      pixelWidth-1,\n      pixelHeight,\n      0,\n      0,\n      pixelWidth-1,\n      pixelHeight\n    );\n\n  }\n  catch(e){}\n\n\n\n  const nyquist=\n    audioContext.sampleRate\/2;\n\n\n\n  const maxFreq=\n    Math.min(\n      20000,\n      nyquist\n    );\n\n\n\n  \/*\n   * Colonne actuelle.\n   *\/\n\n  for(\n    let y=0;\n    y&lt;pixelHeight;\n    y++\n  ){\n\n    \/*\n     * \u00c9chelle logarithmique verticale.\n     * Haut = hautes fr\u00e9quences.\n     * Bas = basses fr\u00e9quences.\n     *\/\n\n    const normalized=\n      y\/\n      (pixelHeight-1);\n\n\n\n    const logMax=\n      Math.log10(\n        maxFreq\n      );\n\n\n\n    const logMin=\n      Math.log10(20);\n\n\n\n    const frequencyAtY=\n      Math.pow(\n        10,\n        logMax-\n        normalized*\n        (logMax-logMin)\n      );\n\n\n\n    const bin=\n      Math.floor(\n        frequencyAtY\/\n        nyquist*\n        spectrumData.length\n      );\n\n\n\n    const value=\n      spectrumData[\n        Math.max(\n          0,\n          Math.min(\n            spectrumData.length-1,\n            bin\n          )\n        )\n      ];\n\n\n\n    const intensity=\n      value\/255;\n\n\n\n    spectrogramCtx.fillStyle=\n      spectrogramColor(\n        intensity\n      );\n\n\n\n    spectrogramCtx.fillRect(\n      pixelWidth-2,\n      y,\n      2,\n      1\n    );\n\n  }\n\n\n\n  spectrogramCtx.setTransform(\n    oldTransform\n  );\n\n}\n\n\n\nfunction spectrogramColor(\n  value\n){\n\n  \/*\n   * Palette sombre :\n   * noir \u2192 bleu \u2192 cyan \u2192 vert \u2192 jaune \u2192 rouge\n   *\/\n\n  const v=\n    Math.max(\n      0,\n      Math.min(\n        1,\n        value\n      )\n    );\n\n\n\n  if(v&lt;.15){\n\n    const t=\n      v\/.15;\n\n\n\n    return `rgb(\n      ${Math.round(2+5*t)},\n      ${Math.round(5+15*t)},\n      ${Math.round(12+45*t)}\n    )`;\n\n  }\n\n\n\n  if(v&lt;.40){\n\n    const t=\n      (v-.15)\/.25;\n\n\n\n    return `rgb(\n      ${Math.round(7+5*t)},\n      ${Math.round(20+120*t)},\n      ${Math.round(57+150*t)}\n    )`;\n\n  }\n\n\n\n  if(v&lt;.65){\n\n    const t=\n      (v-.40)\/.25;\n\n\n\n    return `rgb(\n      ${Math.round(12+60*t)},\n      ${Math.round(140+80*t)},\n      ${Math.round(207-110*t)}\n    )`;\n\n  }\n\n\n\n  if(v&lt;.82){\n\n    const t=\n      (v-.65)\/.17;\n\n\n\n    return `rgb(\n      ${Math.round(72+170*t)},\n      ${Math.round(220+15*t)},\n      ${Math.round(97-75*t)}\n    )`;\n\n  }\n\n\n\n  const t=\n    (v-.82)\/.18;\n\n\n\n  return `rgb(\n    ${Math.round(242+13*t)},\n    ${Math.round(235-170*t)},\n    ${Math.round(22-15*t)}\n  )`;\n\n}\n\n\n\n\/* =========================================================\n   BOUCLE VISUELLE\n========================================================= *\/\n\nfunction startVisualisation(){\n\n  stopVisualisation();\n\n\n\n  scopeData=null;\n\n  spectrumData=null;\n\n\n\n  function frame(){\n\n    if(!isPlaying){\n\n      return;\n\n    }\n\n\n\n    drawScope();\n\n    drawSpectrum();\n\n    drawSpectrogram();\n\n\n\n    animationFrame=\n      requestAnimationFrame(\n        frame\n      );\n\n  }\n\n\n\n  frame();\n\n}\n\n\n\nfunction stopVisualisation(){\n\n  if(animationFrame){\n\n    cancelAnimationFrame(\n      animationFrame\n    );\n\n    animationFrame=null;\n\n  }\n\n\n\n  scopeData=null;\n\n  spectrumData=null;\n\n}\n\n\n\n\/* =========================================================\n   INITIALISATION VISUELLE\n========================================================= *\/\n\nclearSpectrogram();\n\nupdateFilterVisual();\n\n&lt;\/script&gt;\n\n&lt;\/body&gt;\n&lt;\/html&gt;\"><\/iframe><div style=\"padding:10px 4px 0;color:var(--soft)!important;font-size:10px;text-align:right\">Outil d\u2019analyse interactif \u00b7 \u00a9 2026 Lucas Goret \u00b7 Tous droits r\u00e9serv\u00e9s.<\/div><\/div>\n    <\/section>\n\n    <section class=\"section\" id=\"laboratoire\">\n      <div class=\"head\">\n        <div class=\"index\">03 \u2014 Laboratoire<\/div>\n        <div><h2 data-parallax=\"-0.02\">Voir<br>le son.<\/h2><p class=\"intro\">Quatre exp\u00e9riences interactives pour relier repr\u00e9sentation visuelle, ph\u00e9nom\u00e8nes physiques et perception auditive. Un seul son \u00e0 la fois : chaque nouvelle exp\u00e9rience coupe automatiquement la pr\u00e9c\u00e9dente.<\/p><\/div>\n      <\/div>\n      <div class=\"principle-wide\"><p>Visualiser le son permet de relier ce que l\u2019on entend \u00e0 ce qui se produit physiquement.<\/p><\/div>\n      <div class=\"tool-wrap\"><iframe class=\"tool autoheight\" title=\"Laboratoire Voir le son\" srcdoc=\"&lt;!doctype html&gt;\n&lt;html lang=&quot;fr&quot;&gt;\n&lt;head&gt;\n&lt;meta charset=&quot;utf-8&quot;&gt;\n&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width,initial-scale=1&quot;&gt;\n&lt;title&gt;Voir le son \u2014 outil 2 int\u00e9gr\u00e9&lt;\/title&gt;\n&lt;style&gt;\n#vls26{\n  --bg:#09090b;\n  --surface:#121318;\n  --surface-2:#0d0e12;\n  --surface-3:#17181e;\n  --line:#2b2d35;\n  --line-soft:#1d1f26;\n  --text:#f4f4f6;\n  --muted:#a2a4ad;\n  --accent:#918bff;\n  --accent-2:#b8b4ff;\n  --radius:22px;\n  --radius-sm:14px;\n  width:100%;\n  max-width:1280px;\n  margin:0 auto;\n  padding:clamp(28px,4vw,54px);\n  background:var(--bg);\n  color:var(--text);\n  font-family:Inter,Arial,sans-serif;\n  border-radius:28px;\n}\n#vls26 *{box-sizing:border-box}\n#vls26>header{display:none!important}\\n#vls26 header{padding:10px 0 34px}\n#vls26 .kicker{\n  color:var(--accent)!important;\n  font-size:12px;\n  line-height:1.2;\n  letter-spacing:.16em;\n  text-transform:uppercase;\n  font-weight:800;\n  margin-bottom:14px;\n}\n#vls26 h1{\n  margin:0!important;\n  color:var(--text)!important;\n  font-size:clamp(52px,7vw,96px)!important;\n  line-height:.9!important;\n  letter-spacing:-.065em!important;\n  font-weight:760!important;\n}\n#vls26 .intro{\n  max-width:760px;\n  margin:26px 0 0!important;\n  color:var(--muted)!important;\n  font-size:17px!important;\n  line-height:1.7!important;\n}\n#vls26 main{display:grid;gap:28px}\n#vls26 .card{\n  overflow:hidden;\n  border:1px solid var(--line);\n  border-radius:var(--radius);\n  background:linear-gradient(180deg,var(--surface),#101116);\n}\n#vls26 .cardhead{\n  display:grid;\n  grid-template-columns:minmax(0,.9fr) minmax(0,1.1fr);\n  gap:32px;\n  align-items:end;\n  padding:24px 26px 22px;\n  border-bottom:1px solid var(--line);\n}\n#vls26 .num{\n  color:var(--accent)!important;\n  font-size:11px;\n  letter-spacing:.16em;\n  text-transform:uppercase;\n  font-weight:800;\n  margin-bottom:7px;\n}\n#vls26 .title{\n  color:var(--text)!important;\n  font-size:clamp(24px,2.5vw,34px);\n  line-height:1.05;\n  letter-spacing:-.035em;\n  font-weight:750;\n}\n#vls26 .desc{\n  color:var(--muted)!important;\n  font-size:14px;\n  line-height:1.65;\n}\n#vls26 .body{padding:18px}\n#vls26 canvas{\n  display:block;\n  width:100%;\n  background:#08090c;\n  border:1px solid var(--line-soft);\n  border-radius:16px;\n}\n#vls26 .grid2{\n  display:grid;\n  grid-template-columns:1fr 1fr;\n  gap:12px;\n}\n#vls26 .controls{\n  display:grid;\n  grid-template-columns:repeat(4,minmax(0,1fr));\n  gap:12px;\n  margin-top:12px;\n}\n#vls26 .controls.two{grid-template-columns:repeat(2,minmax(0,1fr))}\n#vls26 .control{\n  min-width:0;\n  padding:14px;\n  border:1px solid var(--line);\n  border-radius:var(--radius-sm);\n  background:var(--surface-2);\n}\n#vls26 .label{\n  display:flex;\n  justify-content:space-between;\n  gap:10px;\n  align-items:center;\n  margin-bottom:10px;\n  color:var(--text)!important;\n  font-size:12px;\n  font-weight:750;\n}\n#vls26 .value,#vls26 .big{\n  color:var(--accent-2)!important;\n  font-variant-numeric:tabular-nums;\n}\n#vls26 .big{\n  margin:2px 0 9px;\n  font-size:20px;\n  font-weight:720;\n}\n#vls26 input[type=&quot;range&quot;]{width:100%;accent-color:var(--accent)}\n#vls26 select{\n  width:100%;\n  min-height:42px;\n  padding:9px 10px;\n  border:1px solid var(--line);\n  border-radius:10px;\n  background:#0a0b0f;\n  color:var(--text);\n  font:inherit;\n}\n#vls26 button{\n  appearance:none;\n  min-height:42px;\n  padding:10px 15px;\n  border:1px solid var(--line);\n  border-radius:999px;\n  background:#191a20;\n  color:var(--text);\n  font:inherit;\n  font-size:13px;\n  font-weight:750;\n  cursor:pointer;\n}\n#vls26 button:hover{border-color:#484b58}\n#vls26 button.primary,#vls26 button.active{\n  border-color:transparent;\n  background:var(--accent);\n  color:#09090b;\n}\n#vls26 .actions{\n  display:flex;\n  gap:9px;\n  flex-wrap:wrap;\n  align-items:center;\n  margin-top:12px;\n}\n#vls26 .status{\n  margin-left:auto;\n  color:var(--muted)!important;\n  font-size:12px;\n}\n#vls26 .status.on{color:var(--accent-2)!important}\n#vls26 .source-choice{\n  display:grid;\n  grid-template-columns:1fr 1fr;\n  gap:7px;\n}\n#vls26 .source-choice button{border-radius:10px}\n#vls26 .harmonics{\n  display:grid;\n  gap:7px;\n  margin-top:12px;\n}\n#vls26 .hrow{\n  display:grid;\n  grid-template-columns:38px minmax(0,1fr) 74px;\n  gap:10px;\n  align-items:center;\n  padding:8px 10px;\n  border:1px solid var(--line-soft);\n  border-radius:10px;\n  background:#0b0c10;\n  font-size:12px;\n}\n#vls26 .hf{text-align:right;color:var(--muted)!important}\n#vls26 .adsr{\n  display:grid;\n  grid-template-columns:repeat(4,minmax(0,1fr));\n  gap:12px;\n  margin-top:12px;\n}\n#vls26 .space{\n  display:flex;\n  gap:12px;\n  align-items:center;\n  margin-top:12px;\n}\n#vls26 .spacekey{\n  min-width:190px;\n  padding:13px 18px;\n  text-align:center;\n  border:1px solid var(--line);\n  border-radius:12px;\n  background:#0b0c10;\n  color:var(--muted)!important;\n  font-size:12px;\n  font-weight:800;\n  letter-spacing:.08em;\n}\n#vls26 .spacekey.pressed{\n  background:var(--accent);\n  color:#09090b!important;\n}\n#vls26 .smallnote{\n  color:var(--muted)!important;\n  font-size:12px;\n  line-height:1.55;\n}\n#vls26 footer{\n  display:flex;\n  justify-content:space-between;\n  gap:12px;\n  margin-top:22px;\n  padding-top:18px;\n  border-top:1px solid var(--line-soft);\n  color:#70727c!important;\n  font-size:11px;\n  letter-spacing:.1em;\n  text-transform:uppercase;\n}\n@media(max-width:900px){\n  #vls26{padding:22px}\n  #vls26 .cardhead{grid-template-columns:1fr}\n  #vls26 .controls{grid-template-columns:1fr 1fr}\n  #vls26 .adsr{grid-template-columns:1fr 1fr}\n  #vls26 .grid2{grid-template-columns:1fr}\n}\n@media(max-width:560px){\n  #vls26{padding:14px;border-radius:20px}\n  #vls26 .controls,#vls26 .controls.two,#vls26 .adsr{grid-template-columns:1fr}\n  #vls26 .actions button{flex:1 1 120px}\n  #vls26 .space{flex-direction:column;align-items:stretch}\n  #vls26 .spacekey{min-width:0}\n}\n&lt;\/style&gt;\n&lt;\/head&gt;\n&lt;body style=&quot;margin:0;background:#09090b;padding:18px&quot;&gt;\n&lt;div id=&quot;vls26&quot; data-vls-root&gt;\n&lt;header&gt;\n  &lt;div class=&quot;kicker&quot;&gt;Laboratoire du son&lt;\/div&gt;\n  &lt;h1&gt;Voir le son.&lt;\/h1&gt;\n  &lt;p class=&quot;intro&quot;&gt;Quatre exp\u00e9riences interactives pour relier repr\u00e9sentation visuelle, ph\u00e9nom\u00e8nes physiques et perception auditive. Un seul son \u00e0 la fois : chaque nouvelle exp\u00e9rience coupe automatiquement la pr\u00e9c\u00e9dente.&lt;\/p&gt;\n&lt;\/header&gt;\n\n&lt;main&gt;\n&lt;section class=&quot;card&quot;&gt;\n  &lt;div class=&quot;cardhead&quot;&gt;\n    &lt;div&gt;&lt;div class=&quot;num&quot;&gt;01 \/ Propagation&lt;\/div&gt;&lt;div class=&quot;title&quot;&gt;Compression \u00b7 rar\u00e9faction&lt;\/div&gt;&lt;\/div&gt;\n    &lt;div class=&quot;desc&quot;&gt;Une onde sonore longitudinale fait osciller localement les particules d&#x27;air autour de leur position d&#x27;\u00e9quilibre. La fr\u00e9quence agit sur la cadence et sur la longueur d&#x27;onde.&lt;\/div&gt;\n  &lt;\/div&gt;\n  &lt;div class=&quot;body&quot;&gt;\n    &lt;canvas id=&quot;prop&quot; width=&quot;1400&quot; height=&quot;350&quot;&gt;&lt;\/canvas&gt;\n    &lt;div class=&quot;controls two&quot;&gt;\n      &lt;div class=&quot;control&quot;&gt;&lt;div class=&quot;label&quot;&gt;Fr\u00e9quence &lt;span class=&quot;value&quot; id=&quot;pfv&quot;&gt;&lt;\/span&gt;&lt;\/div&gt;&lt;input id=&quot;pf&quot; type=&quot;range&quot; min=&quot;60&quot; max=&quot;900&quot; value=&quot;294&quot;&gt;&lt;\/div&gt;\n      &lt;div class=&quot;control&quot;&gt;&lt;div class=&quot;label&quot;&gt;Amplitude &lt;span class=&quot;value&quot; id=&quot;pav&quot;&gt;&lt;\/span&gt;&lt;\/div&gt;&lt;input id=&quot;pa&quot; type=&quot;range&quot; min=&quot;.05&quot; max=&quot;1&quot; step=&quot;.01&quot; value=&quot;.65&quot;&gt;&lt;\/div&gt;\n    &lt;\/div&gt;\n    &lt;div class=&quot;actions&quot;&gt;&lt;button class=&quot;primary&quot; id=&quot;pplay&quot;&gt;\u25b6 Lire&lt;\/button&gt;&lt;button id=&quot;pstop&quot;&gt;\u25a0 Stop&lt;\/button&gt;&lt;div class=&quot;status&quot; id=&quot;ps&quot;&gt;Arr\u00eat\u00e9&lt;\/div&gt;&lt;\/div&gt;\n  &lt;\/div&gt;\n&lt;\/section&gt;\n\n&lt;section class=&quot;card&quot;&gt;\n  &lt;div class=&quot;cardhead&quot;&gt;\n    &lt;div&gt;&lt;div class=&quot;num&quot;&gt;02 \/ Salle&lt;\/div&gt;&lt;div class=&quot;title&quot;&gt;R\u00e9flexion \u00b7 absorption \u00b7 r\u00e9verb\u00e9ration&lt;\/div&gt;&lt;\/div&gt;\n    &lt;div class=&quot;desc&quot;&gt;Une source est entendue par un auditeur. Modifiez la taille de la salle et le mat\u00e9riau des murs pendant la lecture. La g\u00e9om\u00e9trie de la salle, l\u2019absorption des parois et les r\u00e9flexions \u00e9voluent ensemble.&lt;\/div&gt;\n  &lt;\/div&gt;\n  &lt;div class=&quot;body&quot;&gt;\n    &lt;canvas id=&quot;room&quot; width=&quot;1400&quot; height=&quot;560&quot;&gt;&lt;\/canvas&gt;\n    &lt;div class=&quot;controls&quot;&gt;\n      &lt;div class=&quot;control&quot;&gt;\n        &lt;div class=&quot;label&quot;&gt;Taille de la salle &lt;span class=&quot;value&quot; id=&quot;rsv&quot;&gt;&lt;\/span&gt;&lt;\/div&gt;\n        &lt;input id=&quot;rsize&quot; type=&quot;range&quot; min=&quot;0&quot; max=&quot;1&quot; step=&quot;.01&quot; value=&quot;0&quot;&gt;\n      &lt;\/div&gt;\n      &lt;div class=&quot;control&quot;&gt;\n        &lt;div class=&quot;label&quot;&gt;Source sonore&lt;\/div&gt;\n        &lt;div class=&quot;source-choice&quot;&gt;&lt;button id=&quot;impulseBtn&quot;&gt;Impulsion&lt;\/button&gt;&lt;button id=&quot;sampleBtn&quot; class=&quot;active&quot;&gt;Voix homme&lt;\/button&gt;&lt;\/div&gt;\n      &lt;\/div&gt;\n      &lt;div class=&quot;control&quot;&gt;\n        &lt;div class=&quot;label&quot;&gt;Mat\u00e9riau des murs&lt;\/div&gt;\n        &lt;select id=&quot;mat&quot;&gt;\n          &lt;option value=&quot;curtain&quot; selected&gt;Rideaux \u00e9pais&lt;\/option&gt;\n          &lt;option value=&quot;wood&quot;&gt;Bois&lt;\/option&gt;\n          &lt;option value=&quot;plaster&quot;&gt;Pl\u00e2tre&lt;\/option&gt;\n          &lt;option value=&quot;concrete&quot;&gt;B\u00e9ton&lt;\/option&gt;\n          &lt;option value=&quot;glass&quot;&gt;Verre&lt;\/option&gt;\n        &lt;\/select&gt;\n      &lt;\/div&gt;\n      &lt;div class=&quot;control&quot;&gt;\n        &lt;div class=&quot;label&quot;&gt;Niveau &lt;span class=&quot;value&quot; id=&quot;rvv&quot;&gt;&lt;\/span&gt;&lt;\/div&gt;\n        &lt;input id=&quot;rv&quot; type=&quot;range&quot; min=&quot;0&quot; max=&quot;1&quot; step=&quot;.01&quot; value=&quot;.70&quot;&gt;\n      &lt;\/div&gt;\n    &lt;\/div&gt;\n    &lt;div class=&quot;actions&quot;&gt;&lt;button class=&quot;primary&quot; id=&quot;rplay&quot;&gt;\u25b6 Lire&lt;\/button&gt;&lt;button id=&quot;rstop&quot;&gt;\u25a0 Stop&lt;\/button&gt;&lt;div class=&quot;status&quot; id=&quot;rs&quot;&gt;Arr\u00eat\u00e9&lt;\/div&gt;&lt;\/div&gt;\n  &lt;\/div&gt;\n&lt;\/section&gt;\n\n&lt;section class=&quot;card&quot;&gt;\n  &lt;div class=&quot;cardhead&quot;&gt;\n    &lt;div&gt;&lt;div class=&quot;num&quot;&gt;03 \/ Modes propres&lt;\/div&gt;&lt;div class=&quot;title&quot;&gt;Corde \u00b7 harmoniques \u00b7 Chladni&lt;\/div&gt;&lt;\/div&gt;\n    &lt;div class=&quot;desc&quot;&gt;Les tirettes r\u00e8glent r\u00e9ellement huit composantes sinuso\u00efdales. La corde affiche leur superposition et la plaque calcule un champ modal simplifi\u00e9 pour rendre visibles les lignes nodales.&lt;\/div&gt;\n  &lt;\/div&gt;\n  &lt;div class=&quot;body&quot;&gt;\n    &lt;div class=&quot;grid2&quot;&gt;&lt;canvas id=&quot;string&quot; width=&quot;900&quot; height=&quot;280&quot;&gt;&lt;\/canvas&gt;&lt;canvas id=&quot;chladni&quot; width=&quot;900&quot; height=&quot;280&quot;&gt;&lt;\/canvas&gt;&lt;\/div&gt;\n    &lt;div class=&quot;controls two&quot;&gt;\n      &lt;div class=&quot;control&quot;&gt;&lt;div class=&quot;label&quot;&gt;Fondamentale &lt;span class=&quot;value&quot; id=&quot;fv&quot;&gt;&lt;\/span&gt;&lt;\/div&gt;&lt;input id=&quot;fund&quot; type=&quot;range&quot; min=&quot;70&quot; max=&quot;500&quot; value=&quot;294&quot;&gt;&lt;\/div&gt;\n      &lt;div class=&quot;control&quot;&gt;&lt;div class=&quot;label&quot;&gt;Niveau global &lt;span class=&quot;value&quot; id=&quot;hv&quot;&gt;&lt;\/span&gt;&lt;\/div&gt;&lt;input id=&quot;hvol&quot; type=&quot;range&quot; min=&quot;0&quot; max=&quot;1&quot; step=&quot;.01&quot; value=&quot;.30&quot;&gt;&lt;\/div&gt;\n    &lt;\/div&gt;\n    &lt;div class=&quot;harmonics&quot; id=&quot;vls-harmonics&quot;&gt;&lt;\/div&gt;\n    &lt;div class=&quot;actions&quot;&gt;&lt;button class=&quot;primary&quot; id=&quot;hplay&quot;&gt;\u25b6 Lire&lt;\/button&gt;&lt;button id=&quot;hstop&quot;&gt;\u25a0 Stop&lt;\/button&gt;&lt;div class=&quot;status&quot; id=&quot;hs&quot;&gt;Arr\u00eat\u00e9&lt;\/div&gt;&lt;\/div&gt;\n  &lt;\/div&gt;\n&lt;\/section&gt;\n\n&lt;section class=&quot;card&quot;&gt;\n  &lt;div class=&quot;cardhead&quot;&gt;\n    &lt;div&gt;&lt;div class=&quot;num&quot;&gt;04 \/ Enveloppe&lt;\/div&gt;&lt;div class=&quot;title&quot;&gt;ADSR&lt;\/div&gt;&lt;\/div&gt;\n    &lt;div class=&quot;desc&quot;&gt;Une source p\u00e9riodique passe dans une enveloppe d&#x27;amplitude. Testez l&#x27;attaque, le decay, le sustain et le release au clic, puis armez la barre espace pour jouer comme avec une touche de clavier ma\u00eetre.&lt;\/div&gt;\n  &lt;\/div&gt;\n  &lt;div class=&quot;body&quot;&gt;\n    &lt;canvas id=&quot;adsr&quot; width=&quot;1400&quot; height=&quot;350&quot;&gt;&lt;\/canvas&gt;\n    &lt;div class=&quot;adsr&quot;&gt;\n      &lt;div class=&quot;control&quot;&gt;&lt;div class=&quot;label&quot;&gt;Attack&lt;\/div&gt;&lt;div class=&quot;big&quot; id=&quot;av&quot;&gt;&lt;\/div&gt;&lt;input id=&quot;attack&quot; type=&quot;range&quot; min=&quot;.005&quot; max=&quot;3&quot; step=&quot;.005&quot; value=&quot;.10&quot;&gt;&lt;\/div&gt;\n      &lt;div class=&quot;control&quot;&gt;&lt;div class=&quot;label&quot;&gt;Decay&lt;\/div&gt;&lt;div class=&quot;big&quot; id=&quot;dv&quot;&gt;&lt;\/div&gt;&lt;input id=&quot;decay&quot; type=&quot;range&quot; min=&quot;.005&quot; max=&quot;3&quot; step=&quot;.005&quot; value=&quot;.30&quot;&gt;&lt;\/div&gt;\n      &lt;div class=&quot;control&quot;&gt;&lt;div class=&quot;label&quot;&gt;Sustain&lt;\/div&gt;&lt;div class=&quot;big&quot; id=&quot;sv&quot;&gt;&lt;\/div&gt;&lt;input id=&quot;sustain&quot; type=&quot;range&quot; min=&quot;0&quot; max=&quot;1&quot; step=&quot;.01&quot; value=&quot;.70&quot;&gt;&lt;\/div&gt;\n      &lt;div class=&quot;control&quot;&gt;&lt;div class=&quot;label&quot;&gt;Release&lt;\/div&gt;&lt;div class=&quot;big&quot; id=&quot;relv&quot;&gt;&lt;\/div&gt;&lt;input id=&quot;release&quot; type=&quot;range&quot; min=&quot;.005&quot; max=&quot;5&quot; step=&quot;.005&quot; value=&quot;.50&quot;&gt;&lt;\/div&gt;\n    &lt;\/div&gt;\n    &lt;div class=&quot;controls&quot;&gt;\n      &lt;div class=&quot;control&quot;&gt;&lt;div class=&quot;label&quot;&gt;Forme d&#x27;onde&lt;\/div&gt;&lt;select id=&quot;wave&quot;&gt;&lt;option value=&quot;sine&quot;&gt;Sinuso\u00efde&lt;\/option&gt;&lt;option value=&quot;triangle&quot;&gt;Triangle&lt;\/option&gt;&lt;option value=&quot;square&quot;&gt;Carr\u00e9e&lt;\/option&gt;&lt;option value=&quot;sawtooth&quot;&gt;Dent de scie&lt;\/option&gt;&lt;\/select&gt;&lt;\/div&gt;\n      &lt;div class=&quot;control&quot;&gt;&lt;div class=&quot;label&quot;&gt;Fr\u00e9quence &lt;span class=&quot;value&quot; id=&quot;afv&quot;&gt;&lt;\/span&gt;&lt;\/div&gt;&lt;input id=&quot;af&quot; type=&quot;range&quot; min=&quot;60&quot; max=&quot;1200&quot; value=&quot;294&quot;&gt;&lt;\/div&gt;\n      &lt;div class=&quot;control&quot;&gt;&lt;div class=&quot;label&quot;&gt;Niveau &lt;span class=&quot;value&quot; id=&quot;alv&quot;&gt;&lt;\/span&gt;&lt;\/div&gt;&lt;input id=&quot;al&quot; type=&quot;range&quot; min=&quot;.02&quot; max=&quot;.5&quot; step=&quot;.01&quot; value=&quot;.20&quot;&gt;&lt;\/div&gt;\n    &lt;\/div&gt;\n    &lt;div class=&quot;actions&quot;&gt;&lt;button id=&quot;arm&quot;&gt;\u25c9 Armer espace&lt;\/button&gt;&lt;button class=&quot;primary&quot; id=&quot;atest&quot;&gt;\u25b6 Test&lt;\/button&gt;&lt;button id=&quot;astop&quot;&gt;\u25a0 Stop&lt;\/button&gt;&lt;div class=&quot;status&quot; id=&quot;as&quot;&gt;Arr\u00eat\u00e9&lt;\/div&gt;&lt;\/div&gt;\n    &lt;div class=&quot;space&quot;&gt;&lt;div class=&quot;spacekey&quot; id=&quot;spacekey&quot;&gt;BARRE ESPACE&lt;\/div&gt;&lt;div class=&quot;smallnote&quot; id=&quot;spacestatus&quot;&gt;Barre espace d\u00e9sarm\u00e9e.&lt;\/div&gt;&lt;\/div&gt;\n  &lt;\/div&gt;\n&lt;\/section&gt;\n&lt;\/main&gt;\n\n&lt;footer&gt;&lt;span&gt;Laboratoire du son&lt;\/span&gt;&lt;span&gt;Web Audio \u00b7 autonome&lt;\/span&gt;&lt;\/footer&gt;\n&lt;\/div&gt;\n\n&lt;script&gt;\n(function(){\n&quot;use strict&quot;;\nconst root=document.querySelector(&quot;#vls26[data-vls-root]&quot;);\nif(!root)return;\nconst $=id=&gt;root.querySelector(&quot;#&quot;+CSS.escape(id));\n\nlet ctx=null,active=null;\nfunction audio(){\n  if(!ctx)ctx=new (window.AudioContext||window.webkitAudioContext)();\n  if(ctx.state===&quot;suspended&quot;)ctx.resume();\n  return ctx;\n}\nfunction status(id,text,on=false){$(id).textContent=text;$(id).classList.toggle(&quot;on&quot;,on)}\nfunction fmt(n,d=2){return Number(n).toFixed(d)}\nfunction stopAll(except){\n  if(except!==&quot;prop&quot;)stopProp();\n  if(except!==&quot;room&quot;)stopRoom();\n  if(except!==&quot;harm&quot;)stopHarm();\n  if(except!==&quot;adsr&quot;)releaseADSR(true);\n}\ndocument.addEventListener(&quot;pointerdown&quot;,()=&gt;{if(ctx&amp;&amp;ctx.state===&quot;suspended&quot;)ctx.resume()},{passive:true});\n\n\/* 01 PROPAGATION *\/\nconst pc=$(&quot;prop&quot;),px=pc.getContext(&quot;2d&quot;),pf=$(&quot;pf&quot;),pa=$(&quot;pa&quot;);\nlet po=null,pg=null,pan=null;\nfunction propLabels(){$(&quot;pfv&quot;).textContent=Math.round(pf.value)+&quot; Hz&quot;;$(&quot;pav&quot;).textContent=Math.round(pa.value*100)+&quot;%&quot;}\nfunction startProp(){\n  stopAll(&quot;prop&quot;);const c=audio();\n  po=c.createOscillator();pg=c.createGain();pan=c.createAnalyser();\n  po.type=&quot;sine&quot;;po.frequency.value=+pf.value;pg.gain.value=+pa.value*.14;\n  pan.fftSize=1024;po.connect(pg).connect(pan).connect(c.destination);po.start();active=&quot;prop&quot;;\n  status(&quot;ps&quot;,&quot;En cours \u2014 &quot;+Math.round(pf.value)+&quot; Hz&quot;,true);\n}\nfunction stopProp(){\n  if(po){try{po.stop()}catch(e){}try{po.disconnect()}catch(e){}}\n  po=null;pg=null;pan=null;if(active===&quot;prop&quot;)active=null;status(&quot;ps&quot;,&quot;Arr\u00eat\u00e9&quot;);\n}\npf.oninput=()=&gt;{propLabels();if(po)po.frequency.setTargetAtTime(+pf.value,ctx.currentTime,.015)};\npa.oninput=()=&gt;{propLabels();if(pg)pg.gain.setTargetAtTime(+pa.value*.14,ctx.currentTime,.015)};\n$(&quot;pplay&quot;).onclick=startProp;$(&quot;pstop&quot;).onclick=stopProp;propLabels();\n\nfunction drawProp(t){\n  const w=pc.width,h=pc.height;px.fillStyle=&quot;#08090c&quot;;px.fillRect(0,0,w,h);\n  const f=+pf.value,a=+pa.value,tt=t*.001;\n  const cy=h*.56,rows=7,cols=76,left=55,right=w-55,span=right-left;\n  const cycles=1.2+(f-60)\/(900-60)*4.8,k=2*Math.PI*cycles\/span;\n  px.strokeStyle=&quot;#1c1d24&quot;;px.beginPath();px.moveTo(left,cy);px.lineTo(right,cy);px.stroke();\n  for(let r=0;r&lt;rows;r++){\n    const y=cy+(r-(rows-1)\/2)*24;\n    for(let i=0;i&lt;cols;i++){\n      const base=left+i*span\/(cols-1);\n      const phase=k*base-2*Math.PI*f*tt*.0012;\n      const s=Math.sin(phase),disp=s*a*15,local=.5+.5*Math.cos(phase);\n      const rad=2.5+1.7*local*a,alpha=.30+.70*local;\n      px.fillStyle=`rgba(244,244,246,${alpha})`;px.beginPath();px.arc(base+disp,y,rad,0,Math.PI*2);px.fill();\n    }\n  }\n  px.beginPath();\n  for(let x=left;x&lt;=right;x+=3){\n    const phase=k*x-2*Math.PI*f*tt*.0012,y=cy-105-Math.sin(phase)*a*38;\n    x===left?px.moveTo(x,y):px.lineTo(x,y);\n  }\n  px.strokeStyle=&quot;#918bff&quot;;px.lineWidth=2;px.stroke();\n  px.fillStyle=&quot;#8a8c96&quot;;px.font=&quot;11px Arial&quot;;px.fillText(&quot;COMPRESSION&quot;,left,27);px.fillText(&quot;RAR\u00c9FACTION&quot;,right-105,27);\n  requestAnimationFrame(drawProp);\n}\nrequestAnimationFrame(drawProp);\n\n\/* 02 SALLE \u2014 bloc valid\u00e9 *\/\nconst rc=$(&quot;room&quot;),rx=rc.getContext(&quot;2d&quot;),rsize=$(&quot;rsize&quot;),mat=$(&quot;mat&quot;),rv=$(&quot;rv&quot;);\nconst impulseBtn=$(&quot;impulseBtn&quot;),sampleBtn=$(&quot;sampleBtn&quot;);\nconst SAMPLE_URL=&quot;https:\/\/lucasgoret.com\/wp-content\/uploads\/2026\/09\/Voix-homme.wav&quot;;\nconst materials={\n  curtain:{label:&quot;Rideaux \u00e9pais&quot;,reflection:.18,rtBase:.26,damp:4200,fill:&quot;#32151d&quot;,stroke:&quot;#8d3447&quot;,accent:&quot;#b84a60&quot;},\n  wood:{label:&quot;Bois&quot;,reflection:.48,rtBase:.52,damp:6900,fill:&quot;#2b211b&quot;,stroke:&quot;#8c674f&quot;,accent:&quot;#b88767&quot;},\n  plaster:{label:&quot;Pl\u00e2tre&quot;,reflection:.62,rtBase:.72,damp:9200,fill:&quot;#d8d7d2&quot;,stroke:&quot;#f2f1ec&quot;,accent:&quot;#ffffff&quot;},\n  concrete:{label:&quot;B\u00e9ton&quot;,reflection:.78,rtBase:1.05,damp:12500,fill:&quot;#373b42&quot;,stroke:&quot;#878d97&quot;,accent:&quot;#a7adb7&quot;},\n  glass:{label:&quot;Verre&quot;,reflection:.88,rtBase:1.22,damp:15500,fill:&quot;#142730&quot;,stroke:&quot;#68abc9&quot;,accent:&quot;#8ed6f5&quot;}\n};\nlet roomMode=&quot;sample&quot;,sampleBuffer=null,roomSource=null,pulseTimer=null;\nlet dry=null,wet=null,conv=null,lowpass=null,roomMaster=null;\nlet roomPlaying=false,roomStartedAt=0,roomOffset=0,roomTimer=null;\n\nfunction roomDims(){\n  const t=+rsize.value;\n  const width=4.5+t*8.5,depth=4+t*6.5;\n  return {t,width,depth,area:width*depth};\n}\nfunction roomLabels(){\n  $(&quot;rsv&quot;).textContent=Math.round(roomDims().area)+&quot; m\u00b2&quot;;\n  $(&quot;rvv&quot;).textContent=Math.round(+rv.value*100)+&quot;%&quot;;\n}\nfunction roomRect(){\n  const w=rc.width,h=rc.height,t=roomDims().t;\n  const rw=w*(.42+.40*t),rh=h*(.42+.34*t);\n  return {x:(w-rw)\/2,y:(h-rh)\/2,w:rw,h:rh};\n}\nfunction roomPositions(){\n  const t=roomDims().t;\n  return {s:{x:.34-.12*t,y:.59+.04*t},l:{x:.66+.12*t,y:.45-.03*t}};\n}\nfunction project(p,r){return{x:r.x+p.x*r.w,y:r.y+p.y*r.h}}\nfunction drawWave(cx,cy,r,a1,a2,alpha,width=1.6){\n  rx.strokeStyle=`rgba(145,139,255,${alpha})`;rx.lineWidth=width;\n  rx.beginPath();rx.arc(cx,cy,r,a1,a2);rx.stroke();\n}\nfunction roundRect(g,x,y,w,h,r,fill,stroke){\n  g.beginPath();g.moveTo(x+r,y);g.arcTo(x+w,y,x+w,y+h,r);g.arcTo(x+w,y+h,x,y+h,r);g.arcTo(x,y+h,x,y,r);g.arcTo(x,y,x+w,y,r);\n  if(fill)g.fill();if(stroke)g.stroke();\n}\nfunction drawSource(x,y){\n  rx.save();rx.translate(x,y);\n  rx.fillStyle=&quot;#111318&quot;;rx.strokeStyle=&quot;#f4f4f6&quot;;rx.lineWidth=2;\n  roundRect(rx,-18,-26,36,52,7,true,true);\n  rx.beginPath();rx.arc(0,-9,7,0,Math.PI*2);rx.stroke();\n  rx.beginPath();rx.arc(0,10,11,0,Math.PI*2);rx.stroke();\n  rx.fillStyle=&quot;#918bff&quot;;rx.beginPath();rx.arc(0,10,3.5,0,Math.PI*2);rx.fill();\n  rx.restore();\n}\nfunction drawListener(x,y){\n  rx.save();rx.translate(x,y);rx.strokeStyle=&quot;#f4f4f6&quot;;rx.lineWidth=3;\n  rx.beginPath();rx.arc(0,0,17,0,Math.PI*2);rx.stroke();\n  rx.beginPath();rx.arc(0,0,6,0,Math.PI*2);rx.stroke();rx.restore();\n}\nfunction drawRoom(){\n  const w=rc.width,h=rc.height;rx.fillStyle=&quot;#08090c&quot;;rx.fillRect(0,0,w,h);\n  const glow=rx.createRadialGradient(w*.5,h*.5,40,w*.5,h*.5,w*.55);\n  glow.addColorStop(0,&quot;rgba(145,139,255,.09)&quot;);glow.addColorStop(1,&quot;rgba(0,0,0,0)&quot;);\n  rx.fillStyle=glow;rx.fillRect(0,0,w,h);\n  const r=roomRect(),m=materials[mat.value],t=roomDims().t;\n  rx.fillStyle=m.fill;rx.globalAlpha=.17;rx.fillRect(r.x,r.y,r.w,r.h);rx.globalAlpha=1;\n  rx.strokeStyle=m.stroke;rx.lineWidth=14;rx.strokeRect(r.x,r.y,r.w,r.h);\n  rx.strokeStyle=&quot;rgba(255,255,255,.10)&quot;;rx.lineWidth=1;rx.strokeRect(r.x+8,r.y+8,r.w-16,r.h-16);\n  rx.save();rx.globalAlpha=.09;rx.strokeStyle=&quot;#8a8d98&quot;;rx.lineWidth=1;\n  for(let i=1;i&lt;5;i++){rx.beginPath();rx.moveTo(r.x+r.w*i\/5,r.y);rx.lineTo(r.x+r.w*i\/5,r.y+r.h);rx.stroke()}\n  for(let i=1;i&lt;4;i++){rx.beginPath();rx.moveTo(r.x,r.y+r.h*i\/4);rx.lineTo(r.x+r.w,r.y+r.h*i\/4);rx.stroke()}\n  rx.restore();\n\n  const pos=roomPositions(),s=project(pos.s,r),l=project(pos.l,r);\n  rx.strokeStyle=&quot;rgba(244,244,246,.48)&quot;;rx.lineWidth=1.5;rx.beginPath();rx.moveTo(s.x,s.y);rx.lineTo(l.x,l.y);rx.stroke();\n  const angle=Math.atan2(l.y-s.y,l.x-s.x);\n  for(let i=1;i&lt;=4;i++)drawWave(s.x,s.y,28+i*28,angle-.72,angle+.72,.42-i*.055,1.8);\n\n  const refl=.20+m.reflection*.55;\n  const walls=[\n    {x:r.x+7,y:s.y,a1:-.55,a2:.55},\n    {x:r.x+r.w-7,y:l.y,a1:Math.PI-.55,a2:Math.PI+.55},\n    {x:(s.x+l.x)\/2,y:r.y+7,a1:.22,a2:Math.PI-.22},\n    {x:(s.x+l.x)\/2,y:r.y+r.h-7,a1:Math.PI+.22,a2:Math.PI*2-.22}\n  ];\n  walls.forEach(wall=&gt;{\n    for(let i=0;i&lt;3;i++)drawWave(wall.x,wall.y,24+i*(28+9*t),wall.a1,wall.a2,refl*(1-i*.18),1.45);\n  });\n  rx.fillStyle=m.accent;rx.globalAlpha=.7;\n  walls.forEach(wall=&gt;{rx.beginPath();rx.arc(wall.x,wall.y,3.5,0,Math.PI*2);rx.fill()});\n  rx.globalAlpha=1;\n  drawSource(s.x,s.y);drawListener(l.x,l.y);\n  rx.fillStyle=&quot;#f4f4f6&quot;;rx.font=&quot;700 18px Arial&quot;;rx.textAlign=&quot;center&quot;;\n  rx.fillText(&quot;SOURCE&quot;,s.x,s.y+48);rx.fillText(&quot;AUDITEUR&quot;,l.x,l.y+48);rx.textAlign=&quot;left&quot;;\n  requestAnimationFrame(drawRoom);\n}\nrequestAnimationFrame(drawRoom);\n\nasync function ensureSample(){\n  const c=audio();\n  if(roomMode===&quot;sample&quot;&amp;&amp;!sampleBuffer){\n    status(&quot;rs&quot;,&quot;Chargement de la voix\u2026&quot;);\n    const res=await fetch(SAMPLE_URL,{mode:&quot;cors&quot;});\n    if(!res.ok)throw new Error(&quot;sample&quot;);\n    sampleBuffer=await c.decodeAudioData(await res.arrayBuffer());\n  }\n}\nfunction roomIR(){\n  const c=audio(),m=materials[mat.value],d=roomDims(),scale=Math.sqrt(d.area\/24);\n  const rt=Math.max(.12,Math.min(3.6,m.rtBase*scale));\n  const len=Math.max(1,Math.floor(c.sampleRate*rt)),ir=c.createBuffer(2,len,c.sampleRate);\n  for(let ch=0;ch&lt;2;ch++){\n    const arr=ir.getChannelData(ch);\n    for(let i=0;i&lt;len;i++){\n      const tt=i\/len,decay=Math.pow(1-tt,2.2+(1-m.reflection)*4.6);\n      arr[i]=(Math.random()*2-1)*decay*(.42+.40*m.reflection);\n    }\n    [d.width*.52,d.depth*.62,d.width*.88,d.depth*1.02].forEach((meters,k)=&gt;{\n      const idx=Math.min(len-1,Math.floor((meters\/343)*c.sampleRate));\n      arr[idx]+=m.reflection*(.68-k*.10);\n    });\n  }\n  return{ir,rt};\n}\nfunction buildRoomGraph(){\n  const c=audio(),m=materials[mat.value],pack=roomIR(),d=roomDims();\n  dry=c.createGain();wet=c.createGain();conv=c.createConvolver();lowpass=c.createBiquadFilter();roomMaster=c.createGain();\n  conv.buffer=pack.ir;lowpass.type=&quot;lowpass&quot;;lowpass.frequency.value=m.damp;\n  const wetAmt=Math.max(.10,Math.min(.92,.14+m.reflection*.52+Math.sqrt(d.area\/120)*.18));\n  dry.gain.value=1-wetAmt*.47;wet.gain.value=wetAmt;roomMaster.gain.value=+rv.value*.9;\n  dry.connect(roomMaster);conv.connect(lowpass).connect(wet).connect(roomMaster);roomMaster.connect(c.destination);\n  return pack.rt;\n}\nfunction startSample(pos=0){\n  const c=audio();\n  roomSource=c.createBufferSource();roomSource.buffer=sampleBuffer;roomSource.loop=true;\n  roomSource.connect(dry);roomSource.connect(conv);\n  roomOffset=pos%sampleBuffer.duration;roomStartedAt=c.currentTime;roomSource.start(0,roomOffset);\n}\nfunction fireImpulse(){\n  if(!roomPlaying||roomMode!==&quot;impulse&quot;)return;\n  const c=audio(),length=Math.floor(c.sampleRate*.085),buf=c.createBuffer(1,length,c.sampleRate),data=buf.getChannelData(0);\n  for(let i=0;i&lt;length;i++)data[i]=(Math.random()*2-1)*Math.exp(-i\/(c.sampleRate*.018));\n  const src=c.createBufferSource(),g=c.createGain();g.gain.value=.72;src.buffer=buf;src.connect(g);g.connect(dry);g.connect(conv);src.start();\n}\nfunction startImpulse(){fireImpulse();pulseTimer=setInterval(fireImpulse,1450)}\nfunction disconnectRoom(){\n  if(roomSource){try{roomSource.disconnect()}catch(e){}roomSource=null}\n  [dry,wet,conv,lowpass,roomMaster].forEach(n=&gt;{if(n)try{n.disconnect()}catch(e){}});\n  dry=wet=conv=lowpass=roomMaster=null;\n}\nfunction stopRoom(reset=true){\n  if(pulseTimer){clearInterval(pulseTimer);pulseTimer=null}\n  if(roomSource&amp;&amp;roomSource.stop){try{roomSource.stop()}catch(e){}}\n  if(!reset&amp;&amp;roomMode===&quot;sample&quot;&amp;&amp;sampleBuffer&amp;&amp;ctx)roomOffset=(roomOffset+(ctx.currentTime-roomStartedAt))%sampleBuffer.duration;\n  disconnectRoom();roomPlaying=false;if(reset)roomOffset=0;if(active===&quot;room&quot;)active=null;status(&quot;rs&quot;,&quot;Arr\u00eat\u00e9&quot;);\n}\nasync function startRoom(){\n  stopAll(&quot;room&quot;);\n  try{\n    await ensureSample();\n    const rt=buildRoomGraph();roomPlaying=true;active=&quot;room&quot;;\n    roomMode===&quot;sample&quot;?startSample(roomOffset):startImpulse();\n    status(&quot;rs&quot;,`En cours \u2014 RT60 \u2248 ${rt.toFixed(2)} s`,true);\n  }catch(e){console.error(e);status(&quot;rs&quot;,&quot;Impossible de charger la voix&quot;)}\n}\nfunction rebuildRoom(){\n  if(!roomPlaying||!ctx)return;\n  clearTimeout(roomTimer);\n  roomTimer=setTimeout(async()=&gt;{\n    let pos=roomOffset;\n    if(roomMode===&quot;sample&quot;&amp;&amp;sampleBuffer)pos=(roomOffset+(ctx.currentTime-roomStartedAt))%sampleBuffer.duration;\n    if(pulseTimer){clearInterval(pulseTimer);pulseTimer=null}\n    if(roomSource&amp;&amp;roomSource.stop){try{roomSource.stop()}catch(e){}}\n    disconnectRoom();\n    const rt=buildRoomGraph();\n    roomMode===&quot;sample&quot;?startSample(pos):startImpulse();\n    roomPlaying=true;active=&quot;room&quot;;status(&quot;rs&quot;,`En cours \u2014 RT60 \u2248 ${rt.toFixed(2)} s`,true);\n  },60);\n}\nfunction setRoomMode(mode){\n  roomMode=mode;\n  impulseBtn.classList.toggle(&quot;active&quot;,mode===&quot;impulse&quot;);\n  sampleBtn.classList.toggle(&quot;active&quot;,mode===&quot;sample&quot;);\n  if(roomPlaying)rebuildRoom();\n}\nimpulseBtn.onclick=()=&gt;setRoomMode(&quot;impulse&quot;);\nsampleBtn.onclick=()=&gt;setRoomMode(&quot;sample&quot;);\nrsize.oninput=()=&gt;{roomLabels();rebuildRoom()};\nmat.onchange=()=&gt;{rebuildRoom()};\nrv.oninput=()=&gt;{roomLabels();if(roomMaster&amp;&amp;ctx)roomMaster.gain.setTargetAtTime(+rv.value*.9,ctx.currentTime,.03)};\n$(&quot;rplay&quot;).onclick=startRoom;$(&quot;rstop&quot;).onclick=()=&gt;stopRoom(true);roomLabels();\n\n\/* 03 HARMONIQUES *\/\nconst sc=$(&quot;string&quot;),sx2=sc.getContext(&quot;2d&quot;),cc=$(&quot;chladni&quot;),cx=cc.getContext(&quot;2d&quot;),fund=$(&quot;fund&quot;),hvol=$(&quot;hvol&quot;),hc=$(&quot;vls-harmonics&quot;);\nconst levels=[1,0,0,0,0,0,0,0],ho=[],hg=[];let hm=null,han=null;\nfor(let i=0;i&lt;8;i++){\n  const row=document.createElement(&quot;div&quot;);row.className=&quot;hrow&quot;;\n  row.innerHTML=`&lt;span&gt;H${i+1}&lt;\/span&gt;&lt;input type=&quot;range&quot; min=&quot;0&quot; max=&quot;1&quot; step=&quot;.01&quot; value=&quot;${levels[i]}&quot; data-h=&quot;${i}&quot;&gt;&lt;span class=&quot;hf&quot; id=&quot;hf${i}&quot;&gt;&lt;\/span&gt;`;\n  hc.appendChild(row);\n}\nfunction harmLabels(){\n  $(&quot;fv&quot;).textContent=Math.round(fund.value)+&quot; Hz&quot;;$(&quot;hv&quot;).textContent=Math.round(hvol.value*100)+&quot;%&quot;;\n  root.querySelectorAll(&quot;[data-h]&quot;).forEach((e,i)=&gt;$(&quot;hf&quot;+i).textContent=Math.round(+fund.value*(i+1))+&quot; Hz&quot;);\n}\nfunction startHarm(){\n  stopAll(&quot;harm&quot;);const c=audio();hm=c.createGain();hm.gain.value=+hvol.value*.13;han=c.createAnalyser();han.fftSize=1024;hm.connect(han).connect(c.destination);\n  root.querySelectorAll(&quot;[data-h]&quot;).forEach((e,i)=&gt;{const o=c.createOscillator(),g=c.createGain();o.type=&quot;sine&quot;;o.frequency.value=+fund.value*(i+1);g.gain.value=+e.value;o.connect(g).connect(hm);o.start();ho[i]=o;hg[i]=g});\n  active=&quot;harm&quot;;status(&quot;hs&quot;,&quot;En cours \u2014 fondamentale &quot;+Math.round(fund.value)+&quot; Hz&quot;,true);\n}\nfunction stopHarm(){\n  ho.forEach(o=&gt;{if(o)try{o.stop()}catch(e){}});ho.length=0;\n  hg.forEach(g=&gt;{if(g)try{g.disconnect()}catch(e){}});hg.length=0;\n  [hm,han].forEach(n=&gt;{if(n)try{n.disconnect()}catch(e){}});\n  hm=han=null;if(active===&quot;harm&quot;)active=null;status(&quot;hs&quot;,&quot;Arr\u00eat\u00e9&quot;);\n}\nfund.oninput=()=&gt;{harmLabels();ho.forEach((o,i)=&gt;{if(o)o.frequency.setTargetAtTime(+fund.value*(i+1),ctx.currentTime,.015)})};\nhvol.oninput=()=&gt;{harmLabels();if(hm)hm.gain.setTargetAtTime(+hvol.value*.13,ctx.currentTime,.015)};\nroot.addEventListener(&quot;input&quot;,e=&gt;{if(e.target.matches(&quot;[data-h]&quot;)){const i=+e.target.dataset.h;if(hg[i]&amp;&amp;ctx)hg[i].gain.setTargetAtTime(+e.target.value,ctx.currentTime,.015)}});\n$(&quot;hplay&quot;).onclick=startHarm;$(&quot;hstop&quot;).onclick=stopHarm;harmLabels();\n\nfunction drawString(t){\n  const w=sc.width,h=sc.height,mid=h*.57,lev=[...root.querySelectorAll(&quot;[data-h]&quot;)].map(e=&gt;+e.value);\n  sx2.fillStyle=&quot;#08090c&quot;;sx2.fillRect(0,0,w,h);\n  sx2.strokeStyle=&quot;#1d1f26&quot;;sx2.beginPath();sx2.moveTo(0,mid);sx2.lineTo(w,mid);sx2.stroke();\n  sx2.beginPath();\n  for(let x=0;x&lt;=w;x++){\n    let y=0;lev.forEach((a,i)=&gt;y+=a*Math.sin(2*Math.PI*(i+1)*x\/w));\n    const py=mid-y*(han?55:38)*(.92+.08*Math.sin(t*.006));\n    x?sx2.lineTo(x,py):sx2.moveTo(x,py);\n  }\n  sx2.strokeStyle=&quot;#918bff&quot;;sx2.lineWidth=2;sx2.stroke();\n  requestAnimationFrame(drawString);\n}\nrequestAnimationFrame(drawString);\n\nfunction drawChladni(){\n  const w=cc.width,h=cc.height,lev=[...root.querySelectorAll(&quot;[data-h]&quot;)].map(e=&gt;+e.value),img=cx.createImageData(w,h);\n  for(let y=0;y&lt;h;y+=3)for(let x=0;x&lt;w;x+=3){\n    const nx=x\/w*2-1,ny=y\/h*2-1;let field=0;\n    lev.forEach((a,i)=&gt;{if(a&lt;.001)return;const n=i+1;field+=a*Math.cos(n*Math.PI*nx)*Math.cos((n+1)*Math.PI*ny)});\n    const node=Math.abs(field)&lt;.045;\n    for(let yy=0;yy&lt;3&amp;&amp;y+yy&lt;h;yy++)for(let xx=0;xx&lt;3&amp;&amp;x+xx&lt;w;xx++){\n      const k=((y+yy)*w+x+xx)*4;\n      if(node){img.data[k]=145;img.data[k+1]=139;img.data[k+2]=255}\n      else{img.data[k]=8;img.data[k+1]=9;img.data[k+2]=12}\n      img.data[k+3]=255;\n    }\n  }\n  cx.putImageData(img,0,0);requestAnimationFrame(drawChladni);\n}\nrequestAnimationFrame(drawChladni);\n\n\/* 04 ADSR *\/\nconst ac=$(&quot;adsr&quot;),ax=ac.getContext(&quot;2d&quot;),attack=$(&quot;attack&quot;),decay=$(&quot;decay&quot;),sustain=$(&quot;sustain&quot;),release=$(&quot;release&quot;),wave=$(&quot;wave&quot;),af=$(&quot;af&quot;),al=$(&quot;al&quot;);\nlet ao=null,ag=null,aan=null,adsrDown=false,armed=false,releaseTimer=null;\nfunction adsrLabels(){\n  $(&quot;av&quot;).textContent=fmt(attack.value)+&quot; s&quot;;$(&quot;dv&quot;).textContent=fmt(decay.value)+&quot; s&quot;;$(&quot;sv&quot;).textContent=Math.round(sustain.value*100)+&quot;%&quot;;$(&quot;relv&quot;).textContent=fmt(release.value)+&quot; s&quot;;\n  $(&quot;afv&quot;).textContent=Math.round(af.value)+&quot; Hz&quot;;$(&quot;alv&quot;).textContent=Math.round(+al.value*100)+&quot;%&quot;;\n}\n[attack,decay,sustain,release,af,al,wave].forEach(e=&gt;e.addEventListener(&quot;input&quot;,adsrLabels));adsrLabels();\nfunction envelopeVoice(){\n  stopAll(&quot;adsr&quot;);const c=audio();ao=c.createOscillator();ag=c.createGain();aan=c.createAnalyser();aan.fftSize=1024;\n  ao.type=wave.value;ao.frequency.value=+af.value;ao.connect(ag).connect(aan).connect(c.destination);\n  const now=c.currentTime,A=+attack.value,D=+decay.value,S=+sustain.value,V=+al.value;\n  ag.gain.cancelScheduledValues(now);ag.gain.setValueAtTime(0,now);ag.gain.linearRampToValueAtTime(V,now+A);ag.gain.linearRampToValueAtTime(V*S,now+A+D);\n  ao.start();adsrDown=true;active=&quot;adsr&quot;;status(&quot;as&quot;,&quot;En cours \u2014 appui \/ maintien&quot;,true);$(&quot;spacekey&quot;).classList.add(&quot;pressed&quot;);\n}\nfunction releaseADSR(silent=false){\n  if(!ao||!ctx){adsrDown=false;return}\n  const now=ctx.currentTime,R=+release.value;\n  ag.gain.cancelScheduledValues(now);ag.gain.setValueAtTime(Math.max(0,ag.gain.value),now);ag.gain.linearRampToValueAtTime(0,now+R);\n  try{ao.stop(now+R+.03)}catch(e){}\n  const old=ao;setTimeout(()=&gt;{try{old.disconnect()}catch(e){}},(R+.1)*1000);\n  ao=null;ag=null;aan=null;adsrDown=false;$(&quot;spacekey&quot;).classList.remove(&quot;pressed&quot;);if(active===&quot;adsr&quot;)active=null;if(!silent)status(&quot;as&quot;,&quot;Arr\u00eat\u00e9&quot;);\n}\nfunction testADSR(){envelopeVoice();clearTimeout(releaseTimer);releaseTimer=setTimeout(()=&gt;releaseADSR(false),(+attack.value+ +decay.value+.55)*1000)}\n$(&quot;atest&quot;).onclick=testADSR;$(&quot;astop&quot;).onclick=()=&gt;releaseADSR(false);\nfunction pressSpace(e){if(!armed||e.repeat)return;if(e.code===&quot;Space&quot;&amp;&amp;![&quot;INPUT&quot;,&quot;SELECT&quot;,&quot;TEXTAREA&quot;,&quot;BUTTON&quot;].includes(document.activeElement?.tagName)){e.preventDefault();if(!adsrDown)envelopeVoice()}}\nfunction releaseSpace(e){if(!armed)return;if(e.code===&quot;Space&quot;){e.preventDefault();if(adsrDown)releaseADSR(false)}}\nwindow.addEventListener(&quot;keydown&quot;,pressSpace);window.addEventListener(&quot;keyup&quot;,releaseSpace);\n$(&quot;arm&quot;).onclick=()=&gt;{armed=!armed;$(&quot;arm&quot;).classList.toggle(&quot;active&quot;,armed);$(&quot;spacestatus&quot;).textContent=armed?&quot;Barre espace arm\u00e9e : appuyer \/ maintenir \/ rel\u00e2cher.&quot;:&quot;Barre espace d\u00e9sarm\u00e9e.&quot;;if(!armed&amp;&amp;adsrDown)releaseADSR(false)};\n\nfunction drawADSR(){\n  const w=ac.width,h=ac.height;ax.fillStyle=&quot;#08090c&quot;;ax.fillRect(0,0,w,h);\n  const A=+attack.value,D=+decay.value,S=+sustain.value,R=+release.value,total=A+D+1.2+R,base=h-48,top=48;\n  ax.strokeStyle=&quot;#1d1f26&quot;;ax.beginPath();ax.moveTo(40,base);ax.lineTo(w-40,base);ax.stroke();\n  const pts=[[0,0],[A,1],[A+D,S],[A+D+1.2,S],[total,0]];\n  ax.beginPath();pts.forEach((p,i)=&gt;{const x=40+p[0]\/total*(w-80),y=base-p[1]*(base-top);i?ax.lineTo(x,y):ax.moveTo(x,y)});\n  ax.strokeStyle=&quot;#918bff&quot;;ax.lineWidth=2;ax.stroke();\n  ax.fillStyle=&quot;#7e8089&quot;;ax.font=&quot;11px Arial&quot;;ax.fillText(&quot;A&quot;,40+A\/total*(w-80)-3,base+22);ax.fillText(&quot;D&quot;,40+(A+D)\/total*(w-80)-3,base+22);ax.fillText(&quot;S&quot;,40+(A+D+.6)\/total*(w-80),base+22);ax.fillText(&quot;R&quot;,w-65,base+22);\n  requestAnimationFrame(drawADSR);\n}\nrequestAnimationFrame(drawADSR);\n})();\n&lt;\/script&gt;\n&lt;\/body&gt;\n&lt;\/html&gt;\"><\/iframe><div style=\"padding:10px 4px 0;color:var(--soft)!important;font-size:10px;text-align:right\">Laboratoire interactif \u00b7 Voir le son \u00b7 \u00a9 2026 Lucas Goret \u00b7 Tous droits r\u00e9serv\u00e9s.<\/div><\/div>\n    <\/section>\n\n    <section class=\"section\" id=\"bases\">\n      <div class=\"head\">\n        <div class=\"index\">04 \u2014 Pratique<\/div>\n        <div><h2 data-parallax=\"-0.02\">Fonctions<br>de base<\/h2><\/div>\n      <\/div>\n\n      <div class=\"basics-hero\">\n        <div class=\"principle\">\n          <p>L\u2019\u00e9dition en forme d\u2019onde est destructive&nbsp;: toute modification sera permanente \u00e0 la sauvegarde.<\/p>\n        <\/div>\n        <div class=\"basics-screen\">\n          <img decoding=\"async\" src=\"https:\/\/lucasgoret.com\/wp-content\/uploads\/2024\/10\/forme-d_onde_2.jpg\" alt=\"Interface du mode forme d\u2019onde dans Adobe Audition\">\n          <div class=\"media-caption\">Mode forme d\u2019onde \u00b7 Adobe Audition<\/div>\n        <\/div>\n      <\/div>\n\n      <div class=\"basics-note\"><p>Il faut donc au pr\u00e9alable faire une sauvegarde de tous les fichiers audio avant de commencer \u00e0 les manipuler.<\/p><\/div>\n\n      <h3 class=\"compact-subhead\" data-parallax=\"-0.010\">Prise en main<\/h3>\n\n      <div class=\"gesture-grid\">\n        <details data-gif=\"https:\/\/lucasgoret.com\/wp-content\/uploads\/2026\/09\/audition_drag_drop_01_clean.gif\">\n          <summary><div class=\"gesture-num\">01<\/div><div><div class=\"gesture-title\">Ouvrir un fichier<\/div><div class=\"gesture-desc\">Glisser et d\u00e9poser un fichier audio dans la fen\u00eatre principale.<\/div><\/div><div class=\"gesture-end\"><span class=\"gesture-key\">Drag & drop<\/span><span class=\"gesture-plus\">+<\/span><\/div><\/summary>\n          <div class=\"gesture-media\"><div class=\"gesture-frame\"><img alt=\"D\u00e9monstration : ouvrir un fichier dans Adobe Audition\"><\/div><\/div>\n        <\/details>\n\n        <details data-gif=\"https:\/\/lucasgoret.com\/wp-content\/uploads\/2026\/09\/audition_play_verified_clean.gif\">\n          <summary><div class=\"gesture-num\">02<\/div><div><div class=\"gesture-title\">Lire<\/div><div class=\"gesture-desc\">Lancer ou arr\u00eater la lecture du fichier.<\/div><\/div><div class=\"gesture-end\"><span class=\"gesture-key\">Espace<\/span><span class=\"gesture-plus\">+<\/span><\/div><\/summary>\n          <div class=\"gesture-media\"><div class=\"gesture-frame\"><img alt=\"D\u00e9monstration : lecture dans Adobe Audition\"><\/div><\/div>\n        <\/details>\n\n        <details data-gif=\"https:\/\/lucasgoret.com\/wp-content\/uploads\/2026\/09\/01_audition_zoom_son_clean.gif\">\n          <summary><div class=\"gesture-num\">03<\/div><div><div class=\"gesture-title\">Zoomer dans le son<\/div><div class=\"gesture-desc\">Utiliser la molette sur les graduations pour agrandir ou r\u00e9duire la vue.<\/div><\/div><div class=\"gesture-end\"><span class=\"gesture-key\">Molette<\/span><span class=\"gesture-plus\">+<\/span><\/div><\/summary>\n          <div class=\"gesture-media\"><div class=\"gesture-frame\"><img alt=\"D\u00e9monstration : zoom dans Adobe Audition\"><\/div><\/div>\n        <\/details>\n\n        <details data-gif=\"https:\/\/lucasgoret.com\/wp-content\/uploads\/2026\/09\/02_audition_selection_portion_clean.gif\">\n          <summary><div class=\"gesture-num\">04<\/div><div><div class=\"gesture-title\">S\u00e9lectionner une portion<\/div><div class=\"gesture-desc\">Cliquer et glisser sur la forme d\u2019onde pour isoler une zone de travail.<\/div><\/div><div class=\"gesture-end\"><span class=\"gesture-key\">Cliquer \u00b7 glisser<\/span><span class=\"gesture-plus\">+<\/span><\/div><\/summary>\n          <div class=\"gesture-media\"><div class=\"gesture-frame\"><img alt=\"D\u00e9monstration : s\u00e9lectionner une portion audio dans Adobe Audition\"><\/div><\/div>\n        <\/details>\n\n        <details data-gif=\"https:\/\/lucasgoret.com\/wp-content\/uploads\/2026\/09\/03_audition_lecture_boucle_clean.gif\">\n          <summary><div class=\"gesture-num\">05<\/div><div><div class=\"gesture-title\">Lire en boucle<\/div><div class=\"gesture-desc\">R\u00e9p\u00e9ter automatiquement la portion s\u00e9lectionn\u00e9e.<\/div><\/div><div class=\"gesture-end\"><span class=\"gesture-key\">Ctrl + L<\/span><span class=\"gesture-plus\">+<\/span><\/div><\/summary>\n          <div class=\"gesture-media\"><div class=\"gesture-frame\"><img alt=\"D\u00e9monstration : lecture en boucle dans Adobe Audition\"><\/div><\/div>\n        <\/details>\n\n        <details data-gif=\"https:\/\/lucasgoret.com\/wp-content\/uploads\/2026\/09\/05_audition_recadrage_ctrl_t_clean.gif\">\n          <summary><div class=\"gesture-num\">06<\/div><div><div class=\"gesture-title\">Recadrage<\/div><div class=\"gesture-desc\">Garder la s\u00e9lection et supprimer tout le reste.<\/div><\/div><div class=\"gesture-end\"><span class=\"gesture-key\">Ctrl + T<\/span><span class=\"gesture-plus\">+<\/span><\/div><\/summary>\n          <div class=\"gesture-media\"><div class=\"gesture-frame\"><img alt=\"D\u00e9monstration : recadrage avec Ctrl + T dans Adobe Audition\"><\/div><\/div>\n        <\/details>\n      <\/div>\n\n      <h3 class=\"compact-subhead\" data-parallax=\"-0.010\">Outils<\/h3>\n      <div class=\"steps tools-row\">\n        <div class=\"step tool-card\">\n      <div class=\"tool-icon\" aria-hidden=\"true\">\n        <svg viewBox=\"0 0 24 24\">\n          <path d=\"M8 4h8M12 4v16M8 20h8\"\/>\n          <path d=\"M10 7h4M10 17h4\" opacity=\".45\"\/>\n        <\/svg>\n      <\/div>\n      <b>S\u00e9lection temporelle (T)<\/b><p>Permet de s\u00e9lectionner une partie du son.<\/p>\n    <\/div>\n        <div class=\"step tool-card\">\n      <div class=\"tool-icon\" aria-hidden=\"true\">\n        <svg viewBox=\"0 0 24 24\"><rect x=\"5\" y=\"5\" width=\"14\" height=\"14\" rx=\"1.5\" stroke-dasharray=\"2.5 2.5\"\/><\/svg>\n      <\/div>\n      <b>Rectangle de s\u00e9lection (E)<\/b><p>S\u00e9lectionne une portion rectangulaire *<\/p>\n    <\/div>\n        <div class=\"step tool-card\">\n      <div class=\"tool-icon\" aria-hidden=\"true\">\n        <svg viewBox=\"0 0 24 24\"><path d=\"M4.5 11.5c0-4 3.8-7 8.2-7 4.1 0 6.8 2.4 6.8 5.3 0 3.4-3.8 5.5-8.2 5.5-2.6 0-4.8-.7-6.1-1.9\"\/><path d=\"M7.2 14.5 5.5 20l3.3-2.2\"\/><\/svg>\n      <\/div>\n      <b>Lasso (D)<\/b><p>Permet de dessiner un contour de forme et en faire une s\u00e9lection *<\/p>\n    <\/div>\n        <div class=\"step tool-card\">\n      <div class=\"tool-icon\" aria-hidden=\"true\">\n        <svg viewBox=\"0 0 24 24\">\n          <path d=\"M14.8 4.2c1.7-1.7 3.7-1.8 5-.5 1.3 1.3 1.2 3.3-.5 5l-7.1 7.1-4-4z\"\/>\n          <path d=\"M8.2 11.8c-1.2.2-2.1.8-2.7 1.8-.7 1.1-.5 2.2-1.4 3.3-.6.7-1.4 1.2-2.4 1.5 2.3 1.3 5.4 1.7 7.4.2 1.2-.9 1.7-2.1 1.5-3.3\"\/>\n          <path d=\"m12.7 6.3 5 5\" opacity=\".45\"\/>\n        <\/svg>\n      <\/div>\n      <b>Pinceau (P)<\/b><p>Permet de dessiner une forme avec un pinceau plus ou moins \u00e9pais *<\/p>\n    <\/div>\n      <\/div>\n      <p>* : uniquement sur le sonogramme.<\/p>\n\n      <div class=\"utility-panel\">\n        <section class=\"utility-col\">\n          <h3>Fonctions de volume<\/h3>\n          <div class=\"utility-list\">\n            <div class=\"utility-item\"><p><strong>R\u00e9glage du volume :<\/strong> cliquer et glisser vers le haut ou le bas.<\/p><\/div>\n            <div class=\"utility-item\"><p><strong>Fondu entrant \/ sortant (fade in\/out) :<\/strong> glisser le petit carr\u00e9 vers la gauche \/ droite pour la dur\u00e9e, haut \/ bas pour la forme de la courbe.<\/p><\/div>\n            <div class=\"utility-item\"><p><strong>Normalisation :<\/strong> Effets &gt; amplitude et compression &gt; normaliser. Ajuste le niveau g\u00e9n\u00e9ral du fichier afin que son pic le plus fort atteigne une valeur d\u00e9finie, sans modifier sa dynamique. \u21d2 Voir la section effets.<\/p><\/div>\n          <\/div>\n        <\/section>\n\n        <section class=\"utility-col\">\n          <h3>Fonctions d\u2019\u00e9dition<\/h3>\n          <div class=\"utility-list\">\n            <div class=\"utility-item\"><p><strong>Copier :<\/strong> ctrl + C \u00b7 <strong>Couper :<\/strong> ctrl + X \u00b7 <strong>Coller :<\/strong> ctrl + V<\/p><\/div>\n            <div class=\"utility-item\">\n              <p><strong>Mixer et coller :<\/strong> maj + ctrl + V. Une fen\u00eatre s\u2019ouvre avec plusieurs options.<\/p>\n              <details class=\"utility-details\">\n                <summary>Options de collage<\/summary>\n                <ul>\n                  <li>Ins\u00e9rer : colle \u00e0 l\u2019emplacement du curseur et d\u00e9cale le reste du son.<\/li>\n                  <li>Superposer : colle en m\u00e9langeant les deux sons.<\/li>\n                  <li>Remplacer : colle et \u00e9crase le son d\u2019origine.<\/li>\n                  <li>Moduler : comme \u00ab superposer \u00bb mais les donn\u00e9es sont multipli\u00e9es au lieu d\u2019\u00eatre additionn\u00e9es.<\/li>\n                  <li>R\u00e9glage des volumes du son existant et du son \u00e0 coller.<\/li>\n                  <li>Coller et boucler (x fois).<\/li>\n                <\/ul>\n              <\/details>\n            <\/div>\n            <div class=\"utility-item\"><p><strong>Recadrage :<\/strong> ctrl + T. Garde la s\u00e9lection et supprime le reste.<\/p><\/div>\n          <\/div>\n        <\/section>\n      <\/div>\n\n      <div class=\"card\" style=\"margin-top:16px\"><h3>Astuces pratiques<\/h3>\n        <p>Au premier lancement de Audition, voici quelques actions \u00e0 effectuer :<\/p>\n        <ul>\n          <li>Dans Windows, Panneau de configuration Son, onglet Lecture : double cliquer sur la sortie audio utilis\u00e9. Onglet Statistiques avanc\u00e9es, d\u00e9cocher les options d\u2019am\u00e9lioration du son.<\/li>\n          <li>Pr\u00e9f\u00e9rences &gt; Cache de m\u00e9dia et de disque : d\u00e9cocher \u00ab enregistrer les fichiers .pkf \u00bb.<\/li>\n          <li>Pr\u00e9f\u00e9rences &gt; Clips multipistes : cocher Synchroniser les clips avec l\u2019\u00e9diteur forme d\u2019onde, Fondu crois\u00e9 automatique, Mettre \u00e0 l\u2019\u00e9chelle l\u2019onde de forme. D\u00e9cocher Utiliser le code temporel incorpor\u00e9.<\/li>\n          <li>Afficher le rack d\u2019effets dans : Fen\u00eatre &gt; Rack d\u2019effets.<\/li>\n          <li>Masquer le panneau \u00ab audio essentiel \u00bb dans : Fen\u00eatre &gt; Audio essentiel.<\/li>\n          <li>Maj + X : modifie le comportement de la barre de lecture.<\/li>\n          <li>Il est possible (et recommand\u00e9) d\u2019enregistrer des actions favorites via Fen\u00eatre &gt; Favoris.<\/li>\n        <\/ul>\n      <\/div>\n    <\/section>\n\n    <section class=\"section\" id=\"representations\">\n      <div class=\"head\">\n        <div class=\"index\">05 \u2014 Lecture<\/div>\n        <div><h2 data-parallax=\"-0.02\">Repr\u00e9sentations<br>graphiques du son<\/h2><p class=\"intro\">Il existe trois possibilit\u00e9s de repr\u00e9sentations graphiques du son : la forme d\u2019onde, le spectre et le spectrogramme (ou sonogramme).<\/p><\/div>\n      <\/div>\n      <div class=\"principle-wide\"><p>Un m\u00eame son peut \u00eatre observ\u00e9 de plusieurs fa\u00e7ons selon ce que l\u2019on cherche \u00e0 comprendre.<\/p><\/div>\n      <div class=\"grid3\">\n        <article class=\"card\"><h3>La forme d\u2019onde<\/h3><p>La forme d\u2019onde repr\u00e9sente les variations d\u2019amplitude du signal dans le temps. Le temps est indiqu\u00e9 sur l\u2019axe horizontal, l\u2019amplitude sur l\u2019axe vertical.<\/p><p>On peut ainsi voir en un coup d\u2019\u0153il les parties du son dont le niveau est plus \u00e9lev\u00e9 que les autres.<\/p><p>Sur un son st\u00e9r\u00e9o, il y aura 2 formes, canal droit et canal gauche. Un son mono aura donc une seule forme.<\/p><\/article>\n        <article class=\"card\"><h3>Le spectre<\/h3><p>Le spectre repr\u00e9sente la r\u00e9partition des fr\u00e9quences contenues dans un son. Dans Audition, il peut \u00eatre observ\u00e9 en temps r\u00e9el pendant la lecture.<\/p><p>Sur l\u2019axe horizontal sont repr\u00e9sent\u00e9es les fr\u00e9quences, des graves \u00e0 gauche aux aigus \u00e0 droite, et sur l\u2019axe vertical leur amplitude. Cela permet de rep\u00e9rer les fr\u00e9quences dominantes ou probl\u00e9matiques et, au besoin, de les corriger avec un \u00e9galiseur.<\/p><\/article>\n        <article class=\"card\"><h3>Le spectrogramme<\/h3><p>Le spectrogramme (ou sonogramme) permet de visualiser simultan\u00e9ment le temps, les fr\u00e9quences et leur intensit\u00e9.<\/p><\/article>\n      <\/div>\n      <div class=\"grid3\" style=\"margin-top:16px\">\n        <div class=\"media\"><img decoding=\"async\" src=\"https:\/\/lucasgoret.com\/wp-content\/uploads\/2026\/09\/audition_forme-donde.gif\" alt=\"Forme d\u2019onde\"><\/div>\n        <div class=\"media\"><img decoding=\"async\" src=\"https:\/\/lucasgoret.com\/wp-content\/uploads\/2024\/10\/jazz3.gif\" alt=\"Spectre audio anim\u00e9\"><\/div>\n        <div class=\"media\"><img decoding=\"async\" src=\"https:\/\/lucasgoret.com\/wp-content\/uploads\/2026\/09\/Audition_vue-spectrale.gif\" alt=\"Spectrogramme de piano\"><\/div>\n      <\/div>\n    <\/section>\n\n    <section class=\"section\" id=\"effets\">\n      <div class=\"head\">\n        <div class=\"index\">06 \u2014 Traitement<\/div>\n        <div><h2 data-parallax=\"-0.02\">Effets<\/h2><p class=\"intro\">En mode forme d\u2019onde, nous allons appliquer uniquement des effets de base, notamment les op\u00e9rations de nettoyage, les ajustements de volume et normalisation, de lecture invers\u00e9e et de time-stretch, \u00e9ventuellement de l\u2019\u00e9galisation.<\/p><\/div>\n      <\/div>\n      <div class=\"principle-wide\"><p>Un effet peut \u00eatre appliqu\u00e9 de mani\u00e8re destructive ou rester modifiable avant d\u2019\u00eatre valid\u00e9.<\/p><\/div>\n      <div class=\"grid2\">\n        <div class=\"card fx-explainer\">\n          <div>\n            <p>Il y a deux mani\u00e8res d\u2019appliquer les effets :<\/p>\n            <ul>\n              <li><strong>Via le menu effets :<\/strong> les effets sont appliqu\u00e9s les uns apr\u00e8s les autres, en mode destructif. Certains effets s\u2019appliquent uniquement de cette mani\u00e8re, notamment la normalisation, le time-stretch, la lecture invers\u00e9e\u2026 On va donc appliquer ces effets en premier.<\/li>\n              <li><strong>Via le rack d\u2019effets :<\/strong> ici on a plus de contr\u00f4le sur les effets. Ils sont individuellement d\u00e9sactivables et modifiables sans destruction du son. Quand on est satisfait, il faut appliquer l\u2019effet ou les effets sur le son.<\/li>\n            <\/ul>\n          <\/div>\n\n          <div class=\"fx-legend\" aria-label=\"L\u00e9gende du rack d\u2019effets\">\n            <div class=\"fx-item\"><span class=\"fx-num\">1<\/span><span class=\"fx-text\">S\u00e9lection du module d\u2019effet. Une fen\u00eatre appara\u00eet avec les r\u00e9glages sp\u00e9cifiques \u00e0 l\u2019effet.<\/span><\/div>\n            <div class=\"fx-item\"><span class=\"fx-num\">2<\/span><span class=\"fx-text\">En double-cliquant sur le nom du module, on ouvre ses r\u00e9glages.<\/span><\/div>\n            <div class=\"fx-item\"><span class=\"fx-num\">3<\/span><span class=\"fx-text\">Activation \/ d\u00e9sactivation du module.<\/span><\/div>\n            <div class=\"fx-item\"><span class=\"fx-num\">4<\/span><span class=\"fx-text\">Activation \/ d\u00e9sactivation de tous les modules du rack.<\/span><\/div>\n            <div class=\"fx-item\"><span class=\"fx-num\">5<\/span><span class=\"fx-text\">R\u00e9gler la quantit\u00e9 globale d\u2019effet souhait\u00e9e sur le son (dry\/wet).<\/span><\/div>\n            <div class=\"fx-item\"><span class=\"fx-num\">6<\/span><span class=\"fx-text\">Appliquer d\u00e9finitivement les effets sur le fichier audio.<\/span><\/div>\n            <div class=\"fx-item\"><span class=\"fx-num\">7<\/span><span class=\"fx-text\">Sauvegarder ou ouvrir les r\u00e9glages.<\/span><\/div>\n          <\/div>\n        <\/div>\n        <div class=\"media\"><img decoding=\"async\" src=\"https:\/\/lucasgoret.com\/wp-content\/uploads\/2024\/10\/rack_FX.jpg\" alt=\"Rack d\u2019effets Adobe Audition\"><\/div>\n      <\/div>\n      <h3 class=\"subsection-title\" data-parallax=\"-0.010\">Quelques effets de base<\/h3>\n      <div class=\"effects\">\n        <div class=\"card\"><h3>Normalisation<\/h3><p>Effets &gt; Amplitude et compression &gt; Normaliser.<\/p><p>La normalisation permet d\u2019ajuster automatiquement le niveau g\u00e9n\u00e9ral d\u2019un fichier afin que son pic le plus fort atteigne une valeur d\u00e9finie.<\/p><p>Elle peut \u00eatre utile lorsqu\u2019un fichier est globalement trop faible ou pour pr\u00e9parer plusieurs sons avant le mixage. Pour nos exercices, on peut par exemple viser un pic situ\u00e9 entre \u201312 et \u20136 dBFS, afin de conserver une marge confortable pour le mixage final.<\/p><p>La normalisation ne modifie pas la dynamique du son : toutes les parties du signal sont augment\u00e9es ou diminu\u00e9es de la m\u00eame quantit\u00e9.<\/p><\/div>\n        <div class=\"media\"><img decoding=\"async\" src=\"https:\/\/lucasgoret.com\/wp-content\/uploads\/2024\/10\/normaliser.jpg\" alt=\"Normalisation dans Adobe Audition\"><\/div>\n        <div class=\"card\"><h3>Pitch<\/h3><p>Effets &gt; Temps et hauteur de ton &gt; Transpositeur. Permet de modifier la hauteur sans modifier la vitesse de lecture. Se r\u00e8gle en demi-tons.<\/p><\/div>\n        <div class=\"card\"><h3>Time-stretch<\/h3><p>Effets &gt; Temps et hauteur de ton &gt; Expansion et compression. Permet de ralentir ou acc\u00e9l\u00e9rer le son, en modifiant ou pas la hauteur.<\/p><\/div>\n        <div class=\"card\"><h3>Lecture invers\u00e9e<\/h3><p>Effets &gt; Retourner. Et non pas inverser, ce qui va inverser la phase, ce qui est tout \u00e0 fait autre chose. Permet de lire un son \u00e0 l\u2019envers.<\/p><\/div>\n      <\/div>\n    <\/section>\n\n    <section class=\"section\" id=\"egalisation\">\n      <div class=\"head\">\n        <div class=\"index\">07 \u2014 Fr\u00e9quences<\/div>\n        <div><h2 data-parallax=\"-0.02\">\u00c9galisation<\/h2><p class=\"intro\">L\u2019\u00e9galisateur (ou equalizer ou EQ) est un outil permettant d\u2019att\u00e9nuer ou amplifier des fr\u00e9quences ou plages de fr\u00e9quences pr\u00e9cises. Il existe plusieurs types d\u2019\u00e9galiseurs.<\/p><\/div>\n      <\/div>\n      <div class=\"accent-line\"><p>L\u2019\u00e9galisation permet d\u2019att\u00e9nuer ou d\u2019amplifier pr\u00e9cis\u00e9ment certaines fr\u00e9quences du son.<\/p><\/div>\n      <div class=\"grid2\">\n        <div class=\"card\"><h3>\u00c9galiseur param\u00e9trique<\/h3><p><em>Effets &gt; Filtre et Egaliseur &gt; Egaliseur param\u00e9trique<\/em><\/p><p>Cet effet permet une correction pr\u00e9cise des fr\u00e9quences. Par exemple, correctement r\u00e9gl\u00e9, il peut permettre d\u2019\u00e9liminer un sifflement qui se serait gliss\u00e9 dans l\u2019enregistrement, ou simuler l\u2019acoustique particuli\u00e8re d\u2019un t\u00e9l\u00e9phone sur une voix\u2026 Cet effet est r\u00e9guli\u00e8rement utilis\u00e9 pour le nettoyage, le mixage et le sound design.<\/p><\/div>\n        <div class=\"media\"><img decoding=\"async\" src=\"https:\/\/lucasgoret.com\/wp-content\/uploads\/2024\/10\/EQ-param-1024x668.jpg\" alt=\"\u00c9galiseur param\u00e9trique\"><\/div>\n        <div class=\"card\"><h3>\u00c9galiseur graphique<\/h3><p><em>Effets &gt; Filtre et \u00e9galiseur &gt; Egaliseur graphique<\/em><\/p><p>Cet \u00e9galiseur est compos\u00e9 de plusieurs faders correspondant chacun \u00e0 une plage de fr\u00e9quences. Au gauche les graves, au milieu les m\u00e9diums et \u00e0 droite les aigus. On peut voir en un coup d\u2019oeil la fa\u00e7on dont le son est modifi\u00e9.<\/p><\/div>\n        <div class=\"media\"><img decoding=\"async\" src=\"https:\/\/lucasgoret.com\/wp-content\/uploads\/2024\/10\/eq-graphique-1024x908.jpg\" alt=\"\u00c9galiseur graphique\"><\/div>\n      <\/div>\n      <h3 style=\"margin-top:42px!important\">Filtre<\/h3>\n      <p>Le filtre permet d\u2019att\u00e9nuer une partie des fr\u00e9quences du signal audio.<\/p>\n      <div class=\"grid3\">\n        <div class=\"card\"><h3>Filtre passe-haut<\/h3><p>Bouton \u00ab HP \u00bb sur l\u2019\u00e9galiseur param\u00e9trique.<\/p><p>Laisse passer les fr\u00e9quences situ\u00e9es au-dessus d\u2019une fr\u00e9quence d\u00e9finie et att\u00e9nue progressivement celles situ\u00e9es en dessous. Il peut par exemple servir \u00e0 retirer des fr\u00e9quences graves inutiles ou \u00e0 cr\u00e9er un effet de t\u00e9l\u00e9phone.<\/p><\/div>\n        <div class=\"card\"><h3>Filtre passe-bas<\/h3><p>Bouton \u00ab PB \u00bb sur l\u2019\u00e9galiseur param\u00e9trique.<\/p><p>Laisse passer les fr\u00e9quences situ\u00e9es en dessous d\u2019une fr\u00e9quence d\u00e9finie et att\u00e9nue progressivement celles situ\u00e9es au-dessus. Il peut par exemple servir \u00e0 cr\u00e9er un son \u00e9touff\u00e9 ou entendu \u00e0 travers une paroi.<\/p><\/div>\n        <div class=\"card\"><h3>Filtre passe-bande<\/h3><p>Laisse principalement passer une plage de fr\u00e9quences comprise entre deux limites et att\u00e9nue les fr\u00e9quences situ\u00e9es de part et d\u2019autre. Il peut par exemple servir \u00e0 imiter un son de radio ou de t\u00e9l\u00e9phone.<\/p><\/div>\n      <\/div>\n      <div class=\"grid3\" style=\"margin-top:16px\">\n        <div class=\"media\"><img decoding=\"async\" src=\"https:\/\/lucasgoret.com\/wp-content\/uploads\/2024\/10\/passe-haut-1024x668.jpg\" alt=\"Filtre passe-haut\"><\/div>\n        <div class=\"media\"><img decoding=\"async\" src=\"https:\/\/lucasgoret.com\/wp-content\/uploads\/2024\/10\/passe-bas-1024x668.jpg\" alt=\"Filtre passe-bas\"><\/div>\n        <div class=\"media\"><img decoding=\"async\" src=\"https:\/\/lucasgoret.com\/wp-content\/uploads\/2024\/10\/passe-bande-1024x668.jpg\" alt=\"Filtre passe-bande\"><\/div>\n      <\/div>\n    <\/section>\n\n    <section class=\"section\" id=\"voix\">\n      <div class=\"head\">\n        <div class=\"index\">08 \u2014 Voix<\/div>\n        <div><h2 data-parallax=\"-0.02\">R\u00e9ussir une prise<br>de son de voix<\/h2><\/div>\n      <\/div>\n      <div class=\"principle-wide\"><p>La qualit\u00e9 finale d\u00e9pend de l\u2019ensemble de la cha\u00eene de production.<\/p><\/div>\n      <div class=\"card\">\n        <h3>L\u2019enregistrement<\/h3>\n        <p>Lors d\u2019une prise de son, la pi\u00e8ce, le placement du microphone, la qualit\u00e9 du microphone et le r\u00e9glage du niveau d\u2019enregistrement ont tous une influence sur le r\u00e9sultat.<\/p>\n        <p>Un excellent microphone ne compensera pas une pi\u00e8ce tr\u00e8s r\u00e9verb\u00e9rante ou un mauvais placement, et les traitements effectu\u00e9s ensuite ne pourront jamais compl\u00e8tement r\u00e9parer une mauvaise prise de son.<\/p>\n        <p>La priorit\u00e9 est donc toujours d\u2019obtenir le meilleur son possible d\u00e8s l\u2019enregistrement.<\/p>\n        <p>Voici quelques astuces pour enregistrer sa voix pour un rendu raisonnable chez soi avec un t\u00e9l\u00e9phone et les moyens du bord.<\/p>\n        <ul>\n          <li>Pr\u00e9parez bien votre texte. Il vaut mieux enregistrer toutes les voix en une seule session, pour limiter les risques d\u2019incoh\u00e9rence.<\/li>\n          <li>Choisissez une pi\u00e8ce de taille moyenne, plut\u00f4t bien meubl\u00e9e, et avec le moins de r\u00e9verb\u00e9rations possible.<\/li>\n          <li>Placez vous de mani\u00e8re \u00e0 avoir une \u00e9tag\u00e8re de livres dans le dos.<\/li>\n          <li>Devant vous, suspendez une couette, un tapis ou un matelas, perpendiculaire au sol, et \u00e0 environ 1 m\u00e8tre de votre visage.<\/li>\n          <li>Tenez votre t\u00e9l\u00e9phone \u00e0 environ 20 \u00e0 30 cm de votre bouche et essayez de garder cette distance constante.<\/li>\n          <li>\u00c9vitez de souffler directement dans le microphone. Le placer l\u00e9g\u00e8rement de c\u00f4t\u00e9 ou parler l\u00e9g\u00e8rement hors axe peut r\u00e9duire les \u00ab P \u00bb, les \u00ab B \u00bb et les souffles trop importants.<\/li>\n          <li>Si votre application permet de r\u00e9gler le niveau d\u2019entr\u00e9e, r\u00e9glez-le suffisamment haut tout en gardant une marge pour \u00e9viter la saturation.<\/li>\n          <li>Faites toujours quelques essais avant de lancer l\u2019enregistrement final.<\/li>\n          <li>Compter jusqu\u2019\u00e0 3 dans sa t\u00eate apr\u00e8s avoir lancer l\u2019enregistrement et avant de le couper.<\/li>\n        <\/ul>\n      <\/div>\n\n      <div class=\"accent-line\"><p>Un traitement ne remplace jamais une bonne prise de son.<\/p><\/div>\n      <div class=\"grid2\" style=\"margin-top:16px\">\n        <div class=\"card\"><h3>Nettoyage du son dans Adobe Audition<\/h3>\n          <ul><li>Une fois le son import\u00e9, observer la forme d\u2019onde. Visuellement, rep\u00e9rez les anomalies : une toux, un souffle, une porte qui claque au loin. Supprimez tous les sons parasites, les silences au d\u00e9but et \u00e0 la fin, les \u00e9ventuels silences entre les interventions de voix.<\/li><li>Il y aura peut-\u00eatre un buzz ou un bourdonnement. Dans ce cas, utiliser <em>Effets &gt; R\u00e9duction \/ restauration du bruit &gt; R\u00e9duction du bruit (processus)<\/em>.<\/li><\/ul>\n          <p>S\u00e9lectionnez sur la forme d\u2019onde une portion qui ne contient QUE le bruit de fond que l\u2019on souhaite \u00e9liminer, puis choisissez \u00ab Capturer l\u2019impression du bruit \u00bb.<\/p>\n          <p>Audition analyse alors ce bruit afin d\u2019en d\u00e9terminer les caract\u00e9ristiques.<\/p>\n          <p>Ouvrez ensuite l\u2019effet <em>R\u00e9duction du bruit (processus)<\/em> et s\u00e9lectionnez le fichier entier.<\/p>\n          <p>Le graphique repr\u00e9sente le bruit d\u00e9tect\u00e9 selon les fr\u00e9quences. La courbe bleue permet de modifier la quantit\u00e9 de r\u00e9duction appliqu\u00e9e aux diff\u00e9rentes fr\u00e9quences : elle n\u2019a pas besoin de suivre la forme du bruit.<\/p>\n          <p>Pour commencer, laissez-la relativement uniforme et ajustez surtout la quantit\u00e9 de r\u00e9duction en \u00e9coutant le r\u00e9sultat.<\/p>\n          <p><strong>Attention :<\/strong> une r\u00e9duction trop importante peut cr\u00e9er des artefacts et rendre la voix artificielle.<\/p>\n        <\/div>\n        <div class=\"grid2\">\n          <div class=\"media\"><img decoding=\"async\" src=\"https:\/\/lucasgoret.com\/wp-content\/uploads\/2024\/10\/reduction_bruit_1-993x1024.png\" alt=\"R\u00e9duction du bruit \u00e9tape 1\"><\/div>\n          <div class=\"media\"><img decoding=\"async\" src=\"https:\/\/lucasgoret.com\/wp-content\/uploads\/2024\/10\/reduction_bruit_2-988x1024.png\" alt=\"R\u00e9duction du bruit \u00e9tape 2\"><\/div>\n        <\/div>\n      <\/div>\n\n      <div class=\"grid2\" style=\"margin-top:16px\">\n        <div class=\"card\"><h3>Am\u00e9lioration du son dans Adobe Audition<\/h3>\n          <ul>\n            <li>S\u2019il y a de la r\u00e9verb\u00e9ration g\u00eanante dans la prise de son, on peut utiliser l\u2019effet <em>Effets &gt; R\u00e9duction \/ restauration du bruit &gt; DeReverb.<\/em> Attention au dosage : trop de traitement peut rendre la voix artificielle.<\/li>\n            <li>Pour r\u00e9duire la dynamique et obtenir une voix plus r\u00e9guli\u00e8re, utiliser un <strong>compresseur<\/strong>. Apr\u00e8s compression, ajuster si n\u00e9cessaire le gain de sortie. Pour nos exercices, des cr\u00eates situ\u00e9es approximativement entre \u201312 et \u20139 dBFS constituent un rep\u00e8re simple avant le mixage.<\/li>\n            <li>Utiliser \u00e9ventuellement un <strong>\u00e9galiseur<\/strong>. Un coupe-bas situ\u00e9 approximativement entre 80 et 120 Hz peut permettre de retirer les fr\u00e9quences graves inutiles. Ajustez toujours \u00e0 l\u2019\u00e9coute pour ne pas enlever le corps de la voix.<\/li>\n            <li>Ne pas h\u00e9siter \u00e0 tester les <strong>presets de l\u2019\u00e9galiseur param\u00e9trique<\/strong>, notamment ceux destin\u00e9s \u00e0 la voix, puis \u00e0 les adapter au r\u00e9sultat souhait\u00e9.<\/li>\n            <li>Vous pouvez \u00e9galement essayer <em>Effets &gt; Sp\u00e9cial &gt; Exhausteur vocal.<\/em><\/li>\n          <\/ul>\n          <p>A ce stade, votre son devrait \u00eatre plus propre. Il existe cependant 2 autres m\u00e9thodes pour nettoyer une voix :<\/p>\n          <p><strong>Le panneau Audio Essentiel<\/strong><\/p>\n          <p>Afficher le panneau ici : <em>Fen\u00eatre &gt; Audio essentiel<\/em><\/p>\n          <p><strong>Ce panneau est disponible uniquement en mode multipiste<\/strong><\/p>\n          <p>Ce panneau nous permet d\u2019appliquer des effets et des traitements rapides en fonction des r\u00f4les de chaque clip.<\/p>\n          <p>On s\u00e9lectionne un clip, puis on s\u00e9lectionne, dans le panneau Audio essentiel, ce \u00e0 quoi correspond le clip : dialogue, musique, effets sonores (bruitages et sound design) et ambiance.<\/p>\n          <p>Audition nous propose ensuite divers effets d\u00e9di\u00e9s \u00e0 chaque cat\u00e9gorie de son, avec des presets appropri\u00e9s.<\/p>\n          <p>Bien que cette m\u00e9thode soit tr\u00e8s simple et convienne \u00e0 la plupart des utilisations communes, nous n\u2019avons pas toujours le r\u00e9glage id\u00e9al que l\u2019on voudrait. Il convient alors d\u2019utiliser les m\u00e9thodes \u00ab manuelles \u00bb.<\/p>\n        <\/div>\n        <div class=\"media\"><img decoding=\"async\" src=\"https:\/\/lucasgoret.com\/wp-content\/uploads\/2024\/10\/audio-essentiel.png\" alt=\"Panneau Audio Essentiel\"><\/div>\n      <\/div>\n    <\/section>\n\n    <section class=\"section\" id=\"liens\">\n      <div class=\"footer-index\">\n        <div class=\"footer-index-head\">\n          <div class=\"eyebrow\">Index pratique<\/div>\n          <div><h2>Liens utiles<\/h2><p class=\"intro\">Des ressources \u00e0 garder sous la main pour chercher des sons, de la musique et nettoyer rapidement une voix.<\/p><\/div>\n        <\/div>\n\n        <div class=\"footer-groups\">\n          <div class=\"footer-group\">\n            <h3>Banques de son gratuites<\/h3>\n            <a href=\"https:\/\/freesound.org\/\" target=\"_blank\" rel=\"noopener\">Freesound<\/a>\n            <a href=\"https:\/\/lasonotheque.org\/\" target=\"_blank\" rel=\"noopener\">La sonoth\u00e8que<\/a>\n            <a href=\"https:\/\/quicksounds.com\/\" target=\"_blank\" rel=\"noopener\">Quick sounds<\/a>\n            <a href=\"https:\/\/sound-effects.bbcrewind.co.uk\/\" target=\"_blank\" rel=\"noopener\">Banque de la BBC<\/a>\n            <a href=\"https:\/\/www.universal-soundbank.com\/\" target=\"_blank\" rel=\"noopener\">Universal soundbank<\/a>\n          <\/div>\n\n          <div class=\"footer-group\">\n            <h3>Musiques libres de droits<\/h3>\n            <a href=\"https:\/\/studio.youtube.com\" target=\"_blank\" rel=\"noopener\">Youtube Studio<\/a>\n            <a href=\"https:\/\/pixabay.com\/music\/\" target=\"_blank\" rel=\"noopener\">Pixabay<\/a>\n            <a href=\"https:\/\/freepd.com\/\" target=\"_blank\" rel=\"noopener\">FreePD<\/a>\n            <a href=\"https:\/\/musopen.org\/\" target=\"_blank\" rel=\"noopener\">Musopen<\/a>\n            <a href=\"https:\/\/www.auboutdufil.com\/\" target=\"_blank\" rel=\"noopener\">Au bout du fil<\/a>\n          <\/div>\n\n          <div class=\"footer-group\">\n            <h3>Nettoyage des voix<\/h3>\n            <a href=\"https:\/\/podcast.adobe.com\/enhance\" target=\"_blank\" rel=\"noopener\">Adobe Podcast \u00b7 Enhance Speech<\/a>\n          <\/div>\n        <\/div>\n\n        <div class=\"footer-note\">\n          <p><strong>Toujours v\u00e9rifier les licences.<\/strong><\/p>\n          <p>On trouve \u00e9galement des tonnes de sons sur YouTube. Les sons peuvent \u00eatre t\u00e9l\u00e9charg\u00e9s avec un outil en ligne.<\/p>\n          <p>Dans la mesure du possible, faire les recherches en anglais pour plus de r\u00e9sultats.<\/p>\n          <p>Utiliser les termes vus dans le \u00ab vocabulaire du sound design \u00bb, essayer en ajoutant les termes \u00ab SFX \u00bb ou \u00ab cinematic \u00bb pour tout ce qui est sound design, et \u00ab foley \u00bb pour tout ce qui est bruitage.<\/p>\n        <\/div>\n      <\/div>\n    <\/section>\n  <\/main>\n\n  <div class=\"shell\">\n    <section class=\"final-card\"><h2>Voir.<br>Comprendre.<br>Manipuler.<\/h2><\/section>\n    <footer class=\"site-footer\"><span>Audition \u00b7 Forme d\u2019onde \u00b7 Cours 02<\/span><span>\u00a9 2026 Lucas Goret \u00b7 Tous droits r\u00e9serv\u00e9s.<\/span><\/footer>\n  <\/div>\n<\/div>\n\n<script>\n(function(){\n  const page=document.getElementById(\"au26\");\n  const theme=document.getElementById(\"auTheme\");\n  if(theme)theme.addEventListener(\"click\",()=>page.classList.toggle(\"light\"));\n\n  const reduced=window.matchMedia&&window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n\n  \/* M\u00eame logique de parallaxe que la page 1 :\n     hero plus perceptible, titres et sous-titres beaucoup plus discrets. *\/\n  page.querySelectorAll(\".head h2\").forEach(el=>{\n    if(!el.hasAttribute(\"data-parallax\"))el.setAttribute(\"data-parallax\",\"-0.022\");\n  });\n  page.querySelectorAll(\".head .intro\").forEach(el=>{\n    if(!el.hasAttribute(\"data-parallax\"))el.setAttribute(\"data-parallax\",\"0.013\");\n  });\n  page.querySelectorAll(\".section > h3\").forEach(el=>{\n    if(!el.hasAttribute(\"data-parallax\"))el.setAttribute(\"data-parallax\",\"-0.010\");\n  });\n\n  const nodes=[...page.querySelectorAll(\"[data-parallax]\")];\n  if(!reduced&&nodes.length){\n    let tick=false;\n    function update(){\n      const vh=window.innerHeight||document.documentElement.clientHeight;\n      nodes.forEach(el=>{\n        const r=el.getBoundingClientRect();\n        if(r.bottom>0&&r.top<vh){\n          const s=parseFloat(el.dataset.parallax)||0;\n          const delta=(r.top+r.height\/2)-(vh\/2);\n          let max=18;\n          if(Math.abs(s)>=.06)max=50;\n          else if(Math.abs(s)>=.02)max=28;\n          const y=Math.max(-max,Math.min(max,delta*s));\n          el.style.transform=`translate3d(0,${y.toFixed(2)}px,0)`;\n        }\n      });\n      tick=false;\n    }\n    addEventListener(\"scroll\",()=>{if(!tick){requestAnimationFrame(update);tick=true}},{passive:true});\n    addEventListener(\"resize\",update,{passive:true});\n    update();\n  }\n\n  function resizeFrame(f){\n    try{\n      const d=f.contentDocument;\n      if(!d)return;\n      const h=Math.max(d.body?.scrollHeight||0,d.documentElement?.scrollHeight||0);\n      if(h>200)f.style.height=(h+8)+\"px\";\n    }catch(e){}\n  }\n\n  const gestureDetails=[...page.querySelectorAll(\".gesture-grid details\")];\n  gestureDetails.forEach(d=>{\n    d.addEventListener(\"toggle\",()=>{\n      if(!d.open)return;\n      gestureDetails.forEach(other=>{\n        if(other!==d&&other.open)other.open=false;\n      });\n      const img=d.querySelector(\"img\");\n      if(img&&!img.getAttribute(\"src\")){\n        img.setAttribute(\"src\",d.dataset.gif);\n        img.setAttribute(\"loading\",\"lazy\");\n        img.setAttribute(\"decoding\",\"async\");\n      }\n    });\n  });\n\n  page.querySelectorAll(\"iframe.autoheight\").forEach(f=>{\n    f.addEventListener(\"load\",()=>{\n      resizeFrame(f);\n      setTimeout(()=>resizeFrame(f),300);\n      setTimeout(()=>resizeFrame(f),1200);\n    });\n  });\n})();\n<\/script>\n\n<!-- COMPORTEMENT GLOBAL \u2014 retour en haut -->\n\n<script id=\"au26-to-top-js\">\n(function(){\n  var button=document.getElementById('au26-to-top');\n  if(!button || button.dataset.ready==='1') return;\n  button.dataset.ready='1';\n  button.addEventListener('click',function(){\n    window.scrollTo({top:0,behavior:'smooth'});\n  });\n})();\n<\/script>\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>INITIATIONSound Design AUDITIONForme d&#8217;onde AUDITIONMultipiste PREMI\u00c8RE PROMixage L\u2019ENREGISTREMENTPrise de son AUDIOBRANDING EXERCICESAstuces Audition \u00b7 Forme d\u2019ondeCours 02 \u00b7 Fondamentaux \u263c Formation \u00b7 Chapitre 02 AuditionForme d\u2019onde. Comprendre le son, apprendre \u00e0 le lire et ma\u00eetriser les op\u00e9rations essentielles dans Adobe Audition. Cours02 \u2014 Audition LogicielAdobe Audition ObjectifVoir \u00b7 Comprendre \u00b7 \u00c9diter Physique du sonAnalyseLaboratoire Fonctions [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"elementor_canvas","meta":{"footnotes":""},"class_list":["post-3347","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/lucasgoret.com\/index.php\/wp-json\/wp\/v2\/pages\/3347","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/lucasgoret.com\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/lucasgoret.com\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/lucasgoret.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/lucasgoret.com\/index.php\/wp-json\/wp\/v2\/comments?post=3347"}],"version-history":[{"count":39,"href":"https:\/\/lucasgoret.com\/index.php\/wp-json\/wp\/v2\/pages\/3347\/revisions"}],"predecessor-version":[{"id":3814,"href":"https:\/\/lucasgoret.com\/index.php\/wp-json\/wp\/v2\/pages\/3347\/revisions\/3814"}],"wp:attachment":[{"href":"https:\/\/lucasgoret.com\/index.php\/wp-json\/wp\/v2\/media?parent=3347"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}