.editor{
max-width:1100px;margin:30px auto;padding:20px;
background:#f4f6ff;border-radius:20px;
box-shadow:0 12px 35px rgba(0,0,0,.18);
font-family:Arial}
.controls button{
margin:5px;padding:10px 16px;border:none;
border-radius:10px;background:#4a6cf7;color:#fff;cursor:pointer}
#wave{height:140px}
audio{width:100%}
const AudioCtx = window.AudioContext || window.webkitAudioContext;
const ctx = new AudioCtx();
let buffer = null;
let currentRegion = null;
const player = document.getElementById("player");
const fileInput = document.getElementById("file");
const waveContainer = document.getElementById("wave");
const ws = WaveSurfer.create({
container: waveContainer,
waveColor: "#9bb1ff",
progressColor: "#4a6cf7",
cursorColor: "#000",
height: 140,
responsive: true,
plugins: [
WaveSurfer.regions.create()
]
});
/* ===== FILE IMPORT (FIXED) ===== */
fileInput.addEventListener("change", async () => {
const file = fileInput.files[0];
if (!file) return;
await ctx.resume(); // IMPORTANT for mobile/Chrome
const url = URL.createObjectURL(file);
player.src = url;
player.load();
player.onloadedmetadata = async () => {
const offline = new OfflineAudioContext(
2,
player.duration * 44100,
44100
);
const source = offline.createMediaElementSource(player);
source.connect(offline.destination);
player.currentTime = 0;
player.play();
const rendered = await offline.startRendering();
player.pause();
player.currentTime = 0;
buffer = rendered;
const wavBlob = audioBufferToWav(buffer);
ws.loadBlob(wavBlob);
};
});
/* ===== WAVE EVENTS ===== */
ws.on("ready", () => {
ws.enableDragSelection({});
});
ws.on("region-click", (region, e) => {
e.stopPropagation();
currentRegion = region;
});
/* ===== EDIT FUNCTIONS ===== */
function split() {
if (!currentRegion) return alert("Region select karo");
}
function deleteRegion() {
if (!currentRegion) return;
buffer = removeSegment(buffer, currentRegion.start, currentRegion.end);
reload();
currentRegion.remove();
currentRegion = null;
}
function cut() {
if (!currentRegion) return;
buffer = keepOnly(buffer, currentRegion.start, currentRegion.end);
reload();
currentRegion.remove();
currentRegion = null;
}
function fadeIn() {
buffer = applyFade(buffer, true);
reload();
}
function fadeOut() {
buffer = applyFade(buffer, false);
reload();
}
function preview() {
player.src = URL.createObjectURL(audioBufferToWav(buffer));
player.play();
}
function download() {
const a = document.createElement("a");
a.href = URL.createObjectURL(audioBufferToWav(buffer));
a.download = "edited-audio.wav";
a.click();
}
function reload() {
const blob = audioBufferToWav(buffer);
ws.loadBlob(blob);
player.src = URL.createObjectURL(blob);
}
/* ===== AUDIO PROCESSING ===== */
function removeSegment(b, s, e) {
const sr = b.sampleRate;
const start = s * sr, end = e * sr;
const nb = ctx.createBuffer(b.numberOfChannels, b.length - (end - start), sr);
for (let c = 0; c < b.numberOfChannels; c++) {
const d = b.getChannelData(c);
const nd = nb.getChannelData(c);
nd.set(d.slice(0, start), 0);
nd.set(d.slice(end), start);
}
return nb;
}
function keepOnly(b, s, e) {
const sr = b.sampleRate;
const start = s * sr, end = e * sr;
const nb = ctx.createBuffer(b.numberOfChannels, end - start, sr);
for (let c = 0; c < b.numberOfChannels; c++) {
nb.getChannelData(c).set(b.getChannelData(c).slice(start, end));
}
return nb;
}
function applyFade(b, fadeIn) {
const nb = ctx.createBuffer(b.numberOfChannels, b.length, b.sampleRate);
for (let c = 0; c < b.numberOfChannels; c++) {
const d = b.getChannelData(c);
const nd = nb.getChannelData(c);
for (let i = 0; i { for (let i = 0; i < s.length; i++) v.setUint8(o++, s.charCodeAt(i)); };
w("RIFF"); v.setUint32(o, 36 + l * n * 2, true); o += 4;
w("WAVEfmt "); v.setUint32(o, 16, true); o += 4;
v.setUint16(o, 1, true); o += 2;
v.setUint16(o, n, true); o += 2;
v.setUint32(o, b.sampleRate, true); o += 4;
v.setUint32(o, b.sampleRate * n * 2, true); o += 4;
v.setUint16(o, n * 2, true); o += 2;
v.setUint16(o, 16, true); o += 2;
w("data"); v.setUint32(o, l * n * 2, true); o += 4;
for (let i = 0; i < l; i++)
for (let c = 0; c < n; c++, o += 2)
v.setInt16(o, b.getChannelData(c)[i] * 32767, true);
return new Blob([v], { type: "audio/wav" });
}