+132
-63
@@ -1,75 +0,144 @@ | ||
| // AudioConverter.js | ||
| class AudioConverter { | ||
| constructor() { | ||
| this.audioContext = new (window.AudioContext || window.webkitAudioContext)(); | ||
| this.bufferPool = new BufferPool(); | ||
| } | ||
| // AudioConverter.js | ||
| class BufferPool { | ||
| constructor() { | ||
| this.buffers = new Map(); | ||
| this.maxSize = 1024 * 1024; // 1MB | ||
| this.currentSize = 0; | ||
| } | ||
| async convertWavToAudu(wavFile) { | ||
| try { | ||
| const arrayBuffer = await this.readFile(wavFile); | ||
| const audioBuffer = await this.audioContext.decodeAudioData(arrayBuffer); | ||
| const auduData = { | ||
| format: 'audu', | ||
| version: 1, | ||
| sampleRate: this.audioContext.sampleRate, | ||
| channels: audioBuffer.numberOfChannels, | ||
| length: audioBuffer.length, | ||
| data: this.bufferToDataUrl(audioBuffer) | ||
| }; | ||
| return auduData; | ||
| } catch (error) { | ||
| throw new AudioConverterError(401, '変換エラーが発生しました', { | ||
| originalError: error | ||
| }); | ||
| getOrCreate(channels, length, sampleRate) { | ||
| const key = `${channels}-${length}-${sampleRate}`; | ||
| if (this.buffers.has(key)) { | ||
| const buffer = this.buffers.get(key); | ||
| this.buffers.delete(key); | ||
| this.currentSize -= buffer.length * channels * 2; | ||
| this.buffers.set(key, buffer); | ||
| this.currentSize += buffer.length * channels * 2; | ||
| return buffer; | ||
| } | ||
| const buffer = new this.audioContext.createBuffer( | ||
| channels, | ||
| length, | ||
| sampleRate | ||
| ); | ||
| if (this.currentSize + length * channels * 2 > this.maxSize) { | ||
| this.cleanup(); | ||
| } | ||
| this.buffers.set(key, buffer); | ||
| this.currentSize += buffer.length * channels * 2; | ||
| return buffer; | ||
| } | ||
| } | ||
| async readFile(file) { | ||
| return new Promise((resolve, reject) => { | ||
| const reader = new FileReader(); | ||
| reader.onload = () => resolve(reader.result); | ||
| reader.onerror = reject; | ||
| reader.readAsArrayBuffer(file); | ||
| }); | ||
| } | ||
| cleanup() { | ||
| const keys = Array.from(this.buffers.keys()); | ||
| while (this.currentSize > this.maxSize / 2 && keys.length > 0) { | ||
| const key = keys.pop(); | ||
| const buffer = this.buffers.get(key); | ||
| this.currentSize -= buffer.length * buffer.numberOfChannels * 2; | ||
| this.buffers.delete(key); | ||
| } | ||
| } | ||
| } | ||
| bufferToDataUrl(buffer) { | ||
| const channels = []; | ||
| for (let channel = 0; channel < buffer.numberOfChannels; channel++) { | ||
| channels.push(buffer.getChannelData(channel)); | ||
| class AudioQueue { | ||
| constructor() { | ||
| this.queue = []; | ||
| this.processing = false; | ||
| } | ||
| return channels; | ||
| } | ||
| async saveToAbuf(auduData) { | ||
| try { | ||
| const blob = new Blob([JSON.stringify(auduData)], { type: 'application/audu' }); | ||
| const url = URL.createObjectURL(blob); | ||
| const a = document.createElement('a'); | ||
| a.href = url; | ||
| a.download = 'output.audu'; | ||
| a.click(); | ||
| return blob; | ||
| } catch (error) { | ||
| throw new AudioConverterError(401, '保存エラーが発生しました', { | ||
| originalError: error | ||
| }); | ||
| enqueue(audioData) { | ||
| this.queue.push(audioData); | ||
| } | ||
| } | ||
| dequeue() { | ||
| return this.queue.shift(); | ||
| } | ||
| isEmpty() { | ||
| return this.queue.length === 0; | ||
| } | ||
| async processQueue() { | ||
| if (this.processing) return; | ||
| this.processing = true; | ||
| while (!this.isEmpty()) { | ||
| const item = this.dequeue(); | ||
| await this.saveToIndexedDB(item); | ||
| } | ||
| this.processing = false; | ||
| } | ||
| } | ||
| class AudioConverterAPI { | ||
| constructor() { | ||
| this.audioContext = new (window.AudioContext || window.webkitAudioContext)(); | ||
| this.bufferPool = new BufferPool(); | ||
| } | ||
| async convertWavToAudu(wavFile) { | ||
| try { | ||
| const arrayBuffer = await this.readFile(wavFile); | ||
| const audioBuffer = await this.audioContext.decodeAudioData(arrayBuffer); | ||
| const auduData = { | ||
| format: "audu", | ||
| version: 1, | ||
| sampleRate: this.audioContext.sampleRate, | ||
| channels: audioBuffer.numberOfChannels, | ||
| length: audioBuffer.length, | ||
| data: this.bufferToDataUrl(audioBuffer), | ||
| }; | ||
| return auduData; | ||
| } catch (error) { | ||
| throw new AudioConverterError(401, "変換エラーが発生しました", { | ||
| originalError: error, | ||
| }); | ||
| } | ||
| } | ||
| async readFile(file) { | ||
| return new Promise((resolve, reject) => { | ||
| const reader = new FileReader(); | ||
| reader.onload = () => resolve(reader.result); | ||
| reader.onerror = reject; | ||
| reader.readAsArrayBuffer(file); | ||
| }); | ||
| } | ||
| bufferToDataUrl(buffer) { | ||
| const channels = []; | ||
| for (let channel = 0; channel < buffer.numberOfChannels; channel++) { | ||
| channels.push(buffer.getChannelData(channel)); | ||
| } | ||
| return channels; | ||
| } | ||
| async saveToAbuf(auduData) { | ||
| try { | ||
| const blob = new Blob([JSON.stringify(auduData)], { | ||
| type: "application/audu", | ||
| }); | ||
| const url = URL.createObjectURL(blob); | ||
| const a = document.createElement("a"); | ||
| a.href = url; | ||
| a.download = "output.audu"; | ||
| a.click(); | ||
| return blob; | ||
| } catch (error) { | ||
| throw new AudioConverterError(401, "保存エラーが発生しました", { | ||
| originalError: error, | ||
| }); | ||
| } | ||
| } | ||
| } | ||
| class AudioConverterError extends Error { | ||
| constructor(code, message, details = {}) { | ||
| super(message); | ||
| this.code = code; | ||
| this.details = details; | ||
| this.name = 'AudioConverterError'; | ||
| } | ||
| constructor(code, message, details = {}) { | ||
| super(message); | ||
| this.code = code; | ||
| this.details = details; | ||
| this.name = "AudioConverterError"; | ||
| } | ||
| } | ||
| export { AudioConverter }; | ||
| export const AudioConverter = new AudioConverterAPI(); |
+1
-1
| { | ||
| "name": "audu-utils", | ||
| "version": "0.0.2", | ||
| "version": "0.0.3", | ||
| "description": "AUDU format utility to combine AudioBuffer generated from multiple audio into one file", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
AI-detected possible typosquat
Supply chain riskAI has identified this package as a potential typosquat of a more popular package. This suggests that the package may be intentionally mimicking another package's name, description, or other metadata.
Found 1 instance in 1 package
AI-detected possible typosquat
Supply chain riskAI has identified this package as a potential typosquat of a more popular package. This suggests that the package may be intentionally mimicking another package's name, description, or other metadata.
Found 1 instance in 1 package
4615
92.13%128
100%