|
| 1 | +# Custom GATT Audio Implementation for Mentra Live |
| 2 | + |
| 3 | +## Overview |
| 4 | + |
| 5 | +This document outlines the implementation of custom LC3 GATT audio for Mentra Live smart glasses, providing an alternative to the standard HFP (Hands-Free Profile) audio system. |
| 6 | + |
| 7 | +## Why Custom GATT Audio? |
| 8 | + |
| 9 | +### Current HFP Limitations |
| 10 | + |
| 11 | +The existing HFP implementation has several significant drawbacks: |
| 12 | + |
| 13 | +1. **Audio System Hijacking**: HFP takes control of the entire phone's audio system |
| 14 | +2. **Concurrent Audio Conflicts**: Cannot play audio from multiple apps simultaneously |
| 15 | + - Example: Playing music while using MentraOS to play audio (ex: text-to-speech) causes one to stop the other |
| 16 | + - Example: Using the microphone in another app prevents MentraOS from using the microphone |
| 17 | + - Standard Android/iOS behavior prevents multiple audio streams |
| 18 | +3. **User Experience Impact**: Forces users to choose between MentraOS audio and other apps |
| 19 | + |
| 20 | +### Custom GATT Audio Benefits |
| 21 | + |
| 22 | +1. **Non-Disruptive**: Android/iOS doesn't recognize custom GATT audio as a system audio device |
| 23 | +2. **Concurrent Audio Support**: Users can play music while MentraOS audio plays through glasses. Users can use the microphone in other apps while MentraOS uses the microphone from the glasses. |
| 24 | +3. **Flexible Control**: App-level control over audio routing and processing |
| 25 | +4. **Better User Experience**: No conflicts with other audio apps |
| 26 | + |
| 27 | +### Custom LC3 GATT vs Standard LE Audio |
| 28 | + |
| 29 | +**Important Distinction**: This implementation uses only the LC3 codec from the LE Audio specification, NOT the full LE Audio standard. |
| 30 | + |
| 31 | +#### Standard LE Audio (NOT what we want) |
| 32 | +- Full Bluetooth LE Audio specification implementation |
| 33 | +- Uses standardized audio profiles and services |
| 34 | +- Phone OS recognizes it as a standard Bluetooth audio device |
| 35 | +- **Same problems as HFP**: Hijacks phone's audio system |
| 36 | +- Prevents concurrent audio from other apps |
| 37 | +- Complex specification with features we don't need (audio sharing, broadcast, etc.) |
| 38 | + |
| 39 | +#### Custom LC3 over GATT (What we want) |
| 40 | +- Uses only the LC3 codec (compression algorithm) from LE Audio |
| 41 | +- Streams raw LC3 data through custom GATT characteristics |
| 42 | +- No standard Bluetooth audio profiles involved |
| 43 | +- **Phone OS doesn't recognize it as an audio device** |
| 44 | +- Completely bypasses phone's audio system |
| 45 | +- Allows concurrent audio from other apps |
| 46 | + |
| 47 | +#### Technical Flow |
| 48 | +1. **App Audio** → LC3 Encode → Custom GATT Message → **Glasses** |
| 49 | +2. **Glasses Mic** → LC3 Encode → Custom GATT Message → **App** |
| 50 | + |
| 51 | +This approach gives us the benefits of LC3 compression without the limitations of standard Bluetooth audio profiles. |
| 52 | + |
| 53 | +#### Coexistence with Standard Audio |
| 54 | +- **Keep existing HFP/LE Audio**: Maintain current standard audio implementation |
| 55 | +- **Runtime toggling**: Switch between standard and custom modes as needed |
| 56 | +- **Use case flexibility**: Standard audio for system integration, custom GATT for concurrent audio scenarios |
| 57 | + |
| 58 | +## Implementation Requirements |
| 59 | + |
| 60 | +### Toggle System |
| 61 | + |
| 62 | +The implementation should provide runtime toggles for different audio modes: |
| 63 | + |
| 64 | +```json |
| 65 | +{ |
| 66 | + "C": "enable_custom_audio_rx", |
| 67 | + "B": true/false |
| 68 | +} |
| 69 | +``` |
| 70 | + |
| 71 | +```json |
| 72 | +{ |
| 73 | + "C": "enable_custom_audio_tx", |
| 74 | + "B": true/false |
| 75 | +} |
| 76 | +``` |
| 77 | + |
| 78 | +```json |
| 79 | +{ |
| 80 | + "C": "enable_hfp_audio_server", |
| 81 | + "B": true/false |
| 82 | +} |
| 83 | +``` |
| 84 | + |
| 85 | +### Audio Direction Support |
| 86 | + |
| 87 | +- **RX (Receive)**: Phone → Glasses audio streaming |
| 88 | +- **TX (Transmit)**: Glasses → Phone microphone audio |
| 89 | + |
| 90 | +### Compatibility |
| 91 | + |
| 92 | +- **Maintain HFP**: Keep existing HFP system for compatibility |
| 93 | +- **Runtime Switching**: Allow toggling between HFP and custom GATT |
| 94 | + |
| 95 | +## Technical Implementation Example |
| 96 | + |
| 97 | +> **Note**: The following technical details are from the Even Realities G1 smart glasses implementation found in `EvenRealitiesG1SGC.java`, which serves as a reference example for custom LC3 GATT audio. This is just an example of how it's done with the Even Realities G1 glasses. |
| 98 | +
|
| 99 | +### GATT Service Structure |
| 100 | + |
| 101 | +``` |
| 102 | +Service UUID: 6E400001-B5A3-F393-E0A9-E50E24DCCA9E (UART Service) |
| 103 | +├── TX Characteristic: 6E400002-B5A3-F393-E0A9-E50E24DCCA9E (Phone → Glasses) |
| 104 | +├── RX Characteristic: 6E400003-B5A3-F393-E0A9-E50E24DCCA9E (Glasses → Phone) |
| 105 | +└── Descriptor: 00002902-0000-1000-8000-00805f9b34fb (Notifications) |
| 106 | +``` |
| 107 | + |
| 108 | +### LC3 Audio Packet Format |
| 109 | + |
| 110 | +``` |
| 111 | +Packet Structure (202 bytes total): |
| 112 | +├── Byte 0: 0xF1 (Audio data identifier) |
| 113 | +├── Byte 1: Sequence number (0-255) |
| 114 | +└── Bytes 2-201: LC3 encoded audio data (200 bytes) |
| 115 | +``` |
| 116 | + |
| 117 | +### Control Commands |
| 118 | + |
| 119 | +``` |
| 120 | +Microphone Control: |
| 121 | +├── Enable: 0x0E 0x01 |
| 122 | +├── Disable: 0x0E 0x00 |
| 123 | +└── Heartbeat: Periodic keep-alive commands |
| 124 | +``` |
| 125 | + |
| 126 | +### Audio Processing Flow |
| 127 | + |
| 128 | +1. **Outgoing Audio (Phone → Glasses)**: |
| 129 | + - Package LC3 audio into GATT packets with sequence numbers |
| 130 | + - Send via TX characteristic |
| 131 | + |
| 132 | +2. **Incoming Audio (Glasses → Phone)**: |
| 133 | + - Receive LC3 packets via RX characteristic |
| 134 | + - Validate sequence numbers |
| 135 | + - Decode LC3 to PCM for processing |
| 136 | + |
| 137 | +## Reference Implementation: Even Realities G1 Smart Glasses |
| 138 | + |
| 139 | +### Overview |
| 140 | + |
| 141 | +The Even Realities G1 implementation in `EvenRealitiesG1SGC.java` provides a working example of custom LC3 GATT audio. |
| 142 | + |
| 143 | +### Key Implementation Details |
| 144 | + |
| 145 | +#### Audio Data Detection |
| 146 | +```java |
| 147 | +// Detect audio packets by header byte |
| 148 | +if (data[0] == (byte) 0xF1) { |
| 149 | + byte sequenceNumber = data[1]; |
| 150 | + byte[] lc3Data = Arrays.copyOfRange(data, 2, 202); |
| 151 | + |
| 152 | + // Decode LC3 to PCM |
| 153 | + byte[] pcmData = L3cCpp.decodeLC3(lc3DecoderPtr, lc3Data); |
| 154 | +} |
| 155 | +``` |
0 commit comments