Skip to content

Commit cb0f56b

Browse files
committed
import colab_utils
1 parent 35360b9 commit cb0f56b

File tree

3 files changed

+340
-0
lines changed

3 files changed

+340
-0
lines changed

colab_utils/audio.py

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
#
2+
# Copyright (c) 2021 Arm Limited and Contributors. All rights reserved.
3+
#
4+
# SPDX-License-Identifier: Apache-2.0
5+
#
6+
7+
from IPython import display
8+
from google.colab import output
9+
import base64
10+
from datetime import datetime
11+
from os import path
12+
13+
def record_wav_file(folder):
14+
def save_wav_file(folder, s):
15+
b = base64.b64decode(s.split(',')[1])
16+
17+
file_path = path.join(folder, datetime.now().strftime("%d-%m-%Y-%H-%M-%S.wav"))
18+
19+
print(f'Saving file: {file_path}')
20+
21+
with open(file_path, 'wb') as f:
22+
f.write(b)
23+
24+
output.register_callback('notebook.save_wav_file', save_wav_file)
25+
26+
display.display(display.Javascript("""
27+
const recorderJsScript = document.createElement("script");
28+
const audioInputSelect = document.createElement("select");
29+
const recordButton = document.createElement("button");
30+
31+
recorderJsScript.src = "https://sandeepmistry.github.io/Recorderjs/dist/recorder.js";
32+
recorderJsScript.type = "text/javascript";
33+
34+
recordButton.innerHTML = "⏺ Start Recording";
35+
36+
document.body.append(recorderJsScript);
37+
document.querySelector("#output-area").appendChild(audioInputSelect);
38+
document.querySelector("#output-area").appendChild(recordButton);
39+
40+
async function updateAudioInputSelect() {
41+
while (audioInputSelect.firstChild) {
42+
audioInputSelect.removeChild(audioInputSelect.firstChild);
43+
}
44+
45+
const deviceInfos = await navigator.mediaDevices.enumerateDevices();
46+
47+
for (let i = 0; i !== deviceInfos.length; ++i) {
48+
const deviceInfo = deviceInfos[i];
49+
const option = document.createElement("option");
50+
51+
option.value = deviceInfo.deviceId;
52+
53+
if (deviceInfo.kind === "audioinput") {
54+
option.text = deviceInfo.label || "Microphone " + (audioInputSelect.length + 1);
55+
option.selected = (option.text.indexOf("MicNode") !== -1);
56+
audioInputSelect.appendChild(option);
57+
}
58+
}
59+
}
60+
61+
const blob2text = (blob) => new Promise(resolve => {
62+
const reader = new FileReader();
63+
reader.onloadend = e => resolve(e.srcElement.result);
64+
reader.readAsDataURL(blob)
65+
});
66+
67+
let recorder = undefined;
68+
let stream = undefined;
69+
70+
// https://www.html5rocks.com/en/tutorials/getusermedia/intro/
71+
recordButton.onclick = async () => {
72+
if (recordButton.innerHTML != "⏺ Start Recording") {
73+
recordButton.disabled = true;
74+
recorder.stop();
75+
76+
recorder.exportWAV(async (blob) => {
77+
const text = await blob2text(blob);
78+
79+
google.colab.kernel.invokeFunction('notebook.save_wav_file', ['###folder###', text], {});
80+
81+
recordButton.innerHTML = "⏺ Start Recording";
82+
recordButton.disabled = false;
83+
84+
stream.getTracks().forEach(function(track) {
85+
if (track.readyState === 'live') {
86+
track.stop();
87+
}
88+
});
89+
});
90+
91+
return;
92+
}
93+
94+
const constraints = {
95+
audio: {
96+
deviceId: {
97+
},
98+
sampleRate: 16000
99+
},
100+
video: false
101+
};
102+
103+
stream = await navigator.mediaDevices.getUserMedia(constraints);
104+
105+
if (audioInputSelect.value === "") {
106+
await updateAudioInputSelect();
107+
108+
stream.getTracks().forEach(function(track) {
109+
if (track.readyState === 'live') {
110+
track.stop();
111+
}
112+
});
113+
114+
constraints.audio.deviceId.exact = audioInputSelect.value;
115+
stream = await navigator.mediaDevices.getUserMedia(constraints);
116+
}
117+
118+
const audioContext = new AudioContext({
119+
sampleRate: 16000
120+
});
121+
122+
const input = audioContext.createMediaStreamSource(stream);
123+
124+
recorder = new Recorder(input, {
125+
numChannels: 1
126+
});
127+
128+
recordButton.innerHTML = "⏹ Stop Recording";
129+
130+
recorder.record();
131+
};
132+
133+
updateAudioInputSelect();
134+
""".replace('###folder###', folder)))

colab_utils/pico.py

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
#
2+
# Copyright (c) 2021 Arm Limited and Contributors. All rights reserved.
3+
#
4+
# SPDX-License-Identifier: Apache-2.0
5+
#
6+
7+
from IPython import display
8+
from google.colab import output
9+
import base64
10+
11+
def flash_pico(binary_file):
12+
def read_binary_base64(binary_file):
13+
with open(binary_file, 'rb') as f:
14+
return base64.b64encode(f.read()).decode('ascii')
15+
16+
output.register_callback('notebook.read_binary_base64', read_binary_base64)
17+
18+
display.display(display.Javascript("""
19+
const picotoolJsScript = document.createElement("script");
20+
21+
picotoolJsScript.src = "https://armdeveloperecosystem.github.io/picotool.js/src/picotool.js";
22+
picotoolJsScript.type = "text/javascript";
23+
24+
document.body.append(picotoolJsScript);
25+
26+
async function readBinary() {
27+
const result = await google.colab.kernel.invokeFunction('notebook.read_binary_base64', ['###binary_file###']);
28+
let str = result.data['text/plain'];
29+
30+
str = str.substring(1, str.length - 1);
31+
32+
return Uint8Array.from(atob(str), c => c.charCodeAt(0));
33+
}
34+
35+
async function flashPico() {
36+
statusDiv.innerHTML = '';
37+
38+
try {
39+
statusDiv.innerHTML += "requesting device ... <br/>";
40+
const usbDevice = await PicoTool.requestDevice();
41+
42+
const fileData = (await readBinary()).buffer;
43+
const writeData = new ArrayBuffer(PicoTool.FLASH_SECTOR_ERASE_SIZE);
44+
45+
const srcDataView = new DataView(fileData);
46+
const dstDataView = new DataView(writeData);
47+
48+
const picoTool = new PicoTool(usbDevice);
49+
50+
statusDiv.innerHTML += "opening device ... <br/>";
51+
await picoTool.open();
52+
53+
// statusDiv.innerHTML += "reset ... <br/>";
54+
await picoTool.reset();
55+
56+
// statusDiv.innerHTML += "exlusive access device ... <br/>";
57+
await picoTool.exlusiveAccess(1);
58+
59+
// statusDiv.innerHTML += "exit xip ... <br/>";
60+
await picoTool.exitXip();
61+
62+
for (let i = 0; i < fileData.byteLength; i += PicoTool.FLASH_SECTOR_ERASE_SIZE) {
63+
let j = 0;
64+
for (j = 0; j < PicoTool.FLASH_SECTOR_ERASE_SIZE && (i + j) < fileData.byteLength; j++) {
65+
dstDataView.setUint8(j, srcDataView.getUint8(i + j));
66+
}
67+
68+
statusDiv.innerHTML += "erasing ... ";
69+
await picoTool.flashErase(PicoTool.FLASH_START + i, PicoTool.FLASH_SECTOR_ERASE_SIZE);
70+
71+
statusDiv.innerHTML += "writing ... ";
72+
await picoTool.write(PicoTool.FLASH_START + i, writeData);
73+
74+
statusDiv.innerHTML += " " + ((i + j) * 100 / fileData.byteLength).toFixed(2) + "% <br/>";
75+
}
76+
77+
statusDiv.innerHTML += "rebooting device ... <br/>";
78+
await picoTool.reboot(0, PicoTool.SRAM_END, 512);
79+
80+
statusDiv.innerHTML += "closing device ... <br/>";
81+
await picoTool.close();
82+
} catch (e) {
83+
statusDiv.innerHTML = 'Error: ' + e.message;
84+
}
85+
}
86+
87+
let statusDiv = undefined;
88+
89+
if ('usb' in navigator) {
90+
const flashButton = document.createElement("button");
91+
92+
flashButton.innerHTML = "Flash";
93+
flashButton.onclick = flashPico;
94+
95+
document.querySelector("#output-area").appendChild(flashButton);
96+
97+
statusDiv = document.createElement("div");
98+
statusDiv.style = "margin: 5px";
99+
100+
document.querySelector("#output-area").appendChild(statusDiv);
101+
} else {
102+
document.querySelector("#output-area").appendChild(document.createTextNode(
103+
"Oh no! Your browser does not support WebUSB!"
104+
));
105+
}
106+
""".replace('###binary_file###', binary_file)))

colab_utils/serial_monitor.py

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
#
2+
# Copyright (c) 2021 Arm Limited and Contributors. All rights reserved.
3+
#
4+
# SPDX-License-Identifier: Apache-2.0
5+
#
6+
7+
from IPython import display
8+
9+
def run_serial_monitor():
10+
display.display(display.Javascript('''
11+
if ('serial' in navigator) {
12+
const scriptElement = document.createElement("script");
13+
scriptElement.src = "https://cdnjs.cloudflare.com/ajax/libs/xterm/3.14.5/xterm.min.js";
14+
document.body.appendChild(scriptElement);
15+
16+
const linkElement = document.createElement("link");
17+
linkElement.rel = "stylesheet"
18+
linkElement.href = "https://cdnjs.cloudflare.com/ajax/libs/xterm/3.14.5/xterm.min.css";
19+
document.body.appendChild(linkElement);
20+
21+
const connectDisconnectButton = document.createElement("button");
22+
23+
connectDisconnectButton.innerHTML = "Connect Port";
24+
25+
document.querySelector("#output-area").appendChild(connectDisconnectButton);
26+
27+
terminalDiv = document.createElement("div");
28+
terminalDiv.style = "margin: 5px";
29+
30+
document.querySelector("#output-area").appendChild(terminalDiv);
31+
32+
let port = undefined;
33+
let reader = undefined;
34+
let keepReading = true;
35+
let term = undefined;
36+
37+
connectDisconnectButton.onclick = async () => {
38+
if (port !== undefined) {
39+
if (reader !== undefined) {
40+
keepReading = false;
41+
try {
42+
await reader.cancel();
43+
} catch (e) {}
44+
}
45+
port = undefined;
46+
reader = undefined;
47+
48+
connectDisconnectButton.innerHTML = "Connect Port";
49+
50+
return;
51+
}
52+
53+
port = await navigator.serial.requestPort();
54+
keepReading = true;
55+
56+
connectDisconnectButton.innerHTML = "Disconnect Port";
57+
58+
await port.open({ baudRate: 115200 });
59+
60+
if (term === undefined) {
61+
term = new Terminal();
62+
term.open(terminalDiv);
63+
}
64+
term.clear();
65+
66+
const decoder = new TextDecoder();
67+
68+
while (port && keepReading) {
69+
try {
70+
reader = port.readable.getReader();
71+
72+
while (true) {
73+
const { value, done } = await reader.read();
74+
if (done) {
75+
keepReading = false;
76+
break;
77+
}
78+
79+
term.write(decoder.decode(value));
80+
}
81+
} catch (error) {
82+
keepReading = false;
83+
} finally {
84+
await reader.releaseLock();
85+
}
86+
}
87+
88+
await port.close();
89+
90+
port = undefined;
91+
reader = undefined;
92+
93+
connectDisconnectButton.innerHTML = "Connect Port";
94+
};
95+
} else {
96+
document.querySelector("#output-area").appendChild(document.createTextNode(
97+
"Oh no! Your browser does not support Web Serial!"
98+
));
99+
}
100+
'''))

0 commit comments

Comments
 (0)