-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathAudioBLE.cpp
More file actions
99 lines (77 loc) · 2.54 KB
/
Copy pathAudioBLE.cpp
File metadata and controls
99 lines (77 loc) · 2.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#pragma once
#include <Arduino.h>
#include "AudioBLE.hpp"
void AudioBLE::begin() {
const char* SERVICE_UUID = "beb5483e-36e1-4688-b7f5-ea07361b26a8";
const char* CHARACTERISTIC_UUID = "4fafc201-1fb5-459e-8fcc-c5c9c331914b";
BLEDevice::init("ESP32-ADPCM");
server = BLEDevice::createServer();
// Prevent hidden watchdog disconnects
class ServerCallbacks : public BLEServerCallbacks {
void onConnect(BLEServer* s) override {
Serial.println("BLE: Client connected.");
}
void onDisconnect(BLEServer* s) override {
Serial.println("BLE: Client disconnected. Restarting advertising.");
BLEDevice::startAdvertising();
}
};
server->setCallbacks(new ServerCallbacks());
BLEService* svc = server->createService(SERVICE_UUID);
m_char = svc->createCharacteristic(
CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE | BLECharacteristic::PROPERTY_NOTIFY);
// Optional: ensure characteristic buffer is large enough
m_char->setValue((uint8_t*)"init", 4);
svc->start();
// Start advertising AFTER service is up
BLEAdvertising* adv = BLEDevice::getAdvertising();
adv->addServiceUUID(SERVICE_UUID);
adv->setScanResponse(true);
// Fixes iPhone “connect then drop” bug
adv->setMinPreferred(0x06);
adv->setMinPreferred(0x12);
// Delay avoids ESP32 display driver collision with BT stack
delay(200);
BLEDevice::startAdvertising();
Serial.println("--- BLEAudio service started ---");
}
void AudioBLE::start() {
m_running = true;
//m_osc->setEnabled(true);
Serial.println("--- BLEServer started correctly ---");
}
void AudioBLE::stop() {
m_running = false;
//m_osc->setEnabled(false);
Serial.println("--- BLEServer stopped correctly ---");
}
void AudioBLE::update() {
if (!m_running || !m_char) return;
static uint32_t last = 0;
uint32_t now = millis();
if (now - last < 20) return;
last = now;
// 160 PCM samples @ 8kHz for 20ms audio frame
constexpr int N = RAW_SAMPLES;
static int16_t pcm[N];
static uint8_t out[N / 2];
// Generate PCM block
for (int i = 0; i < N; i++) {
float s = m_osc->nextSample();
s = constrain(s, -1.0f, 1.0f);
pcm[i] = (int16_t)(s * 32767);
}
// ADPCM encode -> out[]
uint8_t* p = out;
for (int i = 0; i < N; i += 2) {
uint8_t hi = adpcm_encode_sample(pcm[i], m_state);
uint8_t lo = adpcm_encode_sample(pcm[i + 1], m_state);
*p++ = (hi << 4) | lo;
}
// Send BLE notification (safe)
m_char->setValue(out, N / 2);
if (clientSubscribed(m_char) > 0) {
m_char->notify();
}
}