kugelaudio 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/utils.ts ADDED
@@ -0,0 +1,120 @@
1
+ /**
2
+ * Utility functions for KugelAudio SDK.
3
+ */
4
+
5
+ /**
6
+ * Decode base64 string to ArrayBuffer.
7
+ */
8
+ export function base64ToArrayBuffer(base64: string): ArrayBuffer {
9
+ // Handle browser and Node.js
10
+ if (typeof atob === 'function') {
11
+ const binary = atob(base64);
12
+ const bytes = new Uint8Array(binary.length);
13
+ for (let i = 0; i < binary.length; i++) {
14
+ bytes[i] = binary.charCodeAt(i);
15
+ }
16
+ return bytes.buffer;
17
+ } else {
18
+ // Node.js
19
+ const buffer = Buffer.from(base64, 'base64');
20
+ return buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength);
21
+ }
22
+ }
23
+
24
+ /**
25
+ * Encode ArrayBuffer to base64 string.
26
+ */
27
+ export function arrayBufferToBase64(buffer: ArrayBuffer): string {
28
+ const bytes = new Uint8Array(buffer);
29
+ if (typeof btoa === 'function') {
30
+ let binary = '';
31
+ for (let i = 0; i < bytes.length; i++) {
32
+ binary += String.fromCharCode(bytes[i]);
33
+ }
34
+ return btoa(binary);
35
+ } else {
36
+ // Node.js
37
+ return Buffer.from(bytes).toString('base64');
38
+ }
39
+ }
40
+
41
+ /**
42
+ * Decode PCM16 base64 audio to Float32Array.
43
+ */
44
+ export function decodePCM16(base64: string): Float32Array {
45
+ const buffer = base64ToArrayBuffer(base64);
46
+ const int16 = new Int16Array(buffer);
47
+ const float32 = new Float32Array(int16.length);
48
+
49
+ for (let i = 0; i < int16.length; i++) {
50
+ float32[i] = int16[i] / 32768;
51
+ }
52
+
53
+ return float32;
54
+ }
55
+
56
+ /**
57
+ * Create a WAV file from PCM16 audio data.
58
+ */
59
+ export function createWavFile(audio: ArrayBuffer, sampleRate: number): ArrayBuffer {
60
+ const dataSize = audio.byteLength;
61
+ const fileSize = 44 + dataSize; // WAV header is 44 bytes
62
+
63
+ const buffer = new ArrayBuffer(fileSize);
64
+ const view = new DataView(buffer);
65
+
66
+ // RIFF header
67
+ writeString(view, 0, 'RIFF');
68
+ view.setUint32(4, fileSize - 8, true);
69
+ writeString(view, 8, 'WAVE');
70
+
71
+ // fmt subchunk
72
+ writeString(view, 12, 'fmt ');
73
+ view.setUint32(16, 16, true); // Subchunk1Size (16 for PCM)
74
+ view.setUint16(20, 1, true); // AudioFormat (1 for PCM)
75
+ view.setUint16(22, 1, true); // NumChannels (1 for mono)
76
+ view.setUint32(24, sampleRate, true); // SampleRate
77
+ view.setUint32(28, sampleRate * 2, true); // ByteRate
78
+ view.setUint16(32, 2, true); // BlockAlign
79
+ view.setUint16(34, 16, true); // BitsPerSample
80
+
81
+ // data subchunk
82
+ writeString(view, 36, 'data');
83
+ view.setUint32(40, dataSize, true);
84
+
85
+ // Copy audio data
86
+ const audioBytes = new Uint8Array(audio);
87
+ const wavBytes = new Uint8Array(buffer);
88
+ wavBytes.set(audioBytes, 44);
89
+
90
+ return buffer;
91
+ }
92
+
93
+ function writeString(view: DataView, offset: number, str: string): void {
94
+ for (let i = 0; i < str.length; i++) {
95
+ view.setUint8(offset + i, str.charCodeAt(i));
96
+ }
97
+ }
98
+
99
+ /**
100
+ * Create a Blob from WAV data for browser use.
101
+ */
102
+ export function createWavBlob(audio: ArrayBuffer, sampleRate: number): Blob {
103
+ const wavBuffer = createWavFile(audio, sampleRate);
104
+ return new Blob([wavBuffer], { type: 'audio/wav' });
105
+ }
106
+
107
+ /**
108
+ * Check if running in browser environment.
109
+ */
110
+ export function isBrowser(): boolean {
111
+ return typeof window !== 'undefined' && typeof window.document !== 'undefined';
112
+ }
113
+
114
+ /**
115
+ * Check if running in Node.js environment.
116
+ */
117
+ export function isNode(): boolean {
118
+ return typeof process !== 'undefined' && process.versions != null && process.versions.node != null;
119
+ }
120
+