1import{i as Q}from"./1O29X_S1.js";import{p as Mt}from"./sIQ93AGH.js";import{v as I,w as qe,aP as ji,q as ot,B as Nt,L as ze,aQ as Ht,R as fe,N as Yt,g as b,a3 as Di,aF as zi,aG as Oi,ay as At,Q as ue,aR as qi,T as ce,O as Fi,aS as Ri,aT as Ct,aw as Oe,aU as ie,aV as Se,aE as Ui,af as It,aW as rt,aX as Vt,aY as Li,aZ as Wi,a_ as Gi,a$ as Kt,b0 as Jt,b1 as Ye,A as nt,P as Bi,b2 as Ni,b3 as Hi,b4 as Fe,a5 as Zt,b5 as Yi,E as Xt,b6 as Vi,b7 as Ki,x as Ge,z as Ji,b8 as Zi,b9 as Qt,ab as Xi,i as J,aA as ei,ba as Qi,bb as eo,al as to,bc as io,bd as je,be as ti,bf as oo,bg as ro,bh as no,bi as ao,ax as so,bj as lo,bk as co,bl as uo,as as ho,bm as po,bn as fo,bo as go,bp as mo,k as he,bq as yo,br as bo,bs as vo,bt as wo,bu as ko,W as X,U as de,V as _o,X as $o,Y as So,p as Y,h as H,a as O,b as v,e as V,s as Z,Z as ii,d as P,c as F,r as x,u as q,bv as To,f as M,t as oe,n as U,m as Te,bw as Po,o as xo,aO as Mo}from"./Bm9DxLRk.js";import{p as R,r as re,s as E,l as B}from"./DriNFrHA.js";import"./hprzEvy6.js";import{D as oi}from"./JegGaeHh.js";function Ao(t,e,i){I&&qe();var o=new Nt(t),r=!ji();ot(()=>{var n=e();r&&n!==null&&typeof n=="object"&&(n={}),o.ensure(n,i)})}function Co(t,e){return e}function Io(t,e,i){for(var o=[],r=e.length,n,a=e.length,s=0;s<r;s++){let p=e[s];Jt(p,()=>{if(n){if(n.pending.delete(p),n.done.add(p),n.pending.size===0){var d=t.outrogroups;Qe(rt(n.done)),d.delete(n),d.size===0&&(t.outrogroups=null)}}else a-=1},!1)}if(a===0){var l=o.length===0&&i!==null;if(l){var c=i,u=c.parentNode;Hi(u),u.append(c),t.items.clear()}Qe(e,!l)}else n={pending:new Set(e),done:new Set},(t.outrogroups??=new Set).add(n)}function Qe(t,e=!0){for(var i=0;i<t.length;i++)Fe(t[i],e)}var Et;function Eo(t,e,i,o,r,n=null){var a=t,s=new Map,l=(e&Ht)!==0;if(l){var c=t;a=I?fe(Yt(c)):c.appendChild(ze())}I&&qe();var u=null,p=Di(()=>{var y=i();return Vt(y)?y:y==null?[]:rt(y)}),d,g=!0;function m(){h.fallback=u,jo(h,d,a,e,o),u!==null&&(d.length===0?(u.f&ie)===0?Kt(u):(u.f^=ie,_e(u,null,a)):Jt(u,()=>{u=null}))}var f=ot(()=>{d=b(p);var y=d.length;let D=!1;if(I){var z=zi(a)===Oi;z!==(y===0)&&(a=At(),fe(a),ue(!1),D=!0)}for(var S=new Set,W=Oe,_=qi(),k=0;k<y;k+=1){I&&ce.nodeType===Fi&&ce.data===Ri&&(a=ce,D=!0,ue(!1));var A=d[k],G=o(A,k),$=g?null:s.get(G);$?($.v&&Ct($.v,A),$.i&&Ct($.i,k),_&&W.skipped_effects.delete($.e)):($=Do(s,g?a:Et??=ze(),A,G,k,r,e,i),g||($.e.f|=ie),s.set(G,$)),S.add(G)}if(y===0&&n&&!u&&(g?u=Se(()=>n(a)):(u=Se(()=>n(Et??=ze())),u.f|=ie)),I&&y>0&&fe(At()),!g)if(_){for(const[ee,ne]of s)S.has(ee)||W.skipped_effects.add(ne.e);W.oncommit(m),W.ondiscard(()=>{})}else m();D&&ue(!0),b(p)}),h={effect:f,items:s,outrogroups:null,fallback:u};g=!1,I&&(a=ce)}function jo(t,e,i,o,r){var n=(o&Ni)!==0,a=e.length,s=t.items,l=t.effect.first,c,u=null,p,d=[],g=[],m,f,h,y;if(n)for(y=0;y<a;y+=1)m=e[y],f=r(m,y),h=s.get(f).e,(h.f&ie)===0&&(h.nodes?.a?.measure(),(p??=new Set).add(h));for(y=0;y<a;y+=1){if(m=e[y],f=r(m,y),h=s.get(f).e,t.outrogroups!==null)for(const $ of t.outrogroups)$.pending.delete(h),$.done.delete(h);if((h.f&ie)!==0)if(h.f^=ie,h===l)_e(h,null,i);else{var D=u?u.next:l;h===t.effect.last&&(t.effect.last=h.prev),h.prev&&(h.prev.next=h.next),h.next&&(h.next.prev=h.prev),ae(t,u,h),ae(t,h,D),_e(h,D,i),u=h,d=[],g=[],l=u.next;continue}if((h.f&Ye)!==0&&(Kt(h),n&&(h.nodes?.a?.unfix(),(p??=new Set).delete(h))),h!==l){if(c!==void 0&&c.has(h)){if(d.length<g.length){var z=g[0],S;u=z.prev;
1var W=d[0],_=d[d.length-1];for(S=0;S<d.length;S+=1)_e(d[S],z,i);for(S=0;S<g.length;S+=1)c.delete(g[S]);ae(t,W.prev,_.next),ae(t,u,W),ae(t,_,z),l=z,u=_,y-=1,d=[],g=[]}else c.delete(h),_e(h,l,i),ae(t,h.prev,h.next),ae(t,h,u===null?t.effect.first:u.next),ae(t,u,h),u=h;continue}for(d=[],g=[];l!==null&&l!==h;)(c??=new Set).add(l),g.push(l),l=l.next;if(l===null)continue}(h.f&ie)===0&&d.push(h),u=h,l=h.next}if(t.outrogroups!==null){for(const $ of t.outrogroups)$.pending.size===0&&(Qe(rt($.done)),t.outrogroups?.delete($));t.outrogroups.size===0&&(t.outrogroups=null)}if(l!==null||c!==void 0){var k=[];if(c!==void 0)for(h of c)(h.f&Ye)===0&&k.push(h);for(;l!==null;)(l.f&Ye)===0&&l!==t.fallback&&k.push(l),l=l.next;var A=k.length;if(A>0){var G=(o&Ht)!==0&&a===0?i:null;if(n){for(y=0;y<A;y+=1)k[y].nodes?.a?.measure();for(y=0;y<A;y+=1)k[y].nodes?.a?.fix()}Io(t,k,G)}}n&&nt(()=>{if(p!==void 0)for(h of p)h.nodes?.a?.apply()})}function Do(t,e,i,o,r,n,a,s){var l=(a&Li)!==0?(a&Wi)===0?Ui(i,!1,!1):It(i):null,c=(a&Gi)!==0?It(r):null;return oi&&l&&(l.trace=()=>{s()[c?.v??r]}),{v:l,i:c,e:Se(()=>(n(e,l??i,c??r,s),()=>{t.delete(o)}))}}function _e(t,e,i){if(t.nodes)for(var o=t.nodes.start,r=t.nodes.end,n=e&&(e.f&ie)===0?e.nodes.start:i;o!==null;){var a=Bi(o);if(n.before(o),o===r)return;o=a}}function ae(t,e,i){e===null?t.effect.first=i:e.next=i,i===null?t.effect.last=e:i.prev=e}const zo=()=>performance.now(),te={tick:t=>requestAnimationFrame(t),now:()=>zo(),tasks:new Set};function ri(){const t=te.now();te.tasks.forEach(e=>{e.c(t)||(te.tasks.delete(e),e.f())}),te.tasks.size!==0&&te.tick(ri)}function Oo(t){let e;return te.tasks.size===0&&te.tick(ri),{promise:new Promise(i=>{te.tasks.add(e={c:t,f:i})}),abort(){te.tasks.delete(e)}}}function jt(t,e){Qt(()=>{t.dispatchEvent(new CustomEvent(e))})}function qo(t){if(t==="float")return"cssFloat";if(t==="offset")return"cssOffset";if(t.startsWith("--"))return t;const e=t.split("-");return e.length===1?e[0]:e[0]+e.slice(1).map(i=>i[0].toUpperCase()+i.slice(1)).join("")}function Dt(t){const e={},i=t.split(";");for(const o of i){const[r,n]=o.split(":");if(!r||n===void 0)break;const a=qo(r.trim());e[a]=n.trim()}return e}const Fo=t=>t;function Ro(t,e,i,o){var r=(t&Zi)!==0,n="in",a,s=e.inert,l=e.style.overflow,c,u;function p(){return Qt(()=>a??=i()(e,o?.()??{},{direction:n}))}var d={is_global:r,in(){e.inert=s,c?.abort(),jt(e,"introstart"),c=ni(e,p(),u,1,()=>{jt(e,"introend"),c?.abort(),c=a=void 0,e.style.overflow=l})},out(h){{h?.(),a=void 0;return}},stop:()=>{c?.abort()}},g=Zt;if((g.nodes.t??=[]).push(d),Yi){var m=r;if(!m){for(var f=g.parent;f&&(f.f&Xt)!==0;)for(;(f=f.parent)&&(f.f&Vi)===0;);m=!f||(f.f&Ki)!==0}m&&Ge(()=>{Ji(()=>d.in())})}}function ni(t,e,i,o,r){if(Xi(e)){var n,a=!1;return nt(()=>{if(!a){var f=e({direction:"in"});n=ni(t,f,i,o,r)}}),{abort:()=>{a=!0,n?.abort()},deactivate:()=>n.deactivate(),reset:()=>n.reset(),t:()=>n.t()}}if(!e?.duration)return r(),{abort:J,deactivate:J,reset:J,t:()=>o};const{delay:s=0,css:l,tick:c,easing:u=Fo}=e;var p=[];if(c&&c(0,1),l){var d=Dt(l(0,1));p.push(d,d)}var g=()=>1-o,m=t.animate(p,{duration:s,fill:"forwards"});return m.onfinish=()=>{m.cancel();var f=1-o,h=o-f,y=e.duration*Math.abs(h),D=[];if(y>0){var z=!1;if(l)for(var S=Math.ceil(y/16.666666666666668),W=0;W<=S;W+=1){var _=f+h*u(W/S),k=Dt(l(_,1-_));D.push(k),z||=k.overflow==="hidden"}z&&(t.style.overflow="hidden"),g=()=>{var A=m.currentTime;return f+h*u(A/y)},c&&Oo(()=>
1{if(m.playState!=="running")return!1;var A=g();return c(A,1-A),!0})}m=t.animate(D,{duration:y,fill:"forwards"}),m.onfinish=()=>{g=()=>o,c?.(o,1-o),r()}},{abort:()=>{m&&(m.cancel(),m.effect=null,m.onfinish=J)},deactivate:()=>{r=J},reset:()=>{},t:()=>g()}}function Uo(t,e,i,o,r,n){let a=I;I&&qe();var s=null;I&&ce.nodeType===Qi&&(s=ce,qe());var l=I?ce:t,c=new Nt(l,!1);ot(()=>{const u=e()||null;var p=i||u==="svg"?eo:null;if(u===null){c.ensure(null,null),je(!0);return}return c.ensure(u,d=>{if(u){if(s=I?s:p?document.createElementNS(p,u):document.createElement(u),to(s,s),o){I&&io(u)&&s.append(document.createComment(""));var g=I?Yt(s):s.appendChild(ze());I&&(g===null?ue(!1):fe(g)),o(s,g)}Zt.nodes.end=s,d.before(s)}I&&fe(d)}),je(!0),()=>{u&&je(!1)}},Xt),ei(()=>{je(!0)}),a&&(ue(!0),fe(l))}function Lo(t,e){var i=void 0,o;ti(()=>{i!==(i=e())&&(o&&(Fe(o),o=null),i&&(o=Se(()=>{Ge(()=>i(t))})))})}function ai(t){var e,i,o="";if(typeof t=="string"||typeof t=="number")o+=t;else if(typeof t=="object")if(Array.isArray(t)){var r=t.length;for(e=0;e<r;e++)t[e]&&(i=ai(t[e]))&&(o&&(o+=" "),o+=i)}else for(i in t)t[i]&&(o&&(o+=" "),o+=i);return o}function Wo(){for(var t,e,i=0,o="",r=arguments.length;i<r;i++)(t=arguments[i])&&(e=ai(t))&&(o&&(o+=" "),o+=e);return o}function si(t){return typeof t=="object"?Wo(t):t??""}const zt=[...` 2\r\f \v\uFEFF`];function Go(t,e,i){var o=t==null?"":""+t;if(e&&(o=o?o+" "+e:e),i){for(var r in i)if(i[r])o=o?o+" "+r:r;else if(o.length)for(var n=r.length,a=0;(a=o.indexOf(r,a))>=0;){var s=a+n;(a===0||zt.includes(o[a-1]))&&(s===o.length||zt.includes(o[s]))?o=(a===0?"":o.substring(0,a))+o.substring(s+1):a=s}}return o===""?null:o}function Ot(t,e=!1){var i=e?" !important;":";",o="";for(var r in t){var n=t[r];n!=null&&n!==""&&(o+=" "+r+": "+n+i)}return o}function Ve(t){return t[0]!=="-"||t[1]!=="-"?t.toLowerCase():t}function Bo(t,e){if(e){var i="",o,r;if(Array.isArray(e)?(o=e[0],r=e[1]):o=e,t){t=String(t).replaceAll(/\s*\/\*.*?\*\/\s*/g,"").trim();var n=!1,a=0,s=!1,l=[];o&&l.push(...Object.keys(o).map(Ve)),r&&l.push(...Object.keys(r).map(Ve));var c=0,u=-1;const f=t.length;for(var p=0;p<f;p++){var d=t[p];if(s?d==="/"&&t[p-1]==="*"&&(s=!1):n?n===d&&(n=!1):d==="/"&&t[p+1]==="*"?s=!0:d==='"'||d==="'"?n=d:d==="("?a++:d===")"&&a--,!s&&n===!1&&a===0){if(d===":"&&u===-1)u=p;else if(d===";"||p===f-1){if(u!==-1){var g=Ve(t.substring(c,u).trim());if(!l.includes(g)){d!==";"&&p++;var m=t.substring(c,p).trim();i+=" "+m+";"}}c=p+1,u=-1}}}}return o&&(i+=Ot(o)),r&&(i+=Ot(r,!0)),i=i.trim(),i===""?null:i}return t==null?null:String(t)}function Be(t,e,i,o,r,n){var a=t.__className;if(I||a!==i||a===void 0){var s=Go(i,o,n);(!I||s!==t.getAttribute("class"))&&(s==null?t.removeAttribute("class"):e?t.className=s:t.setAttribute("class",s)),t.__className=i}else if(n&&r!==n)for(var l in n){var c=!!n[l];(r==null||c!==!!r[l])&&t.classList.toggle(l,c)}return n}function Ke(t,e={},i,o){for(var r in i){var n=i[r];e[r]!==n&&(i[r]==null?t.style.removeProperty(r):t.style.setProperty(r,n,o))}}function li(t,e,i,o){var r=t.__style;if(I||r!==e){var n=Bo(e,o);(!I||n!==t.getAttribute("style"))&&(n==null?t.removeAttribute("style"):t.style.cssText=n),t.__style=e}else o&&(Array.isArray(o)?(Ke(t,i?.[0],o[0]),Ke(t,i?.[1],o[1],"important")):Ke(t,i,o));return o}function Re(t,e,i=!1){if(t.multiple){if(e==null)return;if(!Vt(e))return oo();for(var o of t.options)o.selected=e.includes($e(o));return}for(o of t.options){var r=$e(o);if(ro(r,e)){o.selected=!0;return}}(!i||e!==void 0)&&(t.selectedIndex=-1)}function ci(t){var e=new MutationObserver(()=>{Re(t,t.__value)});e.observe(t,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["value"]}),ei(()=>{e.disconnect()})}function Pl(t,e,i=e){var o=new WeakSet,r=!0;no(t,"change",n=>{var a=n?"[selected]":":checked",s;if(t.multiple)s=[].map.call(t.querySelectorAll(a),$e);else{var l=t.querySelector(a)??t.querySelector("option:not([disabled])");s=l&&$e(l)}i(s),Oe!==null&&o.add(Oe)}),Ge(()=>{var n=e();if(t===document.activeElement){var a=ao??Oe;if(o.has(a))return}if(Re(t,n,r),r&&n===void 0){var s=t.querySelector(":checked");s!==null&&(n=$e(s),i(n))}t.__value=n,r=!1}),ci(t)}function $e(t){return"__value"in t?t.__value:t.value}const ve=Symbol("class"),we=Symbol("style"),ui=Symbol("is custom element"),di=Symbol("is html");function No(t){if(I){var e=!1,i=()=>
2{if(!e){if(e=!0,t.hasAttribute("value")){var o=t.value;K(t,"value",null),t.value=o}if(t.hasAttribute("checked")){var r=t.checked;K(t,"checked",null),t.checked=r}}};t.__on_r=i,nt(i),wo()}}function xl(t,e){var i=at(t);i.value===(i.value=e??void 0)||t.value===e&&(e!==0||t.nodeName!=="PROGRESS")||(t.value=e??"")}function Ho(t,e){e?t.hasAttribute("selected")||t.setAttribute("selected",""):t.removeAttribute("selected")}function K(t,e,i,o){var r=at(t);if(I&&(r[e]=t.getAttribute(e),e==="src"||e==="srcset"||e==="href"&&t.nodeName==="LINK")){o||Vo(t,e,i??"");return}r[e]!==(r[e]=i)&&(e==="loading"&&(t[lo]=i),i==null?t.removeAttribute(e):typeof i!="string"&&hi(t).includes(e)?t[e]=i:t.setAttribute(e,i))}function Yo(t,e,i,o,r=!1,n=!1){if(I&&r&&t.tagName==="INPUT"){var a=t,s=a.type==="checkbox"?"defaultChecked":"defaultValue";s in i||No(a)}var l=at(t),c=l[ui],u=!l[di];let p=I&&c;p&&ue(!1);var d=e||{},g=t.tagName==="OPTION";for(var m in e)m in i||(i[m]=null);i.class?i.class=si(i.class):i[ve]&&(i.class=null),i[we]&&(i.style??=null);var f=hi(t);for(const _ in i){let k=i[_];if(g&&_==="value"&&k==null){t.value=t.__value="",d[_]=k;continue}if(_==="class"){var h=t.namespaceURI==="http://www.w3.org/1999/xhtml";Be(t,h,k,o,e?.[ve],i[ve]),d[_]=k,d[ve]=i[ve];continue}if(_==="style"){li(t,k,e?.[we],i[we]),d[_]=k,d[we]=i[we];continue}var y=d[_];if(!(k===y&&!(k===void 0&&t.hasAttribute(_)))){d[_]=k;var D=_[0]+_[1];if(D!=="$$")if(D==="on"){const A={},G="$$"+_;let $=_.slice(2);var z=ko($);if(go($)&&($=$.slice(0,-7),A.capture=!0),!z&&y){if(k!=null)continue;t.removeEventListener($,d[G],A),d[G]=null}if(k!=null)if(z)t[`__${$}`]=k,he([$]);else{let ee=function(ne){d[_].call(this,ne)};d[G]=mo($,t,ee,A)}else z&&(t[`__${$}`]=void 0)}else if(_==="style")K(t,_,k);else if(_==="autofocus")yo(t,!!k);else if(!c&&(_==="__value"||_==="value"&&k!=null))t.value=t.__value=k;else if(_==="selected"&&g)Ho(t,k);else{var S=_;u||(S=bo(S));var W=S==="defaultValue"||S==="defaultChecked";if(k==null&&!c&&!W)if(l[_]=null,S==="value"||S==="checked"){let A=t;const G=e===void 0;if(S==="value"){let $=A.defaultValue;A.removeAttribute(S),A.defaultValue=$,A.value=A.__value=G?$:null}else{let $=A.defaultChecked;A.removeAttribute(S),A.defaultChecked=$,A.checked=G?$:!1}}else t.removeAttribute(_);else W||f.includes(S)&&(c||typeof k!="string")?(t[S]=k,S in l&&(l[S]=vo)):typeof k!="function"&&K(t,S,k,n)}}}return p&&ue(!0),d}function et(t,e,i=[],o=[],r=[],n,a=!1,s=!1){so(r,i,o,l=>{var c=void 0,u={},p=t.nodeName==="SELECT",d=!1;if(ti(()=>{var m=e(...l.map(b)),f=Yo(t,c,m,n,a,s);d&&p&&"value"in m&&Re(t,m.value);for(let y of Object.getOwnPropertySymbols(u))m[y]||Fe(u[y]);for(let y of Object.getOwnPropertySymbols(m)){var h=m[y];y.description===ho&&(!c||h!==c[y])&&(u[y]&&Fe(u[y]),u[y]=Se(()=>Lo(t,()=>h))),f[y]=h}c=f}),p){var g=t;Ge(()=>{Re(g,c.value,!0),ci(g)})}d=!0})}function at(t){return t.__attributes??={[ui]:t.nodeName.includes("-"),[di]:t.namespaceURI===co}}var qt=new Map;function hi(t){var e=t.getAttribute("is")||t.nodeName,i=qt.get(e);if(i)return i;qt.set(e,i=[]);for(var o,r=t,n=Element.prototype;n!==r;){o=po(r);for(var a in o)o[a].set&&i.push(a);r=uo(r)}return i}function Vo(t,e,i){oi&&(e==="srcset"&&Ko(t,i)||tt(t.getAttribute(e)??"",i)||fo(e,t.outerHTML.replace(t.innerHTML,t.innerHTML&&"..."),String(i)))}function tt(t,e){return t===e?!0:new URL(t,document.baseURI).href===new URL(e,document.baseURI).href}function Ft(t){return t.split(",").map(e=>e.trim().split(" ").filter(Boolean))}function Ko(t,e){var i=Ft(t.srcset),o=Ft(e);return o.length===i.length&&o.every(([r,n],a)=>n===i[a][1]&&(tt(i[a][0],r)||tt(r,i[a][0])))}class st{#e;get _isEmbedded(){return b(this.#e)}set _isEmbedded(e){X(this.#e,e,!0)}static CONTEXT_KEY="embed-state";get isEmbedded(){return this._isEmbedded}constructor(e){this.#e=de(_o(e))}static setContext(e){return $o(this.CONTEXT_KEY,new st(e))}static getContext(){return So(this.CONTEXT_KEY)}}function Jo(t,e){Y(e,!0);const i=st.getContext();var o=H(),r=O(o);{var n=s=>{var l=H(),c=O(l);Z(c,()=>e.children),v(s,l)},a=s=>{var l=H(),c=O(l);{var u=p=>{var d=H(),g=O(d);Z(g,()=>e.option),v(p,d)};Q(c,p=>{e.option&&p(u)},!0)}v(s,l)};Q(r,s=>{!i.isEmbedded&&e.hide||i.isEmbedded&&e.show?s(n):s(a,!1)})}v(t,o),V()}const Zo={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":2,"stroke-linecap":"round","stroke-linejoin":"round"};var Xo=ii("<svg><!><!></svg>");function ge(t,e){Y(e,!0);const i=R(e,"color",3,"currentColor"),o=R(e,"size",3,24),r=R(e,"strokeWidth",3,2),n=R(e,"absoluteStrokeWidth",3,!1),a=R(e,"iconNode",19,()=>
2[]),s=re(e,["$$slots","$$events","$$legacy","name","color","size","strokeWidth","absoluteStrokeWidth","iconNode","children"]);var l=Xo();et(l,p=>({...Zo,...s,width:o(),height:o(),stroke:i(),"stroke-width":p,class:["lucide-icon lucide",e.name&&`lucide-${e.name}`,e.class]}),[()=>n()?Number(r())*24/Number(o()):r()]);var c=P(l);Eo(c,17,a,Co,(p,d)=>{var g=q(()=>To(b(d),2));let m=()=>b(g)[0],f=()=>b(g)[1];var h=H(),y=O(h);Uo(y,m,!0,(D,z)=>{et(D,()=>({...f()}))}),v(p,h)});var u=F(c);Z(u,()=>e.children??J),x(l),v(t,l),V()}function pi(t,e){Y(e,!0);let i=re(e,["$$slots","$$events","$$legacy"]);const o=[["path",{d:"M18 6 6 18"}],["path",{d:"m6 6 12 12"}]];ge(t,E({name:"x"},()=>i,{get iconNode(){return o},children:(r,n)=>{var a=H(),s=O(a);Z(s,()=>e.children??J),v(r,a)},$$slots:{default:!0}})),V()}he(["click"]);function fi(t,e){Y(e,!0);let i=re(e,["$$slots","$$events","$$legacy"]);const o=[["rect",{width:"14",height:"14",x:"8",y:"8",rx:"2",ry:"2"}],["path",{d:"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"}]];ge(t,E({name:"copy"},()=>i,{get iconNode(){return o},children:(r,n)=>{var a=H(),s=O(a);Z(s,()=>e.children??J),v(r,a)},$$slots:{default:!0}})),V()}function gi(t,e){Y(e,!0);let i=re(e,["$$slots","$$events","$$legacy"]);const o=[["path",{d:"m12 15 2 2 4-4"}],["rect",{width:"14",height:"14",x:"8",y:"8",rx:"2",ry:"2"}],["path",{d:"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"}]];ge(t,E({name:"copy-check"},()=>i,{get iconNode(){return o},children:(r,n)=>{var a=H(),s=O(a);Z(s,()=>e.children??J),v(r,a)},$$slots:{default:!0}})),V()}var Qo=M("<!> Copied!",1),er=M("<!> ",1),tr=M('<button type="button"><!></button>');function Ml(t,e){Y(e,!0);let i=R(e,"buttonClass",3,""),o=R(e,"showDuration",3,2e3),r=R(e,"disabled",3,!1),n=R(e,"buttonText",3,"Copy"),a=de(!1),s;function l(){r()||(Ks.copyText(e.textToCopy),X(a,!0),s&&clearTimeout(s),s=setTimeout(()=>{X(a,!1)},o()))}var c=tr();let u;c.__click=l;var p=P(c);{var d=m=>{var f=Qo(),h=O(f);gi(h,{class:"size-[1.2em]"}),U(),v(m,f)},g=m=>{var f=er(),h=O(f);fi(h,{class:"size-[1.2em]"});var y=F(h);oe(()=>Te(y,` ${n()??""}`)),v(m,f)};Q(p,m=>{b(a)?m(d):m(g,!1)})}x(c),oe(()=>{u=Be(c,1,si(i()),null,u,{"text-success":b(a)}),c.disabled=r()}),v(t,c),V()}he(["click"]);var ir=(t,e)=>{if(!(!t||!e))switch(e){case"constrained":return`(min-width: ${t}px) ${t}px, 100vw`;case"fixed":return`${t}px`;case"fullWidth":return"100vw";default:return}},ke=t=>t||t===0?`${t}px`:void 0,or=({width:t,height:e,aspectRatio:i,layout:o,objectFit:r="cover",background:n})=>{const a=[["object-fit",r]];return n?.startsWith("https:")||n?.startsWith("http:")||n?.startsWith("data:")||n?.startsWith("/")?(a.push(["background-image",`url(${n})`]),a.push(["background-size","cover"]),a.push(["background-repeat","no-repeat"])):a.push(["background",n]),o==="fixed"&&(a.push(["width",ke(t)]),a.push(["height",ke(e)])),o==="constrained"&&(a.push(["max-width",ke(t)]),a.push(["max-height",ke(e)]),a.push(["aspect-ratio",i?`${i}`:void 0]),a.push(["width","100%"])),o==="fullWidth"&&(a.push(["width","100%"]),a.push(["aspect-ratio",i?`${i}`:void 0]),a.push(["height",ke(e)])),Object.fromEntries(a.filter(([,s])=>s))},rr=[6016,5120,4480,3840,3200,2560,2048,1920,1668,1280,1080,960,828,750,640],Rt=24,nr=({width:t,layout:e,resolutions:i=rr})=>{if(e==="fullWidth")return i;if(!t)return[];const o=t*2;return e==="fixed"?[t,o]:e==="constrained"?[t,o,...i.filter(r=>r<o)]:[]},ar=({src:t,width:e,layout:i="constrained",height:o,aspectRatio:r,breakpoints:n,format:a})=>(n||=nr({width:e,layout:i}),n.sort((s,l)=>s-l).map(s=>{let l;return o&&r&&(l=Math.round(s/r)),{url:t,width:s,height:l,format:a}})),sr=t=>{let{src:e,transformer:i,operations:o}=t;return i?ar(t).map(({url:r,...n})=>`${i(e,{...o,...n},t.options)?.toString()} ${n.width}w`).join(`, 3`):""};function lr({width:t,height:e,priority:i,layout:o="constrained",aspectRatio:r,...n}){return t=t&&Number(t)||void 0,e=e&&Number(e)||void 0,i?(n.loading||="eager",n.fetchpriority||="high"):(n.loading||="lazy",n.decoding||="async"),n.alt===""&&(n.role||="presentation"),r?t?e||(e=Math.round(t/r)):e&&(t=Math.round(e*r)):t&&e&&(r=t/e),{width:t,height:e,aspectRatio:r,layout:o,...n}}function cr(t){let{src:e,transformer:i,background:o,layout:r,objectFit:n,breakpoints:a,width:s,height:l,aspectRatio:c,unstyled:u,operations:p,options:d,...g}=lr(t);if(i&&o==="auto"){const f=c?Math.round(Rt/c):void 0,h=i(e,{width:Rt,height:f},d);h&&(o=h.toString())}const m={width:s,height:l,aspectRatio:c,layout:r,objectFit:n,background:o};if(g.sizes||=ir(s,r),u||(g.style={...or(m),...g.style}),i){g.srcset=sr({src:e,width:s,height:l,aspectRatio:c,layout:r,breakpoints:a,transformer:i,operations:p,options:d});const f=i(e,{...p,width:s,height:l},d);f&&(e=f),(r==="fullWidth"||r==="constrained")&&(s=void 0,l=void 0)}return{...g,src:e?.toString(),width:s,height:l}}const ur={"images.ctfassets.net":"contentful","cdn.builder.io":"builder.io","images.prismic.io":"imgix","www.datocms-assets.com":"imgix","cdn.sanity.io":"imgix","images.unsplash.com":"imgix","cdn.shopify.com":"shopify","s7d1.scene7.com":"scene7","ip.keycdn.com":"keycdn","assets.c
3aisy.io":"bunny","images.contentstack.io":"contentstack","ucarecdn.com":"uploadcare","imagedelivery.net":"cloudflare_images","wsrv.nl":"wsrv"},dr={"imgix.net":"imgix","wp.com":"wordpress","files.wordpress.com":"wordpress","b-cdn.net":"bunny","storyblok.com":"storyblok","kc-usercontent.com":"kontent.ai","cloudinary.com":"cloudinary","kxcdn.com":"keycdn","imgeng.in":"imageengine","imagekit.io":"imagekit","cloudimg.io":"cloudimage","ucarecdn.com":"uploadcare","supabase.co":"supabase","graphassets.com":"hygraph"},hr={"/cdn-cgi/image/":"cloudflare","/cdn-cgi/imagedelivery/":"cloudflare_images","/_next/image":"nextjs","/_vercel/image":"vercel","/is/image":"scene7","/_ipx/":"ipx","/_image":"astro","/.netlify/images":"netlify","/storage/v1/object/public/":"supabase","/storage/v1/render/image/public/":"supabase","/v1/storage/buckets/":"appwrite"};function Ue(t){if(!t)return t;const e=Number(t);return isNaN(e)?t:Math.round(e)}const pr=t=>{const{pathname:e,search:i}=t;return`${e}${i}`},T=t=>t.hostname==="n"?pr(t):t.toString(),w=(t,e)=>typeof t=="string"?new URL(t,"http://n/"):t,Ut=t=>t===" "?"+":"%"+t.charCodeAt(0).toString(16).toUpperCase().padStart(2,"0"),mi=t=>t?.startsWith("/")?t.slice(1):t,lt=t=>t?.endsWith("/")?t.slice(0,-1):t,fr=t=>t?.endsWith("/")?t:`${t}/`,gr=(t,e)=>{const i=Ut(t),o=Ut(e);function r(a){return encodeURIComponent(a).replaceAll(t,i).replaceAll(e,o)}function n(a,s){return`${r(a)}${t}${r(String(s))}`}return a=>(Array.isArray(a)?a:Object.entries(a)).flatMap(([l,c])=>c==null?[]:Array.isArray(c)?c.map(u=>n(l,u)):n(l,c)).join(e)},mr=(t,e)=>t==="="&&e==="&"?vr:i=>{const o=i.toString();return Object.fromEntries(o.split(e).map(r=>{const[n,a]=r.split(t);return[decodeURI(n),decodeURI(a)]}))};function yr(t,e=4e3,i=4e3){let{width:o,height:r}=t;return o=Number(o)||void 0,r=Number(r)||void 0,o&&o>e&&(r&&(r=Math.round(r*e/o)),o=e),r&&r>i&&(o&&(o=Math.round(o*i/r)),r=i),{width:o,height:r}}function Pe(t){const e=w(t),i=Object.fromEntries(e.searchParams.entries());for(const o in["width","height","quality"]){const r=i[o];if(r){const n=Number(r);isNaN(n)||(i[o]=n)}}return e.search="",{operations:i,src:T(e)}}function yi({keyMap:t={},formatMap:e={},defaults:i={}},o){o.format&&o.format in e&&(o.format=e[o.format]),o.width&&(o.width=Ue(o.width)),o.height&&(o.height=Ue(o.height));for(const r in t){if(!Object.prototype.hasOwnProperty.call(t,r))continue;const n=r;if(t[n]===!1){delete o[n];continue}t[n]&&o[n]&&(o[t[n]]=o[n],delete o[n])}for(const r in i){if(!Object.prototype.hasOwnProperty.call(i,r))continue;const n=r,a=i[n];if(!o[n]&&a!==void 0){if(t[n]===!1)continue;const s=t[n]??n;if(s in o)continue;o[s]=a}}return o}const Lt=t=>Object.fromEntries(Object.entries(t).map(([e,i])=>[i,e]));function br({keyMap:t={},formatMap:e={},defaults:i={}},o){const r=Lt(t),n=Lt(e),a=yi({keyMap:r,formatMap:n,defaults:i},o);a.width&&(a.width=Ue(a.width)),a.height&&(a.height=Ue(a.height));const s=Number(a.quality);return isNaN(s)||(a.quality=s),a}const vr=t=>{const e=w(t);return Object.fromEntries(e.searchParams.entries())};function me({kvSeparator:t="=",paramSeparator:e="&",...i}={}){const o=gr(t,e);return r=>{const n=yi(i,r);return o(n)}}function wr({kvSeparator:t="=",paramSeparator:e="&",defaults:i,...o}={}){const r=mr(t,e);return n=>{const a=n?r(n):{};return br(o,a)}}function L(t){const e=me(t),i=wr(t);return{operationsGenerator:e,operationsParser:i}}function bi(t){if(t!=null)try{return!!JSON.parse(t?.toString())}catch{return!!t}}const kr=t=>Object.fromEntries(Object.entries(t).filter(([,e])=>e!==void 0));function j(t,e){return((i,o,r)=>{const n=t(i,r);return n?e(n.src,{...n.operations,...kr(o)},{...n.options,...r}):e(i,o,r)})}const _r=new Map(Object.entries(ur)),$r=Object.entries(dr),Sr=Object.entries(hr);function ct(t){return Tr(t)||xe(t)}function Tr(t){if(typeof t=="string"&&!t.startsWith("https://"))return!1;const{hostname:e}=w(t),i=_r.get(e);return i||$r.find(([o])=>e.endsWith(o))?.[1]||!1}function xe(t){const{pathname:e}=w(t);return Sr.find(([i])=>e.startsWith(i))?.[1]||!1}const Pr="/view?",xr="/preview?",{operationsGenerator:Mr,operationsParser:Ar}=L({keyMap:{format:"output"},kvSeparator:"=",paramSeparator:"&"}),Cr=(t,e)=>{const i=w(t.toString().replace(Pr,xr)),o=i.searchParams.get("project")??"",r=Mr(e);return i.search=r,i.searchParams.append("project",o),T(i)},Ir=t=>{if(xe(t)!=="appwrite")return null;const e=w(t),i=Ar(e);delete i.project;const o=e.searchParams.get("project")??"";return e.search="",e.searchParams.append("project",o),{src:e.href,operations:i}},Er=j(Ir,Cr),vi="/_image",{operationsParser:jr,operationsGenerator:
3Dr}=L({keyMap:{format:"f",width:"w",height:"h",quality:"q"},defaults:{fit:"cover"}}),Je=(t,e,i)=>{const o=w(`${lt(i?.baseUrl??"")}${i?.endpoint??vi}`),r=Dr(e);return o.search=r,o.searchParams.set("href",t.toString()),T(o)},zr=t=>{const e=w(t),i=e.searchParams.get("href");if(!i)return null;e.searchParams.delete("href");const o=jr(e);return{src:i,operations:o,options:{baseUrl:e.origin}}},Or=(t,e,i={})=>{if(w(t).pathname!==(i?.endpoint??vi))return Je(t,e,i);const r=zr(t);return r?(i.baseUrl??=r.options.baseUrl,Je(r.src,{...r.operations,...e},i)):Je(t,e,i)},qr=me({defaults:{fit:"cover",format:"webp",sharp:!0}}),Fr=Pe,Rr=(t,e)=>{const i=qr(e),o=w(t);return o.search=i,T(o)},Ur=j(Fr,Rr),Lr=me({keyMap:{format:"output"}}),Wr=Pe,Gr=(t,e)=>{const i=Lr(e),o=w(t);return o.search=i,T(o)},Br=j(Wr,Gr),Nr=(t,e)=>{const{width:i,height:o}=e;return i&&o&&(e.aspect_ratio??=`${Math.round(Number(i))}:${Math.round(Number(o))}`),Br(t,e)},{operationsGenerator:Hr,operationsParser:Yr}=L({keyMap:{format:"f"},defaults:{format:"auto",fit:"cover"},formatMap:{jpg:"jpeg"},kvSeparator:"=",paramSeparator:","}),Vr=(t,e,i)=>{const o=Hr(e),r=w(i?.domain?`https://${i.domain}`:"/");return r.pathname=`/cdn-cgi/image/${o}/${mi(t.toString())}`,T(r)},Kr=(t,e)=>{if(xe(t)!=="cloudflare")return null;const i=w(t),[,,,o,...r]=i.pathname.split("/"),n=Yr(o);return{src:T(w(r.join("/"))),operations:n,options:{domain:e?.domain??(i.hostname==="n"?void 0:i.hostname)}}},Jr=j(Kr,Vr),Zr=/https?:\/\/(?<host>[^\/]+)\/cdn-cgi\/imagedelivery\/(?<accountHash>[^\/]+)\/(?<imageId>[^\/]+)\/*(?<transformations>[^\/]+)*$/g,Xr=/https?:\/\/(?<host>imagedelivery.net)\/(?<accountHash>[^\/]+)\/(?<imageId>[^\/]+)\/*(?<transformations>[^\/]+)*$/g,{operationsGenerator:Qr,operationsParser:en}=L({keyMap:{width:"w",height:"h",format:"f"},defaults:{fit:"cover"},kvSeparator:"=",paramSeparator:","});function wi(t,e){const{host:i,accountHash:o,imageId:r}=t;if(!i||!o||!r)throw new Error("Missing required Cloudflare Images options");return["https:/",...i==="imagedelivery.net"?[i]:[i,"cdn-cgi","imagedelivery"],o,r,e].filter(Boolean).join("/")}const tn=(t,e,i={})=>{const o=Qr(e),r=wi(i,o);return T(w(r))},on=t=>{const e=w(t),i=[...e.toString().matchAll(Zr),...e.toString().matchAll(Xr)];if(!i[0]?.groups)return null;const{host:o,accountHash:r,imageId:n,transformations:a}=i[0].groups,s=en(a||""),l={host:o,accountHash:r,imageId:n};return{src:wi(l),operations:s,options:l}},rn=(t,e,i={})=>{const o=on(t);if(!o)throw new Error("Invalid Cloudflare Images URL");const r={...o.operations,...e};return tn(o.src,r,{...o.options,...i})},{operationsGenerator:nn,operationsParser:an}=L({keyMap:{format:"force_format",width:"w",height:"h",quality:"q"},defaults:{org_if_sml:1}}),sn=(t,e={},{token:i}={})=>{if(!i)throw new Error("Token is required for Cloudimage URLs"+t);let o=t.toString();o=o.replace(/^https?:\/\//,""),o.includes("?")&&(e.ci_url_encoded=1,o=encodeURIComponent(o));const r=nn(e),n=new URL(`https://${i}.cloudimg.io/`);return n.pathname=o,n.search=r,n.toString()},ln=(t,e={})=>{const i=w(t);if(ct(i)!=="cloudimage")return null;const o=an(i);let r=i.pathname;return o.ci_url_encoded&&(r=decodeURIComponent(r),delete o.ci_url_encoded),e.token??=i.hostname.replace(".cloudimg.io",""),{src:`${i.protocol}/${r}`,operations:o,options:e}},cn=j(ln,sn),un=/https?:\/\/(?<host>res\.cloudinary\.com)\/(?<cloudName>[a-zA-Z0-9-]+)\/(?<assetType>image|video|raw)\/(?<deliveryType>upload|fetch|private|authenticated|sprite|facebook|twitter|youtube|vimeo)\/?(?<signature>s\-\-[a-zA-Z0-9]+\-\-)?\/?(?<transformations>(?:[^_\/]+_[^,\/]+,?)*)?\/(?:(?<version>v\d+)\/)?(?<id>(?:[^\s\/]+\/)*[^\s\/]+(?:\.[a-zA-Z0-9]+)?)$/,dn=/https?:\/\/(?<host>(?<cloudName>[a-zA-Z0-9-]+)-res\.cloudinary\.com|[a-zA-Z0-9.-]+)\/(?<assetType>image|video|raw)\/(?<deliveryType>upload|fetch|private|authenticated|sprite|facebook|twitter|youtube|vimeo)\/?(?<signature>s\-\-[a-zA-Z0-9]+\-\-)?\/?(?<transformations>(?:[^_\/]+_[^,\/]+,?)*)?\/(?:(?<version>v\d+)\/)?(?<id>(?:[^\s\/]+\/)*[^\s\/]+(?:\.[a-zA-Z0-9]+)?)$/,{operationsGenerator:hn,operationsParser:pn}=L({keyMap:{width:"w",height:"h",format:"f",quality:"q"},defaults:{format:"auto",c:"lfill"},kvSeparator:"_",paramSeparator:","});function fn({host:t,cloudName:e,assetType:i,deliveryType:o,signature:r,transformations:n,version:a,id:s}){return["https:/",t,t==="res.cloudinary.com"?e:void 0,i,o,r,n,a,s].filter(
3Boolean).join("/")}function gn(t){let e=t.toString().match(un);return e?.length||(e=t.toString().match(dn)),e?.length?e.groups||{}:null}const mn=(t,e)=>{const i=gn(t.toString());if(!i)return t.toString();const o=pn(i.transformations||"");return i.transformations=hn({...o,...e}),fn(i)},yn=me({keyMap:{format:"fm",width:"w",height:"h",quality:"q"},defaults:{fit:"fill"}}),bn=(t,e)=>{const i=yn(e),o=new URL(t);return o.search=i,T(o)},vn=Pe,wn=j(vn,bn),kn=(t,e)=>{const{width:i,height:o}=yr(e,4e3,4e3);return wn(t,{...e,width:i,height:o})},_n=me({defaults:{auto:"webp",disable:"upscale"}}),$n=(t,e,{baseURL:i="https://images.contentstack.io/"}={})=>{e.width&&e.height&&(e.fit??="crop");const o=_n(e),r=w(t);return r.hostname==="n"&&(r.protocol="https:",r.hostname=new URL(i).hostname),r.search=o,T(r)},Sn=t=>{const{src:e,operations:i}=Pe(t)??{};if(!i||!e)return null;const{origin:o}=w(t);return{src:e,operations:i,options:{baseURL:o}}},Tn=j(Sn,$n),Pn=me({defaults:{withoutEnlargement:!0,fit:"cover"}}),xn=(t,e)=>{Array.isArray(e.transforms)&&(e.transforms=JSON.stringify(e.transforms));const i=Pn(e),o=w(t);return o.search=i,T(o)},Mn=t=>{const e=Pe(t);if(e?.operations?.transforms&&typeof e.operations.transforms=="string")try{e.operations.transforms=JSON.parse(e.operations.transforms)}catch{return null}return e},An=j(Mn,xn),Cn=/https:\/\/(?<region>[a-z0-9-]+)\.graphassets\.com\/(?<envId>[a-zA-Z0-9]+)(?:\/(?<transformations>.*?))?\/(?<handle>[a-zA-Z0-9]+)$/;L({keyMap:{width:"width",height:"height",format:"format"},defaults:{format:"auto",fit:"crop"}});const ki=t=>{const i=w(t).toString().match(Cn);if(!i?.groups)return null;const{region:o,envId:r,handle:n,transformations:a}=i.groups,s={};return a&&a.split("/").forEach(c=>{const[u,p]=c.split("=");u==="resize"&&p?p.split(",").forEach(d=>{const[g,m]=d.split(":");g==="width"||g==="height"?s[g]=Number(m):g==="fit"&&(s.fit=m)}):u==="output"&&p?p.split(",").forEach(d=>{const[g,m]=d.split(":");g==="format"&&(s.format=m)}):u==="auto_image"&&(s.format="auto")}),{src:`https://${o}.graphassets.com/${r}/${n}`,operations:s,options:{region:o,envId:r,handle:n}}},In=(t,e,i={})=>{const o=ki(t);if(!o)throw new Error("Invalid Hygraph URL");const{region:r,envId:n,handle:a}={...o.options,...i},s=[];if(e.width||e.height){const p=[];e.width&&e.height?p.push("fit:crop"):e.fit&&p.push(`fit:${e.fit}`),e.width&&p.push(`width:${e.width}`),e.height&&p.push(`height:${e.height}`),p.length&&s.push(`resize=${p.join(",")}`)}e.format==="auto"||!e.format&&!o.operations.format?s.push("auto_image"):e.format&&s.push(`output=format:${e.format}`);const l=`https://${r}.graphassets.com/${n}`,c=s.length>0?"/"+s.join("/"):"",u=w(`${l}${c}/${a}`);return T(u)},En=j(ki,In),{operationsGenerator:jn,operationsParser:Dn}=L({keyMap:{width:"w",height:"h",format:"f"},defaults:{m:"cropbox"},kvSeparator:"_",paramSeparator:"/"}),zn=(t,e)=>{const i=jn(e),o=w(t);return o.searchParams.set("imgeng",i),T(o)},On=t=>{const e=w(t),i=e.searchParams.get("imgeng");if(!i)return null;const o=Dn(i);return e.searchParams.delete("imgeng"),{src:T(e),operations:o}},qn=j(On,zn),{operationsGenerator:Fn,operationsParser:Rn}=L({keyMap:{width:"w",height:"h",format:"f",quality:"q"},defaults:{c:"maintain_ratio",fo:"auto"},kvSeparator:"-",paramSeparator:","}),Un=(t,e)=>{const i=Fn(e),o=w(t);return o.searchParams.set("tr",i),T(o)},Ln=t=>{const e=w(t);let i=null,o=e.pathname;if(e.searchParams.has("tr"))i=e.searchParams.get("tr"),e.searchParams.delete("tr");else{const n=e.pathname.split("/"),a=n.findIndex(s=>s.startsWith("tr:"));a!==-1&&(i=n[a].slice(3),o=n.slice(0,a).concat(n.slice(a+1)).join("/"))}if(!i)return null;e.pathname=o;const r=Rn(i);return{src:T(e),operations:r}},Wn=j(Ln,Un),{operationsGenerator:Gn,operationsParser:Bn}=L({keyMap:{format:"fm",width:"w",height:"h",quality:"q"},defaults:{fit:"min",auto:"format"}}),Nn=t=>{const e=w(t),i=Bn(t);return e.search="",{src:T(e),operations:i}},Hn=(t,e)=>{const i=Gn(e),o=w(t);return o.search=i,o.searchParams.has("fm")&&o.searchParams.get("auto")==="format"&&o.searchParams.delete("auto"),T(o)},Yn=j(Nn,Hn),{operationsGenerator:Vn,operationsParser:Kn}=L({keyMap:{width:"w",height:"h",quality:"q",format:"f"},defaults:{f:"auto"},kvSeparator:"_",paramSeparator:","}),Wt=(t,e,i)=>{e.width&&e.height&&(e.s=`${e.width}x${e.height}`,delete e.width,delete e.height);const o=Vn(e),r=i?.baseURL??"/_ipx",n=w(r);return n.pathname=`${lt(n.pathname)}
3/${o}/${mi(t.toString())}`,T(n)},Jn=t=>{const e=w(t),[,i,o,...r]=e.pathname.split("/");if(!o||!r.length)return null;const n=Kn(o);if(n.s){const[a,s]=n.s.split("x").map(Number);n.width=a,n.height=s,delete n.s}return{src:"/"+r.join("/"),operations:n,options:{baseURL:`${e.origin}/${i}`}}},Zn=(t,e,i)=>{const o=w(t),r=i?.baseURL;if(r&&o.toString().startsWith(r)||o.pathname.startsWith("/_ipx")){const n=Jn(t);if(n)return Wt(n.src,{...n.operations,...e},{baseURL:n.options.baseURL})}return Wt(t,e,{baseURL:r})},_i=["enlarge","flip","flop","negate","normalize","grayscale","removealpha","olrepeat","progressive","adaptive","lossless","nearlossless","metadata"],{operationsGenerator:Xn,operationsParser:Qn}=L({defaults:{fit:"cover"},formatMap:{jpg:"jpeg"}}),ea=(t,e)=>{const i=w(t);for(const o of _i)e[o]!==void 0&&(e[o]=e[o]?1:0);return i.search=Xn(e),T(i)},ta=t=>{const e=w(t),i=Qn(e);for(const o of _i)i[o]!==void 0&&(i[o]=bi(i[o]));return e.search="",{src:T(e),operations:i}},ia=j(ta,ea),{operationsGenerator:oa,operationsParser:ra}=L({formatMap:{jpg:"jpeg"},keyMap:{format:"fm",width:"w",height:"h",quality:"q"}}),na=(t,e)=>{const i=w(t);return e.lossless!==void 0&&(e.lossless=e.lossless?1:0),e.width&&e.height&&(e.fit="crop"),i.search=oa(e),T(i)},aa=t=>{const e=w(t),i=ra(e);return i.lossless!==void 0&&(i.lossless=bi(i.lossless)),e.search="",{src:T(e),operations:i}},sa=j(aa,na),{operationsGenerator:la,operationsParser:ca}=L({defaults:{fit:"cover"},keyMap:{format:"fm",width:"w",height:"h",quality:"q"}}),ua=(t,e,i={})=>{const o=w(`${i.baseUrl||""}/.netlify/images`);return o.search=la(e),o.searchParams.set("url",t.toString()),T(o)},da=t=>{if(xe(t)!=="netlify")return null;const e=w(t),i=ca(e);delete i.url;const o=e.searchParams.get("url")||"";return e.search="",{src:o,operations:i,options:{baseUrl:e.hostname==="n"?void 0:e.origin}}},ha=j(da,ua),{operationsGenerator:pa,operationsParser:fa}=L({keyMap:{width:"w",quality:"q",height:!1,format:!1},defaults:{q:75}}),$i=(t,e,i={})=>{const o=w(`${i.baseUrl||""}/${i.prefix||"_vercel"}/image`);return o.search=pa(e),o.searchParams.append("url",t.toString()),T(o)},Si=(t,e={})=>{if(!["vercel","nextjs"].includes(xe(t)||""))return null;const i=w(t),o=i.searchParams.get("url")||"";i.searchParams.delete("url");const r=fa(i);return i.search="",{src:o,operations:r,options:{baseUrl:e.baseUrl??i.origin}}},ga=j(Si,$i),ma=(t,e,i={})=>$i(t,e,{...i,prefix:"_next"}),ya=(t,e)=>Si(t,e),ba=j(ya,ma),{operationsGenerator:va,operationsParser:wa}=L({keyMap:{width:"wid",height:"hei",quality:"qlt",format:"fmt"},defaults:{fit:"crop,0"}}),Ti="https://s7d1.scene7.com/is/image/",ka=(t,e)=>{const i=new URL(t,Ti);return i.search=va(e),T(i)},_a=t=>{if(ct(t)!=="scene7")return null;const e=new URL(t,Ti),i=wa(e);return e.search="",{src:e.toString(),operations:i}},$a=j(_a,ka),it=/(.+?)(?:_(?:(pico|icon|thumb|small|compact|medium|large|grande|original|master)|(\d*)x(\d*)))?(?:_crop_([a-z]+))?(\.[a-zA-Z]+)(\.png|\.jpg|\.webp|\.avif)?$/,{operationsGenerator:Sa,operationsParser:Ta}=L({keyMap:{format:!1}}),Pa=(t,e)=>{const i=w(t),o=i.pathname.replace(it,"$1$6");return i.pathname=o,i.search=Sa(e),T(i)},xa=t=>{const e=w(t),i=it.exec(e.pathname),o=Ta(e);if(i){const[,,,n,a,s]=i;n&&a&&!o.width&&!o.height&&(o.width=parseInt(n,10),o.height=parseInt(a,10)),s&&(o.crop??=s)}const r=e.pathname.replace(it,"$1$6");e.pathname=r;for(const n of["width","height","crop","pad_color","format"])e.searchParams.delete(n);return{src:e.toString(),operations:o}},Ma=j(xa,Pa),Aa=/(?<id>\/f\/\d+\/\d+x\d+\/\w+\/[^\/]+)\/?(?<modifiers>m\/?(?<crop>\d+x\d+:\d+x\d+)?\/?(?<resize>(?<flipx>\-)?(?<width>\d+)x(?<flipy>\-)?(?<height>\d+))?\/?(filters\:(?<filters>[^\/]+))?)?$/,Ca=/^(?<modifiers>\/(?<crop>\d+x\d+:\d+x\d+)?\/?(?<resize>(?<flipx>\-)?(?<width>\d+)x(?<flipy>\-)?(?<height>\d+))?\/?(filters\:(?<filters>[^\/]+))?\/?)?(?<id>\/f\/.+)$/,Ia=/:(?![^(]*\))/,Ea=t=>t?Object.fromEntries(t.split(Ia).map(e=>{if(!e)return[];const[i,o]=e.split("(");return[i,o.replace(")","")]})):{},ja=t=>{if(!t)return;const e=Object.entries(t).map(([i,o])=>`${i}(${o??""})`);if(e.length!==0)return`filters:${e.join(":")}`},Da=t=>{const e=w(t),o=(e.hostname==="img2.storyblok.com"?Ca:Aa).exec(e.pathname);if(!o||!o.groups)return null;const{id:r,crop:n,width:a,height:s,filters:l,flipx:c,flipy:u}=o.groups,{format:p,...d}=Ea(l??"");e.hostname==="img2.storyblok.com"&&(e.hostname="a.storyblok.com");const g=Object.fromEntries([["width",Number(a)||void 0],["height",Number(s)||void 0],["format",p],["crop",n],["filters",d],["flipx",c],["flipy",u]].filter(([m,f])=>f!==void 0));return{src:`${e.origin}${r}`,operations:g}},za=(t,e)=>{const i=w(t),{width:o=0,height:r=0,format:n,crop:a,filters:s={},flipx:l="",flipy:c=""}=e,u=`${l}${o}x${c}${r}`;n&&(s.format=n);
3const p=[i.pathname,"m",a,u,ja(s)].filter(Boolean);return i.pathname=p.join("/"),T(i)},Oa=j(Da,za),Le="/storage/v1/object/public/",We="/storage/v1/render/image/public/",qa=t=>t.pathname.startsWith(We),{operationsGenerator:Fa,operationsParser:Ra}=L({}),Ua=(t,e)=>{const i=w(t),o=i.pathname.replace(We,Le);return i.pathname=o,e.format&&e.format!=="origin"&&delete e.format,i.search=Fa(e),T(i).replace(Le,We)},La=t=>{const e=w(t),i=Ra(e),o=qa(e),r=e.pathname.replace(We,"").replace(Le,"");return o?{src:`${e.origin}${Le}${r}`,operations:i}:{src:T(e),operations:i}},Wa=j(La,Ua),Pi=/^https?:\/\/(?<host>[^\/]+)\/(?<uuid>[^\/]+)(?:\/(?<filename>[^\/]+)?)?/,{operationsGenerator:Ga,operationsParser:Ba}=L({keyMap:{width:!1,height:!1},defaults:{format:"auto"},kvSeparator:"/",paramSeparator:"/-/"}),Na=t=>{const e=w(t),i=Pi.exec(e.toString());if(!i||!i.groups)return null;const{host:o,uuid:r}=i.groups,[,...n]=e.pathname.split("/-/"),a=Ba(n.join("/-/")||"");if(a.resize){const[s,l]=a.resize.split("x");s&&(a.width=parseInt(s)),l&&(a.height=parseInt(l)),delete a.resize}return{src:`https://${o}/${r}/`,operations:a,options:{host:o}}},Ha=(t,e,i={})=>{const o=w(t),r=i.host||o.hostname,n=Pi.exec(o.toString());n?.groups&&(o.pathname=`/${n.groups.uuid}/`),e.resize=e.resize||`${e.width??""}x${e.height??""}`,delete e.width,delete e.height;const a=fr(Ga(e));return o.hostname=r,o.pathname=lt(o.pathname)+(a?`/-/${a}`:"")+(n?.groups?.filename??""),T(o)},Ya=j(Na,Ha),{operationsGenerator:Va,operationsParser:Ka}=L({keyMap:{width:"w",height:"h"},defaults:{crop:"1"}}),Ja=(t,e)=>{const i=w(t),{crop:o}=e;return typeof o<"u"&&o!=="0"&&(e.crop=o?"1":"0"),i.search=Va(e),T(i)},Za=t=>{const e=w(t),i=Ka(e);return i.crop!==void 0&&(i.crop=i.crop==="1"),e.search="",{src:T(e),operations:i}},Xa=j(Za,Ja),{operationsGenerator:Qa,operationsParser:es}=L({keyMap:{width:"w",height:"h",format:"output",quality:"q"},defaults:{fit:"cover"}}),ts=t=>{const e=w(t),i=e.searchParams.get("url");if(!i)return null;let o=i;!o.startsWith("http://")&&!o.startsWith("https://")&&(o="https://"+o),e.searchParams.delete("url");const r=es(e);return{src:o,operations:r}},is=(t,e)=>{const i=new URL("https://wsrv.nl/"),r=(typeof t=="string"?t:t.toString()).replace(/^https?:\/\//,"");i.searchParams.set("url",r);const n=Qa(e),a=new URLSearchParams(n);for(const[s,l]of a)s!=="url"&&i.searchParams.set(s,l);return T(i)},os=j(ts,is),rs={appwrite:Er,astro:Or,"builder.io":Ur,bunny:Nr,cloudflare:Jr,cloudflare_images:rn,cloudimage:cn,cloudinary:mn,contentful:kn,contentstack:Tn,directus:An,hygraph:En,imageengine:qn,imagekit:Wn,imgix:Yn,ipx:Zn,keycdn:ia,"kontent.ai":sa,netlify:ha,nextjs:ba,scene7:$a,shopify:Ma,storyblok:Oa,supabase:Wa,uploadcare:Ya,vercel:ga,wordpress:Xa,wsrv:os};function ns(t){if(t)return rs[t]}function as({cdn:t,fallback:e,operations:i={},options:o,...r}){if(t??=ct(r.src)||e,!t)return r;const n=ns(t);return n?cr({...r,operations:i?.[t],options:o?.[t],transformer:n}):r}function ss(t,e){const i=RegExp(t,"g");return o=>{if(typeof o!="string")throw new TypeError(`expected an argument of type string, but got ${typeof o}`);return o.match(i)?o.replace(i,e):o}}const ls=ss(/[A-Z]/,t=>`-${t.toLowerCase()}`);function cs(t,e=ls){if(!t||typeof t!="object"||Array.isArray(t))throw new TypeError(`expected an argument of type object, but got ${typeof t}`);return Object.keys(t).map(i=>`${e(i)}: ${t[i]};`).join(` 4`)}var us=M("<img/>");function ds(t,e){Y(e,!0);let i=re(e,["$$slots","$$events","$$legacy","style"]),o=q(()=>as(i)),r=q(()=>b(o).alt),n=q(()=>b(o).style),a=q(()=>b(o).src),s=q(()=>b(o).width),l=q(()=>b(o).height),c=q(()=>b(o).loading),u=q(()=>b(o).decoding),p=q(()=>b(o).srcset),d=q(()=>b(o).role),g=q(()=>b(o).sizes),m=q(()=>b(o).fetchpriority),f=q(()=>[cs(b(n)||{}),e.style].filter(Boolean).join(";"));const{cdn:h,fallback:y,operations:D,options:z,breakpoints:S,background:W,objectFit:_,unstyled:k,layout:A,aspectRatio:G,...$}=i;var ee=us();et(ee,(ne,ye,Me,Ne)=>({...$,style:b(f),loading:b(c),width:b(s),height:b(l),decoding:b(u),role:b(d),fetchpriority:b(m),alt:ne,src:ye,srcset:Me,sizes:Ne}),[()=>b(r)?.toString(),()=>b(a)?.toString(),()=>b(p)?.toString(),()=>b(g)?.toString()]),Po(ee),v(t,ee),V()}function Ze(t,e){Y(e,!0);let i=re(e,["$$slots","$$events","$$legacy","imageId","variant"]),o=q(()=>Js.getImageUrl(e.imageId,e.variant));ds(t,E({get src(){return b(o)}},()=>i)),V()}var hs=ii('<svg width="1.2em" height="1.2em" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M16 2C8.27812 2 2 8.27812 2 16C2 23.7219 8.27812 30 16 30C23.7219 30 30 23.7219 30 16C30 8.27812 23.7219 2 16 2Z" fill="#FC471E"></path><path fill-rule="evenodd" clip-rule="evenodd" d="M20.0193 8.90951C20.0066 8.98984 20 9.07226 20 9.15626C20 10.0043 20.6716 10.6918 21.5 10.6918C22.3284 10.6918 23 10.0043 23 9.15626C23 8.30819 22.3284 7.6207 21.5 7.6207C21.1309 7.6207 20.7929 7.7572 20.5315 7.98359L16.6362 7L15.2283 12.7651C13.3554 12.8913 11.671 13.4719 10.4003 14.3485C10.0395 13.9863 9.54524 13.7629 9 13.7629C7.89543 13.7629 7 14.6796 7 15.8103C7 16.5973 7.43366 17.2805 8.06967 17.6232C8.02372 17.8674 8 18.1166 8 18.3696C8 21.4792 11.5817 24 16 24C20.4183 24 24 21.4792 24 18.3696C24 18.1166 23.9763 17.8674 23.9303 17.6232C24.5663 17.2805 25 16.5973 25 15.8103C25 14.6796 24.1046 13.7629 23 13.7629C22.4548 13.7629 21.9605 13.9863 21.5997 14.3485C20.2153 13.3935 18.3399 12.7897 16.2647 12.7423L17.3638 8.24143L20.0193 8.90951ZM12.5 18.8815C13.3284 18.8815 14 18.194 14 17.3459C14 16.4978 13.3284 15.8103 12.5 15.8103C11.
46716 15.8103 11 16.4978 11 17.3459C11 18.194 11.6716 18.8815 12.5 18.8815ZM19.5 18.8815C20.3284 18.8815 21 18.194 21 17.3459C21 16.4978 20.3284 15.8103 19.5 15.8103C18.6716 15.8103 18 16.4978 18 17.3459C18 18.194 18.6716 18.8815 19.5 18.8815ZM12.7773 20.503C12.5476 20.3462 12.2372 20.4097 12.084 20.6449C11.9308 20.8802 11.9929 21.198 12.2226 21.3548C13.3107 22.0973 14.6554 22.4686 16 22.4686C17.3446 22.4686 18.6893 22.0973 19.7773 21.3548C20.0071 21.198 20.0692 20.8802 19.916 20.6449C19.7628 20.4097 19.4524 20.3462 19.2226 20.503C18.3025 21.1309 17.1513 21.4449 16 21.4449C15.3173 21.4449 14.6345 21.3345 14 21.1137C13.5646 20.9621 13.1518 20.7585 12.7773 20.503Z" fill="white"></path></svg>');function ps(t){var e=hs();v(t,e)}function fs(t,e){Y(e,!0);let i=re(e,["$$slots","$$events","$$legacy"]);const o=[["path",{d:"M18 2h-3a5 5 0 0 0-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 0 1 1-1h3z"}]];ge(t,E({name:"facebook"},()=>i,{get iconNode(){return o},children:(r,n)=>{var a=H(),s=O(a);Z(s,()=>e.children??J),v(r,a)},$$slots:{default:!0}})),V()}function gs(t,e){Y(e,!0);let i=re(e,["$$slots","$$events","$$legacy"]);const o=[["path",{d:"M12 2v13"}],["path",{d:"m16 6-4-4-4 4"}],["path",{d:"M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8"}]];ge(t,E({name:"share"},()=>i,{get iconNode(){return o},children:(r,n)=>{var a=H(),s=O(a);Z(s,()=>e.children??J),v(r,a)},$$slots:{default:!0}})),V()}function ms(t,e){Y(e,!0);let i=re(e,["$$slots","$$events","$$legacy"]);const o=[["path",{d:"M22 4s-.7 2.1-2 3.4c1.6 10-9.4 17.3-18 11.6 2.2.1 4.4-.6 6-2C3 15.5.5 9.6 3 5c2.2 2.6 5.6 4.1 9 4-.9-4.2 4-6.6 7-3.8 1.1 0 3-1.2 3-1.2z"}]];ge(t,E({name:"twitter"},()=>i,{get iconNode(){return o},children:(r,n)=>{var a=H(),s=O(a);Z(s,()=>e.children??J),v(r,a)},$$slots:{default:!0}})),V()}var ys=M('<li role="none"><a target="_blank" rel="noopener noreferrer" class="flex items-center gap-3 rounded-lg px-2 py-2 hover:bg-base-200" role="menuitem"><!> Share on X</a></li> <li role="none"><a target="_blank" rel="noopener noreferrer" class="flex items-center gap-3 rounded-lg px-2 py-2 hover:bg-base-200" role="menuitem"><!> Share on Reddit</a></li> <li role="none"><a target="_blank" rel="noopener noreferrer" class="flex items-center gap-3 rounded-lg px-2 py-2 hover:bg-base-200" role="menuitem"><!> Share on Facebook</a></li>',1),bs=M('<li role="none"><button type="button" class="flex w-full items-center gap-3 rounded-lg px-2 py-2 hover:bg-base-200" role="menuitem"><!> Share with...</button></li>'),vs=M('<div><div role="presentation" class="inline-block"><!></div> <div><div class="modal-backdrop" role="button" tabindex="-1" aria-label="Close dialog"></div> <div class="modal-box bg-base-300"><div class="mb-4 flex items-center justify-between"><h3 class="text-lg font-bold">Share</h3> <button type="button" class="btn btn-circle btn-ghost btn-sm" aria-label="Close dialog"><!></button></div> <ul class="w-full" role="menu"><!> <!> <li role="none"><button type="button" class="flex w-full items-center gap-3 rounded-lg px-2 py-2 hover:bg-base-200" role="menuitem"><!> </button></li></ul></div></div></div>');function Al(t,e){Y(e,!0);const i=q(()=>Mt.url.origin+"/sh"+Mt.url.pathname);let o=q(()=>"share"in navigator),r=de(!1),n=de(!1),a=q(()=>`https://x.com/intent/tweet?text=${encodeURIComponent(e.title)}&url=${encodeURIComponent(b(i))}`),s=q(()=>`https://www.reddit.com/submit?url=${encodeURIComponent(b(i))}&title=${encodeURIComponent(e.title)}`),l=q(()=>`https://www.facebook.com/sharer/sharer.php?u=${encodeURIComponent(b(i))}`);function c(){X(r,!0)}function u(){X(r,!1)}function p(C){(C.key==="Enter"||C.key===" ")&&C.stopPropagation()}async function d(){try{await navigator.clipboard.writeText(b(i)),X(n,!0),setTimeout(()=>{X(n,!1)},2e3)}catch(C){console.error("Failed to copy link:",C)}}async function g(){try{await navigator.share({title:e.title,url:b(i)}),u()}catch(C){C instanceof Error&&C.name!=="AbortError"&&console.error("Failed to share:",C)}}var m=vs(),f=P(m);f.__click=c,f.__keydown=p;var h=P(f);Z(h,()=>e.children),x(f);var y=F(f,2);let D;var z=P(y);z.__click=u,z.__keydown=C=>C.key==="Escape"&&u();var S=F(z,2),W=P(S),_=F(P(W),2);_.__click=u;var k=P(_);pi(k,{class:"size-4"}),x(_),x(W);var A=F(W,2),G=P(A);Jo(G,{hide:!0,children:(C,Ae)=>{var pe=ys(),be=O(pe),Ce=P(be);Ce.__click=u;var Ci=P(Ce);ms(Ci,{class:"size-[1.2em] text-secondary"}),U(),x(Ce),x(be);var He=F(be,2),Ie=P(He);Ie.__click=u;var Ii=P(Ie);ps(Ii),U(),x(Ie),x(He);var xt=F(He,2),Ee=P(xt);Ee.__click=u;var Ei=P(Ee);fs(Ei,{class:"size-[1.2em] text-secondary"}),U(),x(Ee),x(xt),oe(()=>{K(Ce,"href",b(a)),K(Ie,"href",b(s)),K(Ee,"href",b(l))}),v(C,pe)},$$slots:{default:!0}});var $=F(G,2);{var ee=C=>{var Ae=bs(),pe=P(Ae);pe.__click=g;var be=P(pe);gs(be,{class:"size-[1.2em] text-accent"}),U(),x(pe),x(Ae),v(C,Ae)};Q($,C=>{b(o)&&C(ee)})}var ne=F($,2),ye=P(ne);ye.__click=d;var Me=P(ye);{var Ne=C=>{gi(C,{class:"size-[1.2em] text-success"})},Mi=C=>{fi(C,{class:"size-[1.2em]"})};Q(Me,C=>{b(n)?C(Ne):C(Mi,!1)})}var Ai=F(Me);x(ye),x(ne),x(A),x(S),x(y),x(m),oe(()=>{D=Be(y,1,"modal",null,D,{"modal-open":b(r)}),Te(Ai,` ${b(n)?"Copied!":"Copy link"}`)}),v(t,m),V()}he(["click","keydown"]);var ws=M('<div class="sticky top-0 z-10 flex items-center justify-center"><div class="flex items-center justify-center rounded bg-base-content"><a aria-label="Get Pro for a discount"><div class="flex items-center justify-center gap-2 py-2 pr-2 pl-4"><p class="text-sm font-semibold text-base-100"> <span class="font-mono"> </span></p></div></a> <button aria-label="Close discount" class="btn btn-circle bg-transparent bt
4n-ghost btn-sm"><!></button></div></div>');function Cl(t,e){Y(e,!0);const i=q(()=>!!e.promotion?.valid&&e.promotion.percentOff>0);let o=de(!1);var r=H(),n=O(r);{var a=s=>{var l=ws(),c=P(l),u=P(c),p=P(u),d=P(p),g=P(d),m=F(g),f=P(m,!0);x(m),x(d),x(p),x(u);var h=F(u,2);h.__click=()=>X(o,!0);var y=P(h);pi(y,{class:"h-4 w-4 text-base-100"}),x(h),x(c),x(l),oe(()=>{K(u,"href",`/apps/${e.appSlug??""}/pro?${vl.discountParam}=${e.promotion.code??""}`),Te(g,`${e.promotion.percentOff??""}% off Pro with `),Te(f,e.promotion.code)}),v(s,l)};Q(n,s=>{b(i)&&!b(o)&&s(a)})}v(t,r),V()}he(["click"]);function N(t,e){Y(e,!0);var i=H(),o=O(i);Z(o,()=>e.children??J),v(t,i),V()}const ut={title:"Moving From Ear Training Apps to Real Music",description:"Ear-training apps are great for clarity, but the real skill is hearing and labeling notes and chords inside actual songs. This guide lays out a simple, feeling-first routineâshort drills, concrete listening tasks, and creation exercisesâto bridge the gap fast.",authorId:"max-konyi",publishDate:"2025-10-26",updateDate:"2026-03-16",image:"e6c94f92-e597-4b24-8d31-f08df2045600",videoId:"QejyY6SBICU",published:!0},{title:Il,description:El,authorId:jl,publishDate:Dl,updateDate:zl,image:Ol,videoId:ql,published:Fl}=ut;var ks=M('<h2 id="table-of-contents">Table of Contents</h2> <ul><li><a href="#introduction">Introduction</a></li> <li><a href="#the-big-idea">The big idea</a></li> <li><a href="#melody">Melody</a></li> <li><a href="#chords">Chords</a></li> <li><a href="#one-tiny-session-to-try-today">One tiny session to try today</a></li> <li><a href="#want-more">Want more?</a></li></ul> <h2 id="introduction">Introduction</h2> <p>Ear training apps can be very helpful, but being good at an app isnât the goal. Real progress happens when you carry that experience and skill into actual songs. This post distills the main ideas from <a href="https://www.youtube.com/watch?v=QejyY6SBICU" target="_blank" rel="noopener">my latest video</a> into a simple plan you can use today.</p> <hr/> <h2 id="the-big-idea">The big idea</h2> <p>Real music should be part of your ear-training routine from the beginning. Use the app to learn clear, <strong>contextual</strong> feelings of notes and chords (anchored to a tonic), then apply them immediately to songs you love. Apps are just the training room. Real music is all that really matters in the end.</p> <hr/> <h2 id="melody">Melody</h2> <h3 id="what-makes-real-music-harder">What makes real music harder?</h3> <ul><li><strong>Changing harmony</strong> shifts how each scale degree feels in subtle but important ways.</li> <li><strong>Arbitrary instrumentation</strong> (voices, guitars, synths, layers) can fool you if all your training is done in apps with limited sounds.</li> <li><strong>Mindset</strong> is different: the way you listen when training in an app is not necessarily the same as when listening to real music.</li></ul> <h3 id="the-solution">The solution</h3> <ol><li><strong>Master the pure feeling-states</strong> of scale degrees against the drone in <a href="/apps/ear-trainer">Sonofield</a>. <ul><li>If you canât recognize them in the training room, you wonât recognize them in the wild.</li> <li>Learn about all the 12 feeling-states in this post: <a href="/blog/guided-tour-of-musical-feeling">A Guided Tour of Musical Feeling</a>.</li></ul></li> <li><strong>Work with real songs right away</strong>âlistening, labeling, and singing. <ul><li>Over time, your brain learns to hear through the arrangement and find the degree clearly, even as harmony moves.</li></ul></li></ol> <h3 id="try-this-listen-with-labels">Try this: Listen with labels</h3> <blockquote><p><strong>Goal:</strong> Link what you hear to actual degrees in real time.<br/> <strong>Setup:</strong> Pick a simple song (childrenâs songs, pop, country, etc.) and <a href="/blog/find-the-key-of-any-song-in-30-seconds">find the key</a>.</p></blockquote> <h4 id="steps">Steps:</h4> <ol><li>Sing the tonic to lock in the key.</li> <li>Transcribe a short phrase.</li> <li>Work out the scale degrees (e.g., â3-4-3-2-3-1â).</li> <li>Play the phrase again and <strong>listen while thinking of the numbers</strong> as the notes pass. <ul><li><strong>Check:</strong> Do the degree labels âclickâ with the feelings you experience? If not, sing the phrase slowly against a drone to gain clarity. Go back to the song when ready.</li></ul></li></ol> <h3 id="try-this-produce-melodies-consciously">Try this: Produce melodies consciously</h3> <blockquote><p><strong>Goal:</strong> Keep degree awareness while improvising.<br/> <strong>Setup:</strong> Use a drone or simple backing track.</p></blockquote> <h4 id="steps-1">Steps:</h4> <ol><li>Improvise <strong>slowly</strong>
4. Donât play a note until you know which degree it will be.</li> <li>Focus on the feeling-state of each note you play in relation to the tonic, even as the chords change. <ul><li>If you get confused, play the tonic to recalibrate and come back to where you were.</li></ul></li> <li>Donât be fancy. The goal is ear training, not performance.<br/> <strong>Check:</strong> Is there a match between the degrees youâre thinking, feeling, and seeing on your instrument? If not, simplify and meet your ears where theyâre at.</li></ol> <h3 id="try-this-hold-one-degree-while-harmony-changes">Try this: Hold one degree while harmony changes</h3> <blockquote><p><strong>Goal:</strong> Hear how arrangement and chords âshadeâ a single note.<br/> <strong>Setup:</strong> Any song where you <a href="/blog/find-the-key-of-any-song-in-30-seconds">know the key</a>.</p></blockquote> <h4 id="steps-2">Steps:</h4> <ol><li>Choose a degree (e.g., <strong>2</strong>).</li> <li>Sing or play that same degree through an entire verse/chorus while the music moves.</li> <li>Stay focused on the feeling-state of your degree and notice how it subtly shifts in response to the changing harmony and arrangement. <strong>Check:</strong> Can you keep focus on the degree without getting lost? If not, pause the music and recalibrate by singing the degree against a tonic drone before trying again.</li></ol> <h4 id="tips">Tips</h4> <ul><li>Keep the melody in the <strong>foreground of your mind</strong>; let everything else fall back.</li> <li>Aim for <strong>immediate recognition</strong>, not interval math or resolution tricks.</li> <li><strong>Ignore absolute pitch</strong>; track the <em>feeling-state</em> of the degree relative to the tonic.</li></ul> <hr/> <h2 id="chords">Chords</h2> <h3 id="what-makes-real-music-harder-1">What makes real music harder?</h3> <ul><li><strong>Instrumentation:</strong> Chords are spread across the band, not plunked on a single instrument.</li> <li><strong>Voicings & inversions:</strong> Any given chord can be rendered in many ways that you may not be familiar with.</li> <li><strong>Distractions:</strong> Drums, melodies, moving bassânothing stands still.</li></ul> <h3 id="the-solution-1">The solution</h3> <ol><li>In the app or on your instrument, learn <strong>chord qualities</strong> (major, minor, sus, 7thsâ¦) as unique feeling-states.</li> <li>Learn the feeling-states of <strong>chord numbers</strong> (I, ii, IV, bVII, etc.) so you can hear root degrees in a key.</li> <li>In real songs, listen for the <strong>holistic vertical quality</strong> of each momentâlet the whole arrangement fuse into one chord sensationâthen label it as a combination of number and quality (e.g., IVmaj7)</li></ol> <h3 id="try-this-transcribe-songs--analyze-mistakes">Try this: Transcribe songs & analyze mistakes</h3> <blockquote><p><strong>Goal:</strong> Identify chords in real songs.<br/> <strong>Setup:</strong> Find a playlist of harmonically simple music (pop, folk, country, etc.).</p></blockquote> <h4 id="steps-3">Steps:</h4> <ol><li>Work out the chords of the verse/chorus using the feeling-states learned during training.</li> <li>For the chords you canât get instinctively, use any means necessary (app training, music theory, bass notes, transcription apps, etc.). <ul><li>If you are truly stumped, try looking up the chords online.</li></ul></li> <li>Write down the progression in numeral format for clarity (e.g., <strong>Imaj7âviâIVsus2âV9</strong>).</li> <li>Listen back to the song with this knowledge in mind so that your brain can make links between sound, feeling, and label.</li> <li>Repeat for the next songs in the playlist. Quantity is important here.</li></ol> <h3 id="try-this-stay-conscious-when-you-play">Try this: Stay conscious when you play</h3> <blockquote><p><strong>Goal:</strong> Apply accurate chord labels to the music you play.<br/> <strong>Setup:</strong> Choose a song or chord progression you know.</p></blockquote> <h4 id="steps-4">Steps:</h4> <ol><li><a href="/blog/find-the-key-of-any-song-in-30-seconds">Identify the key</a> and label the chords using roman numerals.</li> <li>Say out loud: â<strong>I (major)</strong> ⦠<strong>vi (minor)</strong> ⦠<strong>II (minor)</strong> â¦â as you play.</li> <li>Notice how the <strong>quality</strong> and the <strong>number</strong> each carry a feeling. <ul><li>The end result is a single sensation for each chord which is the combination of both aspects.</li></ul></li> <li>Occasionally alter one element at a time, comparing and contrasting the way it feels. For example: <ol><li>
4Change a single chord to another of the same quality but different number (e.g., <strong>ii</strong> becomes <strong>iii</strong> or <strong>vi</strong>).</li> <li>Change the quality of a single chord while maintaining the same root note (e.g., <strong>IV</strong> becomes <strong>iv</strong> or <strong>IV7</strong>)</li> <li>Change the inversion of a single chord while keeping the same quality and root note (e.g., <strong>Em</strong> becomes <strong>Em/G</strong> or <strong>Em/B</strong>)</li></ol></li> <li>This provides your mind with the information it needs to learn what is important and what can be ignored.</li></ol> <h4 id="reality-check">Reality check</h4> <ul><li>The possibility space of harmony is massive. Use <strong>theory to narrow your options</strong> (common progressions, diatonic sets, bass clues).</li> <li>You wonât catch every voicing by ear at first. Start with <strong>quality + number</strong>; refine details later.</li></ul> <hr/> <h2 id="one-tiny-session-to-try-today">One tiny session to try today</h2> <ul><li><strong>App:</strong> Sing the degrees of a major (or minor) scale in <a href="/apps/ear-trainer">Sonofield</a> against the drone in Free Play.</li> <li><strong>Song:</strong> Listen to a simple song and take note of your instinctive guesses for each melody note.</li> <li><strong>Check:</strong> <a href="/blog/find-the-key-of-any-song-in-30-seconds">Find the key</a> and sing the melody against a tonic drone. Determine the degrees.</li> <li><strong>Confirm:</strong> Listen to the song again with correct scale degrees in mind. Sing along until you feel everything click.</li></ul> <hr/> <h2 id="want-more">Want more?</h2> <p>If you want to master the feeling-first approach Iâve outlined here, download the <a href="/apps/ear-trainer">Sonofield</a> app for free and start your journey on The Path. Learning to play music by ear in this way is both very useful and deeply satisfying. Iâm sure youâll dig it!</p> <p>For a guide on how to find the key of a song check out this blog post: <a href="/blog/find-the-key-of-any-song-in-30-seconds">How to Find the Key of Any Song in 30 Seconds</a>.</p> <p>Talk soon,<br/> Max ð</p>',1);function _s(t,e){const i=B(e,["children","$$slots","$$events","$$legacy"]);N(t,E(()=>i,()=>ut,{children:(o,r)=>{var n=ks();U(100),v(o,n)},$$slots:{default:!0}}))}const Rl=Object.freeze(Object.defineProperty({__proto__:null,default:_s,metadata:ut},Symbol.toStringTag,{value:"Module"})),dt={title:"What Are the Benefits of Ear Training?",description:"Ear training builds practical musical fluency. Youâll recognize scale degrees faster, learn songs by ear, make better improvisation and composition choices, sing and tune more accurately, and move through music with confidence.",authorId:"max-konyi",publishDate:"2025-09-19",updateDate:"2026-03-16",image:"a9479fc8-25d8-48a1-724e-537055033f00",published:!0},{title:Ul,description:Ll,authorId:Wl,publishDate:Gl,updateDate:Bl,image:Nl,published:Hl}=dt;var $s=M(`<h2 id="table-of-contents">Table of Contents</h2> <ul><li><a href="#what-ear-training-actually-trains">What ear training actually trains</a></li> <li><a href="#the-core-benefits">The core benefits</a></li> <li><a href="#how-those-benefits-happen">How those benefits happen</a></li> <li><a href="#a-short-exercise">A short exercise</a></li> <li><a href="#common-myths">Common myths</a></li> <li><a href="#next-steps">Next steps</a></li></ul> <h2 id="what-ear-training-actually-trains">What ear training actually trains</h2> <p>
4Ear training is about learning to recognize and label musical structures (scale degrees, intervals, chords, rhythms, etc.) by ear, without the need for an instrument or guesswork. In truth, however, ear training is actually mind training. You learn to translate the raw experience of music into labels and concepts which fit together in a mental framework, allowing you to understand whatâs happening in real-time. This has massive benefits for musicians of all kinds.</p> <hr/> <h2 id="the-core-benefits">The core benefits</h2> <h3 id="1-learn-songs-by-ear-quickly-and-easily">1. Learn songs by ear quickly and easily</h3> <p>After internalizing the <a href="/blog/guided-tour-of-musical-feeling">feeling-states of scale degrees</a> and chords, the notes which make up the melodies and harmonies of a song become obvious. There is a sense that the answers jump out at you without effort.</p> <p><strong>Youâll notice:</strong></p> <ul><li>Less reliance on sheets and tabs.</li> <li>Fewer rewinds when figuring out a song.</li> <li>Greater confidence in what youâre playing or singing.</li></ul> <h3 id="2-stronger-improvisation--composition-choices">2. Stronger improvisation & composition choices</h3> <p>Ear training applies as much to your musical imagination (AKA âaudiationâ) as it does to external listening. Moving from the sound in your mind to actual notes in the air becomes easy and natural.</p> <p><strong>Youâll notice:</strong></p> <ul><li>Less frustration when improvising or composing.</li> <li>An intuitive sense of which notes work with which chords.</li> <li>Reduced focus on shapes, patterns, and memorized licks.</li></ul> <h3 id="3-easier-transcription--analysis">3. Easier transcription & analysis</h3> <p>The secrets of great music are hidden in plain sound. A developed ear leads to unlocking these secrets through painless transcription and analysis.</p> <p><strong>Youâll notice:</strong></p> <ul><li>Increased speed and accuracy when transcribing.</li> <li>Stronger connection between sound, feeling, and music theory.</li> <li>More fun when studying music.</li></ul> <h3 id="4-better-intonation-timing-and-audiation">4. Better intonation, timing, and audiation</h3> <p>All the fundamentals of music are strengthened through ear training. Itâs like increasing the resolution and clarity of music in your mind.</p> <p><strong>Youâll notice:</strong></p> <ul><li>Finer perception of tuning and intonation.</li> <li>More vibrant audiation.</li> <li>Steadier and more accurate rhythm.</li></ul> <h3 id="5-faster-composition-and-production-workflows">5. Faster composition and production workflows</h3> <p>Hearing more accurately means less time hunting for chords, bass lines, and melodies when writing music or making beats.</p> <p><strong>Youâll notice:</strong></p> <ul><li>More fun and flow when producing/composing music.</li> <li>Better choices that make more musical sense.</li> <li>Easier manipulation of samples and loops through hearing whatâs happening.</li></ul> <h3 id="6-confident-collaboration--jamming">6. Confident collaboration & jamming</h3> <p>A sharp ear means you can play along without having to speak. Shared terminology (labels) means that, when you do need to communicate, there is less confusion.</p> <p><strong>Youâll notice:</strong></p> <ul><li>A relaxed disposition when jamming and rehearsing.</li> <li>The ability to find the right notes without having to ask.</li> <li>Better understanding of musical discussions.</li></ul> <h3 id="7-greater-overall-musical-fluency">7. Greater overall musical fluency</h3> <p>Ear training leads to a deeper feeling of musicality from the ground up. You become a native speaker of the language, able to understand and respond more instinctively.</p> <p><strong>Youâll notice:</strong></p> <ul><li>A real satisfaction born of true understanding.</li> <li>Greater creativity and musical freedom in all areas.</li> <li>Authentic trust in your self, your ear, and your own sensibilities.</li></ul> <hr/> <h2 id="how-those-benefits-happen">How those benefits happen</h2> <ul><li><strong>Contextual training:</strong> real music happens in the context of a key; ear training should be the same.</li> <li><strong>Feeling-first:</strong> get to know the unique quality of the degree, chord, or rhythm youâre trying to learn.</li> <li><strong>Use your voice:</strong> singing, while keeping correct labels in mind, is the most direct route to a keen ear.</li> <li><strong>Wholistic routine:</strong> deep ear training requires engagement with music in a variety of ways, not just via apps.</li> <li><strong>Be consistent:</strong> a little everyday goes a long way!</li></ul> <hr/> <h2 id="a-short-exercise">A short exercise</h2> <h3 id="the-goal">The goal</h3> <p>Get to know the feeling-states of scale degrees 1, 3, and 5.</p> <h3 id="setup">Setup</h3> <ul><li>Option 1: Use <a href="/apps/ear-trainer">Sonofield Ear Trainer</a>. Go to Free Play Mode and start the drone.</li> <li>Option 2: Use an instrument (piano or guitar). Play a steady drone for yourself using a low note between C2 and B2, gently hitting it repeatedly few seconds.</li></ul> <h3 id="steps">Steps</h3> <ol><li>Take a deep breath and relax. A restful mind is key.</li> <li>Sing the tonic (drone note), in any octave that is comfortable, and hold it for 3 to 10 seconds. <
4ol><li>Notice the resolved, stable feeling as you resonate with the drone.</li> <li>Take a short break and repeat the note several times, bathing in the experience.</li></ol></li> <li>Now sing scale degree <strong>5</strong>. Hold it. Feel into the open, clear quality. Explore the resonance.</li> <li>Return to <strong>1</strong> (the tonic) and then alternate between the two degrees, comparing and contrasting them.</li> <li>Now sing scale degree <strong>3</strong>. How does it feel? <em>Sweet? Warm? Lush?</em></li> <li>Compare all three degrees by moving between them slowly: <strong>1â3â5â3â1</strong></li> <li>Remember: ignore the pitch and focus on the feeling.</li></ol> <h3 id="check-your-progress">Check your progress</h3> <p>Once youâve gotten familiar with these feeling-states, open up <a href="/apps/ear-trainer">Sonofield Ear Trainer</a> and go to level 1 in Degree Mode. Take it slow, sing the notes back to clarify them, and see how you do.</p> <p>If it feels difficult or unclear, take a break and return to the drone exercise later on. You need to gain more experience with each degree. This process canât be forced and there is no rush. Take your time and remain consistent.</p> <hr/> <h2 id="common-myths">Common myths</h2> <h3 id="intervals-drills-are-enough">âIntervals drills are enough.â</h3> <p>Intervals training can be helpful, but musical <em>feeling</em> is created through relationship to a tonal center, the tonic. Contextual training is the most powerful approach to develop relative pitch.</p> <h3 id="perfect-pitch-is-better-than-relative-pitch">âPerfect pitch is better than relative pitch.â</h3> <p>Although people with perfect pitch can identify exactly which notes are being played, itâs relative pitch which tells you how the music structured and whatâs really going on. Also, there is little evidence to suggest perfect pitch can be developed at all if you donât already have it.</p> <h3 id="labels-and-music-theory-will-kill-my-creativity">âLabels and music theory will kill my creativity.â</h3> <p>In my experience, the opposite is true. My musical experience has become richer and more nuanced as Iâve progressed in my ear training. As well, since I can trust my ear more, I take more risks and explore new material because I know how to find my way back.</p> <hr/> <h2 id="next-steps">Next steps</h2> <ul><li>Try todayâs exercise once moreâ<strong>sing 1â3â5â3 over a drone</strong>âthen test yourself in <a href="/apps/ear-trainer">Sonofield Ear Trainer</a>. Repeat daily as you explore more scale degrees.</li> <li>Want a deeper overview of the approach? Read <a href="/blog/sonofield-ear-trainer-method">The Sonofield Method</a>.</li></ul> <p>Enjoy the journey!</p> <p>Talk soon, 5Max ð</p>`,1);function Ss(t,e){const i=B(e,["children","$$slots","$$events","$$legacy"]);N(t,E(()=>i,()=>dt,{children:(o,r)=>{var n=$s();U(120),v(o,n)},$$slots:{default:!0}}))}const Yl=Object.freeze(Object.defineProperty({__proto__:null,default:Ss,metadata:dt},Symbol.toStringTag,{value:"Module"})),ht={title:"The Best Ear Training Apps of 2026",description:"A 2026 guide to the best ear training apps for melodies, chords, and intervals. Clear picks, honest trade-offs, and current pricing for Sonofield, ToneGym, EarMaster, Complete Ear Trainer, Tenuto, Chet, Perfect Ear, Earpeggio, and Functional Ear Trainer.",authorId:"max-konyi",publishDate:"2025-10-22",updateDate:"2026-03-16",image:"caeb1439-9bb8-4e07-0665-b5cf7e262600",published:!0},{title:Vl,description:Kl,authorId:Jl,publishDate:Zl,updateDate:Xl,image:Ql,published:ec}=ht;var Ts=M(`<h2 id="table-of-contents">Table of Contents</h2> <ul><li><a href="#introduction">Introduction</a></li> <li><a href="#how-i-judged">How I judged</a></li> <li><a href="#reviews">Reviews</a></li> <li><a href="#conclusion">Conclusion</a></li></ul> <h2 id="introduction">Introduction</h2> <p>Iâve been using ear training apps for over 15 years and have tried almost everything on the market. Most arenât very good, some are decent, and a few are exceptional. In this post, I will give you my top recommendations for various use cases, as well as a compact review of some of the best apps available when it comes to tonal ear training.</p> <h3 id="tldr-quick-picks">TL;DR Quick Picks</h3> <ul><li><strong>Best for melodies:</strong> <a href="#sonofield-iosandroidmacos">Sonofield</a> (feeling-based, contextual, modern)</li> <li><strong>Best for chords:</strong> <a href="#chet-ios">Chet</a> (many input methods, real music examples)</li> <li><strong>Best for producers and desktop users:</strong> <a href="#tonegym-web">ToneGym</a> (browser-based, many tools, community)</li> <li><strong>Best for classrooms:</strong> <a href="#earmaster-iosandroidmacoswindows">EarMaster</a> (desktop + mobile, huge curriculum, standard notation)</li> <li><strong>Best for hands-free training:</strong> <a href="#sonofield-iosandroidmacos">Sonofield</a> (customizable hands-free training)</li></ul> <blockquote><p><strong>Disclosure:</strong> Sonofield is my app. I strive to be honest and fair in my reviews. Prices below are USD and may vary by region.</p></blockquote> <hr/> <h2 id="how-i-judged">How I judged</h2> <ul><li><strong>Contextual training & transfer to real music:</strong> Does the method used mimic actual music through establishing a strong key center?</li> <li><strong>Skills trained:</strong> Which aspects of ear training does the app focus on?</li> <li><strong>UX and UI:</strong> Is the overall experience of the app enjoyable and intuitive?</li> <li><strong>Sound quality:</strong> Are the sounds used pleasing to the ear?</li> <li><strong>Singing support:</strong> Can you sing/confirm degrees cleanly and build internal pitch?</li> <li><strong>Progression & customization:</strong> Is the learning path well crafted? Can you create your own exercises?</li> <li><strong>Platform & price:</strong> iOS/Android/Web/Desktop; one-time purchase vs subscription.</li></ul> <hr/> <h2 id="reviews">Reviews</h2> <h3 id="sonofield-iosandroidmacos">Sonofield (iOS/Android/macOS)</h3> <h4 id="why-its-great">Why itâs great:</h4> <ul><li>A unique and intuitive method based on <a href="/blog/guided-tour-of-musical-feeling">the way notes feel within a key</a>.</li> <li>Beautiful interface and a calming, meditative vibe.</li> <li>Multiple modes for comprehensive training of melodic scale degree recognition. <ul><li>Includes a mic-based voice mode and a useful hands-free training option.</li></ul></li> <li>Full progression path with gamification elements.</li> <li>Try it for free, and a one-time optional Pro upgrade.</li> <li>Progress and Pro status can be synced across devices and operating systems.</li></ul> <h4 id="pricing">Pricing:</h4> <ul><li>Try it for free, and a one-time optional Pro upgrade ($17.99).</li> <li>Pro unlocks all features, customization options, and instruments.</li></ul> <h4 id="best-for">Best for:</h4> <ul><li>Instrumentalists and singers who resonate with a feeling-based approach over interval math.</li></ul> <h4 id="trade-offs">Trade-offs:</h4> <ul><li>No chordal training. <a href="/newsletter/subscribe?item=blog-bstap" target="_blank" rel="noopener">Join our newsletter</a> to get priority access to our coming <strong>Chord App!</strong></li> <li>No standard music notation.</li></ul> <h4 id="links">Links:</h4> <ul><li><a href="/apps/ear-trainer">Sonofield website</a></li> <li><a href="/download/ear-trainer/ios?item=blog-bstap" rel="noopener" target="_blank">Download on iOS and macOS</a></li> <li><a href="/download/ear-trainer/android?item=blog-bstap" rel="noopener" target="_blank">Download on Android</a></li> <li><a href="/apps/ear-trainer/pro">Get Sonofield Pro</a></li></ul> <hr/> <h3 id="complete-ear-trainer-iosandroid">Complete Ear Trainer (iOS/Android)</h3> <h4 id="why-its-great-1">Why itâs great:</h4> <ul><li>Robust curriculum covering intervals, scales, chords, and basic chord progressions.</li> <li>Clean, elegant interface.</li> <li>Deep customization options for personalized training. <ul><li>Includes an option to join custom training programs created by a teacher or friend.</li></ul></li> <li>Gamification elements with leaderboards and achievements.</li> <li>Theory cards that explain relevant concepts.</li></ul> <h4 id="pricing-1">Pricing:</h4> <ul><li>Limited free version and a one-time Full Version upgrade ($12.99). <ul><li>Full Version includes all chapters in each training mode.</li></ul></li></ul> <h4 id="best-for-1">Best for:</h4> <ul><li>Full-spectrum traditional ear training</li></ul> <h4 id="trade-offs-1">Trade-offs:</h4> <ul><li>Not all exercises translate to real-world skills. Can feel sterile or academic.</li> <li>Issues with very high and low registers during questions can be frustrating and unrealistic.</li></ul> <h4 id="links-1">Links:</h4> <ul><li><a href="https://completeeartrainer.com/" rel="nofollow noopener noreferrer" target="_blank">Complete Ear Trainer website</a></li> <li><a href="https://apps.apple.com/app/complete-ear-trainer/id1012455471" rel="nofollow noopener noreferrer" target="_blank">Download on iOS</a></li> <li><a href="https://play.google.com/store/apps/details?id=com.binaryguilt.completeeartrainer" rel="nofollow noopener noreferrer" target="_blank">Download on Android</a></li></ul> <hr/> <h3 id="tonegym-web">ToneGym (Web)</h3> <h4 id="why-its-great-2">Why itâs great:</h4> <ul><li>Big, browser-based platform you can use anywhereâno install.</li> <li>Lots of focused games and workouts for melody, rhythm, intervals, chords, and notation.</li> <li>Community features like message boards, contests, user profiles, and more.</li> <li>Optional music education courses and theory tools.</li></ul> <h4 id="pricing-2">Pricing:</h4> <ul><li>Fairly limited free version.</li> <li>Pro Plan is subscription-based with monthly ($18.95/mo) and yearly tiers ($99.95/yr). <ul><li>Pro gives access to all tools, statistics, and personalized training.</li> <li>There is a one-time lifetime purchase option but it is very pricey.</li></ul></li></ul> <h4 id="best-for-2">Best for:</h4> <ul><li>Beginners who want personalized, gamified practice in the browser instead of a mobile app.</li></ul> <h4 id="trade-offs-2">Trade-offs:</h4> <ul><li>Potentially overwhelming amount of content and extraneous features.</li> <li>Actual exercises are quite basic.</li> <li>The interface feels a bit dated.</li></ul> <h4 id="links-2">Links:</h4> <ul><li><a href="https://www.tonegym.co/" rel="nofollow noopener noreferrer" target="_blank">ToneGym website</a></li></ul> <hr/> <h3 id="tenuto-ios">Tenuto (iOS)</h3> <h4 id="why-its-great-3">Why itâs great:</h4> <ul><li>A tight set of <strong>24</strong> customizable exercises plus <strong>6</strong> calculators covering notes, intervals, scales, chords, fretboard/keyboard ID, and ear training.</li> <li>No fluff, no accounts. Just open and practice; great for quick theory and ear training reps.</li> <li>Traditional training exercises with standard music notation.</li></ul> <h4 id="pricing-3">Pricing:</h4> <ul><li>No free version, although the exercises can be used for free in the browser at <a href="https://www.musictheory.net/exercises" rel="nofollow">musictheory.net</a></li> <li>The app is a one-time purchase ($4.99).</li></ul> <h4 id="best-for-3">Best for:</h4> <ul><li>iOS users who want a reliable toolkit for ear training and theory practice on a budget.</li></ul> <h4 id="trade-offs-3">Trade-offs:</h4> <ul><li>iOS-only; no Android or web.</li> <li>Ear training is only a portion of what is offered.</li> <li>Exercises are quite basic.</li></ul> <h4 id="links-3">Links:</h4> <ul><li><a href="https://www.musictheory.net/products/tenuto" rel="nofollow noopener noreferrer" target="_blank">Tenuto website</a></li> <li><a href="https://apps.apple.com/app/tenuto/id459313476" rel="nofollow noopener noreferrer" target="_blank">Download on iOS</a></li></ul> <hr/> <h3 id="earmaster-iosandroidmacoswindows">EarMaster (iOS/Android/macOS/Windows)</h3> <h4 id="why-its-great-4">Why itâs great:</h4> <ul><li>Massive curriculum for ear training <strong>and</strong> sight-singing: thousands of lessons across melody, rhythm, intervals, chords, solfège, and vocal training.</li> <li>Mic features (voice/clap recognition), MIDI input, and sampled instruments for responsive feedback.</li> <li>Well-suited for schools and choirs (Cloud edition, access codes, admin tools).</li> <li>Traditional academic approach with standard notation and keyboard input.</li></ul> <h4 id="pricing-4">Pricing:</h4> <ul><li>Limited free version with 4 modules of a Beginnerâs Course.</li> <li>Subscriptions are monthly ($5.99/mo) or yearly ($43.80/yr). <ul><li>Subscription includes access to all Ear Master content on mobile and PC/Mac.</li></ul></li></ul> <h4 id="best-for-4">Best for:</h4> <ul><li>Teachers and students looking for a comprehensive ear training solution which aligns and integrates with traditional curricula.</li></ul> <h4 id="trade-offs-4">Trade-offs:</h4> <ul><li>Scope may be too broad for many individual musicians at home.</li> <li>Academic framing; not as minimal or quick to use as other apps.</li> <li>Interface can feel clunky and dated.</li></ul> <h4 id="links-4">Links:</h4> <ul><li><a href="https://earmaster.com/" rel="nofollow noopener noreferrer" target="_blank">EarMaster website</a></li> <li><a href="https://apps.apple.com/app/earmaster-music-theory/id1105030163" rel="nofollow noopener noreferrer" target="_blank">Download on iOS</a></li> <li><a href="https://play.google.com/store/apps/details?id=com.earmaster.android" rel="nofollow noopener noreferrer" target="_blank">Download on Android</a></li> <li><a href="https://earmaster.com/download-form.html?product=pro" rel="nofollow noopener noreferrer" target="_blank">Download on Desktop</a></li></ul> <hr/> <h3 id="functional-ear-trainer-iosandroid">Functional Ear Trainer (iOS/Android)</h3> <h4 id="why-its-great-5">Why itâs great:</h4> <ul><li>Classic functional approach: learn to recognize scale degrees in the context of a key using melodic resolutions.</li> <li>Structured learning path moving through major and minor keys as well as chromatic tone
5s.</li> <li>Multiple modes: single notes, two notes at once, melodies, and hands-free mode.</li> <li>Customizable exercises.</li></ul> <h4 id="pricing-5">Pricing:</h4> <ul><li>Free version is limited but very usable with basic single degree training and custom exercises.</li> <li>At the time of writing, the app is moving from a one-time purchase ($19.99) to a subscription model. This will apparently happen soon but the pricing is not yet public. <ul><li>The Plus version of the app includes all exercise modes and levels, as well as 20+ instrument sounds.</li></ul></li></ul> <h4 id="best-for-5">Best for:</h4> <ul><li>Beginners looking to explore melodic scale degrees using the traditional approach.</li></ul> <h4 id="trade-offs-5">Trade-offs:</h4> <ul><li>Steep price relative to other apps. Will soon be a subscription.</li> <li>The UI is fairly basic and plain.</li></ul> <h4 id="links-5">Links:</h4> <ul><li><a href="https://getfet.app/" rel="nofollow noopener noreferrer" target="_blank">Functional Ear Trainer website</a></li> <li><a href="https://apps.apple.com/app/functional-ear-trainer/id1088761926" rel="nofollow noopener noreferrer" target="_blank">Download on iOS</a></li> <li><a href="https://play.google.com/store/apps/details?id=com.kaizen9.fet.android" rel="nofollow noopener noreferrer" target="_blank">Download on Android</a></li></ul> <hr/> <h3 id="chet-ios">Chet (iOS)</h3> <h4 id="why-its-great-6">Why itâs great:</h4> <ul><li>Large curriculum including single notes, scales, chords, and progressions.</li> <li>Better sound quality than most apps and certain exercises even use real music snippets.</li> <li>On-screen piano, guitar, and bass input as well as mic and MIDI support.</li> <li>Competitive daily challenge with a global leaderboard.</li></ul> <h4 id="pricing-6">Pricing:</h4> <ul><li>Chet is entirely free!</li></ul> <h4 id="best-for-6">Best for:</h4> <ul><li>iOS users on a budget who want to ear train with standard notation and instrument input.</li></ul> <h4 id="trade-offs-6">Trade-offs:</h4> <ul><li>iOS-only; no Android or web.</li> <li>Focuses more on absolute pitches than contextual relationships in a key.</li> <li>Landscape orientation only.</li></ul> <h4 id="links-6">Links:</h4> <ul><li><a href="https://www.ensemble-education.com/chet" rel="nofollow noopener noreferrer" target="_blank">Chet website</a></li> <li><a href="https://apps.apple.com/app/chet-ear-training/id1405525467" rel="nofollow noopener noreferrer" target="_blank">Download on iOS</a></li></ul> <hr/> <h3 id="earpeggio-ios">Earpeggio (iOS)</h3> <h4 id="why-its-great-7">Why itâs great:</h4> <ul><li>A range of simple exercises covering intervals, chords, chord progressions, melody dictation, and rhythm dictation.</li> <li>Goal-based tests and progress stats.</li> <li>Lightweight, functional UI.</li> <li>Virtual keyboard input and standard notation.</li> <li>Includes a unique Melodic Contour exercise, which can be quite helpful.</li></ul> <h4 id="pricing-7">Pricing:</h4> <ul><li>Completely free on iOS!</li></ul> <h4 id="best-for-7">Best for:</h4> <ul><li>iOS users who want quick, classic ear-training drills (including dictation) in a no-nonsense package.</li></ul> <h4 id="trade-offs-7">Trade-offs:</h4> <ul><li>iOS-only; no Android or web version.</li> <li>A focus on traditional identification drills, which arenât always useful in real life.</li> <li>Sound quality and overall vibe are quite basic.</li></ul> <h4 id="links-7">Links:</h4> <ul><li><a href="https://musicate.app/earpeggio" rel="nofollow noopener noreferrer" target="_blank">Earpeggio website</a></li> <li><a href="https://apps.apple.com/app/earpeggio/id884775105" rel="nofollow noopener noreferrer" target="_blank">Download on iOS</a></li></ul> <hr/> <h3 id="perfect-ear-iosandroid">Perfect Ear (iOS/Android)</h3> <h4 id="why-its-great-8">Why itâs great:</h4> <ul><li>Large collection of exercises and drills: from intervals, scales, and chords, to rhythm training, sight reading, and absolute pitch.</li> <li>Guided Courses for different ability levels to help you progress smoothly.</li> <li>Customizable exercises.</li> <li>Daily tracked statistics.</li> <li>Text-based music theory tutorials.</li></ul> <h4 id="pricing-8">Pricing:</h4> <ul><li>Generous free version with many exercises in different categories.</li> <li>Premium version ($4.99) unlocks all exercises. <ul><li>Custom exercise editor is a separate purchase ($1.99)</li></ul></li></ul> <h4 id="best-for-8">Best for:</h4> <ul><li>Learners who want a budget-friendly, customizable âmusic school in your pocketâ across both iOS and Android.</li></ul> <h4 id="trade-offs-8">Trade-offs:</h4> <ul><li>Exercises are quite traditional. Not much in the way of contextual training.</li> <li>Tonal ear training is only a portion of the appâs focus.</li></ul> <h4 id="links-8">Links:</h4> <ul><li><a href="https://www.perfectear.app/" rel="nofollow noopener noreferrer" target="_blank">Perfect Ear website</a></li> <li><a href="https://apps.apple.com/app/perfect-ear-ear-trainer/id1440768353" rel="nofollow noopener noreferrer" target="_blank">Download on iOS</a></li> <li><a href="https://play.google.com/store/apps/details?id=com.evilduck.musiciankit" rel="nofollow noopener noreferrer" target="_blank">Download on Android</a></li></ul> <hr/> <h2 id="conclusion">Conclusion</h2> <p>If thereâs a theme here, itâs this: the <strong>method</strong> matters as much as the <strong>app</strong>. Tools that anchor you to a key tend to transfer faster to real music than apps that only ask you to âhear and copyâ or recognize musical structures without context. From there, itâs just matching the tool to your goal:</p> <ul><li><strong>Melodies & singing:</strong> Start with <a href="#sonofield-iosandroidmacos">Sonofield</a> for feeling-based recognition; add <a href="#earmaster-iosandroidmacoswindows">EarMaster</a> if you want notation-centric sight-singing.</li> <li><strong>Melodic intervals:</strong> <a href="#complete-ear-trainer-iosandroid">Complete Ear Trainer</a> is the best one-time buy.</li> <li><strong>Chords on iOS:</strong> <a href="#chet-ios">Chet</a> has a good variety of exercises and input methods, with some real music examples mixed in.</li> <li><strong>Budget & basics on iOS:</strong> <a href="#tenuto-ios">Tenuto</a>, <a href="#chet-ios">Chet</a>, and <a href="#earpeggio-ios">Earpeggio</a> cover a lot for free or cheap.</li></ul> <p>You donât need the âperfectâ app, you need a <strong>consistent routine</strong> that ties drills to actual music. Sing a bit every session (even if youâre a producer), use a drone when possible, and regularly test yourself on real songs. Pick one primary app that fits your path, then supplement the gaps.</p> <p>Read my post <a href="/blog/the-perfect-ear-training-routine">The Perfect Ear Training Routine</a> for more tips.</p> <p>Read more about <a href="/blog/sonofield-ear-trainer-method">The Sonofield Ear Trainer Method</a>.</p> <hr/> <p>Thatâs it for now! I will update this post periodically as app pricing and features change often.</p> <p>Talk soon, 6Max ð</p>`,1);function Ps(t,e){const i=B(e,["children","$$slots","$$events","$$legacy"]);N(t,E(()=>i,()=>ht,{children:(o,r)=>{var n=Ts();U(256),v(o,n)},$$slots:{default:!0}}
6))}const tc=Object.freeze(Object.defineProperty({__proto__:null,default:Ps,metadata:ht},Symbol.toStringTag,{value:"Module"})),pt={title:"How to Find the Key of Any Song in 30 Seconds",description:"A simple, reliable method to find the key of real music by ear: locate the tonic note, identify the tonality major vs minor, and avoid the most common traps.",authorId:"max-konyi",publishDate:"2026-01-26",updateDate:"2026-02-19",image:"6a2da225-f369-4313-c7c1-4a285dbfc700",videoId:"lYtZxy-bqNY",published:!0},{title:ic,description:oc,authorId:rc,publishDate:nc,updateDate:ac,image:sc,videoId:lc,published:cc}=pt;var xs=M('<h2 id="table-of-contents">Table of Contents</h2> <ul><li><a href="#introduction">Introduction</a></li> <li><a href="#the-30-second-method">The 30 second method</a></li> <li><a href="#finding-the-tonic">Finding the Tonic</a></li> <li><a href="#determining-the-tonality">Determining the tonality</a></li> <li><a href="#common-mistakes">Common mistakes</a></li> <li><a href="#practice-one-daily-drill">Practice: One daily drill</a></li> <li><a href="#beyond-the-tonic">Beyond the tonic</a></li></ul> <h2 id="introduction">Introduction</h2> <p>Most people try to find the key of a song by guessing, or by relying on rules like âitâs the first chordâ or âitâs the last chord.â Sometimes these work but often they donât. Itâs very useful to be able to find the key of a song by ear, without guessing, quickly and accurately.</p> <p>A key has two parts:</p> <ul><li><strong>The tonic</strong>: the note that feels like home, resolution, completion.</li> <li><strong>The tonality</strong>: whether the key is <strong>major</strong> or <strong>minor</strong>.</li></ul> <p>In this post, youâll learn a fast method to find both, plus a few backup checks for when the answer isnât totally clear. We can use <a href="/apps/key-seeker">Key Seeker 64</a> as a practice tool for this and I will be referring to it throughout this post. Key Seeker 64 is also available inside <a href="/apps/ear-trainer">Sonofield Ear Trainer</a>.</p> <hr/> <h2 id="the-30-second-method">The 30 second method</h2> <ol><li><p><strong>Listen long enough to hear the key</strong><br/> Usually 10â15 seconds is enough (or one loop in <a href="/apps/key-seeker">Key Seeker</a>).</p></li> <li><p><strong>Find the tonic</strong><br/> Pause the music and sing the note which feels like âhomeâ, then find it on an instrument.</p></li> <li><p><strong>Decide major or minor</strong><br/> Once you have the tonic, ask: does this feel bright and major, or dark and minor?</p></li> <li><p><strong>Confirm if needed</strong><br/> Use a quick check (below) if youâre unsure.</p></li></ol> <p>Thatâs it. With practice, this process will become very fast and the answers will jump out at you. Eventually, you wonât even need to pause the music.</p> <hr/> <h2 id="finding-the-tonic">Finding the Tonic</h2> <h3 id="technique-1-resolve-the-song-in-your-mind">Technique 1: Resolve the song in your mind</h3> <p>This is the cleanest way to find the tonic.</p> <h4 id="steps">Steps</h4> <ol><li>Play the song long enough to get a sense of the key.</li> <li><strong>Pause</strong> the music.</li> <li>Imagine the whole track collapsing into one final note.</li> <li>Sing the note that feels most resolved.</li> <li>Match that note on an instrument to get the letter name.</li></ol> <h4 id="check">Check</h4> <p>When you hit the tonic, it should feel like you can stop there. No need to âcontinueâ the thought of the song. There is a strong sense of completion or resolution.</p> <ul><li>To get a sense of this feeling, play a descending major or minor scale, ending on the tonic, and focus on the quality of resolution you experience.</li></ul> <h3 id="technique-2-listen-for-the-tonic-in-the-melody-or-bass-line">Technique 2: Listen for the tonic in the melody or bass line</h3> <p>The tonic note will often show up in many places throughout a song, but the easiest places to spot it are:</p> <ul><li>The last note of the main melody. <ul><li>Listen for the point where the melody feels complete and consider that note.</li></ul></li> <li>The bass note of the tonic <em>
6chord</em>. <ul><li>Focus on the chords and see if any feel like home or resolution. If so, the bass note of that chord may be the tonic of the key.</li></ul></li></ul> <p><strong>Important:</strong> do not assume these things to be true. Treat them as a clue or a place to look, not an answer. Keep asking yourself, âDoes this really feel like the tonic?â.</p> <h3 id="technique-3-use-other-scale-degrees">Technique 3: Use other scale degrees</h3> <p>If you already do scale-degree ear training (<a href="/apps/ear-trainer">Sonofield-style</a>), you have even more options and the task is easier.</p> <h4 id="steps-1">Steps</h4> <ol><li>Play a note against the music (or when paused).</li> <li>Identify the degree (5, 3, b6, etc.).</li> <li>Find the note on an instrument.</li> <li>Calculate the tonic (i.e. if C is 5, the tonic must be F).</li></ol> <p>This is one of the many reasons why I say ear training is at the core of musical fluency.</p> <hr/> <h2 id="determining-the-tonality">Determining the tonality</h2> <h3 id="technique-1-resolve">Technique 1: Resolve</h3> <p>The goal is to perceive the tonality directly as a âvibeâ or feeling-state, not as a calculation.</p> <p>By listening to the tonic itself, the âmajornessâ or âminornessâ can be felt within it. Itâs as though the tonic becomes imbued with the tonal quality of the song altogether.</p> <h4 id="steps-2">Steps</h4> <ol><li>Find the tonic.</li> <li>Play or sing the tonic on its own.</li> <li>Ask: does this tonic feel <strong>major</strong> or <strong>minor</strong>?</li></ol> <p>In time, the tonality will become clear even before you play the tonic and you will have no doubt about your answer.</p> <h3 id="technique-2-test-the-third">Technique 2: Test the third</h3> <p>If youâre unsure whether your felt sense of the tonality is correct, you can do a simple check to confirm.</p> <h4 id="steps-3">Steps</h4> <ol><li>As the music plays, sound the <strong>minor third</strong> above the tonic.</li> <li>Then play the <strong>major third</strong> above the tonic and compare.</li> <li>Ask: which fits the music better most of the time?</li></ol> <p><strong>Example:</strong> if you think the tonic is D, compare <strong>F</strong> (minor third) vs <strong>F#</strong> (major third). The one that fits the track more cleanly usually tells you the tonality.</p> <hr/> <h2 id="common-mistakes">Common mistakes</h2> <h3 id="1-confusing-relative-major-and-minor">1. Confusing relative major and minor</h3> <p>Some music can genuinely be heard two ways (minor tonic vs relative major tonic). That ambiguity is normal, especially when the song uses both âtonicâ chords and has no strong cadences.</p> <p>When this happens:</p> <ul><li>Try both tonics as âhome.â</li> <li>Go with whichever one feels most resolved and in alignment with the vibe of the song. <ul><li><a href="/apps/key-seeker">Key Seeker 64</a> will accept either answer in these cases.</li></ul></li></ul> <h3 id="2-trusting-first-chord-or-last-chord-too-much">2. Trusting first chord or last chord too much</h3> <p>Sometimes the first chord of a song is the tonic chord. Sometimes itâs the last chord. The problem is, these arenât guaranteed to be true. You always have to listen for yourself.</p> <p>The first and last chord of a song are good places to look, but the real question is always: <strong>Does it feel like home?</strong></p> <p>If so, the bass note of that chord is most likely the tonic.</p> <hr/> <h2 id="practice-one-daily-drill">Practice: One daily drill</h2> <p>We can use <strong><a href="/apps/key-seeker">Key Seeker 64</a></strong> to practice finding the tonic and tonality of real music in a way that is convenient and reliable. Hereâs how:</p> <h3 id="steps-4">Steps</h3> <ol><li>Press play and listen to to the full loop.</li> <li>Pause the music.</li> <li>Try to sing the note which resolves or completes the song.</li> <li>Find that note on the Key Seeker keyboard (any octave is fine).</li> <li>Listen to the music again with a focus on vibe or emotional tone.</li> <li>Play the tonic in isolation and observe whether it feels major or minor.</li> <li>If unsure, confirm using the third test.</li></ol> <h3 id="progress">Progress</h3> <p>With practice, this process will become quick and painless. Your confidence will increase dramatically and your answers will have a clear sense of certainty.</p> <p><strong>Consistency</strong> is king!</p> <hr/> <h2 id="beyond-the-tonic">Beyond the tonic</h2> <p>If you want develop your ear beyond simple tonic recognition, check out my app <a href="/apps/ear-trainer">Sonofield Ear Trainer</a> for a complete training system. You will learn to recognize all the notes of a key by how they feel, allowing you to intuitively play the melodies you hear or imagine.</p> <p>Talk soon,<br/> Max ð</p>',1);function Ms(t,e){const i=B(e,["children","$$slots","$$events","$$legacy"]);N(t,E(()=>i,()=>pt,{children:(o,r)=>{var n=xs();U(126),v(o,n)},$$slots:{default:!0}}
6))}const uc=Object.freeze(Object.defineProperty({__proto__:null,default:Ms,metadata:pt},Symbol.toStringTag,{value:"Module"})),ft={title:"A Guided Tour of Musical Feeling",description:"A concise reference guide to the feeling-state of each of the 12 scale degrees, anchored to a tonic drone.",authorId:"max-konyi",publishDate:"2026-03-16",image:"c7612996-c7ed-4d15-5fa4-b28116587200",videoId:"AARDtj6wL3U",published:!0},{title:dc,description:hc,authorId:pc,publishDate:fc,image:gc,videoId:mc,published:yc}=ft;var As=M(`<h2 id="table-of-contents">Table of Contents</h2> <ul><li><a href="#introduction">Introduction</a></li> <li><a href="#degree-1--the-tonic">Degree 1 â The tonic</a></li> <li><a href="#degree-2--the-flat-second">Degree â2 â The flat second</a></li> <li><a href="#degree-2--the-second">Degree 2 â The second</a></li> <li><a href="#degree-3--the-flat-third">Degree â3 â The flat third</a></li> <li><a href="#degree-3--the-third">Degree 3 â The third</a></li> <li><a href="#degree-4--the-fourth">Degree 4 â The fourth</a></li> <li><a href="#degree-4--the-sharp-fourth">Degree â¯4 â The sharp fourth</a></li> <li><a href="#degree-5--the-fifth">Degree 5 â The fifth</a></li> <li><a href="#degree-6--the-flat-sixth">Degree â6 â The flat sixth</a></li> <li><a href="#degree-6--the-sixth">Degree 6 â The sixth</a></li> <li><a href="#degree-7--the-flat-seventh">Degree â7 â The flat seventh</a></li> <li><a href="#degree-7--the-seventh">Degree 7 â The seventh</a></li> <li><a href="#a-final-note">A final note</a></li></ul> <h2 id="introduction">Introduction</h2> <p>Most music is tonal, which means it has a key center or <strong>tonic</strong>. When you hear a note inside a key, youâre not only hearing a pitch, youâre hearing a <strong>relationship</strong> to the tonic.</p> <p>That relationship has a recognizable âvibeâ or way that it <em>feels</em>, which I call a <strong>feeling-state</strong>. This feeling-state is a particular character, âcolorâ, or emotional quality which is independent of octave and instrument timbre.</p> <p>Since weâre talking about a relationship, as opposed to a specific pitch, it makes sense to use <strong>scale degree</strong> labels instead of letter names because they can be applied to any key. Each note in the key is given a number, beginning with the tonic as degree 1.</p> <p>The major scale scale is represented as degrees 1 through 7, while the remaining five notes are raised (sharp) or lowered (flat) versions of those seven. Here is a full chromatic scale:</p> <p><strong>1 - b2 - 2 - b3 - 3 - 4 - #4 - 5 - b6 - 6 - b7 - 7</strong></p> <p>Each scale degree has a unique feeling-state which you can learn to recognize, enabling you to know which scale degrees youâre hearing as you listen to music.</p> <p>Two important clarifications:</p> <ul><li><strong>Feeling-states are subjective mental experiences.</strong> Iâm not talking about a physical sensation or typical emotion like happiness or anger.</li> <li><strong>Words are pointers, not definitions.</strong> The descriptions given below are based on my own experience. They are meant to direct your attention, not provide truths you can memorize.</li></ul> <p>If youâre practicing: use a <strong>drone</strong>, sing long tones, and try to <strong>ignore pitch</strong> as much as you can. Ask: <em>What is the quality of this relationship? What else is here besides âhigh vs lowâ?</em></p> <hr/> <h2 id="degree-1--the-tonic">Degree 1 â The tonic</h2> <p>The tonic is home base: the reference point your ear organizes everything around. Itâs the âminimum energyâ feeling in a key, where you can stop and nothing feels unfinished.</p> <h3 id="feeling-words">Feeling words:</h3> <ul><li>perfection</li> <li>whole</li> <li>home</li> <li>complete</li> <li>resolved</li></ul> <hr/> <h2 id="degree-2--the-flat-second">Degree â2 â The flat second</h2> <p>â2 sits one semitone above the tonic. Itâs extremely close to home <em>melodically</em> (pitch) but very distant <em>harmonically</em> (feeling). The feeling-state is quite intense, dark, and in-your-face.</p> <h3 id="feeling-words-1">Feeling words:</h3> <ul><li>hopeless</li> <li>desperate</li> <li>spicy</li> <li>bitter</li></ul> <hr/> <h2 id="degree-2--the-second">Degree 2 â The second</h2> <p>2 has a clean, pure quality which is very similar to 5. To me, it feels âsharpâ and defined yet emotionally calm and neutral. Itâs easily mistaken for 6 or 5.</p> <h3 id="feeling-words-2">Feeling words:</h3> <ul><li>clean</li> <li>sharp</li> <li>crystalline</li> <li>placid</li> <li>razor-like</li></ul> <hr/> <h2 id="degree-3--the-flat-third">Degree â3 â The flat third</h2> <p>â3 is the degree which defines minor. It has serious, somewhat solemn vibe which is darker than b7 but lighter than b6.</p> <h3 id="feeling-words-3">Feeling words:</h3> <ul><li>serious</li> <li>dark</li> <li>solemn</li> <li>gloomy</li> <li>sorrow</li></ul> <hr/> <h2 id="degree-3--the-third">Degree 3 â The third</h2> <p>3 is one of the primary feeling-states in musical experience. It defines a whole axis or dimension of feeling which is present as an ingredient in other, more complex scale degrees. As opposed to the clean neutrality of 5 and its related degrees (1,2, and 4), 3 has a sense of warmth and life.</p> <h3 id="feeling-words-4">Feeling words:</h3> <ul><li>warm</li> <li>glowing</li> <li>juicy</li> <li>sweet</li> <li>bright</li></ul> <hr/> <h2 id="degree-4--the-fourth">Degree 4 â The fourth</h2> <p>4 lives in the same dimension as 5 and so has a clean, neutral quality. However, whereas 5 feels open and expansive, 4 seems to contract or curl inward. Both 4 and 5 are a perfect fifth away from 1, just in opposite directions.
6</p> <h3 id="feeling-words-5">Feeling words:</h3> <ul><li>clean</li> <li>neutral</li> <li>contracted</li> <li>closing</li> <li>dull</li> <li>square</li></ul> <hr/> <h2 id="degree-4--the-sharp-fourth">Degree â¯4 â The sharp fourth</h2> <p>â¯4 sits between 4 and 5 <em>melodically</em> but has a striking, high-voltage character. It can feel like an intensified, more alien version of 7âbright tension with a strange edge.</p> <h3 id="feeling-words-6">Feeling words:</h3> <ul><li>spiky</li> <li>sharp</li> <li>spacey</li> <li>strange</li> <li>intense</li> <li>alien</li></ul> <hr/> <h2 id="degree-5--the-fifth">Degree 5 â The fifth</h2> <p>5 is the closest feeling to 1 without being 1. Itâs stable and consonant, but with more energy or activity than the tonic. It defines a whole dimension of musical feeling - one that is clean, clear and emotionally neutral.</p> <h3 id="feeling-words-7">Feeling words:</h3> <ul><li>clean</li> <li>pure</li> <li>open</li> <li>crystalline</li> <li>active</li> <li>expansive</li></ul> <hr/> <h2 id="degree-6--the-flat-sixth">Degree â6 â The flat sixth</h2> <p>â6 is a strong minor color with a heavier emotional tone than â3. Its dark and dramatic; no fun, no joy. Darker than â3 but still lighter than â2.</p> <h3 id="feeling-words-8">Feeling words:</h3> <ul><li>desperate</li> <li>tragic</li> <li>heavy</li> <li>bleak</li> <li>dark</li> <li>on-edge</li></ul> <hr/> <h2 id="degree-6--the-sixth">Degree 6 â The sixth</h2> <p>6 often feels like a lighter, softened version of 3: still pleasant and warm but less vivid - more pastel, cool or neutral. Itâs like a mix of 4 and 3. Easily confused for 3 or sometimes 2.</p> <h3 id="feeling-words-9">Feeling words:</h3> <ul><li>pleasant</li> <li>light</li> <li>pastel</li> <li>delicate</li> <li>gentle</li></ul> <hr/> <h2 id="degree-7--the-flat-seventh">Degree â7 â The flat seventh</h2> <p>â7 is the lightest of the flat degrees. Neutral and strong with a hint of minor coloring, lending it a somewhat powerful/bold character. Itâs lighthearted and fun without being sweet or delicate.</p> <h3 id="feeling-words-10">Feeling words:</h3> <ul><li>powerful</li> <li>neutral-dark</li> <li>grounded</li> <li>fun</li> <li>easy going</li></ul> <hr/> <h2 id="degree-7--the-seventh">Degree 7 â The seventh</h2> <p>7 sits one semitone below the tonic and has a strong emotional quality which is the combination of 5 and 3. Donât focus on 7 resolving to 1. Instead, get familiar with the feeling-state of 7 itself. Itâs a bittersweet tension full of life.</p> <h3 id="feeling-words-11">Feeling words:</h3> <ul><li>bittersweet</li> <li>nostalgic</li> <li>distressed</li> <li>heartbreak</li></ul> <hr/> <h2 id="a-final-note">A final note</h2> <p>If any of these are unclear, donât force it. These words come from my own subjective experiences and make sense to me but may
6not feel right to you. Put on a drone, sing the degree slowly in different octaves, and give your ear time to learn the feeling directly. Words are clumsy. Use them as a tool but let them go as you can.</p> <p>If you want to make serious progress, check out the <a href="/apps/ear-trainer">Sonofield Ear Trainer app</a> (free) and begin working through The Path. Be sure to use Free Play mode for exploration and gaining familiarity with each degree, as well as Pocket Mode for hands-free training while you do other stuff.</p> <p>Learn more about <a href="/blog/sonofield-ear-trainer-method">The Sonofield Method in this article</a>.</p> <p>Talk soon, 7Max ð</p>`,1);function Cs(t,e){const i=B(e,["children","$$slots","$$events","$$legacy"]);N(t,E(()=>i,()=>ft,{children:(o,r)=>{var n=As();U(154),v(o,n)},$$slots:{default:!0}}))}const bc=Object.freeze(Object.defineProperty({__proto__:null,default:Cs,metadata:ft},Symbol.toStringTag,{value:"Module"}));var Is=M('<button class="custom__play__btn svelte-1kg3r7u" aria-label="Play YouTube video"><!></button>'),Es=M('<button class="play__btn svelte-1kg3r7u" aria-label="Play YouTube video"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" class="iconify iconify--mdi" viewB
7ox="0 0 24 24"><path fill="#ff4e45" d="m10 15 5.19-3L10 9v6m11.56-7.83c.13.47.22 1.1.28 1.9.07.8.1 1.49.1 2.09L22 12c0 2.19-.16 3.8-.44 4.83-.25.9-.83 1.48-1.73 1.73-.47.13-1.33.22-2.65.28-1.3.07-2.49.1-3.59.1L12 19c-4.19 0-6.8-.16-7.83-.44-.9-.25-1.48-.83-1.73-1.73-.13-.47-.22-1.1-.28-1.9-.07-.8-.1-1.49-.1-2.09L2 12c0-2.19.16-3.8.44-4.83.25-.9.83-1.48 1.73-1.73.47-.13 1.33-.22 2.65-.28 1.3-.07 2.49-.1 3.59-.1L12 5c4.19 0 6.8.16 7.83.44.9.25 1.48.83 1.73 1.73Z"></path></svg></button>');function js(t,e){Y(e,!0);let i=R(e,"play",15);var o=H(),r=O(o);{var n=s=>{var l=Is();l.__click=()=>i(!0);var c=P(l);Z(c,()=>e.play_button),x(l),v(s,l)},a=s=>{var l=Es();l.__click=()=>i(!0),v(s,l)};Q(r,s=>{e.play_button?s(n):s(a,!1)})}v(t,o),V()}he(["click"]);function Ds(t){const e=t-1;return e*e*e+1}function zs(t,{delay:e=0,duration:i=400,easing:o=Ds,start:r=0,opacity:n=0}={}){const a=getComputedStyle(t),s=+a.opacity,l=a.transform==="none"?"":a.transform,c=1-r,u=s*(1-n);return{delay:e,duration:i,easing:o,css:(p,d)=>` 8 transform: ${l} scale(${1-c*d}); 9 opacity: ${s-u*d} 10 `}}var Os=M('<iframe frameborder="0" allow="autoplay; picture-in-picture; clipboard-write" allowfullscreen="" class="svelte-1sonaqy"></iframe>');function qs(t,e){let i=R(e,"title",3,""),o=R(e,"id",3,"");var r=Os();oe(()=>{K(r,"src",`https://www.youtube-nocookie.com/embed/${o()??""}?autoplay=1&rel=0`),K(r,"title",i())}),Ro(1,r,()=>zs,()=>e.animations?{delay:500,duration:800}:{}),v(t,r)}var Fs=M('<img referrerpolicy="no-referrer"/>'),Rs=M('<div class="yt__thumb"><!></div>');function Us(t,e){let i=R(e,"id",3,""),o=R(e,"title",3,""),r=R(e,"altThumb",3,""),n=R(e,"play",3,!1),a=R(e,"short",3,!1);var s=Rs(),l=P(s);{var c=p=>{var d=H(),g=O(d);Z(g,()=>e.thumbnail),v(p,d)},u=p=>{var d=H(),g=O(d);Ao(g,n,m=>{var f=Fs();let h;oe(()=>{K(f,"src",`https://i.ytimg.com/vi/${i()??""}/${r()?"hqdefault":"maxresdefault"}.jpg`),K(f,"title",o()),K(f,"alt",`Youtube video: ${o()??""}`),h=Be(f,1,"svelte-1ltmvdf",null,h,{"short-thumbnail":a()})}),v(m,f)}),v(p,d)};Q(l,p=>{e.thumbnail?p(c):p(u,!1)})}x(s),v(t,s)}var Ls=M('<!> <div class="b__overlay svelte-l73nxr" aria-label="video overlay" role="button" tabindex="0"></div> <div class="v__title svelte-l73nxr"> </div>',1),Ws=M('<div class="you__tube svelte-l73nxr"><!> <!></div>');function xi(t,e){Y(e,!0);let i=R(e,"id",3,null),o=R(e,"altThumb",3,!1),r=R(e,"animations",3,!0),n=R(e,"short",3,!1),a=de(""),s={};xo(async()=>{s=await(await fetch(`//www.youtube.com/oembed?url=https://www.youtube.com/watch?v=${i()}&format=json`)).json(),X(a,s?.title,!0)});let l=de(!1);var c=Ws(),u=P(c);{var p=f=>{qs(f,{get id(){return i()},get title(){return b(a)},get animations(){return r()}})},d=f=>{var h=Ls(),y=O(h);Us(y,{get id(){return i()},get title(){return b(a)},get altThumb(){return o()},get play(){return b(l)},get short(){return n()},get thumbnail(){return e.thumbnail}});var D=F(y,2);D.__click=()=>X(l,!0);var z=F(D,2),S=P(z,!0);x(z),oe(()=>Te(S,b(a))),Mo("keypress",D,()=>X(l,!0)),v(f,h)};Q(u,f=>{b(l)?f(p):f(d,!1)})}var g=F(u,2);{var m=f=>{js(f,{get play_button(){return e.play_button},get play(){return b(l)},set play(h){X(l,h,!0)}})};Q(g,f=>{b(l)||f(m)})}x(c),oe(()=>{li(c,`--aspect-ratio:${n()?"9/16":"16/9"}`),K(c,"title",b(a))}),v(t,c),V()}he(["click"]);const gt={title:"The Sonofield Ear Trainer Method",description:"An intuitive approach to melodic ear training that helps you learn to identify musical notes by playing them over a steady drone. The goal is to sharpen your ear and train you to recognize scale degrees by how they feel, not just how they sound.",authorId:"max-konyi",publishDate:"2026-03-16",image:"2406e3dd-78c7-45e9-06f1-c9f5ab4a4e00",published:!0},{title:vc,description:wc,authorId:kc,publishDate:_c,image:$c,published:Sc}=gt;var Gs=M('<h2 id="table-of-contents">Table of Contents</h2> <ul><li><a href="#introduction">Introduction</a></li> <li><a href="#important-terms">Important terms</a></li> <li><a href="#the-circle">The Circle</a></li> <li><a href="#how-it-works">How it works</a></li> <li><a href="#the-path">The Path</a></li> <li><a href="#a-simple-practice-plan">A simple practice plan</a></li> <li><a href="#what-results-to-expect">What results to expect</a></li> <li><a href="#where-to-start">Where to start</a></li> <li><a href="#learn-more">Learn more</a></li></ul> <h2 id="introduction">Introduction</h2> <p>Many people want to learn to play, improvise, and compose music by ear, but are confused about how best to do this. The secret lies in the fact that each note of a key has a unique character, known as a <strong>feeling-state</strong> in <a href="/apps/ear-trainer">Sonofield Ear Trainer</a>, that you can become familiar with and learn to recognize.</p> <p>The Sonofield Method is an intuitive approach to melodic ear training. Instead of memorizing intervals or doing mental math, you learn to recognize musical notes by how they feel when played over a steady drone. Over time, this becomes second nature, enabling you to identify any scale degree in real-time, regardless of whether you hear it in a melody, sing it yourself, or imagine it in your mind.</p> <hr/> <h2 id="important-terms">Important terms</h2> <h3 id="tonic">Tonic</h3> <p>Think of the tonic as âhome base.â Itâs the key centerâthe note that feels totally resolved and restful. All the other notes in a key get their feeling and meaning from their relationship to the tonic.</p> <h3 id="scale-degree">Scale degree</h3> <p>Instead of using letter names like C or Fâ¯, Sonofield labels the notes of a key using numbers known as scale degrees. A standard major scale runs from 1 through 7, and by flattening or sharpening these numbers, you can cover all twelve notes of the chromatic scale.</p> <!> <!> <p>The beauty of this system is that itâs universalâ1 is always âhome,â no matter what key youâre in. The note C feels different in the key of G than
10it does in the key of E, but scale degrees always feel the same.</p> <h3 id="feeling-state">Feeling-state</h3> <p>Each scale degree has its own unique quality or characteristic sound. For example, degree 5 always feels like 5, and degree 3 always feels like 3, no matter the octave or key. These feeling-states are what you learn to recognize in Sonofield.</p> <p>Learn about all the 12 feeling-states in this post: <a href="/blog/guided-tour-of-musical-feeling">A Guided Tour of Musical Feeling</a>.</p> <hr/> <h2 id="the-circle">The Circle</h2> <p>At the heart of the app is the <strong>Sonofield Circle</strong>âa color-coded circle of fifths which serves as both a visual aid and a functional instrument. Degrees close to each other on the circle feel similar, while those across from one another feel very different.</p> <!> <p>This layout helps your ear and mind make intuitive sense of musical space. It is also the primary interface youâll use when training in Sonofield.</p> <hr/> <h2 id="how-it-works">How it works</h2> <p>Sonofield introduces you gradually to all 12 scale degrees through different modes of play:</p> <ul><li><strong>Degrees Mode:</strong> Hear a note over a drone and identify its scale degree. This is the foundation.</li> <li><strong>Melodies Mode:</strong> Short melodic phrases instead of single notes, bringing you closer to real music.</li> <li><strong>Voice Mode:</strong> See a degree, sing it into your mic, and let the appâs tuner guide you. Singing is the fastest way to internalize feeling-states.</li> <li><strong>Pocket Mode:</strong> Hands-free listening. Perfect for walks, commutes, or downtime.</li> <li><strong>Free Play Mode:</strong> Tap around the circle, sing, and explore freely to become familiar with each feeling-state.</li></ul> <p>By practicing across these modes, your ear develops naturally. With repetition, the labels (1, 2, 3, etc.) become automatic, and you start to recognize degrees in the songs you hear every day.</p> <hr/> <h2 id="the-path">The Path</h2> <p>Each mode has a guided sequence of levels, called <strong>The Path</strong>. Think of it as a set of stepping stones: each level introduces a new degree, building steadily until youâve met all 12. Along the way, Free Play and Pocket Mode let you experiment and reinforce what youâre learning in a less structured way.</p> <hr/> <h2 id="a-simple-practice-plan">A simple practice plan</h2> <p>Consistency matters more than clocking hours. You canât force your ear to internalize a new feeling-state; it takes time, patience, and honesty. A balanced daily plan might look like this:</p> <ul><li><strong>5â15 minutes a day</strong> is enough.</li> <li>Start with Free Play. Listen to, sing, and compare scale degrees.</li> <li>Attempt your current levels in Degrees, Melodies, and Voice Modes a few times.</li> <li>Switch modes often to keep things fresh.</li> <li>Use Pocket Mode while doing chores, walking, or commuting.</li></ul> <p>And remember: not practicing is just as important as practicing. Your brain needs downtime to integrate what youâve learned.</p> <hr/> <h2 id="what-results-to-expect">What results to expect</h2> <p>Everyone learns at their own pace. Some degrees click instantly, while others take longer. Take your time; there is no rush. Over time, youâll notice less guessing and more immediate recognition.</p> <p>If you remain consistent, the results will come. One day, youâll hear a melody and instantly know: âThatâs a 6 moving to 5.â Thatâs an exciting moment and reveals the shape of things to come.</p> <hr/> <h2 id="where-to-start">Where to start</h2> <p>If youâre new, begin with Degrees Mode on the first level. Once you pass it, try the same level in Melodies Mode and Voice Mode to add context. Continue on like this, cycling between modes as you progress.</p> <p>If a particular degree feels tricky, spend extra time with it in Free Play. Contrast it against other degrees, sing it, and get comfortable. Remember to utilize Pocket Mode to train while on the go!</p> <hr/> <h2 id="learn-more">Learn more</h2> <p>More information about Sonofield and ear training altogether can be found on <a href="https://www.youtube.com/@maxkonyi" target="_blank" rel="me noopener">my YouTube channel</a>. I am the creator of SET, and the <a href="https://www.youtube.com/watch?v=EU4bV0zE4pk" target="_blank" rel="noopener">Sonofield User Guide</a> video is a good place to begin if youâre looking to get the most out of the app.</p> <p>You can <a href="/apps/ear-trainer">download the app here</a> if you have not already.</p> <div class="not-prose"><!></div>',1);function Bs(t,e){const i=B(e,["children","$$slots","$$events","$$legacy"]);N(t,E(()=>i,()=>gt,{children:(o,r)=>{var n=Gs(),a=F(O(n),22);Ze(a,{imageId:"73e22f54-368a-4c0d-971f-5c1655a89f00",variant:"public",alt:"Major Scale Degrees",layout:"constrained",class:"mx-auto",aspectRatio:1034/166,height:83});var s=F(a,2);Ze(s,{imageId:"00619d5e-6112-43e8-b266-f8eae2ce8400",variant:"public",alt:"Chromatic Scale Degrees",layout:"constrained",class:"mx-auto",aspectRatio:1034/166,height:83});var l=F(s,16);Ze(l,{imageId:"d40c7486-5ffd-4c15-6970-ce442472f100",variant:"public",alt:"Sonofield Ear Trainer Circle",layout:"constrained",class:"rounded-2xl mx-auto",aspectRatio:1,height:280});var c=F(l,54),u=P(c);xi(u,{id:"EU4bV0zE4pk",animations:!1}
10),x(c),v(o,n)},$$slots:{default:!0}}))}const Tc=Object.freeze(Object.defineProperty({__proto__:null,default:Bs,metadata:gt},Symbol.toStringTag,{value:"Module"})),mt={title:"The Perfect Ear Training Routine",description:"A simple, customizable ear training routine built on four essential skills: scale degrees, bass notes, chord qualities, and chord numbers. Learn how to practice each one daily with clarity and consistency.",authorId:"max-konyi",publishDate:"2025-09-22",updateDate:"2026-03-16",image:"6677016a-76c3-46b5-9914-d75f20beab00",published:!0},{title:Pc,description:xc,authorId:Mc,publishDate:Ac,updateDate:Cc,image:Ic,published:Ec}=mt;var Ns=M(`<h2 id="table-of-contents">Table of Contents</h2> <ul><li><a href="#introduction">Introduction</a></li> <li><a href="#key-principles">Key principles</a></li> <li><a href="#the-routine">The routine</a></li> <li><a href="#next-steps">Next steps</a></li></ul> <h2 id="introduction">Introduction</h2> <p>Ear training is the process of learning to hear music clearlyârecognizing notes, chords, and rhythms by ear and translating them into simple concepts like numbers and functions. With this skill, you can figure out chords instantly, sing melodies you imagine, and deconstruct songs without guesswork.</p> <p>But starting can feel overwhelming. Where do you begin? How do you best use your time? What skills actually matter? This routine gives you a template. It isnât one-size-fits-allâyouâll adapt it to your own goalsâbut it covers the four core skills needed to decode music:</p> <ul><li><strong>Melodic scale degrees</strong></li> <li><strong>Bass notes</strong></li> <li><strong>Chord qualities</strong> (major, minor, seventh, etc.)</li> <li><strong>Chord numbers</strong> (function and position in the key)</li></ul> <p>These are your building blocks. With steady practice, youâll become able to identify them in real music without the need for an instrument.</p> <hr/> <h2 id="key-principles">Key principles</h2> <h3 id="music-is-made-of-feeling">Music is made of feeling</h3> <p>Every degree, chord, or bass note carries a unique quality you already perceive when listening. Ear training is about labeling those qualities consistently, so you can recognize them on contact.</p> <h3 id="curiosity-comes-first">Curiosity comes first</h3> <p>Progress comes from asking simple questions as you play and listen: <em>What am I hearing? What am I playing? Which scale degree is this? Which chord quality?</em> That curiosity builds the link between sound, feeling, and label.</p> <h3 id="consistency-beats-intensity">Consistency beats intensity</h3> <p>It isnât about grinding through hours of drills. Short, honest daily sessions are far more powerful. Over time, your perception sharpens naturally through a subconscious process which canât be forced.</p> <h3 id="music-theory-is-a-framework">Music theory is a framework</h3> <p>You donât need to be a theory nerd, but knowing the basicsâkeys, scales, chords, numbersâgives you the map for what youâre hearing. Itâs the bridge between raw sound and clear understanding.</p> <hr/> <h2 id="the-routine">The routine</h2> <p>This routine ensures you spend time focusing on the four main pillars of ear training: melody, bass, chord quality, and chord degree. If you can, make time for some form of it everyday. Adjust it to match your ability level and goals.</p> <p>If you want more information, you can find a video version of this routine on my YouTube channel. Check it out using the link <a href="#next-steps">at the bottom of this post</a>!</p> <h3 id="1-drone-practice">1. Drone practice</h3> <p>Spend time singing or playing long tones against a steady drone. <a href="/blog/guided-tour-of-musical-feeling">Each scale degree has its own resonance and feeling-state</a> within a keyâbathe in it until it feels familiar, like recognizing a friendâs voice.</p> <ul><li>Start with the tonic (same note as the drone).</li> <li>Move through other degrees one by one.</li> <li>Compare and contrast their qualities.</li> <li>Once you have some familiarity, sing simple melodies using the degrees you know.</li></ul> <p>This is the foundation. <a href="/apps/ear-trainer">Sonofield Ear Trainer</a> is built for exactly this kind of degree-over-drone practice. There is no practice more important to internalizing the unique quality of each degree than this.</p> <h3 id="2-melody-transcription">2. Melody transcription</h3> <p>Pick a simple song you enjoy. Sing along until the melody feels comfortable. Then pause the recording and try to
10sing it back slowly, paying attention to the degrees.</p> <ul><li>Find the tonic.</li> <li>Work out the rest of the degrees.</li> <li>Check them on your instrument.</li> <li>Alternate between listening, singing, and labeling until the degrees feel obvious.</li></ul> <p>In the end, you want to listen back to the recorded song and track the scale degrees of the melody in real-time. Youâll know youâve got it when the mental labels click with the music; itâs a palpable experience.</p> <h3 id="3-conscious-improvisation">3. Conscious improvisation</h3> <p>Choose a drone or backing track and begin to improvise slowly and consciously. The trick is to stay aware of which scale degree youâre playing (or singing!) at all times. This builds a subconscious link between your instrument, your body, and the labels.</p> <p>Tips:</p> <ul><li>Donât let your fingers or habits run the show. Let your ear and imagination guide you.</li> <li>Remember, this is about ear training. Focus on the connection between mind and sound. Play simply and slowly.</li> <li>If you get off track and forget where you are in the key, take a moment and recalibrate. Playing 1 and 5 to anchor your ear is always a good idea!</li></ul> <h3 id="4-harmony-practice">4. Harmony practice</h3> <p>Take a simple chord progression and listen from multiple perspectives:</p> <ul><li>Play the bass line in isolation and learn to sing it. <ul><li>Take note of the scale degrees and feel into each one until everything is clear.</li></ul></li> <li>Add the chords back in and notice their qualities (major, minor, seventh, etc.). <ul><li>Focus on the feeling of each quality and how it relates to the bass note.</li></ul></li> <li>Swap qualities: change a chord from major to minor (and vice-versa) while keeping the same root. <ul><li>Example: if the progression is C-Am-Dm-F, take one of the chords and reverse its polarity. <ul><li>Possibility: C-Am-<strong>D</strong>-F</li> <li>Possibility: C-<strong>A</strong>-Dm-F</li></ul></li> <li>Compare the feeling of the chord changing quality while the bass note remains the same.</li></ul></li> <li>Swap numbers: keep the quality but change the degree. <ul><li>Example: Instead of I-vi-ii-IV, try I-vi-ii-<strong>V</strong>.</li> <li>Both IV and V are major, but they occupy different positions with the key and have their own unique feeling-states.</li></ul></li> <li>Transpose the whole progression to a new key and repeat the process. <ul><li>This will show you how the feeling of a chord or progression is relational, not absolute.</li> <li>Even though all the chords and notes are different, the overall quality of the progression is the same.</li></ul></li></ul> <p>These experiments help your mind isolate the important aspects of harmony in relation to ear training. Comparing and contrasting chords in this way will reveal what is common and what is different.</p> <hr/> <h2 id="next-steps">Next steps</h2> <p>This routine is a starting point. Customize it to your own needs, stay curious, and keep it consistent. Over time, youâll notice melodies, chords, and bass lines jump out at you without effort.</p> <p>If you want a deeper dive into melodic training, try the free version of <strong><a href="/apps/ear-trainer">Sonofield Ear Trainer</a></strong>âit guides you through degrees with drones, singing, and practice paths.</p> <p>For a guide on how to find the key of a song check out this blog post: <a href="/blog/find-the-key-of-any-song-in-30-seconds">How to Find the Key of Any Song in 30 Seconds</a>.</p> <p>Here is my video: <a href="https://www.youtube.com/watch?v=r2u_M-U-Jb0" target="_blank" rel="noopener">âThe Perfect Ear Training Routineâ</a></p> <div class="not-prose"><!></div> <p>Talk soon, 11Max ð</p>`,1);function Hs(t,e){const i=B(e,["children","$$slots","$$events","$$legacy"]);N(t,E(()=>i,()=>mt,{children:(o,r)=>{var n=Ns(),a=F(O(n),86),s=P(a);xi(s,{id:"r2u_M-U-Jb0",animations:!1}),x(a),U(2),v(o,n)},$$slots:{default:!0}}))}const jc=Object.freeze(Object.defineProperty({__proto__:null,default:Hs,metadata:mt},Symbol.toStringTag,{value:"Module"})),yt={title:"Max Konyi",description:"Hey ð Iâm a composer, music educator, and the creator of Sonofield. Iâm fascinated by the intersection of music and technology, and I love exploring new ways for people to learn, hear, and understand music more deeply.",image:"b66a8667-a40e-4c3e-edbb-3baa1e729800",jobTitle:"Music Composer and Educator",sameAs:["https://youtube.com/@maxkonyi","https://soundcloud.com/maxkonyi","https://www.sonic-sorcery.com/","https://www.udemy.com/user/max-konyi/","https://www.maxkonyi.com/"],knowsAbout:["Music Production","Music Theory","Composition","Digital Audio Workstations"]},{title:Dc,description:zc,image:Oc,jobTitle:qc,sameAs:Fc,knowsAbout:Rc}=yt;var Ys=M('<h2 id="about-me">About Me</h2> <p>I run a <a href="https://youtube.com/@maxkonyi" target="_blank" rel="me noopener">YouTube channel</a> sharing practical approaches to ear training, harmony, production, and composition. I also have a series of <a href="/authors/max-konyi#my-courses">music theory courses</a> that have helped thousands of students understand how music works from the ground up.</p> <p>My musical background and listening habits are fairly diverse, although jazz, EDM, and video game music are closest to my heart. Guitar is my primary instrument, but I also play piano, bass, and drums. However, writing music is what attracts me most, and I spend most of my time at the computer in my DAW. That focus has led me to work as a composer, sound designer, mix engineer, and content creator across a range of projects over the years.</p> <p>Outside of music, I enjoy video games, reading philosophy, exploring the nature of reality, and walking in the woods. Still, everything is music and my goal is to harmonize.</p> <h2 id="my-courses">My Courses</h2> <p>You can find my music theory courses below. By using the links provided here, as opposed to searching on the Udemy website, you are supporting me most directly:</p> <ul><li><a href="https://www.maxkonyi.com/mwd1" target="_blank" rel="noopener sponsored">Musical Warp Drive - Part 1: Fundamentals, Mind & Ear</a></li> <li><a href="https://www.maxkonyi.com/mwd2" target="_blank" rel="noopener sponsored">Musical Warp Drive - Part 2: Melody</a></li> <li><a href="https://www.maxkonyi.com/mwd3" target="_blank" rel="noopener sponsored">Musical Warp Drive - Part 3: Diatonic Harmony</a></li></ul> <h2 id="my-social-media">My Social Media</h2> <ul><li>See me on <a href="https://youtube.com/@maxkonyi" target="_blank" rel="me noopener">YouTube</a></li> <li>Hear me on <a href="https://soundcloud.com/maxkonyi" target="_blank" rel="me noopener">SoundCloud</a></li> <li>Chat with me on <a href="https://www.sonic-sorcery.com/" target="_blank" rel="me noopener">Sonic Sorcery Discord</a></li> <li>Read more on <a href="https://www.maxkonyi.com/" target="_blank" rel="me noopener">my Website</a></li></ul>',1);function Vs(t,e){const i=B(e,["children","$$slots","$$events","$$legacy"]);N(t,E(()=>i,()=>yt,{children:(o,r)=>{var n=Ys();
11U(16),v(o,n)},$$slots:{default:!0}}))}const Uc=Object.freeze(Object.defineProperty({__proto__:null,default:Vs,metadata:yt},Symbol.toStringTag,{value:"Module"})),Ks={async copyText(t){try{await navigator.clipboard.writeText(t)}catch(e){console.error("Failed to copy: ",e)}}},Xe=[{id:"ear-trainer",path:"/apps/ear-trainer",title:"Sonofield Ear Trainer"},{id:"key-seeker",path:"/apps/key-seeker",title:"Key Seeker 64"},{id:"blog",path:"/blog",title:"Blog"},{id:"other",title:"Other"}],Lc={targets:Xe,targetsWithPath:Xe.filter(t=>t.path),getTargetById:t=>Xe.find(e=>e.id===t)},Js={getImageUrl(t,e){return`https://sonofield.com/cdn-cgi/imagedelivery/7dA3JIZTPFFvDm9VRLjVqA/${t}/${e}`}},bt={title:"About Us",description:"Sonofield is a music-learning company dedicated to musical fluency through ear training. We design innovative tools that help you play music the way you experience itâby feel and contextâso you can play what you hear."},{title:Wc,description:Gc}=bt;var Zs=M('<h1 id="about-sonofield">About Sonofield</h1> <p>Sonofield is a music-learning company dedicated to musical fluency through ear training. We design innovative tools that help you play music the way you experience itâby feel and contextâso you can play what you hear.</p> <h2 id="our-approach">Our approach</h2> <ul><li>Feeling-first: start with raw experience, then name what you hear.</li> <li>Context-driven: anchor your ear with a clear tonal center.</li> <li>Learning-paths: follow a structured, step-by-step curriculum.</li> <li>Thoughtful design: an intuitive, beautiful UI to keep you in the flow-state.</li></ul> <p><a href="/blog/sonofield-ear-trainer-method">Read More About the Method</a></p> <h2 id="the-team">The team</h2> <p>Sonofield is a two-man team comprised of:</p> <ul><li><a href="/authors/max-konyi">Max Konyi</a>: music educator and composer from Canada.</li> <li>Tero Saarikivi: software developer and musician from Finland.</li></ul> <h2 id="get-in-touch">Get in touch</h2> <p>To contact us directly, you can use the following emails:</p> <h3 id="support">Support</h3> <p>If you have any issues with the website or app, please contact us at <a href="mailto:[email protected]">[email protected]</a>.</p> <h3 id="affiliates">Affiliates</h3> <p>If you would like to partner with us or offer Sonofield to your students, contact us at <a href="mailto:[email protected]">[email protected]</a>.</p> <h3 id="questions-and-greetings">Questions and greetings</h3> <p>If you have any questions or would like to say hello, contact us at <a href="mailto:[email protected]">[email protected]</a>.</p>',1);function Xs(t,e){const i=B(e,["children","$$slots","$$events","$$legacy"]);N(t,E(()=>i,()=>bt,{children:(o,r)=>{var n=Zs();U(30),v(o,n)},$$slots:{default:!0}}))}const Bc=Object.freeze(Object.defineProperty({__proto__:null,default:Xs,metadata:bt},Symbol.toStringTag,{value:"Module"})),vt={title:"Sonofield Affiliate Program Terms",description:"Learn about our affiliate program terms."},{title:Nc,description:Hc}=vt;var Qs=M('<h1 id="sonofield-affiliate-program-terms">Sonofield Affiliate Program Terms</h1> <h2 id="program-basics">Program basics</h2> <ul><li>Youâll receive a unique <strong>coupon code</strong> and <strong>sharable link</strong>.</li> <li>Share your link/code <strong>anywhere</strong> (website, socials, YouTube, newsletter, etc.).</li> <li>Your code gives customers <strong>20% off</strong> Sonofield Pro (app is free; <strong>Pro is an optional one-time upgrade</strong>).</li> <li>You earn <strong>50% commission on every Pro sale</strong> attributed to your link/code.</li> <li><strong>Commission basis: 50% of the post-discount price</strong>, excluding any transaction taxes (VAT/GST/sales tax). <ul><li><strong>Sonofield covers</strong> payment processor and payout processing fees; these <strong>do not reduce your commission</strong>.</li></ul></li> <li><strong>Payouts: on the 15th of each month</strong> for the prior monthâs eligible commissions.</li> <li><strong>Where the code works: Website checkout only</strong> (affiliate codes cannot be applied to in-app purchases).</li></ul> <h2 id="tracking--attribution">Tracking & attribution</h2> <ul><li>When a customer uses <strong>your link</strong>
11, your code is <strong>automatically applied during checkout</strong> on the Sonofield website. <ul><li>The code can also be typed in manually during checkout.</li></ul></li> <li>Any purchase made <strong>using your code</strong> will be credited to you.</li> <li>Sales that are <strong>refunded, charged back, fraudulent, or self-purchases</strong> are not commissionable.</li></ul> <h2 id="promotion-rules">Promotion rules</h2> <ul><li>Be honest and follow platform rules; no spam, misleading claims, or impersonation.</li> <li>Donât run paid ads on our brand terms (âSonofieldâ, âSonofield Ear Trainerâ) without written permission.</li> <li><strong>The price of Pro may change in the future.</strong> Be mindful of this when speaking about the offer publicly.</li></ul> <h2 id="payments">Payments</h2> <ul><li><strong>Minimum payout: $25 CAD</strong> (balances roll over until the threshold is met).</li> <li>Payments can be made to a <strong>Wise account</strong> or to your bank via <strong>wire transfer</strong>. <ul><li>You can choose this during your account setup process.</li></ul></li></ul> <h2 id="admin">Admin</h2> <ul><li>We may update or end the program; changes wonât affect already-earned eligible commissions.</li> <li><strong>Governing law:</strong> British Columbia, Canada.</li></ul>',1);function el(t,e){const i=B(e,["children","$$slots","$$events","$$legacy"]);N(t,E(()=>i,()=>vt,{children:(o,r)=>{var n=Qs();U(20),v(o,n)},$$slots:{default:!0}}))}const Yc=Object.freeze(Object.defineProperty({__proto__:null,default:el,metadata:vt},Symbol.toStringTag,{value:"Module"})),wt={title:"Aurachord Privacy Policy",description:"Privacy policy for the Aurachord mobile and web app."},{title:Vc,description:Kc}=wt;var tl=M('<h1 id="aurachord-privacy-policy">Aurachord Privacy Policy</h1> <p>Sonofield Ear Trainer Education Ltd. provides Aurachord, a mobile and web chord ear-training app. You can use Aurachord without an account. This policy explains the limited information used to provide the app.</p> <h2 id="accounts-and-synchronization">Accounts and Synchronization</h2> <p>An optional account lets you synchronize progress, achievements, settings, aggregate statistics, and necessary timestamps. Aurachord does not synchronize a complete answer history. Firebase Authentication supports Google, Apple, and passwordless email sign-in. We store the Firebase user ID, email address, authentication provider, and necessary authentication metadata. We do not ask for a name, age, or profile, or intentionally retain provider display names or profile photos.</p> <p>Firebase services provide authentication, synchronization, App Check, Cloud Functions, and feedback storage, using European regions where supported. Firebase support operations are not guaranteed to remain exclusively in the EU. Postmark sends passwordless authentication and other operational emails not sent by RevenueCat or Stripe.</p> <p>You can delete your account in the app. This removes the account and synchronized data, subject to the limited transaction retention described below.</p> <h2 id="purchases">Purchases</h2> <p>Aurachord Pro is an optional, one-time lifetime purchase, not a subscription. Free use and mobile purchases do not require an account. Apple processes App Store payments, Google processes Google Play payments, and web payments use RevenueCatâs Stripe Billing integration and Stripe-hosted checkout. We do not receive full card details. Stripe collects the purchaserâs email and sends payment messages and receipts; RevenueCat sends the purchase-redemption email.</p> <p>All purchases grant the same Aurachord Pro access across platforms through RevenueCat. RevenueCat processes the purchase, entitlement, device or customer identifier, offering or paywall variant, transaction, refund, platform, country, and app version information needed to provide access and run limited monetization experiments. Before sign-in, RevenueCat uses a pseudonymous identity; after an account is linked, it receives the Firebase user ID, but not a name or profile data.</p> <p>An anonymous purchase can later be attached to one Aurachord account. A web buyer may purchase first and create or connect an account after receiving a redemption link. Minimal transaction and entitlement records may remain after account deleti
11on where needed for restoration, fraud prevention, refunds, accounting, tax, or legal obligations.</p> <h2 id="purchase-experiments-and-affiliates">Purchase Experiments and Affiliates</h2> <p>RevenueCat may run one randomized test at a time involving pricing, paywall content, or layout. The usual primary measure is revenue per exposed customer, or sometimes purchase conversion, with refunds used as a guardrail. This is limited monetization measurement, not general behavioral analytics. Price tests exclude affiliate-code traffic; same-price copy or layout tests may include it when both variants receive the same discount treatment.</p> <p>Tolt provides coupon-only affiliate attribution through Stripe. An affiliate link may redirect to checkout with a coupon prefilled. Aurachord does not use Tolt browser tracking scripts or affiliate cookies. Tolt may process the coupon and necessary Stripe customer and transaction information, such as purchase amount, status, refund, email, and transaction identifiers, to administer commissions.</p> <h2 id="diagnostics-and-feedback">Diagnostics and Feedback</h2> <p>Aurachord uses a separate PostHog EU project only for error tracking. Reports may contain an exception, stack trace, platform, environment, app version, and build, plus an unavoidable SDK-generated anonymous technical identifier. Reports are not associated with a Firebase account, email, RevenueCat identity, supplied user ID, or person profile, and are retained for up to 90 days. Product analytics, autocapture, lifecycle analytics, session replay, surveys, feature flags, and user identification are not enabled.</p> <p>Aurachord has no general behavioral analytics. Before introducing broader analytics, we will update this policy, store disclosures, and any required consent or privacy controls.</p> <p>Feedback is optional and anonymous. It contains the text you submit plus the app version, build, and platform, without an attached account or user ID. Please do not include sensitive personal information. Feedback is retained for up to 12 months.</p> <h2 id="newsletter-video-and-advertising">Newsletter, Video, and Advertising</h2> <p>Aurachord may link to a separate newsletter form managed by Brevo. You are not enrolled automatically. Brevo receives information only when you submit the form, not app progress, Firebase user ID, or purchase history. Marketing emails include an unsubscribe option, and newsletter data is kept until unsubscribe or deletion as applicable.</p> <p>A guided-tour video is embedded without autoplay, using <code>youtube-nocookie.com</code> where supported. Displaying or playing it contacts Google or YouTube. Aurachord has no ads or advertising attribution.</p> <h2 id="retention-transfers-and-your-choices">Retention, Transfers, and Your Choices</h2> <p>Account and synchronized data remain while your account exists and are removed when you delete it, except for the limited transaction records described above. Other retention periods are stated in their sections.</p> <p>Service providers may process information outside your country. We use safeguards where required by applicable law. Where applicable, you may request access, correction, deletion, objection or restriction, portability, or withdrawal of consent by contacting us. Aurachord is not specifically directed to children; a parent or guardian may contact us with questions or a deletion request.</p> <h2 id="contact">Contact</h2> <p>For privacy questions or requests, contact <a href="mailto:[email protected]">[email protected]</a>.</p>',1);function il(t,e){const i=B(e,["children","$$slots","$$events","$$legacy"]);N(t,E(()=>i,()=>wt,{children:(o,r)=>{var n=tl();U(48),v(o,n)},$$slots:{default:!0}}))}const Jc=Object.freeze(Object.defineProperty({__proto__:null,default:il,metadata:wt},Symbol.toStringTag,{value:"Module"})),kt={title:"Aurachord Terms of Service",description:"Terms of service for the Aurachord mobile and web app."},{title:Zc,description:Xc}=kt;var ol=M('<h1 id="aurachord-terms-of-service">Aurachord Terms of Service</h1> <p>Sonofield Ear Trainer Education Ltd. provides Aurachord, a mobile and web chord ear-training app. By using Aurachord, you agree to these terms.</p> <h2 id="accounts-and-use">Accounts and Use</h2> <p>You may use Aurachord without an account. An optional account can synchronize supported app data across devices. You are responsible for access to your sign-in method and for lawful, personal use of the service. You can delete your account in the app, which removes the account and synchronized data.</p> <h2 id="aurachord-pro">Aurachord Pro</h2> <p>Aurachord Pro is an optional, one-time lifetime purchase, not a subscription. It grants the current and future Pro features of Aurachord, including future app versions. App Store, Google Play, and web purchases provide the same Aurachord Pro access across platforms through RevenueCat.</p> <p>A mobile Pro purchase may be made without an account. An anonymous purchase can later be attached to one Aurachord account. Web buyers may purchase first, receive a redemption link by email, and then create or connect an account. Pro is personal and cannot be transferred between unrelated accounts, except when support corrects an error.</p> <p>Deleting an account does not forfeit a valid purchase. Pro can be restored or recovered through the applicable app store or verified web-purchase process.</p> <h2 id="payment-and-refunds">Payment and Refunds</h2> <p>Apple processes App Store payments, Google processes Google Play payments, and web payments use RevenueCatâs Stripe Billing integration and Stripe-hosted checkout. Sonofield does not receive full card details. Apple and Google purchases follow their respective refund processes. Sonofield handles refunds for Stripe purchases subject to applicable law.</p> <p>Prices, taxes, and offers may vary by platform, country, or eligible promotion. RevenueCat may conduct limited randomized pricing, paywall-copy, or layout experiments, as explained in the Privacy Policy.</p> <h2 id="service-availability">Service Availability</h2> <p>Aurachord is provided as is and without warranties, except where applicable law requires otherwise. Features and content may change, and the service may become unavailable or stop working. We do not promise uninterrupted operation, support for every device or environment, or indefinite maintenance. Third-party stores and services are governed by their own terms and availability.</p> <h2 id="liability">Liability</h2> <p>To the extent permitted by law, Sonofield Ear Trainer Education Ltd. is not liable for indirect, incidental, special, consequential, or similar damages or losses related to your use of or inability to use Aurachord. Nothing in these terms excludes rights or liability that cannot legally be excluded.</p> <h2 id="governing-law">Governing Law</h2> <p>These terms are governed by the laws of Canada, subject to mandatory applicable law.</p> <h2 id="contact">Contact</h2> <p>If you have questions about these terms or need help with an entitlement, contact <a href="mailto:[email protected]">[email protected]</a>.</p>',1);function rl(t,e){const i=B(e,["children","$$slots","$$events","$$legacy"]);N(t,E(()=>i,()=>kt,{children:(o,r)=>{var n=ol();U(36),v(o,n)},$$slots:{default:!0}}
11))}const Qc=Object.freeze(Object.defineProperty({__proto__:null,default:rl,metadata:kt},Symbol.toStringTag,{value:"Module"})),_t={title:"Data Deletion",description:"Sonofield Data Deletion Policy. You may request your user account and data deletion at any point."},{title:eu,description:tu}=_t;var nl=M('<h1 id="sonofield-data-deletion">Sonofield Data Deletion</h1> <p>You may start the user removal process in the Account page of the Sonofield Ear Trainer app. You can also contact <a href="mailto:[email protected]">[email protected]</a> for data removal or user removal requests.</p> <ul><li>You may request your user account and data deletion at any point.</li> <li>If you wish to delete some part of the collected data, but keep the rest, we will do so upon request, as long as it maintains the service.</li></ul> <p>Upon request, all user data is deleted, including the created account and any data connected to the user.</p>',1);function al(t,e){const i=B(e,["children","$$slots","$$events","$$legacy"]);N(t,E(()=>i,()=>_t,{children:(o,r)=>{var n=nl();U(6),v(o,n)},$$slots:{default:!0}}))}const iu=Object.freeze(Object.defineProperty({__proto__:null,default:al,metadata:_t},Symbol.toStringTag,{value:"Module"})),$t={title:"Privacy Policy",description:"This privacy policy describes how Sonofield collects, processes, and protects your information when you use the Sonofield mobile and web applications and related services."},{title:ou,description:ru}=$t;var sl=M('<h1 id="sonofield-ear-trainer-privacy-policy">Sonofield Ear Trainer Privacy Policy</h1> <p>This privacy policy (âPrivacy Policyâ) describes how Sonofield Ear Trainer (âwe,â âour,â or âusâ) collects, processes, and protects your information when you use the Sonofield Ear Trainer mobile and web applications (âAppâ) and related services.</p> <p>We may update this Privacy Policy from time to time to reflect changes in our practices or for legal reasons. The current version of this Privacy Policy will always be available within the App and on our website.</p> <hr/> <h2 id="1-contact-details">1. Contact Details</h2> <p><strong>Name:</strong> Sonofield Ear Trainer Education Ltd.</p> <p><strong>Correspondence Address:</strong> PO Box 54523 Highgate PO, 7155 Kingsway Burnaby, BC V5E 4J6 Canada</p> <p><strong>Email Address:</strong> <a href="mailto:[email protected]">[email protected]</a></p> <p>For privacy-related inquiries, please contact us via the email address provided above.</p> <hr/> <h2 id="2-information-we-collect-and-how-we-use-it">2. Information We Collect and How We Use It</h2> <h3 id="device-id">Device ID</h3> <ul><li><strong>What we collect:</strong> A randomly generated device ID connected to your purchase.</li> <li><strong>Purpose:</strong> To help with support cases and manage app subscriptions.</li></ul> <h3 id="purchase-information">Purchase Information</h3> <ul><li><strong>What we collect:</strong> Purchase-related information.</li> <li><strong>Purpose:</strong> To handle subscription and purchase services.</li> <li><strong>Processing Providers:</strong> Qonversion, App Store, Play Store, Stripe.</li> <li><strong>Note:</strong> Qonversion, App Store, Play Store and Stripe process only the necessary information required to provide this service.</li></ul> <h3 id="analytics-data">Analytics Data</h3> <ul><li><strong>What we collect:</strong> Non-personal analytical data related to app usage (e.g., which games were played and performance metrics).</li> <li><strong>Purpose:</strong> To improve the app and provide insights into its functionality.</li> <li><strong>Processing Provider:</strong> PostHog.</li> <li><strong>User Choice:</strong> Users may opt out of analytics data collection via the Appâs account settings.</li></ul> <h3 id="crash-data-and-metrics">Crash Data and Metrics</h3> <ul><li><strong>What we collect:</strong> Non-personal crash-related data and DNS metrics.</li> <li><strong>Purpose:</strong> To identify and resolve technical issues.</li> <li><strong>Processing Provider:</strong> Sentry, Cloudflare.</li> <li><strong>User Choice:</strong> Users may opt out of App crash data collection via the Appâs account settings.</li></ul> <h3 id="email-addresses">Email Addresses</h3> <ul><li><strong>What we collect:</strong> Email addresses of users who sign up for our email list.</li> <li><strong>Purpose:</strong> To send updates, tips, news, and promotional materials.</li> <li><strong>Processing Provider:</strong> Brevo.</li> <li><strong>User Choice:</strong> Users may unsubscribe at any time by following the instructions in the email.</li></ul> <h3 id="signed-in-account-information">Signed-in Account Information</h3> <ul><li><strong>What we collect:</strong> When you create a signed-in account, we collect your email address (used as your login identifier). Once logged in and using the app, we collect and store your game progress data (e.g., levels completed, scores, unlocks) and your premium status.</li> <li><strong>Purpose:</strong> To allow you to securely log in to your account, sync your game progress and premium status across devices, and provide you with the full features of the Sonofield Ear Trainer service as per our terms.</li> <li><strong>Processing Provider(s):</strong> Our own backend servers & Postmark.</li> <li><strong>User Choice:</strong>
11 Users may request account deletion within the app or by contacting <a href="mailto:[email protected]">[email protected]</a>.</li></ul> <hr/> <h2 id="3-purposes-of-processing-and-legal-basis">3. Purposes of Processing and Legal Basis</h2> <ul><li><strong>To provide the service (including account creation, login, progress syncing, and premium features):</strong> Performance of a contract (our Terms of Service with you).</li> <li><strong>For analytics and improvements:</strong> Legitimate interest, with an opt-out option provided.</li> <li><strong>To ensure app functionality and address crashes:</strong> Legitimate interest, with user controls for opting out.</li> <li><strong>For email marketing:</strong> Consent-based; users can withdraw consent at any time.</li></ul> <hr/> <h2 id="4-data-storage-and-retention">4. Data Storage and Retention</h2> <p>We retain personal data only as long as necessary for the specific purposes for which it was collected, as outlined in this Privacy Policy. The retention period depends on the type of data and the purpose of processing.</p> <ul><li><strong>Signed-in Account Data (Email, Game Progress, Premium Status):</strong> We retain this data for as long as your account is considered active. Your account is considered inactive if there have been no logins for a continuous period of two (2) years. If your account becomes inactive, we will send you notifications (one month and three days prior) to inform you that your account is scheduled for deletion. If you do not log in during this notification period, your account and the associated personal data (email, game progress, premium status) will be automatically and permanently deleted. We have determined this 2-year period based on the typical usage patterns of our app by musicians, balancing the possibility of users returning after breaks with the principle of not retaining data longer than necessary.</li> <li><strong>Data Retained for Legal Obligations:</strong> Certain data, such as records related to purchases, may be retained for a period required by applicable laws (e.g., for accounting or tax purposes in Canada). This retention is based on a legal obligation and is separate from the accountâs active status.</li> <li><strong>Email Addresses (for Marketing List):</strong> Email addresses collected for our marketing list are stored until you unsubscribe using the link in the emails or until the information is no longer needed for marketing purposes. We periodically review our marketing lists and cease sending communications to subscribers who show prolonged inactivity with our emails, independent of app login activity.</li> <li><strong>Analytics and Crash Data:</strong> Non-personal analytics and crash data may be retained as long as necessary to monitor app performance, identify trends, and improve the service. Note that analytical data we retain after account deletion is anonymized and cannot be linked back to you personally.</li></ul> <hr/> <h2 id="5-sharing-and-transfers">5. Sharing and Transfers</h2> <p>We share data with the following service providers:</p> <ul><li><strong>Qonversion</strong> (purchase processing)</li> <li><strong>App Store</strong> (purchase processing)</li> <li><strong>Play Store</strong> (purchase processing)</li> <li><strong>Stripe</strong> (purchase processing)</li> <li><strong>PostHog</strong> (analytics)</li> <li><strong>Sentry</strong> (crash reporting)</li> <li><strong>Cloudflare</strong> (dns metrics and crash reporting)</li> <li><strong>Brevo</strong> (email list)</li> <li><strong>Postmark</strong> (account email for up to 45 days)</li></ul> <p>These providers process data in compliance with applicable data protection laws.</p> <hr/> <h2 id="6-your-rights">6. Your Rights</h2> <p>You have the right to:</p> <ul><li><strong>Access your data.</strong></li> <li><strong>Correct or update inaccuracies.</strong></li> <li><strong>Opt-out of analytics and crash data collection.</strong></li> <li><strong>Unsubscribe from email communications.</strong></li> <li><strong>Request Data Deletion (Right to Erasure):</strong> You have the right to request the deletion of your personal data when it is no longer necessary for the purposes for which it was collected, or when you withdraw consent (where applicable), or object to processing, or when the data has been unlawfully processed. This includes the right to request the deletion of your Sonofield Ear Trainer account and all associated personal data. <ul><li><strong>How to Request Deletion:</strong> You can exercise your right to deletion at any time by using the account deleti
11on option within the App found in the account settings or by contacting us directly at <a href="mailto:[email protected]">[email protected]</a>.</li> <li><strong>Upon Deletion:</strong> When your account is deleted (either at your request or automatically due to inactivity as described in Section 4), all personal data associated with your account, including your email address, game progress, and premium status, will be permanently removed, except for any limited data we are legally required to retain for purposes like accounting.</li></ul></li></ul> <hr/> <h2 id="7-information-security">7. Information Security</h2> <p>We use encryption, pseudonymization, and access controls to protect your data. In case of a data breach, we will notify affected users and relevant authorities as required by law.</p>',1);function ll(t,e){const i=B(e,["children","$$slots","$$events","$$legacy"]);N(t,E(()=>i,()=>$t,{children:(o,r)=>{var n=sl();U(82),v(o,n)},$$slots:{default:!0}}))}const nu=Object.freeze(Object.defineProperty({__proto__:null,default:ll,metadata:$t},Symbol.toStringTag,{value:"Module"})),St={title:"Terms of Service",description:"These Terms govern the use of the Sonofield mobile and web applications and related services."},{title:au,description:su}=St;var cl=M('<h1 id="sonofield-ear-trainer-terms-of-service">Sonofield Ear Trainer Terms of Service</h1> <p>Welcome to Sonofield Ear Trainer! The Sonofield Ear Trainer app provides a game-like experience to teach functional ear training and improve your musical skills in an engaging and interactive way.</p> <p>Read these Terms of Service (âTermsâ) carefully. These Terms govern the use of the Sonofield Ear Trainer app and related services (âServiceâ). By accessing or using the Service, you agree to these Terms. If you do not agree, do not use the Service.</p> <p>These Terms form a binding agreement between you (âSubscriberâ or âUserâ) and Sonofield Ear Trainer Ltd. (âSonofieldâ). Apple Inc. and Google LLC are third-party beneficiaries of these Terms.</p> <hr/> <h2 id="1-definitions">1. Definitions</h2> <ul><li><strong>Sonofield:</strong> Refers to Sonofield Ear Trainer Ltd.</li> <li><strong>Service:</strong> The Sonofield Ear Trainer app and any related services.</li> <li><strong>Subscriber:</strong> The individual who creates an account and subscribes to the Service.</li> <li><strong>User:</strong> The Subscriber or any person authorized by the Subscriber to use the Service.</li> <li><strong>Intellectual Property Rights:</strong> Includes copyrights, patents, trademarks, and other proprietary rights.</li> <li><strong>Personal Data:</strong> As defined under applicable data protection laws, including the GDPR.</li></ul> <hr/> <h2 id="2-right-to-use-the-service">2. Right to Use the Service</h2> <ul><li>2.1 Sonofield grants you a limited, non-exclusive, non-transferable, and non-sublicensable license to use the Service for personal, non-commercial purposes.</li> <li>2.2 Access to the Service requires a valid subscription for the âProâ version or a one-time lifetime payment. Free content is available without a subscription or sign-up.</li> <li>2.3 You are responsible for ensuring that all Users comply with these Terms.</li></ul> <hr/> <h2 id="3-user-accounts">3. User Accounts</h2> <ul><li>3.1 When creating an account, you must provide accurate and up-to-date information.</li> <li>3.2 Keep your account credentials secure. You are responsible for all activity under your account.</li> <li>3.3 Sonofield reserves the right to suspend or terminate accounts that breach these Terms or engage in unauthorized use of the Service.</li></ul> <hr/> <h2 id="4-subscription-and-payment">4. Subscription and Payment</h2> <ul><li>4.1 Access to premium features requires a subscription or a one-time lifetime payment. Pricing details are available on our website or within the app.</li> <li>4.2 Payments are processed through third-party providers. Ensure your payment details are accurate and updated.</li> <li>4.3 Subscriptions automatically renew unless canceled before the end of the current billing period. No refunds are provided for unused portions of a subscription unless required by law.</li></ul> <hr/> <h2 id="5-restrictions-on-use">5. Restrictions on Use</h2> <ul><li>5.1 You may not: <ul><li>Reverse engineer or decompile the Service.</li> <li>Use bots or automated tools to interact with the Service.</li> <li>Share your account credentials with unauthorized parties.</li> <li>Use the Service for commercial purposes without explicit permission.</li></ul></li> <li>5.2 Any unauthorized use may result in account suspension or termination.</li></ul> <hr/> <h2 id="6-modifications-to-the-service">6. Modifications to the Service</h2> <ul><li>6.1 Sonofield reserves the right to modify or discontinue any part of the Service without prior notice, provided such changes do not materially reduce the functionality of the Service.</li> <li>6.2 Material changes will be communicated in advance, and you may terminate your subscription if you disagree with such changes.</li></ul> <hr/> <h2 id="7-personal-data">7. Personal Data</h2> <ul><li>7.1 Sonofield processes your Personal Data in accordance with our Privacy Policy. By using the Service, you consent to such processing.</li></ul> <hr/> <h2 id="8-intellectual-property-rights">8. Intellectual Property Rights</h2> <ul><li>8.1 Sonofield retains all rights, title, and interest in the Service and its content. You may not copy, distribute, or create derivative works without explicit permission.</li> <li>8.2 If you believe your Intellectual Property Rights are being infringed, contact us at <a href="mailto:[email protected]">[email protected]</a>.</li></ul> <hr/> <h2 id="9-availability-warranties-and-liability">9. Availability, Warranties, and Liability</h2> <ul><li>9.1 The Service is provided âas isâ and without warranties of any kind.</li> <li>9.2 Sonofield is not liable for: <ul><li>Interruptions or unavailability of the Service.</li> <li>Damages resulting from the use of the Service, to the extent permitted by law.</li></ul></li></ul> <hr/> <h2 id="10-term-and-termination">10. Term and Termination</h2> <ul><li>10.1 These Terms remain in effect until terminated by you or Sonofield.</li> <li>10.2 You may terminate your subscription at any time through your account settings. Termination does not entitle you to a refund unless required by law.</li> <li>10.3 Sonofield may terminate these Terms if you breach any provision or misuse the Service.</li></ul> <hr/> <h2 id="11-governing-law-and-dispute-resolution">11. Governing Law and Dispute Resolution</h2> <ul><li>11.1 These Terms are governed by the laws of Canada.</li> <li>11.2 Any disputes will be resolved through negotiation. If unresolved, disputes will be subject to the exclusive jurisdiction of the courts in Canada.</li></ul>',1);function ul(t,e){const i=B(e,["children","$$slots","$$events","$$legacy"]);N(t,E(()=>i,()=>St,{children:(o,r)=>{var n=cl();U(72),v(o,n)},$$slots:{default:!0}}
11))}const lu=Object.freeze(Object.defineProperty({__proto__:null,default:ul,metadata:St},Symbol.toStringTag,{value:"Module"})),Tt={title:"Windtone Privacy Policy",description:"Privacy policy for the Windtone app."},{title:cu,description:uu}=Tt;var dl=M('<h1 id="windtone-privacy-policy">Windtone Privacy Policy</h1> <p>Windtone is a relaxed ear training app where a wind chime plays and you guess the scale degrees played.</p> <p>Sonofield Ear Trainer Education Ltd. provides Windtone and respects your privacy. The app does not collect personal information, and these pages on the Sonofield website do not collect personal information.</p> <h2 id="app-stores">App Stores</h2> <p>Windtone is distributed through Google Play and the App Store. These stores are the only providers that may collect information automatically when you install or access the app through them. Google and Apple process that information under their own privacy policies.</p> <h2 id="contact">Contact</h2> <p>If you have questions about this privacy policy, contact <a href="mailto:[email protected]">[email protected]</a>.</p>',1);function hl(t,e){const i=B(e,["children","$$slots","$$events","$$legacy"]);N(t,E(()=>i,()=>Tt,{children:(o,r)=>{var n=dl();U(12),v(o,n)},$$slots:{default:!0}}))}const du=Object.freeze(Object.defineProperty({__proto__:null,default:hl,metadata:Tt},Symbol.toStringTag,{value:"Module"})),Pt={title:"Windtone Terms of Service",description:"Terms of service for the Windtone app."},{title:hu,description:pu}=Pt;var pl=M('<h1 id="windtone-terms-of-service">Windtone Terms of Service</h1> <p>Windtone is a relaxed ear training app where a wind chime plays and you guess the scale degrees played. Windtone is free of charge and distributed through Google Play and the App Store. By using Windtone, you agree to these terms.</p> <h2 id="service-availability">Service Availability</h2> <p>Windtone is provided as is and without warranties. The app may change, become unavailable, or stop working at some point. No promise is made that every feature or device environment will continue to work, or that the app will be maintained.</p> <h2 id="liability">Liability</h2> <p>To the extent permitted by law, Sonofield Ear Trainer Education Ltd. is not liable for damages or losses related to your use of Windtone.</p> <h2 id="governing-law">Governing Law</h2> <p>These terms are governed by the laws of Canada, where permitted by applicable law.</p> <h2 id="contact">Contact</h2> <p>If you have questions about these terms, contact <a href="mailto:[email protected]">[email protected]</a>.</p>',1);function fl(t,e){const i=B(e,["children","$$slots","$$events","$$legacy"]);N(t,E(()=>i,()=>Pt,{children:(o,r)=>{var n=pl();U(18),v(o,n)},$$slots:{default:!0}}))}const fu=Object.freeze(Object.defineProperty({__proto__:null,default:fl,metadata:Pt},Symbol.toStringTag,{value:"Module"})),le={"00s-pop-1":{genre:{main:"Pop",sub:"'00s Pop"},difficulty:2,answers:[{tonic:"F#",tonality:"Minor"}]},"80s-pop-1":{genre:{main:"Pop",sub:"'80s Pop"},difficulty:2,answers:[{tonic:"Bb",tonality:"Major"},{tonic:"G",tonality:"Minor"}]},"adult-contemporary-1":{genre:{main:"Pop",sub:"Adult Contemporary"},difficulty:2,answers:[{tonic:"F",tonality:"Major"},{tonic:"D",tonality:"Minor"}]},"afrobeats-1":{genre:{main:"Afro-Latin",sub:"Afrobeats"},difficulty:3,answers:[{tonic:"F",tonality:"Minor"}]},"alt-rock-1":{genre:{main:"Rock",sub:"Alt Rock"},difficulty:3,answers:[{tonic:"A",tonality:"Minor"}]},"alt-rock-2":{genre:{main:"Rock",sub:"Alt Rock"},difficulty:2,answers:[{tonic:"Bb",tonality:"Minor"},{tonic:"Db",tonality:"Major"}]},"ambient-1":{genre:{main:"Electronic",sub:"Ambient"},difficulty:3,answers:[{tonic:"B",tonality:"Minor"}]},"ambient-2":{genre:{main:"Electronic",sub:"Ambient"},difficulty:2,answers:[{tonic:"E",tonality:"Minor"}]},"ambient-3":{genre:{main:"Electronic",sub:"Ambient"},difficulty:2,answers:[{tonic:"F#",tonality:"Minor"}]},"american-folk-1":{genre:{main:"Folk",sub:"American Folk"},difficulty:2,answers:[{tonic:"B",tonality:"Minor"},{tonic:"D",tonality:"Major"}]},"american-folk-2":{genre:{main:"Folk",sub:"American Folk"},difficulty:2,answers:[{tonic:"C",tonality:"Minor"},{tonic:"Eb",tonality:"Major"}]},"big-band-1":{genre:{main:"Jazz",sub:"Big Band"},difficulty:3,answers:[{tonic:"Ab",tonality:"Major"}]},"bluegrass-1":{genre:{main:"Folk",sub:"Bluegrass"},difficulty:2,answers:[{tonic:"Bb",tonality:"Major"}]},"blues-1":{genre:{main:"Jazz",sub:"Blues"},difficulty:2,answers:[{tonic:"B",tonality:"Major"}]},"bollywood-1":{genre:{main:"Pop",sub:"Bollywood"},difficulty:2,answers:[{tonic:"Ab",tonality:"Major"}]},"bollywood-2":{genre:{main:"Pop",sub:"Bollywood"},difficulty:2,answers:[{tonic:"G#",tonality:"Minor"},{tonic:"B",tonality:"Major"}]},"boom-bap-1":{genre:{main:"Hip-Hop",sub:"Boom Bap"},difficulty:1,answers:[{tonic:"A",tonality:"Minor"}]},"boom-bap-2":{genre:{main:"Hip-Hop",sub:"Boom Bap"},difficulty:2,answers:[{tonic:"F",tonality:"Major"}]},"breakbeat-1":{genre:{main:"Dance",sub:"Breakbeat"},difficulty:2,answers:[{tonic:"B",tonality:"Minor"}]},"calypso-1":{genre:{main:"Afro-Latin",sub:"Calypso"},difficulty:2,answers:[{tonic:"Db",tonality:"Major"}]},"celtic-folk-1":{genre:{main:"Folk",sub:"Celtic Folk"},difficulty:2,answers:[{tonic:"G#",tonality:"Minor"}]},"chillout-1":{genre:{main:"Electronic",sub:"Chillout"},difficulty:2,answers:[{tonic:"Eb",tonality:"Major"},{tonic:"C",tonality:"Minor"}]},"city-pop-1":{genre:{main:"Pop",sub:"City Pop"},difficulty:3,answers:[{tonic:"C",tonality:"Major"}]},"city-pop-2":{genre:{main:"Pop",sub:"City Pop"},difficulty:3,answers:[{tonic:"Eb",tonality:"Minor"},{tonic:"Gb",tonality:"Major"}]},"classic-pop-1":{genre:{main:"Pop",sub:"Classic Pop"},difficulty:2,answers:[{tonic:"C",tonality:"Major"}]},"classic-rock-1":{genre:{main:"Rock",sub:"Classic Rock"},difficulty:2,answers:[{tonic:"Ab",tonality:"Major"}]},"classical-1":{genre:{main:"Orchestral",sub:"Classical"},difficulty:3,answers:[{tonic:"D",tonality:"Minor"},{tonic:"F",tonality:"Major"}]},"classical-2":{genre:{main:"Orchestral",sub:"Classical"},difficulty:3,answers:[{tonic:"E",tonality:"Major"},{tonic:"C#",tonality:"Minor"}]},"classical-3":{genre:{main:"Orchestral",sub:"Classical"},difficulty:3,answers:[{tonic:"E",tonality:"Minor"},{tonic:"G",tonality:"Major"}]},"country-1":{genre:{main:"Folk",sub:"Country"},difficulty:2,answers:[{tonic:"D",tonality:"Major"}]},"country-2":{genre:{main:"Folk",sub:"Country"},difficulty:2,answers:[{tonic:"G",tonality:"Major"},{tonic:"E",tonality:"Minor"}]},"dancehall-1":{genre:{main:"Afro-Latin",sub:"Dancehall"},difficulty:2,answers:[{tonic:"B",tonality:"Minor"}]},"deep-house-1":{genre:{main:"Dance",sub:"Deep House"},difficulty:2,answers:[{tonic:"C#",tonality:"Minor"},{tonic:"E",tonality:"Major"}]},"disco-1":{genre:{main:"Soul",sub:"Disco"},difficulty:3,answers:[{tonic:"Bb",tonality:"Major"}]},"disco-2":{genre:{main:"Soul",sub:"Disco"},difficulty:2,answers:[{tonic:"Db",tonality:"Major"}]},"dream-pop-1":{genre:{main:"Pop",sub:"Dream Pop"},difficulty:2,answers:[{tonic:"B",tonality:"Major"}]},"drill-1":{genre:{main:"Hip-Hop",sub:"Drill"},difficulty:2,answers:[{tonic:"F",tonality:"Minor"}]},"drum-and-bass-1":{genre:{main:"Dance",sub:"Drum and Bass"},difficulty:2,answers:[{tonic:"C",tonality:"Major"},{tonic:"A",tonality:"Minor"}]},"drum-and-bass-2":{genre:{main:"Dance",sub:"Drum and Bass"},difficulty:2,answers:[{tonic:"E",tonality:"Minor"},{tonic:"G",tonality:"Major"}]},"dubstep-1":{genre:{main:"Dance",sub:"Dubstep"},difficulty:3,answers:[{tonic:"C",tonality:"Minor"}]},"film-score-1":{genre:{main:"Orchestral",sub:"Film Score"},difficulty:1,answers:[{tonic:"C",tonality:"Minor"}]},"funk-1":{genre:{main:"Soul",sub:"Funk"},difficulty:3,answers:[{tonic:"E",tonality:"Major"}]},"funk-2":{genre:{main:"Soul",sub:"Funk"},difficulty:3,answers:[{tonic:"G",tonality:"Minor"}]},"future-bass-1":{genre:{main:"Dance",sub:"Future Bass"},difficulty:3,answers:[{tonic:"A",tonality:"Minor"}]},"future-bass-2":{genre:{main:"Dance",sub:"Future Bass"},difficulty:3,answers:[{tonic:"Eb",tonality:"Major"},{tonic:"C",tonality:"Minor"}]},"g-funk-1":{genre:{main:"Hip-Hop",sub:"G-Funk"},difficulty:2,answers:[{tonic:"G",tonality:"Minor"}]},"gospel-1":{genre:{main:"Soul",sub:"Gospel"},difficulty:2,answers:[{tonic:"A",tonality:"Major"}]},"grunge-1":{genre:{main:"Rock",sub:"Grunge"},difficulty:2,answers:[{tonic:"C#",tonality:"Minor"}]},"gypsy-jazz-1":{genre:{main:"Jazz",sub:"Gypsy Jazz"},difficulty:3,answers:[{tonic:"D",tonality:"Minor"}]},"hyperpop-1":{genre:{main:"Electronic",sub:"Hyperpop"},difficulty:3,answers:[{tonic:"F",tonality:"Minor"},{tonic:"Ab",tonality:"Major"}]},"indie-rock-1":{genre:{main:"Rock",sub:"Indie Rock"},difficulty:3,answers:[{tonic:"G#",tonality:"Minor"}]},"irish-folk-1":{genre:{main:"Folk",sub:"Irish Folk"},difficulty:2,answers:[{tonic:"Db",tonality:"Major"}]},"bossa-nova-1":{genre:{main:"Jazz",sub:"Bossa Nova"},difficulty:3,answers:[{tonic:"A",tonality:"Major"}]},"jazz-1":{genre:{main:"Jazz",sub:"Jazz"},difficulty:3,answers:[{tonic:"A",tonality:"Major"}]},"k-pop-1":{genre:{main:"Pop",sub:"K-Pop"},difficulty:3,answers:[{tonic:"C#",tonality:"Minor"}]},"kawaii-1":{genre:{main:"Electronic",sub:"Kawaii"},difficulty:3,answers:[{tonic:"Gb",tonality:"Major"},{tonic:"Eb",tonality:"Minor"}]},"latin-jazz-1":{genre:{main:"Afro-Latin",sub:"Latin Jazz"},difficulty:2,answers:[{tonic:"Bb",tonality:"Major"}]},"lofi-hip-hop-1":{genre:{main:"Hip-Hop",sub:"LoFi Hip-Hop"},difficulty:2,answers:[{tonic:"D",tonality:"Major"}]},"lofi-hip-hop-2":{genre:{main:"Hip-Hop",sub:"LoFi Hip-Hop"},difficulty:3,answers:[{tonic:"G",tonality:"Major"}]},"lofi-hip-hop-3":{genre:{main:"Hip-Hop",sub:"LoFi Hip-Hop"},difficulty:2,answers:[{tonic:"Gb",tonality:"Major"},{tonic:"E",tonality:"Minor"}]},"modern-hip-hop-1":{genre:{main:"Hip-Hop",sub:"Modern Hip-Hop"},difficulty:2,answers:[{tonic:"F#",tonality:"Minor"}]},"modern-jazz-1":{genre:{main:"Jazz",sub:"Modern Jazz"},difficulty:3,answers:[{tonic:"Gb",tonality:"Major"}]},"modern-pop-1":{genre:{main:"Pop",sub:"Modern Pop"},difficulty:3,answers:[{tonic:"Bb",tonality:"Minor"},{tonic:"Db",tonality:"Major"}]},"motown-1":{genre:{main:"Soul",sub:"Motown"},difficulty:3,answers:[{tonic:"Eb",tonality:"Major"}]},"neo-soul-1":{genre:{main:"Soul",sub:"Neo-Soul"},difficulty:2,answers:[{tonic:"Bb",tonality:"Minor"}]},"neo-soul-2":{genre:{main:"Soul",sub:"Neo-Soul"},difficulty:2,answers:[{tonic:"C",tonality:"Minor"}]},"neo-soul-3":{genre:{main:"Soul",sub:"Neo-Soul"},difficulty:2,answers:[{tonic:"Eb",tonality:"Minor"}]},"new-age-1":{genre:{main:"Electronic",sub:"New Age"},difficulty:3,answers:[{tonic:"Eb",tonality:"Minor"},{tonic:"Gb",tonality:"Major"}]},"nu-disco-1":{genre:{main:"Dance",sub:"Nu Disco"},difficulty:3,answers:[{tonic:"F#",tonality:"Minor"},{tonic:"Ab",tonality:"Major"}]},"pop-punk-1":{genre:{main:"Rock",sub:"Pop Punk"},difficulty:2,answers:[{tonic:"G",tonality:"Major"},{tonic:"E",tonality:"Minor"}]},"post-rock-1":{genre:{main:"Rock",sub:"Post-Rock"},difficulty:2,answers:[{tonic:"F",tonality:"Major"},{tonic:"D",tonality:"Minor"}]},"prog-metal-1":{genre:{main:"Rock",sub:"Prog Metal"},difficulty:3,answers:[{tonic:"D",tonality:"Minor"}]},"prog-metal-2":{genre:{main:"Rock",sub:"Prog Metal"},difficulty:2,answers:[{tonic:"F",tonality:"Minor"}]},"punk-1":{genre:{main:"Rock",sub:"Punk"},difficulty:2,answers:[{tonic:"Gb",tonality:"Major"}]},"reggae-1":{genre:{main:"Afro-Latin",sub:"Reggae"},difficulty:2,answers:[{tonic:"Ab",tonality:"Major"}]},"reggae-2":{genre:{main:"Afro-Latin",sub:"Reggae"},difficulty:2,answers:[{tonic:"C",tonality:"Major"}]},"reggae-3":{genre:{main:"Afro-Latin",sub:"Reggae"},difficulty:2,answers:[{tonic:"Eb",tonality:"Major"}]},"roots-rock-1":{genre:{main:"Folk",sub:"Roots Rock"},difficulty:2,answers:[{tonic:"E",tonality:"Major"}]},"shoegaze-1":{genre:{main:"Rock",sub:"Shoegaze"},difficulty:3,answers:[{tonic:"G",tonality:"Minor"},{tonic:"Bb",tonality:"Major"}]},"ska-1":{genre:{main:"Afro-Latin",sub:"Ska"},difficulty:2,answers:[{tonic:"B",tonality:"Major"}]},"smooth-jazz-1":{genre:{main:"Jazz",sub:"Smooth Jazz"},difficulty:3,answers:[{tonic:"A",tonality:"Major"}]}
11,"soul-1":{genre:{main:"Soul",sub:"Soul"},difficulty:2,answers:[{tonic:"D",tonality:"Major"}]},"soul-2":{genre:{main:"Soul",sub:"Soul"},difficulty:2,answers:[{tonic:"D",tonality:"Major"}]},"string-quartet-1":{genre:{main:"Orchestral",sub:"String Quartet"},difficulty:2,answers:[{tonic:"B",tonality:"Major"}]},"string-quartet-2":{genre:{main:"Orchestral",sub:"String Quartet"},difficulty:3,answers:[{tonic:"Bb",tonality:"Minor"},{tonic:"Db",tonality:"Major"}]},"synth-pop-1":{genre:{main:"Pop",sub:"Synth Pop"},difficulty:2,answers:[{tonic:"D",tonality:"Minor"},{tonic:"F",tonality:"Major"}]},"synth-pop-2":{genre:{main:"Pop",sub:"Synth Pop"},difficulty:2,answers:[{tonic:"F",tonality:"Major"},{tonic:"D",tonality:"Minor"}]},"synthwave-1":{genre:{main:"Electronic",sub:"Synthwave"},difficulty:2,answers:[{tonic:"C#",tonality:"Minor"}]},"synthwave-2":{genre:{main:"Electronic",sub:"Synthwave"},difficulty:2,answers:[{tonic:"E",tonality:"Minor"}]},"tango-1":{genre:{main:"Afro-Latin",sub:"Tango"},difficulty:3,answers:[{tonic:"Eb",tonality:"Minor"},{tonic:"Gb",tonality:"Major"}]},"trance-1":{genre:{main:"Dance",sub:"Trance"},difficulty:2,answers:[{tonic:"E",tonality:"Major"},{tonic:"C#",tonality:"Minor"}]},"trap-1":{genre:{main:"Hip-Hop",sub:"Trap"},difficulty:2,answers:[{tonic:"Bb",tonality:"Minor"}]},"trip-hop-1":{genre:{main:"Electronic",sub:"Trip-Hop"},difficulty:2,answers:[{tonic:"G#",tonality:"Minor"}]},"uk-garage-1":{genre:{main:"Dance",sub:"UK Garage"},difficulty:3,answers:[{tonic:"G",tonality:"Minor"}]},"yacht-rock-1":{genre:{main:"Rock",sub:"Yacht Rock"},difficulty:3,answers:[{tonic:"A",tonality:"Minor"}]},"yacht-rock-2":{genre:{main:"Rock",sub:"Yacht Rock"},difficulty:3,answers:[{tonic:"G",tonality:"Major"}]}},gl=666,se=bl(Object.keys(le),gl),Gt=se[se.length-1],Bt=se[0],ml={"A#":"Bb","D#":"Eb","G#":"Ab","C#":"Db","F#":"Gb"},gu={songsAmt:Object.keys(le).length,getFinalTonic(t){return t?ml[t]??t:null},checkIsCorrect(t,e){if(!e.tonic||!e.tonality)return!1;const i=this.getBySlug(t);return i?i.answers.some(o=>this.getFinalTonic(o.tonic)===e.tonic&&o.tonality===e.tonality):!1},getBySlug(t){const e=le[t];if(e)return De(t,e)},getNextSong(t){const e=se.indexOf(t);if(e===-1)return;const i=t==Gt?Bt:se[e+1];return De(i,le[i])},getPreviousSong(t){const e=se.indexOf(t);if(e===-1)return;const i=t==Bt?Gt:se[e-1];return De(i,le[i])},getTracklist(){return se},getRandomSongId(){const t=Object.keys(le);return t[Math.floor(Math.random()*t.length)]},getSongsByGenres(){const t=Object.entries(le).reduce((e,[i,o])=>{const r=De(i,o);return e[o.genre.main]||(e[o.genre.main]=[]),e[o.genre.main].push(r),e},{});return Object.entries(t).map(([e,i])=>(i.sort((o,r)=>o.difficulty-r.difficulty),{genre:e,songs:i})).sort((e,i)=>e.genre.localeCompare(i.genre))}};function De(t,e){const i=t.split("-").pop(),o=`${e.genre.sub} #${i}`,r=`https://storage.sonofield.com/songs/key-seeker/v1/${t}.flac`;return{id:t,downloadUrl:r,title:o,...e}}function yl(t){let e=t;return function(){return e=(e*9301+49297)%233280,e/233280}}function bl(t,e){const i=[...t],o=yl(e);for(let r=i.length-1;r>0;r--){const n=Math.floor(o()*(r+1));[i[r],i[n]]=[i[n],i[r]]}return i}const vl={discountParam:"discount",priceParam:"price",cancelToParam:"cancel_to"};export{lu as A,nu as B,ve as C,iu as D,Jo as E,Lc as F,Qc as G,Jc as H,ge as I,Yc as J,Bc as K,gu as L,Pl as M,li as N,Cl as S,vl as U,pi as X,xi as Y,Uc as _,et as a,K as b,xl as c,Ze as d,Eo as e,jc as f,Tc as g,bc as h,Co as i,uc as j,tc as k,Yl as l,Rl as m,Js as n,Uo as o,si as p,Ml as q,No as r,Be as s,Al as t,gs as u,ci as v,Re as w,st as x,fu as y,du as z};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.