minikeys 0.2.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
A tiny javascript library that plays the piano. [Try it out here!](http://liamp.uk/minikeys)
|
|
6
6
|
|
|
7
|
-
To use MiniKeys in a React app, you can use components from [@minikeys/react](https://npmjs.com/)
|
|
7
|
+
To use MiniKeys in a React app, you can use components from [@minikeys/react](https://www.npmjs.com/package/@minikeys/react)
|
|
8
8
|
|
|
9
9
|
<img width="1269" height="486" alt="Screenshot 2025-07-31 at 21 23 08" src="https://github.com/user-attachments/assets/1ff24de7-9222-42f0-ba74-9a3618ef9cd6" />
|
|
10
10
|
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var c=Object.defineProperty;var C=Object.getOwnPropertyDescriptor;var g=Object.getOwnPropertyNames;var D=Object.prototype.hasOwnProperty;var b=(s,e)=>{for(var t in e)c(s,t,{get:e[t],enumerable:!0})},F=(s,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of g(e))!D.call(s,o)&&o!==t&&c(s,o,{get:()=>e[o],enumerable:!(i=C(e,o))||i.enumerable});return s};var w=s=>F(c({},"__esModule",{value:!0}),s);var G={};b(G,{MiniKeys:()=>m,MiniKeysKeyboard:()=>M,keyboardBlackNotes:()=>h,keyboardWhiteNotes:()=>p,midiToNote:()=>d,noteToMidi:()=>n});module.exports=w(G);var n={"C-1":0,"C#-1":1,"D-1":2,"D#-1":3,"E-1":4,"F-1":5,"F#-1":6,"G-1":7,"G#-1":8,"A-1":9,"A#-1":10,"B-1":11,C0:12,"C#0":13,D0:14,"D#0":15,E0:16,F0:17,"F#0":18,G0:19,"G#0":20,A0:21,"A#0":22,B0:23,C1:24,"C#1":25,D1:26,"D#1":27,E1:28,F1:29,"F#1":30,G1:31,"G#1":32,A1:33,"A#1":34,B1:35,C2:36,"C#2":37,D2:38,"D#2":39,E2:40,F2:41,"F#2":42,G2:43,"G#2":44,A2:45,"A#2":46,B2:47,C3:48,"C#3":49,D3:50,"D#3":51,E3:52,F3:53,"F#3":54,G3:55,"G#3":56,A3:57,"A#3":58,B3:59,C4:60,"C#4":61,D4:62,"D#4":63,E4:64,F4:65,"F#4":66,G4:67,"G#4":68,A4:69,"A#4":70,B4:71,C5:72,"C#5":73,D5:74,"D#5":75,E5:76,F5:77,"F#5":78,G5:79,"G#5":80,A5:81,"A#5":82,B5:83,C6:84,"C#6":85,D6:86,"D#6":87,E6:88,F6:89,"F#6":90,G6:91,"G#6":92,A6:93,"A#6":94,B6:95,C7:96,"C#7":97,D7:98,"D#7":99,E7:100,F7:101,"F#7":102,G7:103,"G#7":104,A7:105,"A#7":106,B7:107,C8:108,"C#8":109,D8:110,"D#8":111,E8:112,F8:113,"F#8":114,G8:115,"G#8":116,A8:117,"A#8":118,B8:119,C9:120,"C#9":121,D9:122,"D#9":123,E9:124,F9:125,"F#9":126,G9:127},d=Object.fromEntries(Object.entries(n).map(([s,e])=>[e,s])),h=[null,"A#0",null,"C#1","D#1",null,"F#1","G#1","A#1",null,"C#2","D#2",null,"F#2","G#2","A#2",null,"C#3","D#3",null,"F#3","G#3","A#3",null,"C#4","D#4",null,"F#4","G#4","A#4",null,"C#5","D#5",null,"F#5","G#5","A#5",null,"C#6","D#6",null,"F#6","G#6","A#6",null,"C#7","D#7",null,"F#7","G#7","A#7",null,null,null],p=["A0","B0","C1","D1","E1","F1","G1","A1","B1","C2","D2","E2","F2","G2","A2","B2","C3","D3","E3","F3","G3","A3","B3","C4","D4","E4","F4","G4","A4","B4","C5","D5","E5","F5","G5","A5","B5","C6","D6","E6","F6","G6","A6","B6","C7","D7","E7","F7","G7","A7","B7","C8"],f=[["Digit1","Digit2","Digit3","Digit4","Digit5","Digit6","Digit7","Digit8","Digit9","Digit0","Minus","Equal"],["KeyQ","KeyW","KeyE","KeyR","KeyT","KeyY","KeyU","KeyI","KeyO","KeyP","BracketLeft","BracketRight"],["KeyA","KeyS","KeyD","KeyF","KeyG","KeyH","KeyJ","KeyK","KeyL","Semicolon","Quote"],["KeyZ","KeyX","KeyC","KeyV","KeyB","KeyN","KeyM","Comma","Period","Slash"]],A=(s,e,t,i)=>{let o;if(i&&i<64&&e.size>0)o=e;else if(s.size>0)o=s;else throw new Error("No notes loaded");let a=Array.from(o.keys()).reduce((l,r)=>Math.abs(r-t)<Math.abs(l-t)?r:l);return{closestNoteMidi:a,closestNote:o.get(a)}};var m=class{audioContext;compressorNode;forteNotes=new Map;pianoNotes=new Map;sustain=!1;playingNotes=new Map;progress=0;constructor(){this.audioContext=new AudioContext,this.compressorNode=this.audioContext.createDynamicsCompressor(),this.compressorNode.threshold.value=-24,this.compressorNode.knee.value=0,this.compressorNode.ratio.value=2,this.compressorNode.attack.value=.001,this.compressorNode.release.value=.5,this.compressorNode.connect(this.audioContext.destination)}setSustain=e=>{this.sustain=e,e?this.playingNotes.forEach(t=>{let i=this.audioContext.currentTime;t.node.gain.cancelScheduledValues(i),t.node.gain.setValueAtTime(t.node.gain.value,i)}):this.playingNotes.forEach(t=>{let i=this.audioContext.currentTime;t.node.gain.cancelScheduledValues(i),t.node.gain.setValueAtTime(t.node.gain.value,i),t.node.gain.linearRampToValueAtTime(.001,i+.5)})};loadNotes=async(e,t)=>{this.forteNotes.clear(),this.pianoNotes.clear();let i=e.map(async o=>{let l=await(await fetch(o.url)).arrayBuffer(),r=await this.audioContext.decodeAudioData(l);if(o.velocity==="piano"?this.pianoNotes.set(n[o.note],r):this.forteNotes.set(n[o.note],r),t){let u=(this.pianoNotes.size+this.forteNotes.size)/e.length;u>this.progress&&(this.progress=u,t(this.progress))}});return await Promise.all(i)};playNoteFromMidi=(e,t)=>{if(e<0||e>127)throw new Error("Invalid midi note");if(t&&(t<0||t>127))throw new Error("Invalid velocity value");if(!this.audioContext)throw new Error("Audio context not initialized");let o=this.audioContext.createBufferSource(),{closestNoteMidi:a,closestNote:l}=A(this.forteNotes,this.pianoNotes,e,t);if(l){o.buffer=l;let r=this.audioContext.createGain(),u=Math.min(127,t??127);r.gain.value=(u/127*.9+.1)*.5,o.connect(r),r.connect(this.compressorNode),o.playbackRate.value=2**((e-a)/12),o.start(),this.playingNotes.set(o,{node:r,note:e}),o.onended=()=>{o.disconnect(),this.playingNotes.delete(o)}}else throw new Error("Note not found")};playNoteFromName=(e,t)=>{this.playNoteFromMidi(n[e],t)};liftNoteFromMidi=e=>{this.playingNotes.forEach(t=>{if(t.note===e&&!this.sustain){let i=this.audioContext.currentTime;t.node.gain.cancelScheduledValues(i),t.node.gain.setValueAtTime(t.node.gain.value,i),t.node.gain.exponentialRampToValueAtTime(Number.EPSILON,i+8)}})};liftNoteFromName=(e,t)=>{this.liftNoteFromMidi(n[e])}};var M=class{mode;keyMap=new Map;offset;constructor(e){this.mode=e,e==="single"?this.offset=23:this.offset=16,this.buildNoteMap()}getNoteMap=()=>this.keyMap;getMidiRange=()=>{let e=Array.from(this.keyMap.values()).reduce((i,o)=>o.midiNote&&o.midiNote<i?o.midiNote:i,127),t=Array.from(this.keyMap.values()).reduce((i,o)=>o.midiNote&&o.midiNote>i?o.midiNote:i,0);return{low:e,high:t}};getNoteRange=()=>{let e=this.getMidiRange();return{low:d[e.low],high:d[e.high]}};shiftLeft=()=>{this.offset=Math.max(this.offset-1,0),this.keyMap=new Map,this.buildNoteMap()};shiftLeftOctave=()=>{this.offset=Math.max(this.offset-7,0),this.keyMap=new Map,this.buildNoteMap()};shiftRight=()=>{this.offset=Math.min(this.offset+1,this.mode==="dual"?30:41),this.keyMap=new Map,this.buildNoteMap()};shiftRightOctave=()=>{this.offset=Math.min(this.offset+7,this.mode==="dual"?30:41),this.keyMap=new Map,this.buildNoteMap()};buildNoteMap=()=>{this.mode==="single"?(y(this.keyMap,1,this.offset),N(this.keyMap,2,this.offset)):(y(this.keyMap,0,this.offset),N(this.keyMap,1,this.offset),y(this.keyMap,2,this.offset+12),N(this.keyMap,3,this.offset+12))}},y=(s,e,t)=>{f[e].forEach((i,o)=>{let a=h[t+o];if(a===null)s.set(i,{midiNote:null,type:"disabled"});else if(a!==void 0)s.set(i,{midiNote:n[a],type:"black"});else throw new Error("Invalid note")})},N=(s,e,t)=>{f[e].forEach((i,o)=>{let a=p[t+o];if(a)s.set(i,{midiNote:n[a],type:"white"});else throw new Error("Invalid note")})};0&&(module.exports={MiniKeys,MiniKeysKeyboard,keyboardBlackNotes,keyboardWhiteNotes,midiToNote,noteToMidi});
|
package/dist/index.d.cts
CHANGED
|
@@ -160,6 +160,8 @@ declare class MiniKeys {
|
|
|
160
160
|
loadNotes: (samples: Sample[], handleSampleLoaded?: (progress: number) => void) => Promise<void[]>;
|
|
161
161
|
playNoteFromMidi: (midiNote: number, velocity?: number) => void;
|
|
162
162
|
playNoteFromName: (noteName: NoteName, velocity?: number) => void;
|
|
163
|
+
liftNoteFromMidi: (midiNote: number) => void;
|
|
164
|
+
liftNoteFromName: (noteName: NoteName, velocity?: number) => void;
|
|
163
165
|
}
|
|
164
166
|
|
|
165
167
|
declare class MiniKeysKeyboard {
|
package/dist/index.d.ts
CHANGED
|
@@ -160,6 +160,8 @@ declare class MiniKeys {
|
|
|
160
160
|
loadNotes: (samples: Sample[], handleSampleLoaded?: (progress: number) => void) => Promise<void[]>;
|
|
161
161
|
playNoteFromMidi: (midiNote: number, velocity?: number) => void;
|
|
162
162
|
playNoteFromName: (noteName: NoteName, velocity?: number) => void;
|
|
163
|
+
liftNoteFromMidi: (midiNote: number) => void;
|
|
164
|
+
liftNoteFromName: (noteName: NoteName, velocity?: number) => void;
|
|
163
165
|
}
|
|
164
166
|
|
|
165
167
|
declare class MiniKeysKeyboard {
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var r={"C-1":0,"C#-1":1,"D-1":2,"D#-1":3,"E-1":4,"F-1":5,"F#-1":6,"G-1":7,"G#-1":8,"A-1":9,"A#-1":10,"B-1":11,C0:12,"C#0":13,D0:14,"D#0":15,E0:16,F0:17,"F#0":18,G0:19,"G#0":20,A0:21,"A#0":22,B0:23,C1:24,"C#1":25,D1:26,"D#1":27,E1:28,F1:29,"F#1":30,G1:31,"G#1":32,A1:33,"A#1":34,B1:35,C2:36,"C#2":37,D2:38,"D#2":39,E2:40,F2:41,"F#2":42,G2:43,"G#2":44,A2:45,"A#2":46,B2:47,C3:48,"C#3":49,D3:50,"D#3":51,E3:52,F3:53,"F#3":54,G3:55,"G#3":56,A3:57,"A#3":58,B3:59,C4:60,"C#4":61,D4:62,"D#4":63,E4:64,F4:65,"F#4":66,G4:67,"G#4":68,A4:69,"A#4":70,B4:71,C5:72,"C#5":73,D5:74,"D#5":75,E5:76,F5:77,"F#5":78,G5:79,"G#5":80,A5:81,"A#5":82,B5:83,C6:84,"C#6":85,D6:86,"D#6":87,E6:88,F6:89,"F#6":90,G6:91,"G#6":92,A6:93,"A#6":94,B6:95,C7:96,"C#7":97,D7:98,"D#7":99,E7:100,F7:101,"F#7":102,G7:103,"G#7":104,A7:105,"A#7":106,B7:107,C8:108,"C#8":109,D8:110,"D#8":111,E8:112,F8:113,"F#8":114,G8:115,"G#8":116,A8:117,"A#8":118,B8:119,C9:120,"C#9":121,D9:122,"D#9":123,E9:124,F9:125,"F#9":126,G9:127},u=Object.fromEntries(Object.entries(r).map(([a,t])=>[t,a])),h=[null,"A#0",null,"C#1","D#1",null,"F#1","G#1","A#1",null,"C#2","D#2",null,"F#2","G#2","A#2",null,"C#3","D#3",null,"F#3","G#3","A#3",null,"C#4","D#4",null,"F#4","G#4","A#4",null,"C#5","D#5",null,"F#5","G#5","A#5",null,"C#6","D#6",null,"F#6","G#6","A#6",null,"C#7","D#7",null,"F#7","G#7","A#7",null,null,null],p=["A0","B0","C1","D1","E1","F1","G1","A1","B1","C2","D2","E2","F2","G2","A2","B2","C3","D3","E3","F3","G3","A3","B3","C4","D4","E4","F4","G4","A4","B4","C5","D5","E5","F5","G5","A5","B5","C6","D6","E6","F6","G6","A6","B6","C7","D7","E7","F7","G7","A7","B7","C8"],c=[["Digit1","Digit2","Digit3","Digit4","Digit5","Digit6","Digit7","Digit8","Digit9","Digit0","Minus","Equal"],["KeyQ","KeyW","KeyE","KeyR","KeyT","KeyY","KeyU","KeyI","KeyO","KeyP","BracketLeft","BracketRight"],["KeyA","KeyS","KeyD","KeyF","KeyG","KeyH","KeyJ","KeyK","KeyL","Semicolon","Quote"],["KeyZ","KeyX","KeyC","KeyV","KeyB","KeyN","KeyM","Comma","Period","Slash"]],y=(a,t,e,i)=>{let o;if(i&&i<64&&t.size>0)o=t;else if(a.size>0)o=a;else throw new Error("No notes loaded");let s=Array.from(o.keys()).reduce((l,n)=>Math.abs(n-e)<Math.abs(l-e)?n:l);return{closestNoteMidi:s,closestNote:o.get(s)}};var N=class{audioContext;compressorNode;forteNotes=new Map;pianoNotes=new Map;sustain=!1;playingNotes=new Map;progress=0;constructor(){this.audioContext=new AudioContext,this.compressorNode=this.audioContext.createDynamicsCompressor(),this.compressorNode.threshold.value=-24,this.compressorNode.knee.value=0,this.compressorNode.ratio.value=2,this.compressorNode.attack.value=.001,this.compressorNode.release.value=.5,this.compressorNode.connect(this.audioContext.destination)}setSustain=t=>{this.sustain=t,t?this.playingNotes.forEach(e=>{let i=this.audioContext.currentTime;e.node.gain.cancelScheduledValues(i),e.node.gain.setValueAtTime(e.node.gain.value,i)}):this.playingNotes.forEach(e=>{let i=this.audioContext.currentTime;e.node.gain.cancelScheduledValues(i),e.node.gain.setValueAtTime(e.node.gain.value,i),e.node.gain.linearRampToValueAtTime(.001,i+.5)})};loadNotes=async(t,e)=>{this.forteNotes.clear(),this.pianoNotes.clear();let i=t.map(async o=>{let l=await(await fetch(o.url)).arrayBuffer(),n=await this.audioContext.decodeAudioData(l);if(o.velocity==="piano"?this.pianoNotes.set(r[o.note],n):this.forteNotes.set(r[o.note],n),e){let d=(this.pianoNotes.size+this.forteNotes.size)/t.length;d>this.progress&&(this.progress=d,e(this.progress))}});return await Promise.all(i)};playNoteFromMidi=(t,e)=>{if(t<0||t>127)throw new Error("Invalid midi note");if(e&&(e<0||e>127))throw new Error("Invalid velocity value");if(!this.audioContext)throw new Error("Audio context not initialized");let o=this.audioContext.createBufferSource(),{closestNoteMidi:s,closestNote:l}=y(this.forteNotes,this.pianoNotes,t,e);if(l){o.buffer=l;let n=this.audioContext.createGain(),d=Math.min(127,e??127);n.gain.value=(d/127*.9+.1)*.5,o.connect(n),n.connect(this.compressorNode),o.playbackRate.value=2**((t-s)/12),o.start(),this.playingNotes.set(o,{node:n,note:t}),o.onended=()=>{o.disconnect(),this.playingNotes.delete(o)}}else throw new Error("Note not found")};playNoteFromName=(t,e)=>{this.playNoteFromMidi(r[t],e)};liftNoteFromMidi=t=>{this.playingNotes.forEach(e=>{if(e.note===t&&!this.sustain){let i=this.audioContext.currentTime;e.node.gain.cancelScheduledValues(i),e.node.gain.setValueAtTime(e.node.gain.value,i),e.node.gain.exponentialRampToValueAtTime(Number.EPSILON,i+8)}})};liftNoteFromName=(t,e)=>{this.liftNoteFromMidi(r[t])}};var M=class{mode;keyMap=new Map;offset;constructor(t){this.mode=t,t==="single"?this.offset=23:this.offset=16,this.buildNoteMap()}getNoteMap=()=>this.keyMap;getMidiRange=()=>{let t=Array.from(this.keyMap.values()).reduce((i,o)=>o.midiNote&&o.midiNote<i?o.midiNote:i,127),e=Array.from(this.keyMap.values()).reduce((i,o)=>o.midiNote&&o.midiNote>i?o.midiNote:i,0);return{low:t,high:e}};getNoteRange=()=>{let t=this.getMidiRange();return{low:u[t.low],high:u[t.high]}};shiftLeft=()=>{this.offset=Math.max(this.offset-1,0),this.keyMap=new Map,this.buildNoteMap()};shiftLeftOctave=()=>{this.offset=Math.max(this.offset-7,0),this.keyMap=new Map,this.buildNoteMap()};shiftRight=()=>{this.offset=Math.min(this.offset+1,this.mode==="dual"?30:41),this.keyMap=new Map,this.buildNoteMap()};shiftRightOctave=()=>{this.offset=Math.min(this.offset+7,this.mode==="dual"?30:41),this.keyMap=new Map,this.buildNoteMap()};buildNoteMap=()=>{this.mode==="single"?(f(this.keyMap,1,this.offset),m(this.keyMap,2,this.offset)):(f(this.keyMap,0,this.offset),m(this.keyMap,1,this.offset),f(this.keyMap,2,this.offset+12),m(this.keyMap,3,this.offset+12))}},f=(a,t,e)=>{c[t].forEach((i,o)=>{let s=h[e+o];if(s===null)a.set(i,{midiNote:null,type:"disabled"});else if(s!==void 0)a.set(i,{midiNote:r[s],type:"black"});else throw new Error("Invalid note")})},m=(a,t,e)=>{c[t].forEach((i,o)=>{let s=p[e+o];if(s)a.set(i,{midiNote:r[s],type:"white"});else throw new Error("Invalid note")})};export{N as MiniKeys,M as MiniKeysKeyboard,h as keyboardBlackNotes,p as keyboardWhiteNotes,u as midiToNote,r as noteToMidi};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "minikeys",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "A javascript library that plays the piano",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"minikeys",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"vitest": "^3.0.5"
|
|
38
38
|
},
|
|
39
39
|
"scripts": {
|
|
40
|
-
"build": "tsup",
|
|
40
|
+
"build": "tsup src/index.ts --out-dir dist",
|
|
41
41
|
"ci": "npm run build && npm run check-format && npm run lint && npm run test",
|
|
42
42
|
"lint": "tsc",
|
|
43
43
|
"test": "vitest run",
|