Skip to content

Commit e9c2871

Browse files
committed
codal_app: Add microphone recording interface.
Signed-off-by: Damien George <damien@micropython.org>
1 parent d72c0f8 commit e9c2871

File tree

2 files changed

+92
-0
lines changed

2 files changed

+92
-0
lines changed

src/codal_app/microbithal.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,9 @@ int microbit_hal_compass_get_heading(void);
156156
void microbit_hal_microphone_init(void);
157157
void microbit_hal_microphone_set_threshold(int kind, int value);
158158
int microbit_hal_microphone_get_level(void);
159+
void microbit_hal_microphone_start_recording(uint8_t *buf, size_t len, int rate);
160+
bool microbit_hal_microphone_is_recording(void);
161+
void microbit_hal_microphone_stop_recording(void);
159162

160163
const uint8_t *microbit_hal_get_font_data(char c);
161164

src/codal_app/microbithal_microphone.cpp

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,63 @@
2828
#include "microbithal.h"
2929
#include "MicroBitDevice.h"
3030

31+
#define MIN(a, b) ((a) < (b) ? (a) : (b))
32+
3133
extern "C" void microbit_hal_level_detector_callback(int);
3234

3335
static void level_detector_event_handler(Event evt) {
3436
microbit_hal_level_detector_callback(evt.value);
3537
}
3638

39+
class MyStreamRecording : public DataSink
40+
{
41+
public:
42+
DataSource &upStream;
43+
44+
public:
45+
uint8_t *dest;
46+
size_t dest_pos;
47+
size_t dest_max;
48+
bool request_stop;
49+
50+
MyStreamRecording(DataSource &source);
51+
virtual ~MyStreamRecording();
52+
53+
virtual int pullRequest();
54+
};
55+
56+
MyStreamRecording::MyStreamRecording( DataSource &source ) : upStream( source )
57+
{
58+
}
59+
60+
MyStreamRecording::~MyStreamRecording()
61+
{
62+
}
63+
64+
int MyStreamRecording::pullRequest()
65+
{
66+
ManagedBuffer data = this->upStream.pull();
67+
68+
size_t n = MIN((size_t)data.length(), this->dest_max - this->dest_pos);
69+
if (n == 0 || this->request_stop) {
70+
this->upStream.disconnect();
71+
this->request_stop = false;
72+
} else {
73+
// Copy and convert signed 8-bit to unsigned 8-bit data.
74+
const uint8_t *src = data.getBytes();
75+
uint8_t *dest = this->dest + this->dest_pos;
76+
for (size_t i = 0; i < n; ++i) {
77+
*dest++ = *src++ + 128;
78+
}
79+
this->dest_pos += n;
80+
}
81+
82+
return DEVICE_OK;
83+
}
84+
85+
static MyStreamRecording *recording = NULL;
86+
static SplitterChannel *splitterChannel = NULL;
87+
3788
extern "C" {
3889

3990
static bool microphone_init_done = false;
@@ -59,4 +110,42 @@ int microbit_hal_microphone_get_level(void) {
59110
return value;
60111
}
61112

113+
void microbit_hal_microphone_start_recording(uint8_t *buf, size_t len, int rate) {
114+
if (splitterChannel == NULL) {
115+
splitterChannel = uBit.audio.splitter->createChannel();
116+
splitterChannel->setFormat(DATASTREAM_FORMAT_8BIT_UNSIGNED);
117+
// Increase sample period to 64us, so we can get our desired rate.
118+
splitterChannel->requestSampleRate(1000000 / 64);
119+
}
120+
splitterChannel->requestSampleRate(rate);
121+
122+
if (recording == NULL) {
123+
recording = new MyStreamRecording(*splitterChannel);
124+
} else {
125+
if (microbit_hal_microphone_is_recording()) {
126+
microbit_hal_microphone_stop_recording();
127+
while (microbit_hal_microphone_is_recording()) {
128+
microbit_hal_idle();
129+
}
130+
}
131+
}
132+
133+
recording->dest = buf;
134+
recording->dest_pos = 0;
135+
recording->dest_max = len;
136+
recording->request_stop = false;
137+
138+
splitterChannel->connect(*recording);
139+
}
140+
141+
bool microbit_hal_microphone_is_recording(void) {
142+
return recording != NULL && splitterChannel->isConnected();
143+
}
144+
145+
void microbit_hal_microphone_stop_recording(void) {
146+
if (recording != NULL) {
147+
recording->request_stop = true;
148+
}
149+
}
150+
62151
}

0 commit comments

Comments
 (0)