benjamin-paine commited on
Commit
1509d53
1 Parent(s): d444944

Upload 2 files

Browse files
Files changed (2) hide show
  1. hey-buddy-0.1.0.min.js +0 -0
  2. 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
- /** Configuration */
2
- const colors = {
3
- "buddy": [0,119,187],
4
- "hey buddy": [51,187,238],
5
- "hi buddy": [0,153,136],
6
- "sup buddy": [238,119,51],
7
- "yo buddy": [204,51,17],
8
- "okay buddy": [238,51,119],
9
- "speech": [22,200,206],
10
- "frame budget": [25,255,25]
11
- };
12
 
13
- const rootUrl = "https://huggingface.co/benjamin-paine/hey-buddy/resolve/main";
14
- const wakeWords = ["buddy", "hey buddy", "hi buddy", "sup buddy", "yo buddy", "okay buddy"];
15
- const canvasSize = { width: 640, height: 100 };
16
- const graphLineWidth = 1;
17
- const options = {
18
- debug: true,
19
- modelPath: wakeWords.map((word) => `${rootUrl}/models/${word.replace(' ', '-')}.onnx`),
20
- vadModelPath: `${rootUrl}/pretrained/silero-vad.onnx`,
21
- spectrogramModelPath: `${rootUrl}/pretrained/mel-spectrogram.onnx`,
22
- embeddingModelPath: `${rootUrl}/pretrained/speech-embedding.onnx`,
 
 
 
 
 
 
 
 
 
23
  };
24
 
25
- /** Helper method for conversion */
26
- const float32ToWavBlob = (audioData, sampleRate, numChannels = 1) => {
 
 
 
 
 
 
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 = audioData.length * numChannels * 2; // 16-bit PCM data length
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, audioData);
68
 
69
  // Create and return the Blob
70
  return new Blob([view], { type: 'audio/wav' });
71
  }
72
 
73
- /** Helper method for turning the audio samples into an audio element */
74
- const saveRecording = (audioContainer, audioSamples, sampleRate = 16000) => {
75
- const blob = float32ToWavBlob(audioSamples, sampleRate);
76
- const url = URL.createObjectURL(blob);
77
- audioContainer.innerHTML = `<audio controls src="${url}"></audio>`;
 
 
 
 
 
 
 
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
- saveRecording(audioContainer, audioSamples);
 
 
 
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 */