diff --git a/playground/js/audio/audio-canvas.js b/playground/js/audio/audio-canvas.js
index 2493064..32f27e9 100644
--- a/playground/js/audio/audio-canvas.js
+++ b/playground/js/audio/audio-canvas.js
@@ -99,7 +99,7 @@ export class AudioCanvas {
Drop audio files here
- MP3, WAV, FLAC, OGG, M4A
+ MP3, WAV, FLAC, OGG, M4A, OPUS, WebM, AIFF
`;
this._container.appendChild(this._dropOverlay);
@@ -169,10 +169,29 @@ export class AudioCanvas {
0 clips
+
+
`;
this._container.appendChild(bar);
this._controlBar = bar;
+ // Hidden file input for picker
+ this._fileInput = document.createElement('input');
+ this._fileInput.type = 'file';
+ this._fileInput.multiple = true;
+ this._fileInput.accept = 'audio/*,.mp3,.wav,.flac,.ogg,.m4a,.aac,.opus,.webm,.mp4,.wma,.aif,.aiff';
+ this._fileInput.style.display = 'none';
+ this._container.appendChild(this._fileInput);
+ this._fileInput.addEventListener('change', () => {
+ if (this._fileInput.files.length) this._handleDrop(this._fileInput.files);
+ this._fileInput.value = '';
+ });
+ bar.querySelector('#ac-add-files').addEventListener('click', () => this._fileInput.click());
+
// Submode buttons
bar.querySelectorAll('.ac-sbtn').forEach(btn => {
btn.addEventListener('click', () => this.setSubmode(btn.dataset.submode));
@@ -264,7 +283,7 @@ export class AudioCanvas {
async _handleDrop(files) {
if (!this._audioCtx) await this._initAudio();
const valid = [...files].filter(f =>
- f.type.startsWith('audio/') || /\.(mp3|wav|flac|ogg|m4a|aac)$/i.test(f.name));
+ f.type.startsWith('audio/') || /\.(mp3|wav|flac|ogg|m4a|aac|opus|webm|mp4|wma|aif|aiff)$/i.test(f.name));
for (const file of valid) await this._loadFile(file);
}