sourav-das/stem-separator
3
1var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {2 function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }3 return new (P || (P = Promise))(function (resolve, reject) {4 function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }5 function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }6 function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }7 step((generator = generator.apply(thisArg, _arguments || [])).next());8 });9};10/** Decode an array buffer into an audio buffer */11function decode(audioData, sampleRate) {12 return __awaiter(this, void 0, void 0, function* () {13 const audioCtx = new AudioContext({ sampleRate });14 try {15 return yield audioCtx.decodeAudioData(audioData);16 }17 finally {18 // Ensure AudioContext is always closed, even on synchronous errors19 audioCtx.close();20 }21 });22}23/** Normalize peaks to -1..1 */24function normalize(channelData) {25 const firstChannel = channelData[0];26 if (firstChannel.some((n) => n > 1 || n < -1)) {27 const length = firstChannel.length;28 let max = 0;29 for (let i = 0; i < length; i++) {30 const absN = Math.abs(firstChannel[i]);31 if (absN > max)32 max = absN;33 }34 for (const channel of channelData) {35 for (let i = 0; i < length; i++) {36 channel[i] /= max;37 }38 }39 }40 return channelData;41}42/** Create an audio buffer from pre-decoded audio data */43function createBuffer(channelData, duration) {44 // Validate inputs45 if (!channelData || channelData.length === 0) {46 throw new Error('channelData must be a non-empty array');47 }48 if (duration <= 0) {49 throw new Error('duration must be greater than 0');50 }51 // If a single array of numbers is passed, make it an array of arrays52 if (typeof channelData[0] === 'number')53 channelData = [channelData];54 // Validate channel data after conversion55 if (!channelData[0] || channelData[0].length === 0) {56 throw new Error('channelData must contain non-empty channel arrays');57 }58 // Normalize to -1..159 normalize(channelData);60 // Convert to Float32Array for consistency61 const float32Channels = channelData.map((channel) => channel instanceof Float32Array ? channel : Float32Array.from(channel));62 return {63 duration,64 length: float32Channels[0].length,65 sampleRate: float32Channels[0].length / duration,66 numberOfChannels: float32Channels.length,67 getChannelData: (i) => {68 const channel = float32Channels[i];69 if (!channel) {70 throw new Error(`Channel ${i} not found`);71 }72 return channel;73 },74 copyFromChannel: AudioBuffer.prototype.copyFromChannel,75 copyToChannel: AudioBuffer.prototype.copyToChannel,76 };77}78const Decoder = {79 decode,80 createBuffer,81};82export default Decoder;83 