-
Notifications
You must be signed in to change notification settings - Fork 24
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
1ebee8e
commit 318cb25
Showing
14 changed files
with
299 additions
and
63 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,4 @@ | ||
build/ | ||
build/ | ||
edge-impulse-sdk/ | ||
tflite-model/ | ||
model-parameters/ |
Binary file not shown.
Binary file not shown.
This file was deleted.
Oops, something went wrong.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
cmake_minimum_required(VERSION 3.12) | ||
|
||
include(pico_sdk_import.cmake) | ||
|
||
project(pico_daq) | ||
|
||
pico_sdk_init() | ||
|
||
add_executable(pico_daq | ||
pico_daq.cpp | ||
base64.cpp | ||
) | ||
|
||
pico_enable_stdio_usb(pico_daq 1) | ||
pico_enable_stdio_uart(pico_daq 1) | ||
|
||
pico_add_extra_outputs(pico_daq) | ||
|
||
target_link_libraries(pico_daq | ||
pico_stdlib | ||
hardware_adc | ||
hardware_dma | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
# pico-daq | ||
|
||
This program samples from the ADC, converts the sampled values to base64, and then dumps it out over Serial. You can then read in the base 64 values into a program to convert them to whatever you'd like. | ||
|
||
## A note on the sampling | ||
|
||
At 5 kHz w/ 16-bit samples (the default in the program) the Pico cannot write out data as fast as it reads it. Therefore, at the end of each sampling window, the program will pause ADC sampling as it finishes writing out the rest of the samples. This will lead to some jumps in the data. For my purposes of collecting audio for training a ML model this is fine. If this is not ok, try using 8-bit samples or turn down the sample rate until the LED on the Pico starts to flash. | ||
|
||
## Logging Base64 Values | ||
|
||
On macOS and Linux you can use the `screen` tool to save off the base64 values: | ||
|
||
screen -L /dev/tty.usbmodem21301 115200 | ||
|
||
This command opens a serial console for the Pico and then will save the resulting text to the file `screenlog.0`, which you can then convert back to whatever format you'd like. Obviously you'd need to change `/dev/....` to the address of your Pico. | ||
|
||
## Converting to WAV | ||
|
||
I included a sample program to read in the base64 text values and convert it to WAV files that can be played on your computer. See `py/b64_16_to_wav.py`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
/* | ||
base64.cpp and base64.h | ||
Copyright (C) 2004-2008 René Nyffenegger | ||
This source code is provided 'as-is', without any express or implied | ||
warranty. In no event will the author be held liable for any damages | ||
arising from the use of this software. | ||
Permission is granted to anyone to use this software for any purpose, | ||
including commercial applications, and to alter it and redistribute it | ||
freely, subject to the following restrictions: | ||
1. The origin of this source code must not be misrepresented; you must not | ||
claim that you wrote the original source code. If you use this source code | ||
in a product, an acknowledgment in the product documentation would be | ||
appreciated but is not required. | ||
2. Altered source versions must be plainly marked as such, and must not be | ||
misrepresented as being the original source code. | ||
3. This notice may not be removed or altered from any source distribution. | ||
René Nyffenegger [email protected] | ||
*/ | ||
|
||
#include "base64.h" | ||
|
||
static const std::string base64_chars = | ||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" | ||
"abcdefghijklmnopqrstuvwxyz" | ||
"0123456789+/"; | ||
|
||
|
||
static inline bool is_base64(unsigned char c) { | ||
return (isalnum(c) || (c == '+') || (c == '/')); | ||
} | ||
|
||
std::string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_len) { | ||
std::string ret; | ||
int i = 0; | ||
int j = 0; | ||
unsigned char char_array_3[3]; | ||
unsigned char char_array_4[4]; | ||
|
||
while (in_len--) { | ||
char_array_3[i++] = *(bytes_to_encode++); | ||
if (i == 3) { | ||
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; | ||
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); | ||
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); | ||
char_array_4[3] = char_array_3[2] & 0x3f; | ||
|
||
for(i = 0; (i <4) ; i++) | ||
ret += base64_chars[char_array_4[i]]; | ||
i = 0; | ||
} | ||
} | ||
|
||
if (i) | ||
{ | ||
for(j = i; j < 3; j++) | ||
char_array_3[j] = '\0'; | ||
|
||
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; | ||
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); | ||
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); | ||
char_array_4[3] = char_array_3[2] & 0x3f; | ||
|
||
for (j = 0; (j < i + 1); j++) | ||
ret += base64_chars[char_array_4[j]]; | ||
|
||
while((i++ < 3)) | ||
ret += '='; | ||
|
||
} | ||
|
||
return ret; | ||
|
||
} | ||
std::string base64_decode(std::string const& encoded_string) { | ||
int in_len = encoded_string.size(); | ||
int i = 0; | ||
int j = 0; | ||
int in_ = 0; | ||
unsigned char char_array_4[4], char_array_3[3]; | ||
std::string ret; | ||
|
||
while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) { | ||
char_array_4[i++] = encoded_string[in_]; in_++; | ||
if (i ==4) { | ||
for (i = 0; i <4; i++) | ||
char_array_4[i] = base64_chars.find(char_array_4[i]); | ||
|
||
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); | ||
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); | ||
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; | ||
|
||
for (i = 0; (i < 3); i++) | ||
ret += char_array_3[i]; | ||
i = 0; | ||
} | ||
} | ||
|
||
if (i) { | ||
for (j = i; j <4; j++) | ||
char_array_4[j] = 0; | ||
|
||
for (j = 0; j <4; j++) | ||
char_array_4[j] = base64_chars.find(char_array_4[j]); | ||
|
||
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); | ||
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); | ||
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; | ||
|
||
for (j = 0; (j < i - 1); j++) ret += char_array_3[j]; | ||
} | ||
|
||
return ret; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
#include <string> | ||
|
||
std::string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_len); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
// Sample from the ADC continuously at a particular sample rate | ||
// and then outputs base64 bytes via Serial | ||
// much of this code is from pico-examples/adc/dma_capture/dma_capture.c | ||
// the rest is written by Alex Wulff (www.AlexWulff.com) | ||
|
||
#include <stdio.h> | ||
#include <cstring> | ||
#include "pico/stdlib.h" | ||
#include "hardware/adc.h" | ||
#include "hardware/dma.h" | ||
#include "base64.h" | ||
|
||
// set this to determine sample rate | ||
// 0 = 500,000 Hz | ||
// 960 = 50,000 Hz | ||
// 9600 = 5,000 Hz | ||
#define CLOCK_DIV 9600 | ||
|
||
// Channel 0 is GPIO26 | ||
#define CAPTURE_CHANNEL 0 | ||
#define LED_PIN 25 | ||
#define NSAMP 20000 | ||
|
||
uint16_t capture_buf[NSAMP]; | ||
uint16_t sending_buf[NSAMP]; | ||
|
||
int main() { | ||
stdio_init_all(); | ||
|
||
gpio_init(LED_PIN); | ||
gpio_set_dir(LED_PIN, GPIO_OUT); | ||
adc_gpio_init(26 + CAPTURE_CHANNEL); | ||
|
||
adc_init(); | ||
adc_select_input(CAPTURE_CHANNEL); | ||
adc_fifo_setup( | ||
true, // Write each completed conversion to the sample FIFO | ||
true, // Enable DMA data request (DREQ) | ||
1, // DREQ (and IRQ) asserted when at least 1 sample present | ||
false, // We won't see the ERR bit because of 8 bit reads; disable. | ||
false // Don't shift each sample to 8 bits when pushing to FIFO | ||
); | ||
|
||
// set sample rate | ||
adc_set_clkdiv(CLOCK_DIV); | ||
|
||
sleep_ms(1000); | ||
// Set up the DMA to start transferring data as soon as it appears in FIFO | ||
uint dma_chan = dma_claim_unused_channel(true); | ||
dma_channel_config cfg = dma_channel_get_default_config(dma_chan); | ||
|
||
// Reading from constant address, writing to incrementing byte addresses | ||
channel_config_set_transfer_data_size(&cfg, DMA_SIZE_16); | ||
channel_config_set_read_increment(&cfg, false); | ||
channel_config_set_write_increment(&cfg, true); | ||
|
||
// Pace transfers based on availability of ADC samples | ||
channel_config_set_dreq(&cfg, DREQ_ADC); | ||
|
||
while (1) { | ||
adc_fifo_drain(); | ||
adc_run(false); | ||
|
||
dma_channel_configure(dma_chan, &cfg, | ||
capture_buf, // dst | ||
&adc_hw->fifo, // src | ||
NSAMP, // transfer count | ||
true // start immediately | ||
); | ||
|
||
// if the light does not flash, then there is some data loss. | ||
// pico can't print the data out fast enough, so the capturing | ||
// finishes before the data is done printing. This will result | ||
// in the ADC not collecting for portions of the sampling | ||
|
||
// run sampling routine | ||
gpio_put(LED_PIN, 1); | ||
adc_run(true); | ||
|
||
// first transmission will be garbage since we haven't filled the buffer yet | ||
std::string encoded = | ||
base64_encode((unsigned char const *)sending_buf, NSAMP*2); | ||
printf("%s", encoded.c_str()); | ||
|
||
gpio_put(LED_PIN, 0); | ||
|
||
dma_channel_wait_for_finish_blocking(dma_chan); | ||
|
||
|
||
memcpy(sending_buf, capture_buf, NSAMP*2); | ||
} | ||
} |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
from pydub import AudioSegment | ||
import numpy as np | ||
import base64 | ||
|
||
if __name__=="__main__": | ||
infile = "/Users/alex/Desktop/pico/other-3" | ||
outfile = "/Users/alex/Desktop/pico/other.wav" | ||
|
||
f = open(infile, "r") | ||
|
||
byte_data = bytearray() | ||
vals = f.read(6000) | ||
# Reading all at once didn't work for some reason | ||
while vals: | ||
byte_data.extend(base64.b64decode(vals)) | ||
vals = f.read(6000) | ||
f.close() | ||
|
||
# Enforce little endian | ||
dt = np.dtype(np.uint16) | ||
dt = dt.newbyteorder('<') | ||
data = np.frombuffer(byte_data, dtype=dt) | ||
|
||
data = data.astype(np.int32) | ||
data = data-np.mean(data) | ||
data = data.astype(np.int16) | ||
|
||
audio = AudioSegment( | ||
data.tobytes(), | ||
sample_width=2, | ||
frame_rate=5000, | ||
channels=1 | ||
) | ||
|
||
audio.export(outfile, format="wav") |
Submodule pico-light-voice
added at
5a8258
Submodule pico-voice-v1
added at
5a8258