Spaces:
Running
Running
benjamin-paine
commited on
Commit
•
1509d53
1
Parent(s):
d444944
Upload 2 files
Browse files- hey-buddy-0.1.0.min.js +0 -0
- index.js +72 -31
hey-buddy-0.1.0.min.js
CHANGED
The diff for this file is too large to render.
See raw diff
|
|
index.js
CHANGED
@@ -1,29 +1,41 @@
|
|
1 |
-
/**
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
"speech": [22,200,206],
|
10 |
-
"frame budget": [25,255,25]
|
11 |
-
};
|
12 |
|
13 |
-
|
14 |
-
const
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
23 |
};
|
24 |
|
25 |
-
/**
|
26 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
27 |
// Helper to write a string to the DataView
|
28 |
const writeString = (view, offset, string) => {
|
29 |
for (let i = 0; i < string.length; i++) {
|
@@ -44,7 +56,7 @@ const float32ToWavBlob = (audioData, sampleRate, numChannels = 1) => {
|
|
44 |
// Calculate sizes
|
45 |
const blockAlign = numChannels * 2; // 2 bytes per sample for 16-bit audio
|
46 |
const wavHeaderSize = 44;
|
47 |
-
const dataLength =
|
48 |
const buffer = new ArrayBuffer(wavHeaderSize + dataLength);
|
49 |
const view = new DataView(buffer);
|
50 |
|
@@ -64,19 +76,45 @@ const float32ToWavBlob = (audioData, sampleRate, numChannels = 1) => {
|
|
64 |
view.setUint32(40, dataLength, true); // Subchunk2Size
|
65 |
|
66 |
// Convert the Float32Array audio samples to 16-bit PCM and write them to the DataView
|
67 |
-
floatTo16BitPCM(view, wavHeaderSize,
|
68 |
|
69 |
// Create and return the Blob
|
70 |
return new Blob([view], { type: 'audio/wav' });
|
71 |
}
|
72 |
|
73 |
-
/**
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
78 |
}
|
79 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
80 |
/** Main */
|
81 |
document.addEventListener("DOMContentLoaded", () => {
|
82 |
/** DOM elements */
|
@@ -110,7 +148,10 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
110 |
|
111 |
// When recording is complete, replace the audio element
|
112 |
heyBuddy.onRecording((audioSamples) => {
|
113 |
-
|
|
|
|
|
|
|
114 |
});
|
115 |
|
116 |
/** Add graphs */
|
|
|
1 |
+
/**
|
2 |
+
* Play audio samples using the Web Audio API.
|
3 |
+
* @param {Float32Array} audioSamples - The audio samples to play.
|
4 |
+
* @param {number} sampleRate - The sample rate of the audio samples.
|
5 |
+
*/
|
6 |
+
function playAudioSamples(audioSamples, sampleRate = 16000) {
|
7 |
+
// Create an AudioContext
|
8 |
+
const audioContext = new (window.AudioContext || window.webkitAudioContext)();
|
|
|
|
|
|
|
9 |
|
10 |
+
// Create an AudioBuffer
|
11 |
+
const audioBuffer = audioContext.createBuffer(
|
12 |
+
1, // number of channels
|
13 |
+
audioSamples.length, // length of the buffer in samples
|
14 |
+
sampleRate // sample rate (samples per second)
|
15 |
+
);
|
16 |
+
|
17 |
+
// Fill the AudioBuffer with the Float32Array of audio samples
|
18 |
+
audioBuffer.getChannelData(0).set(audioSamples);
|
19 |
+
|
20 |
+
// Create a BufferSource node
|
21 |
+
const source = audioContext.createBufferSource();
|
22 |
+
source.buffer = audioBuffer;
|
23 |
+
|
24 |
+
// Connect the source to the AudioContext's destination (the speakers)
|
25 |
+
source.connect(audioContext.destination);
|
26 |
+
|
27 |
+
// Start playback
|
28 |
+
source.start();
|
29 |
};
|
30 |
|
31 |
+
/**
|
32 |
+
* Turns floating-point audio samples to a Wave blob.
|
33 |
+
* @param {Float32Array} audioSamples - The audio samples to play.
|
34 |
+
* @param {number} sampleRate - The sample rate of the audio samples.
|
35 |
+
* @param {number} numChannels - The number of channels in the audio. Defaults to 1 (mono).
|
36 |
+
* @return {Blob} A blob of type `audio/wav`
|
37 |
+
*/
|
38 |
+
function samplesToBlob(audioSamples, sampleRate = 16000, numChannels = 1) {
|
39 |
// Helper to write a string to the DataView
|
40 |
const writeString = (view, offset, string) => {
|
41 |
for (let i = 0; i < string.length; i++) {
|
|
|
56 |
// Calculate sizes
|
57 |
const blockAlign = numChannels * 2; // 2 bytes per sample for 16-bit audio
|
58 |
const wavHeaderSize = 44;
|
59 |
+
const dataLength = audioSamples.length * numChannels * 2; // 16-bit PCM data length
|
60 |
const buffer = new ArrayBuffer(wavHeaderSize + dataLength);
|
61 |
const view = new DataView(buffer);
|
62 |
|
|
|
76 |
view.setUint32(40, dataLength, true); // Subchunk2Size
|
77 |
|
78 |
// Convert the Float32Array audio samples to 16-bit PCM and write them to the DataView
|
79 |
+
floatTo16BitPCM(view, wavHeaderSize, audioSamples);
|
80 |
|
81 |
// Create and return the Blob
|
82 |
return new Blob([view], { type: 'audio/wav' });
|
83 |
}
|
84 |
|
85 |
+
/**
|
86 |
+
* Renders a blob to an audio element with controls.
|
87 |
+
* Use `appendChild(result)` to add to the document or a node.
|
88 |
+
* @param {Blob} audioBlob - A blob with a valid audio type.
|
89 |
+
* @see samplesToBlob
|
90 |
+
*/
|
91 |
+
function blobToAudio(audioBlob) {
|
92 |
+
const url = URL.createObjectURL(audioBlob);
|
93 |
+
const audio = document.createElement("audio");
|
94 |
+
audio.controls = true;
|
95 |
+
audio.src = url;
|
96 |
+
return audio;
|
97 |
}
|
98 |
|
99 |
+
/** Configuration */
|
100 |
+
const colors = {
|
101 |
+
"buddy": [0,119,187],
|
102 |
+
"hey buddy": [51,187,238],
|
103 |
+
"hi buddy": [0,153,136],
|
104 |
+
"sup buddy": [238,119,51],
|
105 |
+
"yo buddy": [204,51,17],
|
106 |
+
"okay buddy": [238,51,119],
|
107 |
+
"speech": [22,200,206],
|
108 |
+
"frame budget": [25,255,25]
|
109 |
+
};
|
110 |
+
const wakeWords = ["buddy", "hey buddy", "hi buddy", "sup buddy", "yo buddy", "okay buddy"];
|
111 |
+
const canvasSize = { width: 640, height: 100 };
|
112 |
+
const graphLineWidth = 1;
|
113 |
+
const options = {
|
114 |
+
debug: true,
|
115 |
+
modelPath: wakeWords.map((word) => `/models/${word.replace(' ', '-')}.onnx`)
|
116 |
+
};
|
117 |
+
|
118 |
/** Main */
|
119 |
document.addEventListener("DOMContentLoaded", () => {
|
120 |
/** DOM elements */
|
|
|
148 |
|
149 |
// When recording is complete, replace the audio element
|
150 |
heyBuddy.onRecording((audioSamples) => {
|
151 |
+
const audioBlob = samplesToBlob(audioSamples);
|
152 |
+
const audioElement = blobToAudio(audioBlob);
|
153 |
+
audioContainer.innerHTML = "";
|
154 |
+
audioContainer.appendChild(audioElement);
|
155 |
});
|
156 |
|
157 |
/** Add graphs */
|