Merge branch 'main' into werkstatt
This commit is contained in:
Generated
+174
-174
@@ -3097,9 +3097,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "25.3.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-25.3.5.tgz",
|
||||
"integrity": "sha512-oX8xrhvpiyRCQkG1MFchB09f+cXftgIXb3a7UUa4Y3wpmZPw5tyZGTLWhlESOLq1Rq6oDlc8npVU2/9xiCuXMA==",
|
||||
"version": "25.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-25.4.0.tgz",
|
||||
"integrity": "sha512-9wLpoeWuBlcbBpOY3XmzSTG3oscB6xjBEEtn+pYXTfhyXhIxC5FsBer2KTopBlvKEiW9l13po9fq+SJY/5lkhw==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
@@ -8329,9 +8329,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/mediabunny": {
|
||||
"version": "1.38.1",
|
||||
"resolved": "https://registry.npmjs.org/mediabunny/-/mediabunny-1.38.1.tgz",
|
||||
"integrity": "sha512-iqZjL21WG32qpdlONAyBBnmhLo4EvF+v4wnfe1rXEKT/7ogiYOZnQGL8TZi7QIFV71DSg7a64egFWUgf3oeSYA==",
|
||||
"version": "1.39.1",
|
||||
"resolved": "https://registry.npmjs.org/mediabunny/-/mediabunny-1.39.1.tgz",
|
||||
"integrity": "sha512-gaQKDWtfLhgSN9tRj37lgznHf9MOvey7sbT6GdQA7mWl1kaE5R+P1lfl9CDsgtzongx12IG9X/y2vgZmTHzGDg==",
|
||||
"license": "MPL-2.0",
|
||||
"workspaces": [
|
||||
"packages/*"
|
||||
@@ -10017,9 +10017,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/preact": {
|
||||
"version": "10.28.4",
|
||||
"resolved": "https://registry.npmjs.org/preact/-/preact-10.28.4.tgz",
|
||||
"integrity": "sha512-uKFfOHWuSNpRFVTnljsCluEFq57OKT+0QdOiQo8XWnQ/pSvg7OpX5eNOejELXJMWy+BwM2nobz0FkvzmnpCNsQ==",
|
||||
"version": "10.29.0",
|
||||
"resolved": "https://registry.npmjs.org/preact/-/preact-10.29.0.tgz",
|
||||
"integrity": "sha512-wSAGyk2bYR1c7t3SZ3jHcM6xy0lcBcDel6lODcs9ME6Th++Dx2KU+6D3HD8wMMKGA8Wpw7OMd3/4RGzYRpzwRg==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
@@ -10811,14 +10811,14 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/sass": {
|
||||
"version": "1.97.3",
|
||||
"resolved": "https://registry.npmjs.org/sass/-/sass-1.97.3.tgz",
|
||||
"integrity": "sha512-fDz1zJpd5GycprAbu4Q2PV/RprsRtKC/0z82z0JLgdytmcq0+ujJbJ/09bPGDxCLkKY3Np5cRAOcWiVkLXJURg==",
|
||||
"version": "1.98.0",
|
||||
"resolved": "https://registry.npmjs.org/sass/-/sass-1.98.0.tgz",
|
||||
"integrity": "sha512-+4N/u9dZ4PrgzGgPlKnaaRQx64RO0JBKs9sDhQ2pLgN6JQZ25uPQZKQYaBJU48Kd5BxgXoJ4e09Dq7nMcOUW3A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"chokidar": "^4.0.0",
|
||||
"immutable": "^5.0.2",
|
||||
"immutable": "^5.1.5",
|
||||
"source-map-js": ">=0.6.2 <2.0.0"
|
||||
},
|
||||
"bin": {
|
||||
@@ -11790,27 +11790,27 @@
|
||||
}
|
||||
},
|
||||
"node_modules/turbo": {
|
||||
"version": "2.8.14",
|
||||
"resolved": "https://registry.npmjs.org/turbo/-/turbo-2.8.14.tgz",
|
||||
"integrity": "sha512-UCTxeMNYT1cKaHiIFdLCQ7ulI+jw5i5uOnJOrRXsgUD7G3+OjlUjwVd7JfeVt2McWSVGjYA3EVW/v1FSsJ5DtA==",
|
||||
"version": "2.8.16",
|
||||
"resolved": "https://registry.npmjs.org/turbo/-/turbo-2.8.16.tgz",
|
||||
"integrity": "sha512-u6e9e3cTTpE2adQ1DYm3A3r8y3LAONEx1jYvJx6eIgSY4bMLxIxs0riWzI0Z/IK903ikiUzRPZ2c1Ph5lVLkhA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"turbo": "bin/turbo"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"turbo-darwin-64": "2.8.14",
|
||||
"turbo-darwin-arm64": "2.8.14",
|
||||
"turbo-linux-64": "2.8.14",
|
||||
"turbo-linux-arm64": "2.8.14",
|
||||
"turbo-windows-64": "2.8.14",
|
||||
"turbo-windows-arm64": "2.8.14"
|
||||
"turbo-darwin-64": "2.8.16",
|
||||
"turbo-darwin-arm64": "2.8.16",
|
||||
"turbo-linux-64": "2.8.16",
|
||||
"turbo-linux-arm64": "2.8.16",
|
||||
"turbo-windows-64": "2.8.16",
|
||||
"turbo-windows-arm64": "2.8.16"
|
||||
}
|
||||
},
|
||||
"node_modules/turbo-darwin-64": {
|
||||
"version": "2.8.14",
|
||||
"resolved": "https://registry.npmjs.org/turbo-darwin-64/-/turbo-darwin-64-2.8.14.tgz",
|
||||
"integrity": "sha512-9sFi7n2lLfEsGWi5OEoA/eTtQU2BPKtzSYKqufMtDeRmqMT9vKjbv9gJCRkllSVE9BOXA0qXC3diyX8V8rKIKw==",
|
||||
"version": "2.8.16",
|
||||
"resolved": "https://registry.npmjs.org/turbo-darwin-64/-/turbo-darwin-64-2.8.16.tgz",
|
||||
"integrity": "sha512-KWa4hUMWrpADC6Q/wIHRkBLw6X6MV9nx6X7hSXbTrrMz0KdaKhmfudUZ3sS76bJFmgArBU25cSc0AUyyrswYxg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -11822,9 +11822,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/turbo-darwin-arm64": {
|
||||
"version": "2.8.14",
|
||||
"resolved": "https://registry.npmjs.org/turbo-darwin-arm64/-/turbo-darwin-arm64-2.8.14.tgz",
|
||||
"integrity": "sha512-aS4yJuy6A1PCLws+PJpZP0qCURG8Y5iVx13z/WAbKyeDTY6W6PiGgcEllSaeLGxyn++382ztN/EZH85n2zZ6VQ==",
|
||||
"version": "2.8.16",
|
||||
"resolved": "https://registry.npmjs.org/turbo-darwin-arm64/-/turbo-darwin-arm64-2.8.16.tgz",
|
||||
"integrity": "sha512-NBgaqBDLQSZlJR4D5XCkQq6noaO0RvIgwm5eYFJYL3bH5dNu8o0UBpq7C5DYnQI8+ybyoHFjT5/icN4LeUYLow==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -11836,9 +11836,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/turbo-linux-64": {
|
||||
"version": "2.8.14",
|
||||
"resolved": "https://registry.npmjs.org/turbo-linux-64/-/turbo-linux-64-2.8.14.tgz",
|
||||
"integrity": "sha512-XC6wPUDJkakjhNLaS0NrHDMiujRVjH+naEAwvKLArgqRaFkNxjmyNDRM4eu3soMMFmjym6NTxYaF74rvET+Orw==",
|
||||
"version": "2.8.16",
|
||||
"resolved": "https://registry.npmjs.org/turbo-linux-64/-/turbo-linux-64-2.8.16.tgz",
|
||||
"integrity": "sha512-VYPdcCRevI9kR/hr1H1xwXy7QQt/jNKiim1e1mjANBXD2E9VZWMkIL74J1Huad5MbU3/jw7voHOqDPLJPC2p6w==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -11850,9 +11850,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/turbo-linux-arm64": {
|
||||
"version": "2.8.14",
|
||||
"resolved": "https://registry.npmjs.org/turbo-linux-arm64/-/turbo-linux-arm64-2.8.14.tgz",
|
||||
"integrity": "sha512-ChfE7isyVNjZrVSPDwcfqcHLG/FuIBbOFxnt1FM8vSuBGzHAs8AlTdwFNIxlEMJfZ8Ad9mdMxdmsCUPIWiQ6cg==",
|
||||
"version": "2.8.16",
|
||||
"resolved": "https://registry.npmjs.org/turbo-linux-arm64/-/turbo-linux-arm64-2.8.16.tgz",
|
||||
"integrity": "sha512-beq8tgUVI3uwkQkXJMiOr/hfxQRw54M3elpBwqgYFfemiK5LhCjjcwO0DkE8GZZfElBIlk+saMAQOZy3885wNQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -11864,9 +11864,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/turbo-windows-64": {
|
||||
"version": "2.8.14",
|
||||
"resolved": "https://registry.npmjs.org/turbo-windows-64/-/turbo-windows-64-2.8.14.tgz",
|
||||
"integrity": "sha512-FTbIeQL1ycLFW2t9uQNMy+bRSzi3Xhwun/e7ZhFBdM+U0VZxxrtfYEBM9CHOejlfqomk6Jh7aRz0sJoqYn39Hg==",
|
||||
"version": "2.8.16",
|
||||
"resolved": "https://registry.npmjs.org/turbo-windows-64/-/turbo-windows-64-2.8.16.tgz",
|
||||
"integrity": "sha512-Ig7b46iUgiOIkea/D3Z7H+zNzvzSnIJcLYFpZLA0RxbUTrbLhv9qIPwv3pT9p/abmu0LXVKHxaOo+p26SuDhzw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -11878,9 +11878,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/turbo-windows-arm64": {
|
||||
"version": "2.8.14",
|
||||
"resolved": "https://registry.npmjs.org/turbo-windows-arm64/-/turbo-windows-arm64-2.8.14.tgz",
|
||||
"integrity": "sha512-KgZX12cTyhY030qS7ieT8zRkhZZE2VWJasDFVUSVVn17nR7IShpv68/7j5UqJNeRLIGF1XPK0phsP5V5yw3how==",
|
||||
"version": "2.8.16",
|
||||
"resolved": "https://registry.npmjs.org/turbo-windows-arm64/-/turbo-windows-arm64-2.8.16.tgz",
|
||||
"integrity": "sha512-fOWjbEA2PiE2HEnFQrwNZKYEdjewyPc2no9GmrXklZnTCuMsxeCN39aVlKpKpim03Zq/ykIuvApGwq8ZbfS2Yw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -12956,19 +12956,19 @@
|
||||
},
|
||||
"packages/app/lab": {
|
||||
"name": "@opendaw/lab",
|
||||
"version": "0.0.121",
|
||||
"version": "0.0.126",
|
||||
"license": "LGPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@opendaw/lib-box": "^0.0.77",
|
||||
"@opendaw/lib-dom": "^0.0.76",
|
||||
"@opendaw/lib-dsp": "^0.0.76",
|
||||
"@opendaw/lib-jsx": "^0.0.76",
|
||||
"@opendaw/lib-runtime": "^0.0.72",
|
||||
"@opendaw/lib-std": "^0.0.71",
|
||||
"@opendaw/studio-adapters": "^0.0.97",
|
||||
"@opendaw/studio-boxes": "^0.0.82",
|
||||
"@opendaw/studio-core": "^0.0.121",
|
||||
"@opendaw/studio-enums": "^0.0.67"
|
||||
"@opendaw/lib-box": "^0.0.78",
|
||||
"@opendaw/lib-dom": "^0.0.77",
|
||||
"@opendaw/lib-dsp": "^0.0.77",
|
||||
"@opendaw/lib-jsx": "^0.0.77",
|
||||
"@opendaw/lib-runtime": "^0.0.73",
|
||||
"@opendaw/lib-std": "^0.0.72",
|
||||
"@opendaw/studio-adapters": "^0.0.99",
|
||||
"@opendaw/studio-boxes": "^0.0.83",
|
||||
"@opendaw/studio-core": "^0.0.126",
|
||||
"@opendaw/studio-enums": "^0.0.68"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@opendaw/eslint-config": "^0.0.27",
|
||||
@@ -12999,14 +12999,14 @@
|
||||
},
|
||||
"packages/app/nam-test": {
|
||||
"name": "@opendaw/nam-test",
|
||||
"version": "0.0.8",
|
||||
"version": "0.0.9",
|
||||
"license": "LGPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@opendaw/lib-dom": "^0.0.68",
|
||||
"@opendaw/lib-dsp": "^0.0.66",
|
||||
"@opendaw/lib-jsx": "^0.0.68",
|
||||
"@opendaw/lib-runtime": "^0.0.72",
|
||||
"@opendaw/lib-std": "^0.0.71",
|
||||
"@opendaw/lib-runtime": "^0.0.73",
|
||||
"@opendaw/lib-std": "^0.0.72",
|
||||
"@opendaw/nam-wasm": "^1.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -13095,21 +13095,21 @@
|
||||
},
|
||||
"packages/app/studio": {
|
||||
"name": "@opendaw/app-studio",
|
||||
"version": "0.0.121",
|
||||
"version": "0.0.126",
|
||||
"license": "LGPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@opendaw/lib-box": "^0.0.77",
|
||||
"@opendaw/lib-dom": "^0.0.76",
|
||||
"@opendaw/lib-dsp": "^0.0.76",
|
||||
"@opendaw/lib-jsx": "^0.0.76",
|
||||
"@opendaw/lib-midi": "^0.0.58",
|
||||
"@opendaw/lib-runtime": "^0.0.72",
|
||||
"@opendaw/lib-std": "^0.0.71",
|
||||
"@opendaw/studio-adapters": "^0.0.97",
|
||||
"@opendaw/studio-boxes": "^0.0.82",
|
||||
"@opendaw/studio-core": "^0.0.121",
|
||||
"@opendaw/studio-enums": "^0.0.67",
|
||||
"@opendaw/studio-scripting": "^0.0.50",
|
||||
"@opendaw/lib-box": "^0.0.78",
|
||||
"@opendaw/lib-dom": "^0.0.77",
|
||||
"@opendaw/lib-dsp": "^0.0.77",
|
||||
"@opendaw/lib-jsx": "^0.0.77",
|
||||
"@opendaw/lib-midi": "^0.0.59",
|
||||
"@opendaw/lib-runtime": "^0.0.73",
|
||||
"@opendaw/lib-std": "^0.0.72",
|
||||
"@opendaw/studio-adapters": "^0.0.99",
|
||||
"@opendaw/studio-boxes": "^0.0.83",
|
||||
"@opendaw/studio-core": "^0.0.126",
|
||||
"@opendaw/studio-enums": "^0.0.68",
|
||||
"@opendaw/studio-scripting": "^0.0.52",
|
||||
"@types/d3-force": "^3.0.10",
|
||||
"d3-force": "^3.0.0",
|
||||
"dropbox": "^10.34.0",
|
||||
@@ -13159,11 +13159,11 @@
|
||||
},
|
||||
"packages/lib/box": {
|
||||
"name": "@opendaw/lib-box",
|
||||
"version": "0.0.77",
|
||||
"version": "0.0.78",
|
||||
"license": "LGPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@opendaw/lib-runtime": "^0.0.72",
|
||||
"@opendaw/lib-std": "^0.0.71"
|
||||
"@opendaw/lib-runtime": "^0.0.73",
|
||||
"@opendaw/lib-std": "^0.0.72"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@opendaw/eslint-config": "^0.0.27",
|
||||
@@ -13172,13 +13172,13 @@
|
||||
},
|
||||
"packages/lib/box-forge": {
|
||||
"name": "@opendaw/lib-box-forge",
|
||||
"version": "0.0.79",
|
||||
"version": "0.0.80",
|
||||
"license": "LGPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@opendaw/lib-box": "^0.0.77",
|
||||
"@opendaw/lib-dom": "^0.0.76",
|
||||
"@opendaw/lib-runtime": "^0.0.72",
|
||||
"@opendaw/lib-std": "^0.0.71",
|
||||
"@opendaw/lib-box": "^0.0.78",
|
||||
"@opendaw/lib-dom": "^0.0.77",
|
||||
"@opendaw/lib-runtime": "^0.0.73",
|
||||
"@opendaw/lib-std": "^0.0.72",
|
||||
"ts-morph": "^25.0.1",
|
||||
"tsx": "^4.20.3"
|
||||
},
|
||||
@@ -13189,12 +13189,12 @@
|
||||
},
|
||||
"packages/lib/dawproject": {
|
||||
"name": "@opendaw/lib-dawproject",
|
||||
"version": "0.0.62",
|
||||
"version": "0.0.63",
|
||||
"license": "LGPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@opendaw/lib-dsp": "^0.0.76",
|
||||
"@opendaw/lib-runtime": "^0.0.72",
|
||||
"@opendaw/lib-xml": "^0.0.57",
|
||||
"@opendaw/lib-dsp": "^0.0.77",
|
||||
"@opendaw/lib-runtime": "^0.0.73",
|
||||
"@opendaw/lib-xml": "^0.0.58",
|
||||
"jszip": "^3.10.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -13252,11 +13252,11 @@
|
||||
},
|
||||
"packages/lib/dom": {
|
||||
"name": "@opendaw/lib-dom",
|
||||
"version": "0.0.76",
|
||||
"version": "0.0.77",
|
||||
"license": "LGPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@opendaw/lib-runtime": "^0.0.72",
|
||||
"@opendaw/lib-std": "^0.0.71",
|
||||
"@opendaw/lib-runtime": "^0.0.73",
|
||||
"@opendaw/lib-std": "^0.0.72",
|
||||
"@types/wicg-file-system-access": "^2023.10.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -13266,10 +13266,10 @@
|
||||
},
|
||||
"packages/lib/dsp": {
|
||||
"name": "@opendaw/lib-dsp",
|
||||
"version": "0.0.76",
|
||||
"version": "0.0.77",
|
||||
"license": "LGPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@opendaw/lib-std": "^0.0.71"
|
||||
"@opendaw/lib-std": "^0.0.72"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@opendaw/eslint-config": "^0.0.27",
|
||||
@@ -13278,13 +13278,13 @@
|
||||
},
|
||||
"packages/lib/fusion": {
|
||||
"name": "@opendaw/lib-fusion",
|
||||
"version": "0.0.83",
|
||||
"version": "0.0.85",
|
||||
"license": "LGPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@opendaw/lib-box": "^0.0.77",
|
||||
"@opendaw/lib-dom": "^0.0.76",
|
||||
"@opendaw/lib-runtime": "^0.0.72",
|
||||
"@opendaw/lib-std": "^0.0.71"
|
||||
"@opendaw/lib-box": "^0.0.78",
|
||||
"@opendaw/lib-dom": "^0.0.77",
|
||||
"@opendaw/lib-runtime": "^0.0.73",
|
||||
"@opendaw/lib-std": "^0.0.72"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@opendaw/eslint-config": "^0.0.27",
|
||||
@@ -14014,11 +14014,11 @@
|
||||
},
|
||||
"packages/lib/jsx": {
|
||||
"name": "@opendaw/lib-jsx",
|
||||
"version": "0.0.76",
|
||||
"version": "0.0.77",
|
||||
"license": "LGPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@opendaw/lib-dom": "^0.0.76",
|
||||
"@opendaw/lib-std": "^0.0.71"
|
||||
"@opendaw/lib-dom": "^0.0.77",
|
||||
"@opendaw/lib-std": "^0.0.72"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@opendaw/eslint-config": "^0.0.27",
|
||||
@@ -14027,11 +14027,11 @@
|
||||
},
|
||||
"packages/lib/midi": {
|
||||
"name": "@opendaw/lib-midi",
|
||||
"version": "0.0.58",
|
||||
"version": "0.0.59",
|
||||
"license": "LGPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@opendaw/lib-dsp": "^0.0.76",
|
||||
"@opendaw/lib-std": "^0.0.71"
|
||||
"@opendaw/lib-dsp": "^0.0.77",
|
||||
"@opendaw/lib-std": "^0.0.72"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@opendaw/eslint-config": "^0.0.27",
|
||||
@@ -14040,10 +14040,10 @@
|
||||
},
|
||||
"packages/lib/runtime": {
|
||||
"name": "@opendaw/lib-runtime",
|
||||
"version": "0.0.72",
|
||||
"version": "0.0.73",
|
||||
"license": "LGPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@opendaw/lib-std": "^0.0.71"
|
||||
"@opendaw/lib-std": "^0.0.72"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@opendaw/eslint-config": "^0.0.27",
|
||||
@@ -14052,7 +14052,7 @@
|
||||
},
|
||||
"packages/lib/std": {
|
||||
"name": "@opendaw/lib-std",
|
||||
"version": "0.0.71",
|
||||
"version": "0.0.72",
|
||||
"license": "LGPL-3.0-or-later",
|
||||
"devDependencies": {
|
||||
"@opendaw/eslint-config": "^0.0.27",
|
||||
@@ -14062,10 +14062,10 @@
|
||||
},
|
||||
"packages/lib/xml": {
|
||||
"name": "@opendaw/lib-xml",
|
||||
"version": "0.0.57",
|
||||
"version": "0.0.58",
|
||||
"license": "LGPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@opendaw/lib-std": "^0.0.71"
|
||||
"@opendaw/lib-std": "^0.0.72"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@opendaw/eslint-config": "^0.0.27",
|
||||
@@ -14132,16 +14132,16 @@
|
||||
},
|
||||
"packages/studio/adapters": {
|
||||
"name": "@opendaw/studio-adapters",
|
||||
"version": "0.0.97",
|
||||
"version": "0.0.99",
|
||||
"license": "LGPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@opendaw/lib-box": "^0.0.77",
|
||||
"@opendaw/lib-dsp": "^0.0.76",
|
||||
"@opendaw/lib-fusion": "^0.0.83",
|
||||
"@opendaw/lib-runtime": "^0.0.72",
|
||||
"@opendaw/lib-std": "^0.0.71",
|
||||
"@opendaw/studio-boxes": "^0.0.82",
|
||||
"@opendaw/studio-enums": "^0.0.67",
|
||||
"@opendaw/lib-box": "^0.0.78",
|
||||
"@opendaw/lib-dsp": "^0.0.77",
|
||||
"@opendaw/lib-fusion": "^0.0.85",
|
||||
"@opendaw/lib-runtime": "^0.0.73",
|
||||
"@opendaw/lib-std": "^0.0.72",
|
||||
"@opendaw/studio-boxes": "^0.0.83",
|
||||
"@opendaw/studio-enums": "^0.0.68",
|
||||
"soundfont2": "^0.5.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -14151,35 +14151,35 @@
|
||||
},
|
||||
"packages/studio/boxes": {
|
||||
"name": "@opendaw/studio-boxes",
|
||||
"version": "0.0.82",
|
||||
"version": "0.0.83",
|
||||
"license": "LGPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@opendaw/lib-box": "^0.0.77",
|
||||
"@opendaw/lib-std": "^0.0.71",
|
||||
"@opendaw/studio-enums": "^0.0.67"
|
||||
"@opendaw/lib-box": "^0.0.78",
|
||||
"@opendaw/lib-std": "^0.0.72",
|
||||
"@opendaw/studio-enums": "^0.0.68"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@opendaw/eslint-config": "^0.0.27",
|
||||
"@opendaw/studio-forge-boxes": "^0.0.82",
|
||||
"@opendaw/studio-forge-boxes": "^0.0.83",
|
||||
"@opendaw/typescript-config": "^0.0.29"
|
||||
}
|
||||
},
|
||||
"packages/studio/core": {
|
||||
"name": "@opendaw/studio-core",
|
||||
"version": "0.0.121",
|
||||
"version": "0.0.126",
|
||||
"license": "LGPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@opendaw/lib-box": "^0.0.77",
|
||||
"@opendaw/lib-dawproject": "^0.0.62",
|
||||
"@opendaw/lib-dom": "^0.0.76",
|
||||
"@opendaw/lib-dsp": "^0.0.76",
|
||||
"@opendaw/lib-fusion": "^0.0.83",
|
||||
"@opendaw/lib-runtime": "^0.0.72",
|
||||
"@opendaw/lib-std": "^0.0.71",
|
||||
"@opendaw/lib-box": "^0.0.78",
|
||||
"@opendaw/lib-dawproject": "^0.0.63",
|
||||
"@opendaw/lib-dom": "^0.0.77",
|
||||
"@opendaw/lib-dsp": "^0.0.77",
|
||||
"@opendaw/lib-fusion": "^0.0.85",
|
||||
"@opendaw/lib-runtime": "^0.0.73",
|
||||
"@opendaw/lib-std": "^0.0.72",
|
||||
"@opendaw/nam-wasm": "^1.0.3",
|
||||
"@opendaw/studio-adapters": "^0.0.97",
|
||||
"@opendaw/studio-boxes": "^0.0.82",
|
||||
"@opendaw/studio-enums": "^0.0.67",
|
||||
"@opendaw/studio-adapters": "^0.0.99",
|
||||
"@opendaw/studio-boxes": "^0.0.83",
|
||||
"@opendaw/studio-enums": "^0.0.68",
|
||||
"dropbox": "^10.34.0",
|
||||
"y-websocket": "^1.4.5",
|
||||
"yjs": "^13.6.27",
|
||||
@@ -14189,9 +14189,9 @@
|
||||
"@ffmpeg/ffmpeg": "^0.12.15",
|
||||
"@ffmpeg/util": "^0.12.2",
|
||||
"@opendaw/eslint-config": "^0.0.27",
|
||||
"@opendaw/studio-core-processors": "^0.0.100",
|
||||
"@opendaw/studio-core-workers": "^0.0.92",
|
||||
"@opendaw/studio-forge-boxes": "^0.0.82",
|
||||
"@opendaw/studio-core-processors": "^0.0.103",
|
||||
"@opendaw/studio-core-workers": "^0.0.94",
|
||||
"@opendaw/studio-forge-boxes": "^0.0.83",
|
||||
"@opendaw/typescript-config": "^0.0.29"
|
||||
},
|
||||
"peerDependencies": {
|
||||
@@ -14201,16 +14201,16 @@
|
||||
},
|
||||
"packages/studio/core-processors": {
|
||||
"name": "@opendaw/studio-core-processors",
|
||||
"version": "0.0.100",
|
||||
"version": "0.0.103",
|
||||
"license": "LGPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@opendaw/lib-box": "^0.0.77",
|
||||
"@opendaw/lib-dsp": "^0.0.76",
|
||||
"@opendaw/lib-runtime": "^0.0.72",
|
||||
"@opendaw/lib-std": "^0.0.71",
|
||||
"@opendaw/studio-adapters": "^0.0.97",
|
||||
"@opendaw/studio-boxes": "^0.0.82",
|
||||
"@opendaw/studio-enums": "^0.0.67",
|
||||
"@opendaw/lib-box": "^0.0.78",
|
||||
"@opendaw/lib-dsp": "^0.0.77",
|
||||
"@opendaw/lib-runtime": "^0.0.73",
|
||||
"@opendaw/lib-std": "^0.0.72",
|
||||
"@opendaw/studio-adapters": "^0.0.99",
|
||||
"@opendaw/studio-boxes": "^0.0.83",
|
||||
"@opendaw/studio-enums": "^0.0.68",
|
||||
"@types/audioworklet": "^0.0.77"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -15169,16 +15169,16 @@
|
||||
},
|
||||
"packages/studio/core-workers": {
|
||||
"name": "@opendaw/studio-core-workers",
|
||||
"version": "0.0.92",
|
||||
"version": "0.0.94",
|
||||
"license": "LGPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@opendaw/lib-box": "^0.0.77",
|
||||
"@opendaw/lib-dsp": "^0.0.76",
|
||||
"@opendaw/lib-runtime": "^0.0.72",
|
||||
"@opendaw/lib-std": "^0.0.71",
|
||||
"@opendaw/studio-adapters": "^0.0.97",
|
||||
"@opendaw/studio-boxes": "^0.0.82",
|
||||
"@opendaw/studio-enums": "^0.0.67"
|
||||
"@opendaw/lib-box": "^0.0.78",
|
||||
"@opendaw/lib-dsp": "^0.0.77",
|
||||
"@opendaw/lib-runtime": "^0.0.73",
|
||||
"@opendaw/lib-std": "^0.0.72",
|
||||
"@opendaw/studio-adapters": "^0.0.99",
|
||||
"@opendaw/studio-boxes": "^0.0.83",
|
||||
"@opendaw/studio-enums": "^0.0.68"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@opendaw/eslint-config": "^0.0.27",
|
||||
@@ -15187,10 +15187,10 @@
|
||||
},
|
||||
"packages/studio/enums": {
|
||||
"name": "@opendaw/studio-enums",
|
||||
"version": "0.0.67",
|
||||
"version": "0.0.68",
|
||||
"license": "LGPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@opendaw/lib-std": "^0.0.71"
|
||||
"@opendaw/lib-std": "^0.0.72"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@opendaw/eslint-config": "^0.0.27",
|
||||
@@ -15199,14 +15199,14 @@
|
||||
},
|
||||
"packages/studio/forge-boxes": {
|
||||
"name": "@opendaw/studio-forge-boxes",
|
||||
"version": "0.0.82",
|
||||
"version": "0.0.83",
|
||||
"license": "LGPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@opendaw/lib-box": "^0.0.77",
|
||||
"@opendaw/lib-dsp": "^0.0.76",
|
||||
"@opendaw/lib-runtime": "^0.0.72",
|
||||
"@opendaw/lib-std": "^0.0.71",
|
||||
"@opendaw/studio-enums": "^0.0.67"
|
||||
"@opendaw/lib-box": "^0.0.78",
|
||||
"@opendaw/lib-dsp": "^0.0.77",
|
||||
"@opendaw/lib-runtime": "^0.0.73",
|
||||
"@opendaw/lib-std": "^0.0.72",
|
||||
"@opendaw/studio-enums": "^0.0.68"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@opendaw/eslint-config": "^0.0.27",
|
||||
@@ -15215,16 +15215,16 @@
|
||||
},
|
||||
"packages/studio/scripting": {
|
||||
"name": "@opendaw/studio-scripting",
|
||||
"version": "0.0.50",
|
||||
"version": "0.0.52",
|
||||
"license": "LGPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@opendaw/lib-box": "^0.0.77",
|
||||
"@opendaw/lib-dsp": "^0.0.76",
|
||||
"@opendaw/lib-runtime": "^0.0.72",
|
||||
"@opendaw/lib-std": "^0.0.71",
|
||||
"@opendaw/studio-adapters": "^0.0.97",
|
||||
"@opendaw/studio-boxes": "^0.0.82",
|
||||
"@opendaw/studio-enums": "^0.0.67"
|
||||
"@opendaw/lib-box": "^0.0.78",
|
||||
"@opendaw/lib-dsp": "^0.0.77",
|
||||
"@opendaw/lib-runtime": "^0.0.73",
|
||||
"@opendaw/lib-std": "^0.0.72",
|
||||
"@opendaw/studio-adapters": "^0.0.99",
|
||||
"@opendaw/studio-boxes": "^0.0.83",
|
||||
"@opendaw/studio-enums": "^0.0.68"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@opendaw/eslint-config": "^0.0.27",
|
||||
@@ -15233,23 +15233,23 @@
|
||||
},
|
||||
"packages/studio/sdk": {
|
||||
"name": "@opendaw/studio-sdk",
|
||||
"version": "0.0.123",
|
||||
"version": "0.0.128",
|
||||
"license": "LGPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@opendaw/lib-box": "^0.0.77",
|
||||
"@opendaw/lib-dawproject": "^0.0.62",
|
||||
"@opendaw/lib-dom": "^0.0.76",
|
||||
"@opendaw/lib-dsp": "^0.0.76",
|
||||
"@opendaw/lib-fusion": "^0.0.83",
|
||||
"@opendaw/lib-jsx": "^0.0.76",
|
||||
"@opendaw/lib-midi": "^0.0.58",
|
||||
"@opendaw/lib-runtime": "^0.0.72",
|
||||
"@opendaw/lib-std": "^0.0.71",
|
||||
"@opendaw/lib-xml": "^0.0.57",
|
||||
"@opendaw/studio-adapters": "^0.0.97",
|
||||
"@opendaw/studio-boxes": "^0.0.82",
|
||||
"@opendaw/studio-core": "^0.0.121",
|
||||
"@opendaw/studio-enums": "^0.0.67"
|
||||
"@opendaw/lib-box": "^0.0.78",
|
||||
"@opendaw/lib-dawproject": "^0.0.63",
|
||||
"@opendaw/lib-dom": "^0.0.77",
|
||||
"@opendaw/lib-dsp": "^0.0.77",
|
||||
"@opendaw/lib-fusion": "^0.0.85",
|
||||
"@opendaw/lib-jsx": "^0.0.77",
|
||||
"@opendaw/lib-midi": "^0.0.59",
|
||||
"@opendaw/lib-runtime": "^0.0.73",
|
||||
"@opendaw/lib-std": "^0.0.72",
|
||||
"@opendaw/lib-xml": "^0.0.58",
|
||||
"@opendaw/studio-adapters": "^0.0.99",
|
||||
"@opendaw/studio-boxes": "^0.0.83",
|
||||
"@opendaw/studio-core": "^0.0.126",
|
||||
"@opendaw/studio-enums": "^0.0.68"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@opendaw/typescript-config": "^0.0.29"
|
||||
|
||||
@@ -3,6 +3,26 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.0.126](https://github.com/andremichelle/openDAW/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-12)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/lab
|
||||
|
||||
## [0.0.125](https://github.com/andremichelle/openDAW/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-12)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/lab
|
||||
|
||||
## [0.0.124](https://github.com/andremichelle/openDAW/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-11)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/lab
|
||||
|
||||
## [0.0.123](https://github.com/andremichelle/openDAW/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-11)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/lab
|
||||
|
||||
## [0.0.122](https://github.com/andremichelle/openDAW/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-10)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/lab
|
||||
|
||||
## [0.0.121](https://github.com/andremichelle/openDAW/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-07)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/lab
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@opendaw/lab",
|
||||
"private": true,
|
||||
"version": "0.0.121",
|
||||
"version": "0.0.126",
|
||||
"type": "module",
|
||||
"license": "LGPL-3.0-or-later",
|
||||
"scripts": {
|
||||
@@ -11,16 +11,16 @@
|
||||
"lint": "eslint \"src/**/*.ts\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@opendaw/lib-box": "^0.0.77",
|
||||
"@opendaw/lib-dom": "^0.0.76",
|
||||
"@opendaw/lib-dsp": "^0.0.76",
|
||||
"@opendaw/lib-jsx": "^0.0.76",
|
||||
"@opendaw/lib-runtime": "^0.0.72",
|
||||
"@opendaw/lib-std": "^0.0.71",
|
||||
"@opendaw/studio-adapters": "^0.0.97",
|
||||
"@opendaw/studio-boxes": "^0.0.82",
|
||||
"@opendaw/studio-core": "^0.0.121",
|
||||
"@opendaw/studio-enums": "^0.0.67"
|
||||
"@opendaw/lib-box": "^0.0.78",
|
||||
"@opendaw/lib-dom": "^0.0.77",
|
||||
"@opendaw/lib-dsp": "^0.0.77",
|
||||
"@opendaw/lib-jsx": "^0.0.77",
|
||||
"@opendaw/lib-runtime": "^0.0.73",
|
||||
"@opendaw/lib-std": "^0.0.72",
|
||||
"@opendaw/studio-adapters": "^0.0.99",
|
||||
"@opendaw/studio-boxes": "^0.0.83",
|
||||
"@opendaw/studio-core": "^0.0.126",
|
||||
"@opendaw/studio-enums": "^0.0.68"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@opendaw/eslint-config": "^0.0.27",
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.0.9](https://github.com/andremichelle/openDAW/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-10)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/nam-test
|
||||
|
||||
## [0.0.8](https://github.com/andremichelle/openDAW/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-04)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/nam-test
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@opendaw/nam-test",
|
||||
"private": true,
|
||||
"version": "0.0.8",
|
||||
"version": "0.0.9",
|
||||
"type": "module",
|
||||
"license": "LGPL-3.0-or-later",
|
||||
"scripts": {
|
||||
@@ -14,8 +14,8 @@
|
||||
"@opendaw/lib-dom": "^0.0.68",
|
||||
"@opendaw/lib-dsp": "^0.0.66",
|
||||
"@opendaw/lib-jsx": "^0.0.68",
|
||||
"@opendaw/lib-runtime": "^0.0.72",
|
||||
"@opendaw/lib-std": "^0.0.71",
|
||||
"@opendaw/lib-runtime": "^0.0.73",
|
||||
"@opendaw/lib-std": "^0.0.72",
|
||||
"@opendaw/nam-wasm": "^1.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -3,6 +3,26 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.0.126](https://github.com/andremichelle/openDAW/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-12)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/app-studio
|
||||
|
||||
## [0.0.125](https://github.com/andremichelle/openDAW/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-12)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/app-studio
|
||||
|
||||
## [0.0.124](https://github.com/andremichelle/openDAW/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-11)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/app-studio
|
||||
|
||||
## [0.0.123](https://github.com/andremichelle/openDAW/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-11)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/app-studio
|
||||
|
||||
## [0.0.122](https://github.com/andremichelle/openDAW/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-10)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/app-studio
|
||||
|
||||
## [0.0.121](https://github.com/andremichelle/openDAW/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-07)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/app-studio
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@opendaw/app-studio",
|
||||
"private": true,
|
||||
"version": "0.0.121",
|
||||
"version": "0.0.126",
|
||||
"type": "module",
|
||||
"license": "LGPL-3.0-or-later",
|
||||
"scripts": {
|
||||
@@ -11,18 +11,18 @@
|
||||
"lint": "eslint \"src/**/*.ts\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@opendaw/lib-box": "^0.0.77",
|
||||
"@opendaw/lib-dom": "^0.0.76",
|
||||
"@opendaw/lib-dsp": "^0.0.76",
|
||||
"@opendaw/lib-jsx": "^0.0.76",
|
||||
"@opendaw/lib-midi": "^0.0.58",
|
||||
"@opendaw/lib-runtime": "^0.0.72",
|
||||
"@opendaw/lib-std": "^0.0.71",
|
||||
"@opendaw/studio-adapters": "^0.0.97",
|
||||
"@opendaw/studio-boxes": "^0.0.82",
|
||||
"@opendaw/studio-core": "^0.0.121",
|
||||
"@opendaw/studio-enums": "^0.0.67",
|
||||
"@opendaw/studio-scripting": "^0.0.50",
|
||||
"@opendaw/lib-box": "^0.0.78",
|
||||
"@opendaw/lib-dom": "^0.0.77",
|
||||
"@opendaw/lib-dsp": "^0.0.77",
|
||||
"@opendaw/lib-jsx": "^0.0.77",
|
||||
"@opendaw/lib-midi": "^0.0.59",
|
||||
"@opendaw/lib-runtime": "^0.0.73",
|
||||
"@opendaw/lib-std": "^0.0.72",
|
||||
"@opendaw/studio-adapters": "^0.0.99",
|
||||
"@opendaw/studio-boxes": "^0.0.83",
|
||||
"@opendaw/studio-core": "^0.0.126",
|
||||
"@opendaw/studio-enums": "^0.0.68",
|
||||
"@opendaw/studio-scripting": "^0.0.52",
|
||||
"@types/d3-force": "^3.0.10",
|
||||
"d3-force": "^3.0.0",
|
||||
"dropbox": "^10.34.0",
|
||||
|
||||
@@ -14,6 +14,7 @@ const IgnoredErrors = [
|
||||
]
|
||||
const BrowserInternalPatterns = ["feature named"]
|
||||
const MonacoPatterns = ["monaco-editor", "vs/base/common/errors"]
|
||||
const ThirdPartyAppPatterns = ["_callback_receiveMIDIMessage", "_callback_addSource"]
|
||||
const UrlPattern = /https?:\/\/[^\s)]+/g
|
||||
|
||||
export class ErrorHandler {
|
||||
@@ -58,6 +59,12 @@ export class ErrorHandler {
|
||||
event.preventDefault()
|
||||
return true
|
||||
}
|
||||
if (event instanceof ErrorEvent
|
||||
&& ThirdPartyAppPatterns.some(pattern => event.message.includes(pattern))) {
|
||||
console.warn(`Third-party app error ignored: ${event.message}`)
|
||||
event.preventDefault()
|
||||
return true
|
||||
}
|
||||
// Handle Monaco editor errors from error events
|
||||
// Monaco rethrows worker error Event objects through its error pipeline,
|
||||
// arriving as ErrorEvent where event.error is a raw Event (not an Error).
|
||||
|
||||
@@ -126,10 +126,16 @@ export class StudioService implements ProjectEnv {
|
||||
readonly soundfontManager: GlobalSoundfontLoaderManager,
|
||||
readonly cloudAuthManager: CloudAuthManager,
|
||||
readonly buildInfo: BuildInfo) {
|
||||
this.#sampleService = new SampleService(audioContext,
|
||||
sample => this.#signals.notify({type: "import-sample", sample}))
|
||||
this.#soundfontService = new SoundfontService(
|
||||
soundfont => this.#signals.notify({type: "import-soundfont", soundfont}))
|
||||
this.#sampleService = new SampleService(audioContext)
|
||||
this.#sampleService.subscribe(([sample, _]) => this.#signals.notify({
|
||||
type: "import-sample",
|
||||
sample
|
||||
}))
|
||||
this.#soundfontService = new SoundfontService()
|
||||
this.#soundfontService.subscribe(([soundfont, _]) => this.#signals.notify({
|
||||
type: "import-soundfont",
|
||||
soundfont
|
||||
}))
|
||||
this.samplePlayback = new SamplePlayback()
|
||||
this.#projectProfileService = new ProjectProfileService({
|
||||
env: this,
|
||||
|
||||
@@ -32,7 +32,7 @@ export namespace SlotUtils {
|
||||
layout.x1 = x1
|
||||
layout.y0 = rowHeight * channelIndex
|
||||
layout.y1 = rowHeight * (channelIndex + 1)
|
||||
PeaksPainter.renderBlocks(context, peaks, channelIndex, layout)
|
||||
PeaksPainter.renderPixelStrips(context, peaks, channelIndex, layout)
|
||||
}
|
||||
if (x0 > 0.0 || forceBounds) {
|
||||
context.fillRect(Math.round(x0), 0, 1, height * devicePixelRatio)
|
||||
@@ -49,7 +49,7 @@ export namespace SlotUtils {
|
||||
layout.x1 = x0
|
||||
layout.y0 = rowHeight * channelIndex
|
||||
layout.y1 = rowHeight * (channelIndex + 1)
|
||||
PeaksPainter.renderBlocks(context, peaks, channelIndex, layout)
|
||||
PeaksPainter.renderPixelStrips(context, peaks, channelIndex, layout)
|
||||
}
|
||||
}
|
||||
if (u1 < numFrames) {
|
||||
@@ -61,7 +61,7 @@ export namespace SlotUtils {
|
||||
layout.x1 = wd
|
||||
layout.y0 = rowHeight * channelIndex
|
||||
layout.y1 = rowHeight * (channelIndex + 1)
|
||||
PeaksPainter.renderBlocks(context, peaks, channelIndex, layout)
|
||||
PeaksPainter.renderPixelStrips(context, peaks, channelIndex, layout)
|
||||
}
|
||||
}
|
||||
context.globalAlpha = 1.0
|
||||
|
||||
@@ -57,7 +57,7 @@ export const AudioEditorCanvas = ({
|
||||
if (pass.isEmpty()) {return}
|
||||
const tempoMap = reader.trackBoxAdapter.unwrap().context.tempoMap
|
||||
AudioRenderer.render(context, range, file, tempoMap, observableOptPlayMode, waveformOffset.getValue(),
|
||||
gain.getValue(), {top: 0, bottom: actualHeight},
|
||||
gain.getValue(), {top: 0, bottom: painter.height},
|
||||
`hsl(${reader.hue}, ${60}%, 45%)`, pass.unwrap(), false)
|
||||
|
||||
const cursor = cursorModel.getValue()
|
||||
|
||||
@@ -33,11 +33,13 @@ export abstract class TimelineDragAndDrop<T extends (ClipCaptureTarget | RegionC
|
||||
if (target?.type === "track" && target.track.trackBoxAdapter.type !== TrackType.Audio) {
|
||||
return Option.None
|
||||
}
|
||||
if (target?.type === "clip" && target.clip.trackBoxAdapter.unwrap().type !== TrackType.Audio) {
|
||||
return Option.None
|
||||
if (target?.type === "clip") {
|
||||
const adapter = target.clip.trackBoxAdapter
|
||||
if (adapter.isEmpty() || adapter.unwrap().type !== TrackType.Audio) {return Option.None}
|
||||
}
|
||||
if (target?.type === "region" && target.region.trackBoxAdapter.unwrap().type !== TrackType.Audio) {
|
||||
return Option.None
|
||||
if (target?.type === "region") {
|
||||
const adapter = target.region.trackBoxAdapter
|
||||
if (adapter.isEmpty() || adapter.unwrap().type !== TrackType.Audio) {return Option.None}
|
||||
}
|
||||
if (data.type !== "sample" && data.type !== "instrument" && data.type !== "file") {
|
||||
return Option.None
|
||||
@@ -94,9 +96,13 @@ export abstract class TimelineDragAndDrop<T extends (ClipCaptureTarget | RegionC
|
||||
} else if (drop?.type === "track") {
|
||||
trackBoxAdapter = drop.track.trackBoxAdapter
|
||||
} else if (drop?.type === "clip") {
|
||||
trackBoxAdapter = drop.clip.trackBoxAdapter.unwrap()
|
||||
const clipTrack = drop.clip.trackBoxAdapter
|
||||
if (clipTrack.isEmpty()) {return}
|
||||
trackBoxAdapter = clipTrack.unwrap()
|
||||
} else if (drop?.type === "region") {
|
||||
trackBoxAdapter = drop.region.trackBoxAdapter.unwrap()
|
||||
const regionTrack = drop.region.trackBoxAdapter
|
||||
if (regionTrack.isEmpty()) {return}
|
||||
trackBoxAdapter = regionTrack.unwrap()
|
||||
} else {
|
||||
return panic("Illegal State")
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import css from "./RegionLane.sass?inline"
|
||||
import {Html} from "@opendaw/lib-dom"
|
||||
import {Lifecycle} from "@opendaw/lib-std"
|
||||
import {createElement} from "@opendaw/lib-jsx"
|
||||
import {renderRegions} from "@/ui/timeline/tracks/audio-unit/regions/RegionRenderer.ts"
|
||||
import {RegionRenderer} from "@/ui/timeline/tracks/audio-unit/regions/RegionRenderer.ts"
|
||||
import {TrackBoxAdapter, TrackType} from "@opendaw/studio-adapters"
|
||||
import {TracksManager} from "@/ui/timeline/tracks/audio-unit/TracksManager.ts"
|
||||
import {CanvasPainter, TimelineRange} from "@opendaw/studio-core"
|
||||
@@ -26,7 +26,7 @@ export const RegionLane = ({lifecycle, trackManager, range, adapter}: Construct)
|
||||
const element: Element = (<div className={className}>{canvas}</div>)
|
||||
const painter = lifecycle.own(new CanvasPainter(canvas, ({context}) => {
|
||||
if (visible) {
|
||||
renderRegions(context, trackManager, range, adapter.listIndex)
|
||||
RegionRenderer.render(context, trackManager, range, adapter.listIndex)
|
||||
updated = true
|
||||
}
|
||||
}))
|
||||
|
||||
@@ -17,158 +17,166 @@ import {Context2d} from "@opendaw/lib-dom"
|
||||
import {RegionPaintBucket} from "@/ui/timeline/tracks/audio-unit/regions/RegionPaintBucket"
|
||||
import {RegionLabel} from "@/ui/timeline/RegionLabel"
|
||||
|
||||
export const renderRegions = (context: CanvasRenderingContext2D,
|
||||
tracks: TracksManager,
|
||||
range: TimelineRange,
|
||||
index: int): void => {
|
||||
const canvas = context.canvas
|
||||
const {width, height} = canvas
|
||||
const {fontFamily} = getComputedStyle(canvas)
|
||||
export namespace RegionRenderer {
|
||||
let audioRenderStrategy: AudioRenderer.Strategy = AudioRenderer.DefaultStrategy
|
||||
|
||||
// subtract one pixel to avoid making special cases for a possible outline
|
||||
const unitMin = range.unitMin - range.unitPadding - range.unitsPerPixel
|
||||
const unitMax = range.unitMax
|
||||
export const setAudioRenderStrategy = (strategy: AudioRenderer.Strategy): void => {audioRenderStrategy = strategy}
|
||||
|
||||
const dpr = devicePixelRatio
|
||||
const fontSize = RegionLabel.fontSize() * dpr
|
||||
const labelHeight = RegionLabel.labelHeight() * dpr
|
||||
const bound: RegionBound = {top: labelHeight + 1.0, bottom: height - 2.5}
|
||||
export const render = (context: CanvasRenderingContext2D,
|
||||
tracks: TracksManager,
|
||||
range: TimelineRange,
|
||||
index: int): void => {
|
||||
const canvas = context.canvas
|
||||
const {width, height} = canvas
|
||||
const {fontFamily} = getComputedStyle(canvas)
|
||||
|
||||
context.clearRect(0, 0, width, height)
|
||||
context.textBaseline = "middle"
|
||||
context.font = `${fontSize}px ${fontFamily}`
|
||||
// subtract one pixel to avoid making special cases for a possible outline
|
||||
const unitMin = range.unitMin - range.unitPadding - range.unitsPerPixel
|
||||
const unitMax = range.unitMax
|
||||
|
||||
const grid = true
|
||||
if (grid) {
|
||||
const {timelineBoxAdapter: {signatureTrack}} = tracks.service.project
|
||||
context.fillStyle = "rgba(0, 0, 0, 0.3)"
|
||||
TimeGrid.fragment(
|
||||
signatureTrack,
|
||||
range,
|
||||
({pulse}) => {
|
||||
const x0 = Math.floor(range.unitToX(pulse)) * dpr
|
||||
context.fillRect(x0, 0, dpr, height)
|
||||
},
|
||||
{minLength: 32}
|
||||
)
|
||||
}
|
||||
const renderRegions = (strategy: RegionModifyStrategy, filterSelected: boolean, hideSelected: boolean): void => {
|
||||
const optTrack = tracks.getByIndex(strategy.translateTrackIndex(index))
|
||||
if (optTrack.isEmpty()) {return}
|
||||
const trackBoxAdapter = optTrack.unwrap().trackBoxAdapter
|
||||
const trackDisabled = !trackBoxAdapter.enabled.getValue()
|
||||
const regions = strategy.iterateRange(trackBoxAdapter.regions.collection, unitMin, unitMax)
|
||||
for (const [region, next] of Iterables.pairWise(regions)) {
|
||||
if (region.isSelected ? hideSelected : !filterSelected) {continue}
|
||||
const actualComplete = strategy.readComplete(region)
|
||||
const position = strategy.readPosition(region)
|
||||
const complete = region.isSelected
|
||||
? actualComplete
|
||||
: // for no-stretched audio region
|
||||
Math.min(actualComplete, next?.position ?? Number.POSITIVE_INFINITY)
|
||||
const x0Int = Math.floor(range.unitToX(Math.max(position, unitMin))) * dpr
|
||||
const x1Int = Math.max(Math.floor(range.unitToX(Math.min(complete, unitMax)) - 1) * dpr, x0Int + dpr)
|
||||
const xnInt = x1Int - x0Int
|
||||
const {labelColor, labelBackground, contentColor, contentBackground, loopStrokeColor} =
|
||||
RegionPaintBucket.create(region, region.isSelected && !filterSelected, trackDisabled)
|
||||
context.clearRect(x0Int, 0, xnInt, height)
|
||||
context.fillStyle = labelBackground
|
||||
context.fillRect(x0Int, 0, xnInt, labelHeight)
|
||||
context.fillStyle = contentBackground
|
||||
context.fillRect(x0Int, labelHeight, xnInt, height - labelHeight)
|
||||
const maxTextWidth = xnInt - 3 * dpr // subtract text-padding
|
||||
context.fillStyle = labelColor
|
||||
if (strategy.readMirror(region)) {
|
||||
context.font = `italic ${fontSize}px ${fontFamily}`
|
||||
} else {
|
||||
context.font = `${fontSize}px ${fontFamily}`
|
||||
}
|
||||
const text = region.label.length === 0 ? "◻" : region.label
|
||||
context.fillText(Context2d.truncateText(context, text, maxTextWidth).text, x0Int + 3 * dpr, 1 + labelHeight / 2)
|
||||
if (!region.hasCollection) {continue}
|
||||
context.fillStyle = contentColor
|
||||
region.accept({
|
||||
visitNoteRegionBoxAdapter: (region: NoteRegionBoxAdapter): void => {
|
||||
const optCollection = region.optCollection
|
||||
if (optCollection.isEmpty()) {return}
|
||||
for (const pass of LoopableRegion.locateLoops({
|
||||
position, complete,
|
||||
loopOffset: strategy.readLoopOffset(region),
|
||||
loopDuration: strategy.readLoopDuration(region)
|
||||
}, unitMin, unitMax)) {
|
||||
if (pass.index > 0) {
|
||||
const x = Math.floor(range.unitToX(pass.resultStart) * dpr)
|
||||
context.fillStyle = loopStrokeColor
|
||||
context.fillRect(x, labelHeight, 1, height - labelHeight)
|
||||
}
|
||||
NotesRenderer.render(context, range, optCollection.unwrap(), bound, contentColor, pass)
|
||||
}
|
||||
const dpr = devicePixelRatio
|
||||
const cssLabelHeight = RegionLabel.labelHeight()
|
||||
const fontSize = RegionLabel.fontSize() * dpr
|
||||
const labelHeight = cssLabelHeight * dpr
|
||||
const bound: RegionBound = {top: cssLabelHeight + 1, bottom: canvas.clientHeight - 2}
|
||||
|
||||
context.clearRect(0, 0, width, height)
|
||||
context.textBaseline = "middle"
|
||||
context.font = `${fontSize}px ${fontFamily}`
|
||||
|
||||
const grid = true
|
||||
if (grid) {
|
||||
const {timelineBoxAdapter: {signatureTrack}} = tracks.service.project
|
||||
context.fillStyle = "rgba(0, 0, 0, 0.3)"
|
||||
TimeGrid.fragment(
|
||||
signatureTrack,
|
||||
range,
|
||||
({pulse}) => {
|
||||
const x0 = Math.floor(range.unitToX(pulse)) * dpr
|
||||
context.fillRect(x0, 0, dpr, height)
|
||||
},
|
||||
visitAudioRegionBoxAdapter: (region: AudioRegionBoxAdapter): void => {
|
||||
for (const pass of LoopableRegion.locateLoops({
|
||||
position, complete,
|
||||
loopOffset: strategy.readLoopOffset(region),
|
||||
loopDuration: strategy.readLoopDuration(region)
|
||||
}, unitMin, unitMax)) {
|
||||
if (pass.index > 0) {
|
||||
const x = Math.floor(range.unitToX(pass.resultStart) * dpr)
|
||||
context.fillStyle = loopStrokeColor
|
||||
context.fillRect(x, labelHeight, 1, height - labelHeight)
|
||||
}
|
||||
const tempoMap = region.trackBoxAdapter.unwrap().context.tempoMap
|
||||
AudioRenderer.render(context, range, region.file, tempoMap,
|
||||
region.observableOptPlayMode, region.waveformOffset.getValue(),
|
||||
region.gain.getValue(), bound, contentColor, pass
|
||||
)
|
||||
}
|
||||
AudioFadingRenderer.render(context, range, region.fading, bound, position, complete, labelBackground)
|
||||
const isRecording = region.file.getOrCreateLoader().state.type === "record"
|
||||
if (isRecording) {}
|
||||
},
|
||||
visitValueRegionBoxAdapter: (region: ValueRegionBoxAdapter) => {
|
||||
const padding = dpr
|
||||
const top = labelHeight + padding
|
||||
const bottom = height - padding * 2
|
||||
context.save()
|
||||
context.beginPath()
|
||||
context.rect(x0Int + padding, top, x1Int - x0Int - padding, bottom - top + padding)
|
||||
context.clip()
|
||||
const valueToY = (value: unitValue): number => bottom + value * (top - bottom)
|
||||
const events = region.events.unwrap()
|
||||
for (const pass of LoopableRegion.locateLoops({
|
||||
position, complete,
|
||||
loopOffset: strategy.readLoopOffset(region),
|
||||
loopDuration: strategy.readLoopDuration(region)
|
||||
}, unitMin, unitMax)) {
|
||||
if (pass.index > 0) {
|
||||
const x = Math.floor(range.unitToX(pass.resultStart) * dpr)
|
||||
context.fillStyle = loopStrokeColor
|
||||
context.fillRect(x, labelHeight, 1, height - labelHeight)
|
||||
}
|
||||
const windowMin = pass.resultStart - pass.rawStart
|
||||
const windowMax = pass.resultEnd - pass.rawStart
|
||||
context.strokeStyle = contentColor
|
||||
context.beginPath()
|
||||
const adapters = ValueEvent.iterateWindow(events, windowMin, windowMax)
|
||||
ValueStreamRenderer.render(context, range, adapters, valueToY, contentColor, 0.2, 0.0, pass)
|
||||
context.stroke()
|
||||
}
|
||||
context.restore()
|
||||
}
|
||||
})
|
||||
const isEditing = tracks.service.project.userEditingManager.timeline.isEditing(region.box)
|
||||
if (isEditing) {
|
||||
{minLength: 32}
|
||||
)
|
||||
}
|
||||
const renderRegions = (strategy: RegionModifyStrategy, filterSelected: boolean, hideSelected: boolean): void => {
|
||||
const optTrack = tracks.getByIndex(strategy.translateTrackIndex(index))
|
||||
if (optTrack.isEmpty()) {return}
|
||||
const trackBoxAdapter = optTrack.unwrap().trackBoxAdapter
|
||||
const trackDisabled = !trackBoxAdapter.enabled.getValue()
|
||||
const regions = strategy.iterateRange(trackBoxAdapter.regions.collection, unitMin, unitMax)
|
||||
for (const [region, next] of Iterables.pairWise(regions)) {
|
||||
if (region.isSelected ? hideSelected : !filterSelected) {continue}
|
||||
const actualComplete = strategy.readComplete(region)
|
||||
const position = strategy.readPosition(region)
|
||||
const complete = region.isSelected
|
||||
? actualComplete
|
||||
: // for no-stretched audio region
|
||||
Math.min(actualComplete, next?.position ?? Number.POSITIVE_INFINITY)
|
||||
const x0Int = Math.floor(range.unitToX(Math.max(position, unitMin))) * dpr
|
||||
const x1Int = Math.max(Math.floor(range.unitToX(Math.min(complete, unitMax)) - 1) * dpr, x0Int + dpr)
|
||||
const xnInt = x1Int - x0Int
|
||||
const {labelColor, labelBackground, contentColor, contentBackground, loopStrokeColor} =
|
||||
RegionPaintBucket.create(region, region.isSelected && !filterSelected, trackDisabled)
|
||||
context.clearRect(x0Int, 0, xnInt, height)
|
||||
context.fillStyle = labelBackground
|
||||
context.fillRect(x1Int - dpr, labelHeight, dpr, height - labelHeight - dpr)
|
||||
context.fillRect(x0Int, labelHeight, dpr, height - labelHeight - dpr)
|
||||
context.fillRect(x0Int, height - dpr, xnInt, height - dpr)
|
||||
context.fillRect(x0Int, 0, xnInt, labelHeight)
|
||||
context.fillStyle = contentBackground
|
||||
context.fillRect(x0Int, labelHeight, xnInt, height - labelHeight)
|
||||
const maxTextWidth = xnInt - 3 * dpr // subtract text-padding
|
||||
context.fillStyle = labelColor
|
||||
if (strategy.readMirror(region)) {
|
||||
context.font = `italic ${fontSize}px ${fontFamily}`
|
||||
} else {
|
||||
context.font = `${fontSize}px ${fontFamily}`
|
||||
}
|
||||
const text = region.label.length === 0 ? "◻" : region.label
|
||||
context.fillText(Context2d.truncateText(context, text, maxTextWidth).text, x0Int + 3 * dpr, 1 + labelHeight / 2)
|
||||
if (!region.hasCollection) {continue}
|
||||
context.fillStyle = contentColor
|
||||
region.accept({
|
||||
visitNoteRegionBoxAdapter: (region: NoteRegionBoxAdapter): void => {
|
||||
const optCollection = region.optCollection
|
||||
if (optCollection.isEmpty()) {return}
|
||||
for (const pass of LoopableRegion.locateLoops({
|
||||
position, complete,
|
||||
loopOffset: strategy.readLoopOffset(region),
|
||||
loopDuration: strategy.readLoopDuration(region)
|
||||
}, unitMin, unitMax)) {
|
||||
if (pass.index > 0) {
|
||||
const x = Math.floor(range.unitToX(pass.resultStart) * dpr)
|
||||
context.fillStyle = loopStrokeColor
|
||||
context.fillRect(x, labelHeight, 1, height - labelHeight)
|
||||
}
|
||||
NotesRenderer.render(context, range, optCollection.unwrap(), bound, contentColor, pass)
|
||||
}
|
||||
},
|
||||
visitAudioRegionBoxAdapter: (region: AudioRegionBoxAdapter): void => {
|
||||
for (const pass of LoopableRegion.locateLoops({
|
||||
position, complete,
|
||||
loopOffset: strategy.readLoopOffset(region),
|
||||
loopDuration: strategy.readLoopDuration(region)
|
||||
}, unitMin, unitMax)) {
|
||||
if (pass.index > 0) {
|
||||
const x = Math.floor(range.unitToX(pass.resultStart) * dpr)
|
||||
context.fillStyle = loopStrokeColor
|
||||
context.fillRect(x, labelHeight, 1, height - labelHeight)
|
||||
}
|
||||
const tempoMap = region.trackBoxAdapter.unwrap().context.tempoMap
|
||||
AudioRenderer.render(context, range, region.file, tempoMap,
|
||||
region.observableOptPlayMode, region.waveformOffset.getValue(),
|
||||
region.gain.getValue(), bound, contentColor, pass,
|
||||
true, audioRenderStrategy
|
||||
)
|
||||
}
|
||||
AudioFadingRenderer.render(context, range, region.fading, bound, position, complete, labelBackground)
|
||||
const isRecording = region.file.getOrCreateLoader().state.type === "record"
|
||||
if (isRecording) {}
|
||||
},
|
||||
visitValueRegionBoxAdapter: (region: ValueRegionBoxAdapter) => {
|
||||
const padding = dpr
|
||||
const top = labelHeight + padding
|
||||
const bottom = height - padding * 2
|
||||
context.save()
|
||||
context.beginPath()
|
||||
context.rect(x0Int + padding, top, x1Int - x0Int - padding, bottom - top + padding)
|
||||
context.clip()
|
||||
const valueToY = (value: unitValue): number => bottom + value * (top - bottom)
|
||||
const events = region.events.unwrap()
|
||||
for (const pass of LoopableRegion.locateLoops({
|
||||
position, complete,
|
||||
loopOffset: strategy.readLoopOffset(region),
|
||||
loopDuration: strategy.readLoopDuration(region)
|
||||
}, unitMin, unitMax)) {
|
||||
if (pass.index > 0) {
|
||||
const x = Math.floor(range.unitToX(pass.resultStart) * dpr)
|
||||
context.fillStyle = loopStrokeColor
|
||||
context.fillRect(x, labelHeight, 1, height - labelHeight)
|
||||
}
|
||||
const windowMin = pass.resultStart - pass.rawStart
|
||||
const windowMax = pass.resultEnd - pass.rawStart
|
||||
context.strokeStyle = contentColor
|
||||
context.beginPath()
|
||||
const adapters = ValueEvent.iterateWindow(events, windowMin, windowMax)
|
||||
ValueStreamRenderer.render(context, range, adapters, valueToY, contentColor, 0.2, 0.0, pass)
|
||||
context.stroke()
|
||||
}
|
||||
context.restore()
|
||||
}
|
||||
})
|
||||
const isEditing = tracks.service.project.userEditingManager.timeline.isEditing(region.box)
|
||||
if (isEditing) {
|
||||
context.fillStyle = labelBackground
|
||||
context.fillRect(x1Int - dpr, labelHeight, dpr, height - labelHeight - dpr)
|
||||
context.fillRect(x0Int, labelHeight, dpr, height - labelHeight - dpr)
|
||||
context.fillRect(x0Int, height - dpr, xnInt, height - dpr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const modifier: Option<RegionModifyStrategies> = tracks.currentRegionModifier
|
||||
const strategy = modifier.unwrapOrElse(RegionModifyStrategies.Identity)
|
||||
|
||||
renderRegions(strategy.unselectedModifyStrategy(), true, !strategy.showOrigin())
|
||||
renderRegions(strategy.selectedModifyStrategy(), false, false)
|
||||
}
|
||||
|
||||
const modifier: Option<RegionModifyStrategies> = tracks.currentRegionModifier
|
||||
const strategy = modifier.unwrapOrElse(RegionModifyStrategies.Identity)
|
||||
|
||||
renderRegions(strategy.unselectedModifyStrategy(), true, !strategy.showOrigin())
|
||||
renderRegions(strategy.selectedModifyStrategy(), false, false)
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,10 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.0.80](https://github.com/andremichelle/openDAW/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-10)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/lib-box-forge
|
||||
|
||||
## [0.0.79](https://github.com/andremichelle/openDAW/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-04)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/lib-box-forge
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opendaw/lib-box-forge",
|
||||
"version": "0.0.79",
|
||||
"version": "0.0.80",
|
||||
"private": true,
|
||||
"sideEffects": false,
|
||||
"license": "LGPL-3.0-or-later",
|
||||
@@ -16,10 +16,10 @@
|
||||
"test": "npm run gen && vitest run"
|
||||
},
|
||||
"dependencies": {
|
||||
"@opendaw/lib-box": "^0.0.77",
|
||||
"@opendaw/lib-dom": "^0.0.76",
|
||||
"@opendaw/lib-runtime": "^0.0.72",
|
||||
"@opendaw/lib-std": "^0.0.71",
|
||||
"@opendaw/lib-box": "^0.0.78",
|
||||
"@opendaw/lib-dom": "^0.0.77",
|
||||
"@opendaw/lib-runtime": "^0.0.73",
|
||||
"@opendaw/lib-std": "^0.0.72",
|
||||
"ts-morph": "^25.0.1",
|
||||
"tsx": "^4.20.3"
|
||||
},
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.0.78](https://github.com/andremichelle/openDAW/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-10)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/lib-box
|
||||
|
||||
## [0.0.77](https://github.com/andremichelle/openDAW/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-04)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/lib-box
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opendaw/lib-box",
|
||||
"version": "0.0.77",
|
||||
"version": "0.0.78",
|
||||
"sideEffects": false,
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -23,8 +23,8 @@
|
||||
"test": "vitest run"
|
||||
},
|
||||
"dependencies": {
|
||||
"@opendaw/lib-runtime": "^0.0.72",
|
||||
"@opendaw/lib-std": "^0.0.71"
|
||||
"@opendaw/lib-runtime": "^0.0.73",
|
||||
"@opendaw/lib-std": "^0.0.72"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@opendaw/eslint-config": "^0.0.27",
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.0.63](https://github.com/andremichelle/openDAW/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-10)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/lib-dawproject
|
||||
|
||||
## [0.0.62](https://github.com/andremichelle/openDAW/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-04)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/lib-dawproject
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opendaw/lib-dawproject",
|
||||
"version": "0.0.62",
|
||||
"version": "0.0.63",
|
||||
"sideEffects": false,
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -23,9 +23,9 @@
|
||||
"test": "vitest run"
|
||||
},
|
||||
"dependencies": {
|
||||
"@opendaw/lib-dsp": "^0.0.76",
|
||||
"@opendaw/lib-runtime": "^0.0.72",
|
||||
"@opendaw/lib-xml": "^0.0.57",
|
||||
"@opendaw/lib-dsp": "^0.0.77",
|
||||
"@opendaw/lib-runtime": "^0.0.73",
|
||||
"@opendaw/lib-xml": "^0.0.58",
|
||||
"jszip": "^3.10.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.0.77](https://github.com/andremichelle/openDAW/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-10)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/lib-dom
|
||||
|
||||
## [0.0.76](https://github.com/andremichelle/openDAW/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-04)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/lib-dom
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opendaw/lib-dom",
|
||||
"version": "0.0.76",
|
||||
"version": "0.0.77",
|
||||
"sideEffects": false,
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -23,8 +23,8 @@
|
||||
"test": "vitest run"
|
||||
},
|
||||
"dependencies": {
|
||||
"@opendaw/lib-runtime": "^0.0.72",
|
||||
"@opendaw/lib-std": "^0.0.71",
|
||||
"@opendaw/lib-runtime": "^0.0.73",
|
||||
"@opendaw/lib-std": "^0.0.72",
|
||||
"@types/wicg-file-system-access": "^2023.10.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.0.77](https://github.com/andremichelle/openDAW/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-10)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/lib-dsp
|
||||
|
||||
## [0.0.76](https://github.com/andremichelle/openDAW/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-04)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/lib-dsp
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opendaw/lib-dsp",
|
||||
"version": "0.0.76",
|
||||
"version": "0.0.77",
|
||||
"sideEffects": false,
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -27,7 +27,7 @@
|
||||
"test": "vitest run"
|
||||
},
|
||||
"dependencies": {
|
||||
"@opendaw/lib-std": "^0.0.71"
|
||||
"@opendaw/lib-std": "^0.0.72"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@opendaw/eslint-config": "^0.0.27",
|
||||
|
||||
@@ -3,6 +3,14 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.0.85](https://github.com/andremichelle/openDAW/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-11)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/lib-fusion
|
||||
|
||||
## [0.0.84](https://github.com/andremichelle/openDAW/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-10)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/lib-fusion
|
||||
|
||||
## [0.0.83](https://github.com/andremichelle/openDAW/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-04)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/lib-fusion
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opendaw/lib-fusion",
|
||||
"version": "0.0.83",
|
||||
"version": "0.0.85",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
"license": "LGPL-3.0-or-later",
|
||||
@@ -23,10 +23,10 @@
|
||||
"test": "vitest run"
|
||||
},
|
||||
"dependencies": {
|
||||
"@opendaw/lib-box": "^0.0.77",
|
||||
"@opendaw/lib-dom": "^0.0.76",
|
||||
"@opendaw/lib-runtime": "^0.0.72",
|
||||
"@opendaw/lib-std": "^0.0.71"
|
||||
"@opendaw/lib-box": "^0.0.78",
|
||||
"@opendaw/lib-dom": "^0.0.77",
|
||||
"@opendaw/lib-runtime": "^0.0.73",
|
||||
"@opendaw/lib-std": "^0.0.72"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@opendaw/eslint-config": "^0.0.27",
|
||||
|
||||
@@ -13,10 +13,10 @@ export namespace PeaksPainter {
|
||||
v1: number // value max (+1)
|
||||
}
|
||||
|
||||
export const renderBlocks = (path: CanvasRenderingContext2D,
|
||||
peaks: Peaks,
|
||||
channelIndex: int,
|
||||
{u0, u1, v0, v1, x0, x1, y0, y1}: Layout): void => {
|
||||
export const renderPixelStrips = (path: CanvasRenderingContext2D,
|
||||
peaks: Peaks,
|
||||
channelIndex: int,
|
||||
{u0, u1, v0, v1, x0, x1, y0, y1}: Layout): void => {
|
||||
const unitsEachPixel = (u1 - u0) / (x1 - x0)
|
||||
const stage = peaks.nearest(unitsEachPixel)
|
||||
if (stage === null) {return}
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.0.77](https://github.com/andremichelle/openDAW/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-10)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/lib-jsx
|
||||
|
||||
## [0.0.76](https://github.com/andremichelle/openDAW/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-04)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/lib-jsx
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opendaw/lib-jsx",
|
||||
"version": "0.0.76",
|
||||
"version": "0.0.77",
|
||||
"license": "LGPL-3.0-or-later",
|
||||
"sideEffects": false,
|
||||
"main": "./dist/index.js",
|
||||
@@ -23,8 +23,8 @@
|
||||
"test": "echo \"No tests to run\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@opendaw/lib-dom": "^0.0.76",
|
||||
"@opendaw/lib-std": "^0.0.71"
|
||||
"@opendaw/lib-dom": "^0.0.77",
|
||||
"@opendaw/lib-std": "^0.0.72"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@opendaw/eslint-config": "^0.0.27",
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.0.59](https://github.com/andremichelle/openDAW/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-10)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/lib-midi
|
||||
|
||||
## [0.0.58](https://github.com/andremichelle/openDAW/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-04)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/lib-midi
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opendaw/lib-midi",
|
||||
"version": "0.0.58",
|
||||
"version": "0.0.59",
|
||||
"sideEffects": false,
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -23,8 +23,8 @@
|
||||
"test": "echo \"No tests to run\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@opendaw/lib-dsp": "^0.0.76",
|
||||
"@opendaw/lib-std": "^0.0.71"
|
||||
"@opendaw/lib-dsp": "^0.0.77",
|
||||
"@opendaw/lib-std": "^0.0.72"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@opendaw/eslint-config": "^0.0.27",
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.0.73](https://github.com/andremichelle/openDAW/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-10)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/lib-runtime
|
||||
|
||||
## [0.0.72](https://github.com/andremichelle/openDAW/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-04)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/lib-runtime
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opendaw/lib-runtime",
|
||||
"version": "0.0.72",
|
||||
"version": "0.0.73",
|
||||
"license": "LGPL-3.0-or-later",
|
||||
"sideEffects": false,
|
||||
"publishConfig": {
|
||||
@@ -23,7 +23,7 @@
|
||||
"test": "vitest run"
|
||||
},
|
||||
"dependencies": {
|
||||
"@opendaw/lib-std": "^0.0.71"
|
||||
"@opendaw/lib-std": "^0.0.72"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@opendaw/eslint-config": "^0.0.27",
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.0.72](https://github.com/andremichelle/openDAW/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-10)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/lib-std
|
||||
|
||||
## [0.0.71](https://github.com/andremichelle/openDAW/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-04)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/lib-std
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opendaw/lib-std",
|
||||
"version": "0.0.71",
|
||||
"version": "0.0.72",
|
||||
"license": "LGPL-3.0-or-later",
|
||||
"sideEffects": false,
|
||||
"publishConfig": {
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.0.58](https://github.com/andremichelle/openDAW/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-10)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/lib-xml
|
||||
|
||||
## [0.0.57](https://github.com/andremichelle/openDAW/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-04)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/lib-xml
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opendaw/lib-xml",
|
||||
"version": "0.0.57",
|
||||
"version": "0.0.58",
|
||||
"sideEffects": false,
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -23,7 +23,7 @@
|
||||
"test": "echo \"No tests to run\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@opendaw/lib-std": "^0.0.71"
|
||||
"@opendaw/lib-std": "^0.0.72"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@opendaw/eslint-config": "^0.0.27",
|
||||
|
||||
@@ -3,6 +3,14 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.0.99](https://github.com/andremichelle/openDAW/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-11)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/studio-adapters
|
||||
|
||||
## [0.0.98](https://github.com/andremichelle/openDAW/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-10)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/studio-adapters
|
||||
|
||||
## [0.0.97](https://github.com/andremichelle/openDAW/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-07)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/studio-adapters
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opendaw/studio-adapters",
|
||||
"version": "0.0.97",
|
||||
"version": "0.0.99",
|
||||
"license": "LGPL-3.0-or-later",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
@@ -23,13 +23,13 @@
|
||||
"test": "echo \"No tests to run\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@opendaw/lib-box": "^0.0.77",
|
||||
"@opendaw/lib-dsp": "^0.0.76",
|
||||
"@opendaw/lib-fusion": "^0.0.83",
|
||||
"@opendaw/lib-runtime": "^0.0.72",
|
||||
"@opendaw/lib-std": "^0.0.71",
|
||||
"@opendaw/studio-boxes": "^0.0.82",
|
||||
"@opendaw/studio-enums": "^0.0.67",
|
||||
"@opendaw/lib-box": "^0.0.78",
|
||||
"@opendaw/lib-dsp": "^0.0.77",
|
||||
"@opendaw/lib-fusion": "^0.0.85",
|
||||
"@opendaw/lib-runtime": "^0.0.73",
|
||||
"@opendaw/lib-std": "^0.0.72",
|
||||
"@opendaw/studio-boxes": "^0.0.83",
|
||||
"@opendaw/studio-enums": "^0.0.68",
|
||||
"soundfont2": "^0.5.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -118,6 +118,16 @@ export class NoteEventCollectionBoxAdapter implements BoxAdapter, SelectableLoca
|
||||
return result
|
||||
}
|
||||
|
||||
overlapping(from: ppqn, to: ppqn, pitch: int): ReadonlyArray<NoteEventBoxAdapter> {
|
||||
const result: Array<NoteEventBoxAdapter> = []
|
||||
for (const event of this.#events.asArray()) {
|
||||
if (event.pitch === pitch && event.complete > from && event.position < to) {
|
||||
result.push(event)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
requestSorting(): void {
|
||||
this.#events.onIndexingChanged()
|
||||
this.onEventPropertyChanged()
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.0.83](https://github.com/andremichelle/openDAW/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-10)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/studio-boxes
|
||||
|
||||
## [0.0.82](https://github.com/andremichelle/openDAW/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-06)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/studio-boxes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opendaw/studio-boxes",
|
||||
"version": "0.0.82",
|
||||
"version": "0.0.83",
|
||||
"license": "LGPL-3.0-or-later",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
@@ -22,13 +22,13 @@
|
||||
"test": "echo \"No tests to run\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@opendaw/lib-box": "^0.0.77",
|
||||
"@opendaw/lib-std": "^0.0.71",
|
||||
"@opendaw/studio-enums": "^0.0.67"
|
||||
"@opendaw/lib-box": "^0.0.78",
|
||||
"@opendaw/lib-std": "^0.0.72",
|
||||
"@opendaw/studio-enums": "^0.0.68"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@opendaw/eslint-config": "^0.0.27",
|
||||
"@opendaw/studio-forge-boxes": "^0.0.82",
|
||||
"@opendaw/studio-forge-boxes": "^0.0.83",
|
||||
"@opendaw/typescript-config": "^0.0.29"
|
||||
},
|
||||
"gitHead": "e4f70170c5947610932306da94e7f0bb817e43b3"
|
||||
|
||||
@@ -3,6 +3,18 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.0.103](https://github.com/andremichelle/openDAW/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-11)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/studio-core-processors
|
||||
|
||||
## [0.0.102](https://github.com/andremichelle/openDAW/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-11)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/studio-core-processors
|
||||
|
||||
## [0.0.101](https://github.com/andremichelle/openDAW/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-10)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/studio-core-processors
|
||||
|
||||
## [0.0.100](https://github.com/andremichelle/openDAW/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-07)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/studio-core-processors
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opendaw/studio-core-processors",
|
||||
"version": "0.0.100",
|
||||
"version": "0.0.103",
|
||||
"license": "LGPL-3.0-or-later",
|
||||
"private": true,
|
||||
"exports": {
|
||||
@@ -13,13 +13,13 @@
|
||||
"test": "vitest run"
|
||||
},
|
||||
"dependencies": {
|
||||
"@opendaw/lib-box": "^0.0.77",
|
||||
"@opendaw/lib-dsp": "^0.0.76",
|
||||
"@opendaw/lib-runtime": "^0.0.72",
|
||||
"@opendaw/lib-std": "^0.0.71",
|
||||
"@opendaw/studio-adapters": "^0.0.97",
|
||||
"@opendaw/studio-boxes": "^0.0.82",
|
||||
"@opendaw/studio-enums": "^0.0.67",
|
||||
"@opendaw/lib-box": "^0.0.78",
|
||||
"@opendaw/lib-dsp": "^0.0.77",
|
||||
"@opendaw/lib-runtime": "^0.0.73",
|
||||
"@opendaw/lib-std": "^0.0.72",
|
||||
"@opendaw/studio-adapters": "^0.0.99",
|
||||
"@opendaw/studio-boxes": "^0.0.83",
|
||||
"@opendaw/studio-enums": "^0.0.68",
|
||||
"@types/audioworklet": "^0.0.77"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -9,7 +9,6 @@ import {
|
||||
Observer,
|
||||
Option,
|
||||
panic,
|
||||
quantizeFloor,
|
||||
SortedSet,
|
||||
Subscription,
|
||||
SyncStream,
|
||||
@@ -120,7 +119,15 @@ export class EngineProcessor extends AudioWorkletProcessor implements EngineCont
|
||||
#playbackTimestamp: ppqn = 0.0 // this is where we start playing again (after paused)
|
||||
#perfWriteIndex: number = 0
|
||||
|
||||
constructor({processorOptions: {syncStreamBuffer, controlFlagsBuffer, hrClockBuffer, project, exportConfiguration}}: {
|
||||
constructor({
|
||||
processorOptions: {
|
||||
syncStreamBuffer,
|
||||
controlFlagsBuffer,
|
||||
hrClockBuffer,
|
||||
project,
|
||||
exportConfiguration
|
||||
}
|
||||
}: {
|
||||
processorOptions: EngineProcessorAttachment
|
||||
} & AudioNodeOptions) {
|
||||
super()
|
||||
@@ -500,7 +507,7 @@ export class EngineProcessor extends AudioWorkletProcessor implements EngineCont
|
||||
const position = this.#timeInfo.position
|
||||
const [nominator, denominator] = this.#timelineBoxAdapter.signature
|
||||
const countInOffset = PPQN.fromSignature(this.#preferences.settings.recording.countInBars * nominator, denominator)
|
||||
this.#recordingStartTime = quantizeFloor(position, PPQN.fromSignature(nominator, denominator))
|
||||
this.#recordingStartTime = position
|
||||
this.#timeInfo.isCountingIn = true
|
||||
this.#timeInfo.metronomeEnabled = true
|
||||
this.#timeInfo.transporting = true
|
||||
|
||||
@@ -1,15 +1,9 @@
|
||||
import {int} from "@opendaw/lib-std"
|
||||
import {int, UUID} from "@opendaw/lib-std"
|
||||
import {AudioBuffer, AudioData} from "@opendaw/lib-dsp"
|
||||
import {VoiceState} from "./VoiceState"
|
||||
|
||||
/**
|
||||
* PitchVoice is used for pitch-stretch mode (warp marker based).
|
||||
* It does NOT implement the Voice interface as it's managed differently
|
||||
* by the TapeDeviceProcessor (not via TimeStretchSequencer).
|
||||
*
|
||||
* Uses fadeDirection to track fading in (+1) vs fading out (-1).
|
||||
*/
|
||||
export class PitchVoice {
|
||||
readonly sourceUuid: UUID.Bytes
|
||||
readonly #output: AudioBuffer
|
||||
readonly #data: AudioData
|
||||
readonly #fadeLength: number
|
||||
@@ -22,8 +16,9 @@ export class PitchVoice {
|
||||
#blockOffset: int
|
||||
#fadeOutBlockOffset: int = 0
|
||||
|
||||
constructor(output: AudioBuffer, data: AudioData, fadeLength: number, playbackRate: number,
|
||||
constructor(sourceUuid: UUID.Bytes, output: AudioBuffer, data: AudioData, fadeLength: number, playbackRate: number,
|
||||
offset: number = 0.0, blockOffset: int = 0) {
|
||||
this.sourceUuid = sourceUuid
|
||||
this.#output = output
|
||||
this.#data = data
|
||||
this.#fadeLength = fadeLength
|
||||
|
||||
@@ -20,14 +20,12 @@ import {DeviceProcessor} from "../../DeviceProcessor"
|
||||
import {NoteEventTarget} from "../../NoteEventSource"
|
||||
import {VOICE_FADE_DURATION} from "./Tape/constants"
|
||||
import {PitchVoice} from "./Tape/PitchVoice"
|
||||
import {Voice} from "./Tape/Voice"
|
||||
import {TimeStretchSequencer} from "./Tape/TimeStretchSequencer"
|
||||
|
||||
type AnyVoice = Voice | PitchVoice
|
||||
|
||||
type Lane = {
|
||||
adapter: TrackBoxAdapter
|
||||
voices: Array<AnyVoice>
|
||||
pitchVoices: SortedSet<UUID.Bytes, PitchVoice>
|
||||
fadingVoices: Array<PitchVoice>
|
||||
sequencer: TimeStretchSequencer
|
||||
}
|
||||
|
||||
@@ -37,6 +35,11 @@ export class TapeDeviceProcessor extends AbstractProcessor implements DeviceProc
|
||||
readonly #peaks: PeakBroadcaster
|
||||
readonly #lanes: SortedSet<UUID.Bytes, Lane>
|
||||
readonly #fadingGainBuffer: Float32Array = new Float32Array(RenderQuantum)
|
||||
readonly #unitGainBuffer: Float32Array = (() => {
|
||||
const buffer = new Float32Array(RenderQuantum)
|
||||
buffer.fill(1.0)
|
||||
return buffer
|
||||
})()
|
||||
|
||||
#enabled: boolean = true
|
||||
|
||||
@@ -55,7 +58,8 @@ export class TapeDeviceProcessor extends AbstractProcessor implements DeviceProc
|
||||
this.#adapter.deviceHost().audioUnitBoxAdapter().tracks.catchupAndSubscribe({
|
||||
onAdd: (adapter: TrackBoxAdapter) => this.#lanes.add({
|
||||
adapter,
|
||||
voices: [],
|
||||
pitchVoices: UUID.newSet<PitchVoice>(voice => voice.sourceUuid),
|
||||
fadingVoices: [],
|
||||
sequencer: new TimeStretchSequencer()
|
||||
}),
|
||||
onRemove: (adapter: TrackBoxAdapter) => this.#lanes.removeByKey(adapter.uuid),
|
||||
@@ -79,7 +83,8 @@ export class TapeDeviceProcessor extends AbstractProcessor implements DeviceProc
|
||||
this.#audioOutput.clear()
|
||||
this.eventInput.clear()
|
||||
this.#lanes.forEach(lane => {
|
||||
lane.voices = []
|
||||
lane.pitchVoices.clear()
|
||||
lane.fadingVoices = []
|
||||
lane.sequencer.reset()
|
||||
})
|
||||
}
|
||||
@@ -98,12 +103,17 @@ export class TapeDeviceProcessor extends AbstractProcessor implements DeviceProc
|
||||
#processBlock(lane: Lane, block: Block): void {
|
||||
const {adapter} = lane
|
||||
if (adapter.type !== TrackType.Audio || !adapter.enabled.getValue()) {
|
||||
lane.voices.forEach(voice => voice.startFadeOut(0))
|
||||
this.#fadeOutAllPitchVoices(lane)
|
||||
lane.sequencer.reset()
|
||||
return
|
||||
}
|
||||
const {p0, p1, flags} = block
|
||||
const {p0, p1, s0, s1, flags} = block
|
||||
if (!Bits.every(flags, BlockFlag.transporting | BlockFlag.playing)) {return}
|
||||
if (Bits.some(flags, BlockFlag.discontinuous)) {
|
||||
this.#fadeOutAllPitchVoices(lane)
|
||||
lane.sequencer.reset()
|
||||
}
|
||||
const visitedUuids: Set<string> = new Set()
|
||||
const intervals = this.context.clipSequencing.iterate(adapter.uuid, p0, p1)
|
||||
for (const {optClip, sectionFrom, sectionTo} of intervals) {
|
||||
optClip.match({
|
||||
@@ -113,7 +123,6 @@ export class TapeDeviceProcessor extends AbstractProcessor implements DeviceProc
|
||||
const file = region.file
|
||||
const optData = file.getOrCreateLoader().data
|
||||
if (optData.isEmpty()) {return}
|
||||
const waveformOffset = region.waveformOffset.getValue()
|
||||
const timeStretch = region.asPlayModeTimeStretch
|
||||
if (timeStretch.nonEmpty()) {
|
||||
const transients: EventCollection<TransientMarkerBoxAdapter> = file.transients
|
||||
@@ -121,13 +130,15 @@ export class TapeDeviceProcessor extends AbstractProcessor implements DeviceProc
|
||||
for (const cycle of LoopableRegion.locateLoops(region, p0, p1)) {
|
||||
const timeStretchBoxAdapter = timeStretch.unwrap()
|
||||
this.#processPassTimestretch(lane, block, cycle,
|
||||
optData.unwrap(), timeStretchBoxAdapter, transients, waveformOffset, region.fading,
|
||||
optData.unwrap(), timeStretchBoxAdapter, transients,
|
||||
region.waveformOffset.getValue(), region.fading,
|
||||
region.position, region.duration)
|
||||
}
|
||||
} else {
|
||||
visitedUuids.add(UUID.toString(region.uuid))
|
||||
for (const cycle of LoopableRegion.locateLoops(region, p0, p1)) {
|
||||
this.#processPassPitch(
|
||||
lane, block, cycle, region, optData.unwrap())
|
||||
lane, block, cycle, region, optData.unwrap(), region.uuid)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -152,26 +163,39 @@ export class TapeDeviceProcessor extends AbstractProcessor implements DeviceProc
|
||||
timeStretch, transients, clip.waveformOffset.getValue(), null, 0, clip.duration)
|
||||
}
|
||||
} else {
|
||||
visitedUuids.add(UUID.toString(clip.uuid))
|
||||
for (const cycle of LoopableRegion.locateLoops({
|
||||
position: 0.0,
|
||||
loopDuration: clip.duration,
|
||||
loopOffset: 0.0,
|
||||
complete: Number.POSITIVE_INFINITY
|
||||
}, sectionFrom, sectionTo)) {
|
||||
this.#processPassPitch(lane, block, cycle, clip, optData.unwrap())
|
||||
this.#processPassPitch(lane, block, cycle, clip, optData.unwrap(), clip.uuid)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
lane.pitchVoices.removeByPredicate(voice => {
|
||||
if (visitedUuids.has(UUID.toString(voice.sourceUuid))) {return false}
|
||||
voice.startFadeOut(0)
|
||||
lane.fadingVoices.push(voice)
|
||||
return true
|
||||
})
|
||||
const sn = s1 - s0
|
||||
for (const voice of lane.fadingVoices) {
|
||||
voice.process(s0, sn, this.#unitGainBuffer)
|
||||
}
|
||||
lane.fadingVoices = lane.fadingVoices.filter(voice => !voice.done())
|
||||
}
|
||||
|
||||
#processPassPitch(lane: Lane,
|
||||
block: Block,
|
||||
cycle: LoopableRegion.LoopCycle,
|
||||
adapter: AudioContentBoxAdapter,
|
||||
data: AudioData): void {
|
||||
const {p0, p1, s0, s1, flags} = block
|
||||
data: AudioData,
|
||||
sourceUuid: UUID.Bytes): void {
|
||||
const {p0, p1, s0, s1} = block
|
||||
const sn = s1 - s0
|
||||
const pn = p1 - p0
|
||||
const r0 = (cycle.resultStart - p0) / pn
|
||||
@@ -181,15 +205,11 @@ export class TapeDeviceProcessor extends AbstractProcessor implements DeviceProc
|
||||
const bpn = (bp1 - bp0) | 0
|
||||
const waveformOffset: number = adapter.waveformOffset.getValue()
|
||||
assert(s0 <= bp0 && bp1 <= s1, () => `Out of bounds ${bp0}, ${bp1}`)
|
||||
if (Bits.some(flags, BlockFlag.discontinuous)) {
|
||||
lane.voices.forEach(voice => voice.startFadeOut(0))
|
||||
lane.sequencer.reset()
|
||||
}
|
||||
const asPlayModePitch = adapter.asPlayModePitchStretch
|
||||
if (adapter.isPlayModeNoStretch) {
|
||||
const elapsedSeconds = this.context.tempoMap.intervalToSeconds(cycle.rawStart, cycle.resultStart)
|
||||
const offset = (elapsedSeconds + waveformOffset) * data.sampleRate
|
||||
this.#updateOrCreatePitchVoice(lane, data, data.sampleRate / sampleRate, offset, 0)
|
||||
this.#updateOrCreatePitchVoice(lane, sourceUuid, data, data.sampleRate / sampleRate, offset, 0)
|
||||
} else if (asPlayModePitch.isEmpty()) {
|
||||
const audioDurationSamples = data.numberOfFrames
|
||||
const audioDurationNormalized = cycle.resultEndValue - cycle.resultStartValue
|
||||
@@ -197,25 +217,25 @@ export class TapeDeviceProcessor extends AbstractProcessor implements DeviceProc
|
||||
const timelineSamplesInCycle = (cycle.resultEnd - cycle.resultStart) / pn * sn
|
||||
const playbackRate = audioSamplesInCycle / timelineSamplesInCycle
|
||||
const offset = cycle.resultStartValue * data.numberOfFrames + waveformOffset * data.sampleRate
|
||||
this.#updateOrCreatePitchVoice(lane, data, playbackRate, offset, 0)
|
||||
this.#updateOrCreatePitchVoice(lane, sourceUuid, data, playbackRate, offset, 0)
|
||||
} else {
|
||||
const pitchBoxAdapter = asPlayModePitch.unwrap()
|
||||
const warpMarkers = pitchBoxAdapter.warpMarkers
|
||||
const firstWarp = warpMarkers.first()
|
||||
const lastWarp = warpMarkers.last()
|
||||
if (firstWarp === null || lastWarp === null) {
|
||||
lane.voices.forEach(voice => voice.startFadeOut(0))
|
||||
this.#evictPitchVoice(lane, sourceUuid)
|
||||
return
|
||||
}
|
||||
const contentPpqn = cycle.resultStart - cycle.rawStart
|
||||
if (contentPpqn < firstWarp.position || contentPpqn >= lastWarp.position) {
|
||||
lane.voices.forEach(voice => voice.startFadeOut(0))
|
||||
this.#evictPitchVoice(lane, sourceUuid)
|
||||
return
|
||||
}
|
||||
const currentSeconds = this.#ppqnToSeconds(contentPpqn, cycle.resultStartValue, warpMarkers)
|
||||
const playbackRate = this.#getPlaybackRateFromWarp(contentPpqn, warpMarkers, data.sampleRate, pn, sn)
|
||||
const offset = (currentSeconds + waveformOffset) * data.sampleRate
|
||||
this.#updateOrCreatePitchVoice(lane, data, playbackRate, offset, 0)
|
||||
this.#updateOrCreatePitchVoice(lane, sourceUuid, data, playbackRate, offset, 0)
|
||||
}
|
||||
if (isInstanceOf(adapter, AudioRegionBoxAdapter) && adapter.fading.hasFading) {
|
||||
const regionPosition = adapter.position
|
||||
@@ -226,40 +246,55 @@ export class TapeDeviceProcessor extends AbstractProcessor implements DeviceProc
|
||||
} else {
|
||||
this.#fadingGainBuffer.fill(1.0, 0, bpn)
|
||||
}
|
||||
for (const voice of lane.voices) {
|
||||
const voice = lane.pitchVoices.getOrNull(sourceUuid)
|
||||
if (voice !== null) {
|
||||
voice.process(bp0 | 0, bpn, this.#fadingGainBuffer)
|
||||
if (voice.done()) {
|
||||
lane.pitchVoices.removeByKey(sourceUuid)
|
||||
}
|
||||
}
|
||||
lane.voices = lane.voices.filter(voice => !voice.done())
|
||||
}
|
||||
|
||||
#updateOrCreatePitchVoice(lane: Lane, data: AudioData, playbackRate: number, offset: number, blockOffset: int): void {
|
||||
#updateOrCreatePitchVoice(lane: Lane, sourceUuid: UUID.Bytes, data: AudioData,
|
||||
playbackRate: number, offset: number, blockOffset: int): void {
|
||||
const fadeLengthSamples = Math.round(VOICE_FADE_DURATION * sampleRate)
|
||||
if (lane.voices.length === 0) {
|
||||
lane.voices.push(new PitchVoice(this.#audioOutput, data, fadeLengthSamples, playbackRate, offset, blockOffset))
|
||||
const existing = lane.pitchVoices.getOrNull(sourceUuid)
|
||||
if (existing === null) {
|
||||
lane.pitchVoices.add(
|
||||
new PitchVoice(sourceUuid, this.#audioOutput, data, fadeLengthSamples, playbackRate, offset, blockOffset), true)
|
||||
} else if (existing.isFadingOut()) {
|
||||
lane.fadingVoices.push(existing)
|
||||
lane.pitchVoices.add(
|
||||
new PitchVoice(sourceUuid, this.#audioOutput, data, fadeLengthSamples, playbackRate, offset, blockOffset), true)
|
||||
} else {
|
||||
let hasActiveVoice = false
|
||||
for (const voice of lane.voices) {
|
||||
if (voice instanceof PitchVoice) {
|
||||
if (voice.isFadingOut()) {
|
||||
continue
|
||||
}
|
||||
const drift = Math.abs(voice.readPosition - offset)
|
||||
if (drift > fadeLengthSamples) {
|
||||
voice.startFadeOut(blockOffset)
|
||||
} else {
|
||||
voice.setPlaybackRate(playbackRate)
|
||||
hasActiveVoice = true
|
||||
}
|
||||
} else {
|
||||
voice.startFadeOut(blockOffset)
|
||||
}
|
||||
}
|
||||
if (!hasActiveVoice) {
|
||||
lane.voices.push(new PitchVoice(this.#audioOutput, data, fadeLengthSamples, playbackRate, offset, blockOffset))
|
||||
const drift = Math.abs(existing.readPosition - offset)
|
||||
if (drift > fadeLengthSamples) {
|
||||
existing.startFadeOut(blockOffset)
|
||||
lane.fadingVoices.push(existing)
|
||||
lane.pitchVoices.add(
|
||||
new PitchVoice(sourceUuid, this.#audioOutput, data, fadeLengthSamples, playbackRate, offset, blockOffset), true)
|
||||
} else {
|
||||
existing.setPlaybackRate(playbackRate)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#evictPitchVoice(lane: Lane, sourceUuid: UUID.Bytes): void {
|
||||
const voice = lane.pitchVoices.removeByKeyIfExist(sourceUuid)
|
||||
if (voice !== null) {
|
||||
voice.startFadeOut(0)
|
||||
lane.fadingVoices.push(voice)
|
||||
}
|
||||
}
|
||||
|
||||
#fadeOutAllPitchVoices(lane: Lane): void {
|
||||
for (const voice of lane.pitchVoices) {
|
||||
voice.startFadeOut(0)
|
||||
lane.fadingVoices.push(voice)
|
||||
}
|
||||
lane.pitchVoices.clear()
|
||||
}
|
||||
|
||||
#processPassTimestretch(lane: Lane,
|
||||
block: Block,
|
||||
cycle: LoopableRegion.LoopCycle,
|
||||
@@ -270,11 +305,7 @@ export class TapeDeviceProcessor extends AbstractProcessor implements DeviceProc
|
||||
fadingConfig: FadingEnvelope.Config | null,
|
||||
regionPosition: number,
|
||||
regionDuration: number): void {
|
||||
for (const voice of lane.voices) {
|
||||
if (voice instanceof PitchVoice) {
|
||||
voice.startFadeOut(0)
|
||||
}
|
||||
}
|
||||
this.#fadeOutAllPitchVoices(lane)
|
||||
const {p0, p1, s0, s1} = block
|
||||
const sn = s1 - s0
|
||||
const pn = p1 - p0
|
||||
@@ -300,8 +331,6 @@ export class TapeDeviceProcessor extends AbstractProcessor implements DeviceProc
|
||||
cycle,
|
||||
this.#fadingGainBuffer
|
||||
)
|
||||
lane.voices = lane.voices.filter(voice =>
|
||||
voice instanceof PitchVoice && !voice.done())
|
||||
}
|
||||
|
||||
#getPlaybackRateFromWarp(ppqn: number,
|
||||
@@ -329,4 +358,4 @@ export class TapeDeviceProcessor extends AbstractProcessor implements DeviceProc
|
||||
const alpha = (ppqn - left.position) / (right.position - left.position)
|
||||
return left.seconds + alpha * (right.seconds - left.seconds)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,14 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.0.94](https://github.com/andremichelle/openDAW/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-11)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/studio-core-workers
|
||||
|
||||
## [0.0.93](https://github.com/andremichelle/openDAW/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-10)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/studio-core-workers
|
||||
|
||||
## [0.0.92](https://github.com/andremichelle/openDAW/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-07)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/studio-core-workers
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opendaw/studio-core-workers",
|
||||
"version": "0.0.92",
|
||||
"version": "0.0.94",
|
||||
"license": "LGPL-3.0-or-later",
|
||||
"private": true,
|
||||
"exports": {
|
||||
@@ -12,13 +12,13 @@
|
||||
"test": "echo \"No tests to run\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@opendaw/lib-box": "^0.0.77",
|
||||
"@opendaw/lib-dsp": "^0.0.76",
|
||||
"@opendaw/lib-runtime": "^0.0.72",
|
||||
"@opendaw/lib-std": "^0.0.71",
|
||||
"@opendaw/studio-adapters": "^0.0.97",
|
||||
"@opendaw/studio-boxes": "^0.0.82",
|
||||
"@opendaw/studio-enums": "^0.0.67"
|
||||
"@opendaw/lib-box": "^0.0.78",
|
||||
"@opendaw/lib-dsp": "^0.0.77",
|
||||
"@opendaw/lib-runtime": "^0.0.73",
|
||||
"@opendaw/lib-std": "^0.0.72",
|
||||
"@opendaw/studio-adapters": "^0.0.99",
|
||||
"@opendaw/studio-boxes": "^0.0.83",
|
||||
"@opendaw/studio-enums": "^0.0.68"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@opendaw/eslint-config": "^0.0.27",
|
||||
|
||||
@@ -3,6 +3,26 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.0.126](https://github.com/andremichelle/openDAW/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-12)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/studio-core
|
||||
|
||||
## [0.0.125](https://github.com/andremichelle/openDAW/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-12)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/studio-core
|
||||
|
||||
## [0.0.124](https://github.com/andremichelle/openDAW/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-11)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/studio-core
|
||||
|
||||
## [0.0.123](https://github.com/andremichelle/openDAW/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-11)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/studio-core
|
||||
|
||||
## [0.0.122](https://github.com/andremichelle/openDAW/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-10)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/studio-core
|
||||
|
||||
## [0.0.121](https://github.com/andremichelle/openDAW/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-07)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/studio-core
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opendaw/studio-core",
|
||||
"version": "0.0.121",
|
||||
"version": "0.0.126",
|
||||
"license": "LGPL-3.0-or-later",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
@@ -33,17 +33,17 @@
|
||||
"test": "vitest run --config vitest.config.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@opendaw/lib-box": "^0.0.77",
|
||||
"@opendaw/lib-dawproject": "^0.0.62",
|
||||
"@opendaw/lib-dom": "^0.0.76",
|
||||
"@opendaw/lib-dsp": "^0.0.76",
|
||||
"@opendaw/lib-fusion": "^0.0.83",
|
||||
"@opendaw/lib-runtime": "^0.0.72",
|
||||
"@opendaw/lib-std": "^0.0.71",
|
||||
"@opendaw/lib-box": "^0.0.78",
|
||||
"@opendaw/lib-dawproject": "^0.0.63",
|
||||
"@opendaw/lib-dom": "^0.0.77",
|
||||
"@opendaw/lib-dsp": "^0.0.77",
|
||||
"@opendaw/lib-fusion": "^0.0.85",
|
||||
"@opendaw/lib-runtime": "^0.0.73",
|
||||
"@opendaw/lib-std": "^0.0.72",
|
||||
"@opendaw/nam-wasm": "^1.0.3",
|
||||
"@opendaw/studio-adapters": "^0.0.97",
|
||||
"@opendaw/studio-boxes": "^0.0.82",
|
||||
"@opendaw/studio-enums": "^0.0.67",
|
||||
"@opendaw/studio-adapters": "^0.0.99",
|
||||
"@opendaw/studio-boxes": "^0.0.83",
|
||||
"@opendaw/studio-enums": "^0.0.68",
|
||||
"dropbox": "^10.34.0",
|
||||
"y-websocket": "^1.4.5",
|
||||
"yjs": "^13.6.27",
|
||||
@@ -57,9 +57,9 @@
|
||||
"@ffmpeg/ffmpeg": "^0.12.15",
|
||||
"@ffmpeg/util": "^0.12.2",
|
||||
"@opendaw/eslint-config": "^0.0.27",
|
||||
"@opendaw/studio-core-processors": "^0.0.100",
|
||||
"@opendaw/studio-core-workers": "^0.0.92",
|
||||
"@opendaw/studio-forge-boxes": "^0.0.82",
|
||||
"@opendaw/studio-core-processors": "^0.0.103",
|
||||
"@opendaw/studio-core-workers": "^0.0.94",
|
||||
"@opendaw/studio-forge-boxes": "^0.0.83",
|
||||
"@opendaw/typescript-config": "^0.0.29"
|
||||
},
|
||||
"gitHead": "e4f70170c5947610932306da94e7f0bb817e43b3"
|
||||
|
||||
@@ -4,10 +4,12 @@ import {
|
||||
Errors,
|
||||
isInstanceOf,
|
||||
isNotUndefined,
|
||||
Notifier,
|
||||
Observer,
|
||||
panic,
|
||||
Procedure,
|
||||
Progress,
|
||||
RuntimeNotifier,
|
||||
Subscription,
|
||||
UUID
|
||||
} from "@opendaw/lib-std"
|
||||
import {Files} from "@opendaw/lib-dom"
|
||||
@@ -20,18 +22,22 @@ export namespace AssetService {
|
||||
export type ImportArgs = {
|
||||
uuid?: UUID.Bytes
|
||||
name?: string,
|
||||
bpm?: number,
|
||||
arrayBuffer: ArrayBuffer,
|
||||
progressHandler?: Progress.Handler
|
||||
progressHandler?: Progress.Handler,
|
||||
origin?: "import" | "recording"
|
||||
}
|
||||
}
|
||||
|
||||
export abstract class AssetService<T extends Sample | Soundfont> {
|
||||
export abstract class AssetService<T extends Sample | Soundfont, RAW = void> {
|
||||
protected abstract readonly nameSingular: string
|
||||
protected abstract readonly namePlural: string
|
||||
protected abstract readonly boxType: Class<AudioFileBox | SoundfontFileBox>
|
||||
protected abstract readonly filePickerOptions: FilePickerOptions
|
||||
|
||||
protected constructor(protected readonly onUpdate: Procedure<T>) {}
|
||||
protected readonly notifier: Notifier<[T, RAW]> = new Notifier<[T, RAW]>()
|
||||
|
||||
subscribe(observer: Observer<[T, RAW]>): Subscription {return this.notifier.subscribe(observer)}
|
||||
|
||||
async browse(multiple: boolean): Promise<ReadonlyArray<T>> {
|
||||
return this.browseFiles(multiple, this.filePickerOptions)
|
||||
|
||||
@@ -1,30 +1,21 @@
|
||||
import {
|
||||
ByteArrayInput,
|
||||
int,
|
||||
Notifier,
|
||||
Observer,
|
||||
Option,
|
||||
panic,
|
||||
Procedure,
|
||||
Progress,
|
||||
Subscription,
|
||||
Terminable,
|
||||
Terminator,
|
||||
UUID
|
||||
} from "@opendaw/lib-std"
|
||||
import {AudioData, BPMTools} from "@opendaw/lib-dsp"
|
||||
import {Peaks, SamplePeaks} from "@opendaw/lib-fusion"
|
||||
import {
|
||||
mergeChunkPlanes,
|
||||
RingBuffer,
|
||||
SampleLoader,
|
||||
SampleLoaderState,
|
||||
SampleMetaData
|
||||
} from "@opendaw/studio-adapters"
|
||||
import {SampleStorage} from "./samples"
|
||||
import {AudioData} from "@opendaw/lib-dsp"
|
||||
import {Peaks} from "@opendaw/lib-fusion"
|
||||
import {mergeChunkPlanes, RingBuffer, SampleLoader, SampleLoaderState} from "@opendaw/studio-adapters"
|
||||
import {RenderQuantum} from "./RenderQuantum"
|
||||
import {Workers} from "./Workers"
|
||||
import {PeaksWriter} from "./PeaksWriter"
|
||||
import {SampleService} from "./samples"
|
||||
|
||||
export class RecordingWorklet extends AudioWorkletNode implements Terminable, SampleLoader {
|
||||
readonly #terminator: Terminator = new Terminator()
|
||||
@@ -42,6 +33,8 @@ export class RecordingWorklet extends AudioWorkletNode implements Terminable, Sa
|
||||
#limitSamples: int = Number.POSITIVE_INFINITY
|
||||
#state: SampleLoaderState = {type: "record"}
|
||||
#onSaved: Option<Procedure<UUID.Bytes>> = Option.None
|
||||
#sampleService: Option<SampleService> = Option.None
|
||||
#bpm: Option<number> = Option.None
|
||||
|
||||
constructor(context: BaseAudioContext, config: RingBuffer.Config) {
|
||||
super(context, "recording-processor", {
|
||||
@@ -76,6 +69,8 @@ export class RecordingWorklet extends AudioWorkletNode implements Terminable, Sa
|
||||
}
|
||||
|
||||
set onSaved(callback: Procedure<UUID.Bytes>) {this.#onSaved = Option.wrap(callback)}
|
||||
set bpm(value: number) {this.#bpm = Option.wrap(value)}
|
||||
set sampleService(service: SampleService) {this.#sampleService = Option.wrap(service)}
|
||||
|
||||
setFillLength(value: int): void {this.#peakWriter.numFrames = value}
|
||||
|
||||
@@ -102,36 +97,22 @@ export class RecordingWorklet extends AudioWorkletNode implements Terminable, Sa
|
||||
|
||||
toString(): string {return `{RecordingWorklet}`}
|
||||
|
||||
async #finalize(): Promise<SampleStorage.NewSample> {
|
||||
async #finalize(): Promise<void> {
|
||||
this.#isRecording = false
|
||||
this.#reader.stop()
|
||||
if (this.#output.length === 0) {return panic("No recording data available")}
|
||||
const totalSamples: int = this.#limitSamples
|
||||
const sample_rate = this.context.sampleRate
|
||||
const numberOfChannels = this.channelCount
|
||||
const mergedFrames = mergeChunkPlanes(this.#output, RenderQuantum, this.#output.length * RenderQuantum)
|
||||
.map(frame => frame.slice(-totalSamples))
|
||||
const audioData = AudioData.create(sample_rate, totalSamples, numberOfChannels)
|
||||
mergedFrames.forEach((frame, i) => audioData.frames[i].set(frame))
|
||||
const audioData = AudioData.create(this.context.sampleRate, totalSamples, this.channelCount)
|
||||
mergedFrames.forEach((frame, index) => audioData.frames[index].set(frame))
|
||||
this.#data = Option.wrap(audioData)
|
||||
const shifts = SamplePeaks.findBestFit(totalSamples)
|
||||
const peaks = await Workers
|
||||
.Peak.generateAsync(Progress.Empty, shifts, audioData.frames, totalSamples, numberOfChannels)
|
||||
this.#peaks = Option.wrap(SamplePeaks.from(new ByteArrayInput(peaks)))
|
||||
const bpm = BPMTools.detect(audioData.frames[0], sample_rate)
|
||||
const duration = totalSamples / sample_rate
|
||||
const meta: SampleMetaData = {name: "Recording", bpm, sample_rate, duration, origin: "recording"}
|
||||
const sample: SampleStorage.NewSample = {
|
||||
uuid: this.uuid,
|
||||
audio: audioData,
|
||||
peaks: peaks as ArrayBuffer,
|
||||
meta
|
||||
}
|
||||
await SampleStorage.get().save(sample)
|
||||
this.#onSaved.ifSome(callback => callback(this.uuid))
|
||||
const sample = await this.#sampleService
|
||||
.unwrap("SampleService not set")
|
||||
.importRecording(audioData, this.#bpm.unwrapOrElse(120))
|
||||
this.#onSaved.ifSome(callback => callback(UUID.parse(sample.uuid)))
|
||||
this.#setState({type: "loaded"})
|
||||
this.terminate()
|
||||
return sample
|
||||
}
|
||||
|
||||
#setState(value: SampleLoaderState): void {
|
||||
|
||||
@@ -103,7 +103,7 @@ export class CaptureAudio extends Capture<CaptureAudioBox> {
|
||||
|
||||
async prepareRecording(): Promise<void> {
|
||||
const {project} = this.manager
|
||||
const {env: {audioContext, audioWorklets, sampleManager}} = project
|
||||
const {env: {audioContext, audioWorklets, sampleManager, sampleService}} = project
|
||||
if (isUndefined(audioContext.outputLatency)) {
|
||||
const approved = RuntimeNotifier.approve({
|
||||
headline: "Warning",
|
||||
@@ -122,6 +122,8 @@ export class CaptureAudio extends Capture<CaptureAudioBox> {
|
||||
}
|
||||
const {gainNode, channelCount} = audioChain
|
||||
const recordingWorklet = audioWorklets.createRecording(channelCount, RenderQuantum)
|
||||
recordingWorklet.bpm = project.timelineBox.bpm.getValue()
|
||||
recordingWorklet.sampleService = sampleService
|
||||
sampleManager.record(recordingWorklet)
|
||||
gainNode.connect(recordingWorklet)
|
||||
this.#preparedWorklet = recordingWorklet
|
||||
|
||||
@@ -124,7 +124,27 @@ export namespace RecordAudio {
|
||||
currentTake = Option.wrap(createTakeRegion(position, currentWaveformOffset, previousTrack))
|
||||
}
|
||||
|
||||
recordingWorklet.onSaved = uuid => project.trackUserCreatedSample(uuid)
|
||||
recordingWorklet.onSaved = uuid => {
|
||||
project.trackUserCreatedSample(uuid)
|
||||
editing.modify(() => {
|
||||
fileBox.ifSome(oldFileBox => {
|
||||
editing.modify(() => {
|
||||
const newFileBox = AudioFileBox.create(boxGraph, uuid, box => {
|
||||
box.fileName.setValue(oldFileBox.fileName.getValue())
|
||||
box.startInSeconds.setValue(oldFileBox.startInSeconds.getValue())
|
||||
box.endInSeconds.setValue(oldFileBox.endInSeconds.getValue())
|
||||
})
|
||||
for (const pointer of [...oldFileBox.pointerHub.incoming()]) {
|
||||
pointer.refer(newFileBox)
|
||||
}
|
||||
for (const pointer of [...oldFileBox.transientMarkers.pointerHub.incoming()]) {
|
||||
pointer.refer(newFileBox.transientMarkers)
|
||||
}
|
||||
oldFileBox.delete()
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
terminator.ownAll(
|
||||
Terminable.create(() => {
|
||||
tryCatch(() => sourceNode.disconnect(recordingWorklet))
|
||||
|
||||
@@ -46,6 +46,7 @@ export namespace RecordMidi {
|
||||
const {loopArea} = timelineBox
|
||||
const terminator = new Terminator()
|
||||
const activeNotes = new Map<byte, ActiveNote>()
|
||||
const pendingNotes = new Map<byte, byte>()
|
||||
const latency = PPQN.secondsToPulses(audioContext.outputLatency ?? 10.0, timelineBox.bpm.getValue())
|
||||
let currentTake: Option<TakeData> = Option.None
|
||||
let lastPosition: ppqn = 0
|
||||
@@ -108,6 +109,20 @@ export namespace RecordMidi {
|
||||
}
|
||||
}
|
||||
|
||||
const flushPendingNotes = (take: TakeData) => {
|
||||
for (const [pitch, velocity] of pendingNotes) {
|
||||
const event = NoteEventBox.create(boxGraph, UUID.generate(), box => {
|
||||
box.position.setValue(0)
|
||||
box.duration.setValue(MIN_NOTE_DURATION)
|
||||
box.pitch.setValue(pitch)
|
||||
box.velocity.setValue(velocity)
|
||||
box.events.refer(take.collection.events)
|
||||
})
|
||||
activeNotes.set(pitch, {event, take, creationOffset: positionOffset})
|
||||
}
|
||||
pendingNotes.clear()
|
||||
}
|
||||
|
||||
const startNewTake = (position: ppqn) => {
|
||||
const previousTrack = currentTake.mapOr(take => take.trackBox, null)
|
||||
currentTake = Option.wrap(createTakeRegion(position, previousTrack))
|
||||
@@ -135,7 +150,9 @@ export namespace RecordMidi {
|
||||
if (currentTake.isEmpty()) {
|
||||
editing.modify(() => {
|
||||
const pos = quantizeFloor(currentPosition, beats)
|
||||
currentTake = Option.wrap(createTakeRegion(pos, null))
|
||||
const take = createTakeRegion(pos, null)
|
||||
currentTake = Option.wrap(take)
|
||||
flushPendingNotes(take)
|
||||
}, false)
|
||||
}
|
||||
currentTake.ifSome(({regionBox, collection}) => {
|
||||
@@ -166,7 +183,10 @@ export namespace RecordMidi {
|
||||
const writePosition = position.getValue() + latency
|
||||
if (NoteSignal.isOn(signal)) {
|
||||
const {pitch, velocity} = signal
|
||||
if (currentTake.isEmpty()) {return}
|
||||
if (currentTake.isEmpty()) {
|
||||
pendingNotes.set(pitch, velocity)
|
||||
return
|
||||
}
|
||||
const take = currentTake.unwrap()
|
||||
const {regionBox, collection} = take
|
||||
editing.modify(() => {
|
||||
@@ -182,7 +202,11 @@ export namespace RecordMidi {
|
||||
activeNotes.set(pitch, {event, take, creationOffset: positionOffset})
|
||||
}, false)
|
||||
} else if (NoteSignal.isOff(signal)) {
|
||||
activeNotes.delete(signal.pitch)
|
||||
if (pendingNotes.has(signal.pitch)) {
|
||||
pendingNotes.delete(signal.pitch)
|
||||
} else {
|
||||
activeNotes.delete(signal.pitch)
|
||||
}
|
||||
}
|
||||
}))
|
||||
return terminator
|
||||
|
||||
@@ -2,11 +2,15 @@ import {SampleLoaderManager, SoundfontLoaderManager} from "@opendaw/studio-adapt
|
||||
import {Editing, Func} from "@opendaw/lib-std"
|
||||
import {BoxGraph} from "@opendaw/lib-box"
|
||||
import {AudioWorklets} from "../AudioWorklets"
|
||||
import {SampleService} from "../samples"
|
||||
import {SoundfontService} from "../soundfont"
|
||||
|
||||
export interface ProjectEnv {
|
||||
audioContext: AudioContext
|
||||
audioWorklets: AudioWorklets
|
||||
sampleManager: SampleLoaderManager
|
||||
soundfontManager: SoundfontLoaderManager
|
||||
sampleService: SampleService
|
||||
soundfontService: SoundfontService
|
||||
createEditing?: Func<BoxGraph, Editing>
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import {ppqn, PPQN, TimeBase} from "@opendaw/lib-dsp"
|
||||
import {ColorCodes, Sample, TrackType} from "@opendaw/studio-adapters"
|
||||
import {int, isDefined, panic, quantizeCeil, UUID} from "@opendaw/lib-std"
|
||||
import {int, isDefined, panic, quantizeRound, UUID} from "@opendaw/lib-std"
|
||||
import {
|
||||
AudioClipBox,
|
||||
AudioFileBox,
|
||||
@@ -25,6 +25,7 @@ export namespace AudioContentFactory {
|
||||
warpMarkers?: ReadonlyArray<WarpMarkerTemplate>
|
||||
waveformOffset?: number
|
||||
gainInDb?: number
|
||||
disableQuantize?: boolean
|
||||
}
|
||||
|
||||
export type Clip = Props & { index: int }
|
||||
@@ -43,14 +44,13 @@ export namespace AudioContentFactory {
|
||||
* Calculates the duration of an audio region based on sample properties.
|
||||
* Returns duration in PPQN for stretched regions, or in seconds for non-stretched.
|
||||
*/
|
||||
export const calculateDuration = (sample: Sample): ppqn => {
|
||||
export const calculateDuration = (sample: Sample, disableQuantize: boolean = false): ppqn => {
|
||||
const {duration: durationInSeconds, bpm} = sample
|
||||
if (bpm === 0) {
|
||||
// Non-stretched: duration is in seconds
|
||||
return durationInSeconds
|
||||
}
|
||||
// Stretched: duration is in PPQN
|
||||
return quantizeCeil(PPQN.secondsToPulses(durationInSeconds, bpm), PPQN.SemiQuaver)
|
||||
const pulses = PPQN.secondsToPulses(durationInSeconds, bpm)
|
||||
return disableQuantize ? pulses : quantizeRound(pulses, PPQN.SemiQuaver)
|
||||
}
|
||||
|
||||
// --- Region Creation --- //
|
||||
@@ -125,7 +125,8 @@ export namespace AudioContentFactory {
|
||||
return panic("Cannot create audio-region on non-audio track")
|
||||
}
|
||||
const {name, duration: durationInSeconds, bpm} = sample
|
||||
const durationInPPQN = props.duration ?? quantizeCeil(PPQN.secondsToPulses(durationInSeconds, bpm), PPQN.SemiQuaver)
|
||||
const pulses = PPQN.secondsToPulses(durationInSeconds, bpm)
|
||||
const durationInPPQN = props.duration ?? (!props.disableQuantize ? quantizeRound(pulses, PPQN.SemiQuaver) : pulses)
|
||||
if (isDefined(props.warpMarkers)) {
|
||||
AudioContentHelpers.addWarpMarkers(boxGraph, playMode, props.warpMarkers)
|
||||
} else {
|
||||
@@ -155,7 +156,8 @@ export namespace AudioContentFactory {
|
||||
return panic("Cannot create audio-region on non-audio track")
|
||||
}
|
||||
const {name, duration: durationInSeconds, bpm} = sample
|
||||
const durationInPPQN = props.duration ?? quantizeCeil(PPQN.secondsToPulses(durationInSeconds, bpm), PPQN.SemiQuaver)
|
||||
const pulses = PPQN.secondsToPulses(durationInSeconds, bpm)
|
||||
const durationInPPQN = props.duration ?? (!props.disableQuantize ? quantizeRound(pulses, PPQN.SemiQuaver) : pulses)
|
||||
if (isDefined(props.warpMarkers)) {
|
||||
AudioContentHelpers.addWarpMarkers(boxGraph, playMode, props.warpMarkers)
|
||||
} else {
|
||||
|
||||
@@ -9,6 +9,13 @@ const isIntEncodedAsFloat = (v: number) =>
|
||||
v > 0 && v < 1e-6 && Number.isFinite(v) && (v / 1.401298464324817e-45) % 1 === 0
|
||||
|
||||
export const migrateAudioClipBox = (boxGraph: BoxGraph<BoxIO.TypeMap>, box: AudioClipBox): void => {
|
||||
if (box.file.targetVertex.isEmpty()) {
|
||||
console.debug("Migrate 'AudioClipBox' remove clip without AudioFileBox")
|
||||
boxGraph.beginTransaction()
|
||||
box.delete()
|
||||
boxGraph.endTransaction()
|
||||
return
|
||||
}
|
||||
if (box.events.isEmpty()) {
|
||||
console.debug("Migrate 'AudioClipBox' to have a ValueEventCollectionBox")
|
||||
boxGraph.beginTransaction()
|
||||
|
||||
@@ -12,6 +12,13 @@ const toSeconds = (property: ValueOwner<ppqn>, bpm: number): seconds =>
|
||||
PPQN.pulsesToSeconds(property.getValue(), bpm)
|
||||
|
||||
export const migrateAudioRegionBox = (boxGraph: BoxGraph<BoxIO.TypeMap>, box: AudioRegionBox, bpm: number): void => {
|
||||
if (box.file.targetVertex.isEmpty()) {
|
||||
console.debug("Migrate 'AudioRegionBox' remove region without AudioFileBox")
|
||||
boxGraph.beginTransaction()
|
||||
box.delete()
|
||||
boxGraph.endTransaction()
|
||||
return
|
||||
}
|
||||
const {duration, loopOffset, loopDuration, playback} = box
|
||||
if (isIntEncodedAsFloat(duration.getValue())
|
||||
|| isIntEncodedAsFloat(loopOffset.getValue())
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {Arrays, Class, isUndefined, Procedure, Progress, tryCatch, UUID} from "@opendaw/lib-std"
|
||||
import {Arrays, Class, isDefined, Progress, tryCatch, UUID} from "@opendaw/lib-std"
|
||||
import {Box} from "@opendaw/lib-box"
|
||||
import {AudioData, estimateBpm} from "@opendaw/lib-dsp"
|
||||
import {Promises} from "@opendaw/lib-runtime"
|
||||
@@ -12,18 +12,27 @@ import {Workers} from "../Workers"
|
||||
import {SampleStorage} from "./SampleStorage"
|
||||
import {OpenSampleAPI} from "./OpenSampleAPI"
|
||||
|
||||
export class SampleService extends AssetService<Sample> {
|
||||
export class SampleService extends AssetService<Sample, AudioData> {
|
||||
protected readonly namePlural: string = "Samples"
|
||||
protected readonly nameSingular: string = "Sample"
|
||||
protected readonly boxType: Class<Box> = AudioFileBox
|
||||
protected readonly filePickerOptions: FilePickerOptions = FilePickerAcceptTypes.WavFiles
|
||||
|
||||
constructor(readonly audioContext: AudioContext, onUpdate: Procedure<Sample>) {
|
||||
super(onUpdate)
|
||||
constructor(readonly audioContext: AudioContext) {super()}
|
||||
|
||||
async importRecording(audioData: AudioData, bpm: number, name: string = "Recording"): Promise<Sample> {
|
||||
const arrayBuffer = WavFile.encodeFloats({
|
||||
frames: audioData.frames.slice(),
|
||||
numberOfFrames: audioData.numberOfFrames,
|
||||
numberOfChannels: audioData.numberOfChannels,
|
||||
sampleRate: audioData.sampleRate
|
||||
})
|
||||
return this.importFile({name, bpm, arrayBuffer, origin: "recording"})
|
||||
}
|
||||
|
||||
async importFile({uuid, name, arrayBuffer, progressHandler = Progress.Empty}
|
||||
: AssetService.ImportArgs): Promise<Sample> {
|
||||
async importFile({uuid, name, bpm, arrayBuffer, progressHandler = Progress.Empty, origin = "import"}
|
||||
: AssetService.ImportArgs,
|
||||
transformMeta?: (meta: SampleMetaData, audioData: Readonly<AudioData>) => Promise<void>): Promise<Sample> {
|
||||
console.debug(`importSample '${name}' (${arrayBuffer.byteLength >> 10}kb)`)
|
||||
uuid ??= await UUID.sha256(arrayBuffer)
|
||||
const audioData = await this.#decodeAudio(arrayBuffer)
|
||||
@@ -36,15 +45,18 @@ export class SampleService extends AssetService<Sample> {
|
||||
audioData.numberOfFrames,
|
||||
audioData.numberOfChannels) as ArrayBuffer
|
||||
const meta: SampleMetaData = {
|
||||
bpm: estimateBpm(duration),
|
||||
name: isUndefined(name) ? "Unnnamed" : name,
|
||||
bpm: bpm ?? estimateBpm(duration),
|
||||
name: name ?? "Unnnamed",
|
||||
duration,
|
||||
sample_rate: audioData.sampleRate,
|
||||
origin: "import"
|
||||
origin
|
||||
}
|
||||
if (isDefined(transformMeta)) {
|
||||
await transformMeta(meta, audioData)
|
||||
}
|
||||
await SampleStorage.get().save({uuid, audio: audioData, peaks, meta})
|
||||
const sample = {uuid: UUID.toString(uuid), ...meta}
|
||||
this.onUpdate(sample)
|
||||
await SampleStorage.get().save({uuid, audio: audioData, peaks, meta})
|
||||
this.notifier.notify([sample, audioData])
|
||||
return sample
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {Arrays, Class, Option, panic, Procedure, RuntimeNotifier, UUID} from "@opendaw/lib-std"
|
||||
import {Arrays, Class, Option, panic, RuntimeNotifier, UUID} from "@opendaw/lib-std"
|
||||
import {Box} from "@opendaw/lib-box"
|
||||
import {Wait} from "@opendaw/lib-runtime"
|
||||
import {SoundfontFileBox} from "@opendaw/studio-boxes"
|
||||
@@ -9,7 +9,7 @@ import {OpenSoundfontAPI} from "./OpenSoundfontAPI"
|
||||
import {AssetService} from "../AssetService"
|
||||
import {ExternalLib} from "../ExternalLib"
|
||||
|
||||
export class SoundfontService extends AssetService<Soundfont> {
|
||||
export class SoundfontService extends AssetService<Soundfont, void> {
|
||||
protected readonly namePlural: string = "Soundfonts"
|
||||
protected readonly nameSingular: string = "Soundfont"
|
||||
protected readonly boxType: Class<Box> = SoundfontFileBox
|
||||
@@ -18,9 +18,8 @@ export class SoundfontService extends AssetService<Soundfont> {
|
||||
#local: Option<Array<Soundfont>> = Option.None
|
||||
#remote: Option<ReadonlyArray<Soundfont>> = Option.None
|
||||
|
||||
constructor(onUpdate: Procedure<Soundfont>) {
|
||||
super(onUpdate)
|
||||
|
||||
constructor() {
|
||||
super()
|
||||
Promise.all([
|
||||
SoundfontStorage.get().list(),
|
||||
OpenSoundfontAPI.get().all()
|
||||
@@ -72,7 +71,7 @@ export class SoundfontService extends AssetService<Soundfont> {
|
||||
if (!list.some(other => other.uuid === soundfont.uuid)) {
|
||||
list.push(soundfont)
|
||||
}
|
||||
this.onUpdate(soundfont)
|
||||
this.notifier.notify([soundfont, undefined])
|
||||
updater.terminate()
|
||||
return soundfont
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import {AudioFileBoxAdapter, AudioPlayMode} from "@opendaw/studio-adapters"
|
||||
import {TimelineRange} from "../timeline/TimelineRange"
|
||||
|
||||
export namespace AudioRenderer {
|
||||
type Segment = {
|
||||
export type Segment = {
|
||||
x0: number
|
||||
x1: number
|
||||
u0: number
|
||||
@@ -14,27 +14,58 @@ export namespace AudioRenderer {
|
||||
outside: boolean
|
||||
}
|
||||
|
||||
export const render = (
|
||||
context: CanvasRenderingContext2D,
|
||||
range: TimelineRange,
|
||||
file: AudioFileBoxAdapter,
|
||||
tempoMap: TempoMap,
|
||||
playMode: Option<AudioPlayMode>,
|
||||
waveformOffset: number,
|
||||
gain: number,
|
||||
{top, bottom}: RegionBound,
|
||||
contentColor: string,
|
||||
{rawStart, resultStart, resultEnd}: LoopableRegion.LoopCycle,
|
||||
clip: boolean = true
|
||||
export interface Strategy {
|
||||
render(context: CanvasRenderingContext2D,
|
||||
segments: ReadonlyArray<Segment>,
|
||||
peaks: Peaks,
|
||||
bound: RegionBound,
|
||||
gain: number): void
|
||||
}
|
||||
|
||||
export const DefaultStrategy: Strategy = {
|
||||
render(context, segments, peaks, {top, bottom}, gain): void {
|
||||
const dpr = devicePixelRatio
|
||||
const actualTop = top * dpr
|
||||
const actualBottom = bottom * dpr
|
||||
const height = actualBottom - actualTop
|
||||
const numberOfChannels = peaks.numChannels
|
||||
const peaksHeight = Math.floor((height - 4) / numberOfChannels)
|
||||
const scale = dbToGain(-gain)
|
||||
for (const {x0, x1, u0, u1, outside} of segments) {
|
||||
context.globalAlpha = outside ? 0.25 : 1.0
|
||||
for (let channel = 0; channel < numberOfChannels; channel++) {
|
||||
PeaksPainter.renderPixelStrips(context, peaks, channel, {
|
||||
u0,
|
||||
u1,
|
||||
v0: -scale,
|
||||
v1: +scale,
|
||||
x0,
|
||||
x1,
|
||||
y0: 3 + actualTop + channel * peaksHeight,
|
||||
y1: 3 + actualTop + (channel + 1) * peaksHeight
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const render = (context: CanvasRenderingContext2D,
|
||||
range: TimelineRange,
|
||||
file: AudioFileBoxAdapter,
|
||||
tempoMap: TempoMap,
|
||||
playMode: Option<AudioPlayMode>,
|
||||
waveformOffset: number,
|
||||
gain: number,
|
||||
bound: RegionBound,
|
||||
contentColor: string,
|
||||
{rawStart, resultStart, resultEnd}: LoopableRegion.LoopCycle,
|
||||
clip: boolean = true,
|
||||
strategy: Strategy = DefaultStrategy
|
||||
) => {
|
||||
if (file.peaks.isEmpty()) {return}
|
||||
const peaks: Peaks = file.peaks.unwrap()
|
||||
const durationInSeconds = file.endInSeconds - file.startInSeconds
|
||||
const numFrames = peaks.numFrames
|
||||
const numberOfChannels = peaks.numChannels
|
||||
const ht = bottom - top
|
||||
const peaksHeight = Math.floor((ht - 4) / numberOfChannels)
|
||||
const scale = dbToGain(-gain)
|
||||
const segments: Array<Segment> = []
|
||||
if (playMode.nonEmpty()) {
|
||||
const {warpMarkers} = playMode.unwrap()
|
||||
@@ -357,20 +388,6 @@ export namespace AudioRenderer {
|
||||
}
|
||||
|
||||
context.fillStyle = contentColor
|
||||
for (const {x0, x1, u0, u1, outside} of segments) {
|
||||
context.globalAlpha = outside && !clip ? 0.25 : 1.0
|
||||
for (let channel = 0; channel < numberOfChannels; channel++) {
|
||||
PeaksPainter.renderBlocks(context, peaks, channel, {
|
||||
u0,
|
||||
u1,
|
||||
v0: -scale,
|
||||
v1: +scale,
|
||||
x0,
|
||||
x1,
|
||||
y0: 3 + top + channel * peaksHeight,
|
||||
y1: 3 + top + (channel + 1) * peaksHeight
|
||||
})
|
||||
}
|
||||
}
|
||||
strategy.render(context, segments, peaks, bound, gain)
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,9 @@ export namespace AudioFadingRenderer {
|
||||
startPPQN: number,
|
||||
endPPQN: number,
|
||||
color: string): void => {
|
||||
const dpr = devicePixelRatio
|
||||
const actualTop = top * dpr
|
||||
const actualBottom = bottom * dpr
|
||||
const {inSlope: fadeInSlope, outSlope: fadeOutSlope} = fading
|
||||
const duration = endPPQN - startPPQN
|
||||
const totalFading = fading.in + fading.out
|
||||
@@ -19,46 +22,46 @@ export namespace AudioFadingRenderer {
|
||||
const fadeOut = fading.out * scale
|
||||
context.strokeStyle = color
|
||||
context.fillStyle = "rgba(0,0,0,0.25)"
|
||||
context.lineWidth = devicePixelRatio
|
||||
context.lineWidth = dpr
|
||||
if (fadeIn > 0) {
|
||||
const fadeInEndPPQN = startPPQN + fadeIn
|
||||
const x0 = range.unitToX(startPPQN) * devicePixelRatio
|
||||
const x1 = range.unitToX(fadeInEndPPQN) * devicePixelRatio
|
||||
const x0 = range.unitToX(startPPQN) * dpr
|
||||
const x1 = range.unitToX(fadeInEndPPQN) * dpr
|
||||
const xn = x1 - x0
|
||||
const path = new Path2D()
|
||||
path.moveTo(x0, bottom)
|
||||
path.moveTo(x0, actualBottom)
|
||||
let x = x0
|
||||
Curve.run(fadeInSlope, xn, bottom, top, y => path.lineTo(++x, y))
|
||||
path.lineTo(x1, top)
|
||||
Curve.run(fadeInSlope, xn, actualBottom, actualTop, y => path.lineTo(++x, y))
|
||||
path.lineTo(x1, actualTop)
|
||||
context.stroke(path)
|
||||
path.lineTo(x0, top)
|
||||
path.lineTo(x0, bottom)
|
||||
path.lineTo(x0, actualTop)
|
||||
path.lineTo(x0, actualBottom)
|
||||
context.fill(path)
|
||||
}
|
||||
if (fadeOut > 0) {
|
||||
const x0 = range.unitToX(endPPQN - fadeOut) * devicePixelRatio
|
||||
const x1 = range.unitToX(endPPQN) * devicePixelRatio
|
||||
const x0 = range.unitToX(endPPQN - fadeOut) * dpr
|
||||
const x1 = range.unitToX(endPPQN) * dpr
|
||||
const xn = x1 - x0
|
||||
const path = new Path2D()
|
||||
path.moveTo(x0, top)
|
||||
path.moveTo(x0, actualTop)
|
||||
let x = x0
|
||||
Curve.run(fadeOutSlope, xn, top, bottom, y => path.lineTo(++x, y))
|
||||
path.lineTo(x1, bottom)
|
||||
Curve.run(fadeOutSlope, xn, actualTop, actualBottom, y => path.lineTo(++x, y))
|
||||
path.lineTo(x1, actualBottom)
|
||||
context.strokeStyle = color
|
||||
context.stroke(path)
|
||||
path.lineTo(x1, top)
|
||||
path.lineTo(x0, top)
|
||||
path.lineTo(x1, actualTop)
|
||||
path.lineTo(x0, actualTop)
|
||||
context.fill(path)
|
||||
}
|
||||
const handleRadius = 1.5 * devicePixelRatio
|
||||
const x0 = Math.max(range.unitToX(startPPQN + fadeIn), range.unitToX(startPPQN)) * devicePixelRatio
|
||||
const x1 = Math.min(range.unitToX(endPPQN - fadeOut), range.unitToX(endPPQN)) * devicePixelRatio
|
||||
const handleRadius = 1.5 * dpr
|
||||
const x0 = Math.max(range.unitToX(startPPQN + fadeIn), range.unitToX(startPPQN)) * dpr
|
||||
const x1 = Math.min(range.unitToX(endPPQN - fadeOut), range.unitToX(endPPQN)) * dpr
|
||||
context.fillStyle = color
|
||||
context.beginPath()
|
||||
context.arc(x0, top, handleRadius, 0, TAU)
|
||||
context.arc(x0, actualTop, handleRadius, 0, TAU)
|
||||
context.fill()
|
||||
context.beginPath()
|
||||
context.arc(x1, top, handleRadius, 0, TAU)
|
||||
context.arc(x1, actualTop, handleRadius, 0, TAU)
|
||||
context.fill()
|
||||
}
|
||||
}
|
||||
@@ -2,4 +2,5 @@ export * from "./audio"
|
||||
export * from "./env"
|
||||
export * from "./fading"
|
||||
export * from "./notes"
|
||||
export * from "./value"
|
||||
export * from "./riffle"
|
||||
export * from "./value"
|
||||
@@ -9,7 +9,10 @@ export namespace NotesRenderer {
|
||||
{top, bottom}: RegionBound,
|
||||
contentColor: string,
|
||||
{rawStart, regionStart, resultStart, resultEnd}: LoopableRegion.LoopCycle) => {
|
||||
const height = bottom - top
|
||||
const dpr = devicePixelRatio
|
||||
const actualTop = top * dpr
|
||||
const actualBottom = bottom * dpr
|
||||
const height = actualBottom - actualTop
|
||||
context.fillStyle = contentColor
|
||||
const padding = 8
|
||||
const noteHeight = 5
|
||||
@@ -19,9 +22,9 @@ export namespace NotesRenderer {
|
||||
const position = rawStart + note.position
|
||||
if (position < regionStart) {continue}
|
||||
const complete = Math.min(rawStart + note.complete, resultEnd)
|
||||
const x0 = Math.floor(range.unitToX(position) * devicePixelRatio)
|
||||
const x1 = Math.floor(range.unitToX(complete) * devicePixelRatio)
|
||||
const y = top + padding + Math.floor(note.normalizedPitch() * (height - (padding * 2 + noteHeight)))
|
||||
const x0 = Math.floor(range.unitToX(position) * dpr)
|
||||
const x1 = Math.floor(range.unitToX(complete) * dpr)
|
||||
const y = actualTop + padding + Math.floor(note.normalizedPitch() * (height - (padding * 2 + noteHeight)))
|
||||
context.fillRect(x0, y, Math.max(1, x1 - x0), noteHeight)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
import {dbToGain} from "@opendaw/lib-dsp"
|
||||
import {Peaks} from "@opendaw/lib-fusion"
|
||||
import {AudioRenderer} from "./audio"
|
||||
|
||||
export const RiffleStrategy: AudioRenderer.Strategy = {
|
||||
render(context, segments, peaks, {top, bottom}, gain): void {
|
||||
if (segments.length === 0) {return}
|
||||
const dpr = devicePixelRatio
|
||||
const actualTop = top * dpr
|
||||
const actualBottom = bottom * dpr
|
||||
const height = actualBottom - actualTop
|
||||
const numberOfChannels = peaks.numChannels
|
||||
const peaksHeight = Math.floor(height / numberOfChannels)
|
||||
const gainScale = dbToGain(-gain)
|
||||
const blockWidth = 3 * dpr
|
||||
// noinspection PointlessArithmeticExpressionJS
|
||||
const gap = dpr * 1
|
||||
const pixelsPerBlock = blockWidth + gap
|
||||
let globalX0 = Infinity
|
||||
let globalX1 = -Infinity
|
||||
for (const {x0, x1} of segments) {
|
||||
globalX0 = Math.min(globalX0, Math.floor(x0))
|
||||
globalX1 = Math.max(globalX1, Math.floor(x1))
|
||||
}
|
||||
if (globalX0 >= globalX1) {return}
|
||||
const seg0 = segments[0]
|
||||
const pxPerUnit = (seg0.x1 - seg0.x0) / (seg0.u1 - seg0.u0)
|
||||
const anchorX = seg0.x0 - seg0.u0 * pxPerUnit
|
||||
const gridPhase = ((globalX0 - anchorX) % pixelsPerBlock + pixelsPerBlock) % pixelsPerBlock
|
||||
const firstBlockX = globalX0 - gridPhase
|
||||
for (let channel = 0; channel < numberOfChannels; channel++) {
|
||||
const data = peaks.data[channel]
|
||||
const channelY0 = actualTop + channel * peaksHeight
|
||||
const channelY1 = actualTop + (channel + 1) * peaksHeight
|
||||
const centerY = (channelY0 + channelY1) / 2
|
||||
const yScale = (channelY1 - channelY0 - 1.0) / (gainScale * 2)
|
||||
for (let bx = firstBlockX; bx < globalX1; bx += pixelsPerBlock) {
|
||||
const bxEnd = bx + pixelsPerBlock
|
||||
let blockMin = 0.0
|
||||
let blockMax = 0.0
|
||||
let blockAlpha = 0.0
|
||||
let hasData = false
|
||||
for (const seg of segments) {
|
||||
const segX0 = Math.floor(seg.x0)
|
||||
const segX1 = Math.floor(seg.x1)
|
||||
if (segX0 >= bxEnd || segX1 <= bx) {continue}
|
||||
const pixelSpan = seg.x1 - seg.x0
|
||||
if (pixelSpan <= 0) {continue}
|
||||
const uPerPx = (seg.u1 - seg.u0) / pixelSpan
|
||||
const stage = peaks.nearest(uPerPx)
|
||||
if (stage === null) {continue}
|
||||
const uPerPeak = stage.unitsEachPeak()
|
||||
const peaksPerPx = uPerPx / uPerPeak
|
||||
const overflow = seg.x0 - segX0
|
||||
const fromAtX0 = (seg.u0 - overflow * uPerPx) / uPerPx * peaksPerPx
|
||||
const overlapStart = Math.max(bx, segX0)
|
||||
const overlapEnd = Math.min(bxEnd, segX1)
|
||||
const fromPeak = fromAtX0 + (overlapStart - segX0) * peaksPerPx
|
||||
const toPeak = fromAtX0 + (overlapEnd - segX0) * peaksPerPx
|
||||
const idxFrom = Math.max(0, Math.floor(fromPeak))
|
||||
const idxTo = Math.floor(toPeak)
|
||||
for (let idx = idxFrom; idx < idxTo; idx++) {
|
||||
const bits = data[stage.dataOffset + idx]
|
||||
blockMin = Math.min(Peaks.unpack(bits, 0), blockMin)
|
||||
blockMax = Math.max(Peaks.unpack(bits, 1), blockMax)
|
||||
}
|
||||
if (idxFrom < idxTo) {hasData = true}
|
||||
blockAlpha = Math.max(blockAlpha, seg.outside ? 0.25 : 1.0)
|
||||
}
|
||||
if (!hasData) {continue}
|
||||
context.globalAlpha = blockAlpha
|
||||
const x = Math.max(bx, globalX0)
|
||||
const w = Math.min(blockWidth, Math.min(bxEnd, globalX1) - x)
|
||||
if (w <= 0) {continue}
|
||||
const yMin = channelY0 + Math.floor((blockMin + gainScale) * yScale)
|
||||
const yMax = channelY0 + Math.floor((blockMax + gainScale) * yScale)
|
||||
const ry0 = Math.max(channelY0, Math.min(yMin, yMax))
|
||||
const ry1 = Math.min(channelY1, Math.max(yMin, yMax))
|
||||
const finalY1 = ry0 === ry1 ? ry0 + 1 : ry1
|
||||
const maxDist = Math.max(centerY - ry0, finalY1 - centerY)
|
||||
const symY0 = centerY - maxDist
|
||||
const symY1 = centerY + maxDist
|
||||
const h = symY1 - symY0
|
||||
const r = Math.min(dpr, w / 2, h / 2)
|
||||
context.beginPath()
|
||||
context.roundRect(x, symY0, w, h, r)
|
||||
context.fill()
|
||||
}
|
||||
}
|
||||
context.globalAlpha = 1.0
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,10 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.0.68](https://github.com/andremichelle/openDAW/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-10)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/studio-enums
|
||||
|
||||
## [0.0.67](https://github.com/andremichelle/openDAW/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-04)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/studio-enums
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opendaw/studio-enums",
|
||||
"version": "0.0.67",
|
||||
"version": "0.0.68",
|
||||
"license": "LGPL-3.0-or-later",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
@@ -22,7 +22,7 @@
|
||||
"test": "echo \"No tests to run\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@opendaw/lib-std": "^0.0.71"
|
||||
"@opendaw/lib-std": "^0.0.72"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@opendaw/eslint-config": "^0.0.27",
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.0.83](https://github.com/andremichelle/openDAW/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-10)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/studio-forge-boxes
|
||||
|
||||
## [0.0.82](https://github.com/andremichelle/openDAW/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-06)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/studio-forge-boxes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opendaw/studio-forge-boxes",
|
||||
"version": "0.0.82",
|
||||
"version": "0.0.83",
|
||||
"license": "LGPL-3.0-or-later",
|
||||
"private": true,
|
||||
"exports": {
|
||||
@@ -14,11 +14,11 @@
|
||||
"test": "echo \"No tests to run\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@opendaw/lib-box": "^0.0.77",
|
||||
"@opendaw/lib-dsp": "^0.0.76",
|
||||
"@opendaw/lib-runtime": "^0.0.72",
|
||||
"@opendaw/lib-std": "^0.0.71",
|
||||
"@opendaw/studio-enums": "^0.0.67"
|
||||
"@opendaw/lib-box": "^0.0.78",
|
||||
"@opendaw/lib-dsp": "^0.0.77",
|
||||
"@opendaw/lib-runtime": "^0.0.73",
|
||||
"@opendaw/lib-std": "^0.0.72",
|
||||
"@opendaw/studio-enums": "^0.0.68"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@opendaw/eslint-config": "^0.0.27",
|
||||
|
||||
@@ -3,6 +3,14 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.0.52](https://github.com/andremichelle/openDAW/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-11)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/studio-scripting
|
||||
|
||||
## [0.0.51](https://github.com/andremichelle/openDAW/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-10)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/studio-scripting
|
||||
|
||||
## [0.0.50](https://github.com/andremichelle/openDAW/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-07)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/studio-scripting
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opendaw/studio-scripting",
|
||||
"version": "0.0.50",
|
||||
"version": "0.0.52",
|
||||
"license": "LGPL-3.0-or-later",
|
||||
"type": "module",
|
||||
"publishConfig": {
|
||||
@@ -30,13 +30,13 @@
|
||||
"test": "echo \"No tests to run\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@opendaw/lib-box": "^0.0.77",
|
||||
"@opendaw/lib-dsp": "^0.0.76",
|
||||
"@opendaw/lib-runtime": "^0.0.72",
|
||||
"@opendaw/lib-std": "^0.0.71",
|
||||
"@opendaw/studio-adapters": "^0.0.97",
|
||||
"@opendaw/studio-boxes": "^0.0.82",
|
||||
"@opendaw/studio-enums": "^0.0.67"
|
||||
"@opendaw/lib-box": "^0.0.78",
|
||||
"@opendaw/lib-dsp": "^0.0.77",
|
||||
"@opendaw/lib-runtime": "^0.0.73",
|
||||
"@opendaw/lib-std": "^0.0.72",
|
||||
"@opendaw/studio-adapters": "^0.0.99",
|
||||
"@opendaw/studio-boxes": "^0.0.83",
|
||||
"@opendaw/studio-enums": "^0.0.68"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@opendaw/eslint-config": "^0.0.27",
|
||||
|
||||
@@ -3,6 +3,26 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.0.128](https://github.com/andremichelle/opendaw/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-12)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/studio-sdk
|
||||
|
||||
## [0.0.127](https://github.com/andremichelle/opendaw/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-12)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/studio-sdk
|
||||
|
||||
## [0.0.126](https://github.com/andremichelle/opendaw/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-11)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/studio-sdk
|
||||
|
||||
## [0.0.125](https://github.com/andremichelle/opendaw/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-11)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/studio-sdk
|
||||
|
||||
## [0.0.124](https://github.com/andremichelle/opendaw/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-10)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/studio-sdk
|
||||
|
||||
## [0.0.123](https://github.com/andremichelle/opendaw/compare/@opendaw/[email protected]...@opendaw/[email protected]) (2026-03-07)
|
||||
|
||||
**Note:** Version bump only for package @opendaw/studio-sdk
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opendaw/studio-sdk",
|
||||
"version": "0.0.123",
|
||||
"version": "0.0.128",
|
||||
"license": "LGPL-3.0-or-later",
|
||||
"type": "module",
|
||||
"publishConfig": {
|
||||
@@ -42,20 +42,20 @@
|
||||
"@opendaw/typescript-config": "^0.0.29"
|
||||
},
|
||||
"dependencies": {
|
||||
"@opendaw/lib-box": "^0.0.77",
|
||||
"@opendaw/lib-dawproject": "^0.0.62",
|
||||
"@opendaw/lib-dom": "^0.0.76",
|
||||
"@opendaw/lib-dsp": "^0.0.76",
|
||||
"@opendaw/lib-fusion": "^0.0.83",
|
||||
"@opendaw/lib-jsx": "^0.0.76",
|
||||
"@opendaw/lib-midi": "^0.0.58",
|
||||
"@opendaw/lib-runtime": "^0.0.72",
|
||||
"@opendaw/lib-std": "^0.0.71",
|
||||
"@opendaw/lib-xml": "^0.0.57",
|
||||
"@opendaw/studio-adapters": "^0.0.97",
|
||||
"@opendaw/studio-boxes": "^0.0.82",
|
||||
"@opendaw/studio-core": "^0.0.121",
|
||||
"@opendaw/studio-enums": "^0.0.67"
|
||||
"@opendaw/lib-box": "^0.0.78",
|
||||
"@opendaw/lib-dawproject": "^0.0.63",
|
||||
"@opendaw/lib-dom": "^0.0.77",
|
||||
"@opendaw/lib-dsp": "^0.0.77",
|
||||
"@opendaw/lib-fusion": "^0.0.85",
|
||||
"@opendaw/lib-jsx": "^0.0.77",
|
||||
"@opendaw/lib-midi": "^0.0.59",
|
||||
"@opendaw/lib-runtime": "^0.0.73",
|
||||
"@opendaw/lib-std": "^0.0.72",
|
||||
"@opendaw/lib-xml": "^0.0.58",
|
||||
"@opendaw/studio-adapters": "^0.0.99",
|
||||
"@opendaw/studio-boxes": "^0.0.83",
|
||||
"@opendaw/studio-core": "^0.0.126",
|
||||
"@opendaw/studio-enums": "^0.0.68"
|
||||
},
|
||||
"gitHead": "e4f70170c5947610932306da94e7f0bb817e43b3"
|
||||
}
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
* The current version of the OpenDAW SDK.
|
||||
* This value is automatically synchronized with package.json during publish.
|
||||
*/
|
||||
export const OPENDAW_SDK_VERSION = "0.0.123"
|
||||
export const OPENDAW_SDK_VERSION = "0.0.128"
|
||||
|
||||
Reference in New Issue
Block a user