Music Rhythm Feature
Project Overview: This module is applicable to Wi-Fi + BLE protocol RGBIC string light devices, supporting both local music rhythm and cloud music rhythm modes. It can adjust light color and brightness in real-time based on audio signals to achieve synchronization between music and lighting effects.
🖼️ Preview:
The music rhythm feature listens to device microphone or App audio signals, analyzes audio characteristics (such as decibel values, frequencies, etc.) in real-time, and converts audio characteristics into lighting effects. This feature supports multiple music mode selections, adjustable sensitivity, and both random color and preset color modes, providing users with an immersive music lighting experience.
Feature List
- Local Music Rhythm: Captures audio through device microphone for real-time analysis and light control
- APP Music Rhythm: Obtains audio data through APP audio interface to control lighting effects
- Music Mode Selection: Supports multiple built-in music modes (Rock, Jazz, Classical, etc.)
- Sensitivity Adjustment: Adjustable audio sensitivity to control light response level
- Random Color Mode: Randomly selects colors based on audio for dynamic effects
- Preset Color Mode: Uses preset color combinations for fixed color schemes
- Mode Switching: Supports switching between local music and cloud music modes
- State Synchronization: Music rhythm state synchronizes with device state
Module Implementation Details
Implementation Overview
The music rhythm feature uses two different implementation approaches:
- Local Music Rhythm: Uses
dreamlightmic_music_dataDP point, device captures and processes audio through microphone, panel controls music mode and parameters through DP point - APP Music Rhythm: Uses
music_dataDP point, obtains audio data through App's MediaKit audio interface, panel calculates colors in real-time and sends commands
Core design concepts:
- Data Separation: Local and cloud use different DP points and data structures
- Real-time Processing: Cloud mode uses throttling for audio data processing to avoid frequent sending
- State Management: Uses cloud storage to save current music mode and sensitivity settings
- Color Strategy: Supports both random color and preset color strategies
Core Components
src/components/music/index.tsx: Main music rhythm component, responsible for mode switching and overall layoutsrc/components/music/local/index.tsx: Local music rhythm componentsrc/components/music/app/index.tsx: APP music rhythm componentsrc/hooks/useLocalMusicInit.ts: Local music initialization and management Hooksrc/standModel/musicModel/LocalMusic/dpParser/localMusic__dreamlightmic_music_data.ts: Local music DP parsersrc/components/music/app/sdk.ts: APP music audio processing SDKsrc/hooks/useStoreSensitivity.ts: Sensitivity storage management Hooksrc/components/random-colors/index.tsx: Random color selection component
Component Responsibilities:
- Music Component: Acts as a container component, manages music mode switching (local/cloud), coordinates sub-components
- LocalMusic Component: Handles local music mode, displays music list and sensitivity adjustment
- AppMusic Component: Handles cloud music mode, registers audio listeners and color calculation
- useLocalMusicInit Hook: Encapsulates local music initialization, playback, and sensitivity adjustment logic
- Audio SDK: Encapsulates MediaKit audio interface, provides audio data callbacks
Data Flow
sequenceDiagram
participant User as User
participant Music as Music Component
participant Local as Local Music Component
participant App as Cloud Music Component
participant Hook as Init Hook
participant SDK as Audio SDK
participant DP as DP Protocol
participant Device as Device
User->>Music: Select music mode
Music->>Local: Display local music
User->>Local: Select music type
Local->>Hook: Call onPlay
Hook->>DP: Encode dreamlightmic_music_data
DP->>Device: Send DP
Device->>Device: Microphone captures audio
Device->>User: Display lighting effect
User->>Music: Switch to cloud music
Music->>App: Display cloud music
User->>App: Select music type
App->>SDK: Register audio listener
SDK->>SDK: Get audio data
SDK->>App: Callback audio data
App->>App: Calculate color and brightness
App->>DP: Encode music_data
DP->>Device: Send DP
Device->>User: Display lighting effectMermaid Flowcharts
Main Feature Flow:
flowchart TD
A[Enter music rhythm page] --> B{Select music mode}
B -->|Local music| C[Display local music list]
B -->|Cloud music| D[Display cloud music list]
C --> E[User selects music type]
D --> F[User selects music type]
E --> G[Set music parameters]
F --> H[Register audio listener]
G --> I[Encode dreamlightmic_music_data]
H --> J[Get audio data]
J --> K[Calculate color and brightness]
K --> L[Encode music_data]
I --> M[Send DP to device]
L --> M
M --> N[Device executes lighting effect]
N --> O[User observes effect]
O --> P{Continue adjusting?}
P -->|Yes| Q[Adjust sensitivity/color]
P -->|No| R[Maintain current state]
Q --> G
Q --> KData Flow Diagram:
sequenceDiagram
participant User as User Action
participant UI as UI Component
participant Hook as Business Hook
participant Parser as DP Parser
participant Device as Device/Audio
participant Storage as Cloud Storage
User->>UI: Select music mode
UI->>Hook: Initialize music data
Hook->>Storage: Read saved music ID
Storage-->>Hook: Return music ID
Hook->>Parser: Build DP data
Parser->>Device: Send DP command
Note over Device: Local mode: Device processes audio<br/>Cloud mode: App provides audio
Device->>Device: Analyze audio characteristics
Device->>User: Display lighting effect
User->>UI: Adjust sensitivity
UI->>Hook: Update sensitivity
Hook->>Parser: Update DP data
Parser->>Device: Send update
Hook->>Storage: Save sensitivityComponent Interaction Diagram:
graph TB
A[Music Component] -->|Switch mode| B[LocalMusic Component]
A -->|Switch mode| C[AppMusic Component]
A -->|Use| D[RandomColors Component]
B -->|Call| E[useLocalMusicInit]
C -->|Use| F[Audio SDK]
E -->|Use| G[useStoreSensitivity]
E -->|Encode| H[LocalMusicParser]
F -->|Callback| C
C -->|Encode| I[MusicDataParser]
H -->|Send| J[Device]
I -->|Send| J
G -->|Save| K[Cloud Storage]State Transition Diagram:
stateDiagram-v2
[*] --> Initialization: Page load
Initialization --> SelectMode: User action
SelectMode --> LocalMode: Select local
SelectMode --> CloudMode: Select cloud
LocalMode --> SelectMusic: Display list
CloudMode --> SelectMusic: Display list
SelectMusic --> Playing: Start playing
Playing --> AdjustParams: User adjusts
AdjustParams --> Playing: Update params
Playing --> StopPlaying: User stops
StopPlaying --> SelectMode: Reselect
StopPlaying --> [*]: Exit pageKey Code Snippets
Local Music Playback:
Cloud Music Audio Listener:
Audio Data Processing SDK:
Sensitivity Adjustment:
Data Structures
Local Music DP Data Structure:
Cloud Music DP Data Structure:
Audio Data Callback Structure:
Random Color Data Structure:
API Calls
Local Music DP Interface:
- DP Point:
dreamlightmic_music_data - Call Method:
structuredActions.dreamlightmic_music_data.set(data, options) - Data Format: Hexadecimal string encoded by
MicMusicFormater - Call Timing:
- When selecting music mode
- When adjusting sensitivity
- When switching between random/preset colors
- When restoring previous state during initialization
Cloud Music DP Interface:
- DP Point:
music_data - Call Method:
structuredActions.music_data.set(data, options) - Data Format: Protocol-encoded data object
- Call Timing:
- On audio data callback (throttled 300ms)
- When selecting music mode
- When switching between random/preset colors
Audio Interface:
- Interface:
ty.media.getRGBAudioManager() - Methods:
startRGBRecord(): Start audio recordingstopRGBRecord(): Stop audio recordingonAudioRgbChange(callback): Register audio data callbackoffAudioRgbChange(): Unregister audio data callback
- Call Timing:
- Register when entering cloud music mode
- Unregister when leaving cloud music mode
Cloud Storage Interface:
- Storage Keys:
CLOUD_KEY_LOCAL_MUSIC_ID: Local music IDCLOUD_KEY_APP_MUSIC_ID: Cloud music IDCLOUD_RANDOM_COLOR_ID: Random color ID
- Call Method:
useCloudStorageKey(key, options) - Data Format: String (music ID or color ID)
Notes
Implementation Challenges
-
Audio Data Processing Performance:
- Challenge: High frequency of audio data callbacks, frequent calculation and sending may cause performance issues
- Solution: Use throttle to limit processing frequency (300ms), reduce calculation and sending times
-
State Synchronization Issue:
- Challenge: Using closures in audio callbacks, React state may not be the latest value
- Solution: Use
useRefto save latest state, read from ref in callbacks
-
Color Calculation Logic:
- Challenge: Need to dynamically calculate brightness based on decibel values while supporting both random and preset colors
- Solution: Use
calcPositionfunction to calculate decibel to brightness mapping, select color strategy based on mode
-
Mode Switch Cleanup:
- Challenge: Need to cleanup previous listeners and state when switching music modes
- Solution: Call
offMusic2RgbChangewhen component unmounts, cleanup audio listeners and screen-on state
-
Sensitivity Persistence:
- Challenge: Different music modes need separate sensitivity save and restore
- Solution: Use
useStoreSensitivityHook, store sensitivity values with music ID as key
Common Issues
-
Issue: Cloud music mode has no effect
- Cause: Audio interface not initialized or permission not granted
- Solution: Check if
getRGBAudioManageris available, ensure microphone permission is granted
-
Issue: Local music mode device not responding
- Cause: DP data format error or device doesn't support the music mode
- Solution: Check if DP data encoding is correct, confirm device supported music mode list
-
Issue: Color changes not smooth
- Cause: Throttle time set too long or DP sending failed
- Solution: Adjust throttle time (recommended 300ms), check network connection and device status
-
Issue: Sensitivity adjustment not working
- Cause: Sensitivity value not saved correctly or DP sending failed
- Solution: Check if cloud storage is working, confirm DP send success callback
-
Issue: State confusion after mode switch
- Cause: Previous mode state and listeners not properly cleaned up
- Solution: Call cleanup function when switching modes, reset related states
Performance Optimization
-
Throttle Processing:
- Audio data callback uses throttle (300ms), reduces calculation and sending frequency
- Sensitivity adjustment uses throttle (100ms), avoids frequent updates
-
Ref Usage:
- Use
useRefto save latest state, avoid closure issues - Use
useRefto cache audio manager instance, avoid repeated creation
- Use
-
Conditional Rendering:
- Conditionally render corresponding components based on music mode, reduce unnecessary rendering
- Use
useMemoto cache music list data
-
Data Caching:
- Sensitivity data cached to cloud storage, avoid repeated calculation
- Music list data uses
useMemofor caching
-
Screen-on Management:
- Only keep screen on during audio listening, restore when exiting
- Use
setKeepScreenOnto manage screen state
Edge Cases
-
Audio Interface Unavailable:
- Handling: Show error prompt, disable cloud music mode
- Code: Check
getRGBAudioManagerreturn value, provide fallback solution
-
Device Doesn't Support Music Mode:
- Handling: Determine support status based on DP schema, hide unsupported features
- Code: Use
useSupportto check DP support status
-
Audio Data Anomaly:
- Handling: Validate data format, don't process abnormal data
- Code: Add data validation logic in callback
-
Decibel Value Out of Range:
- Handling: Limit decibel value range, use boundary values when out of range
- Code: Use
Math.maxandMath.minto limit range
-
Empty Color List:
- Handling: Use default color or calculate color from audio RGB values
- Code: Check color list length, provide default values
-
Component Unmount Cleanup:
- Handling: Cancel listeners and restore state in
useEffectcleanup function - Code: Return cleanup function, call
offMusic2RgbChange
- Handling: Cancel listeners and restore state in
Dependencies
-
Dependent Modules:
@ray-js/panel-sdk: Provides DP operations and structured data interface@ray-js/ray: Provides screen-on management interfacelodash-es: Provides throttle function- MediaKit: Provides audio interface (TTT capability)
-
Dependent By Modules:
- Home page module: Uses music rhythm component
- Work mode switch: Music mode as one of work modes
-
Dependency Notes:
- MediaKit needs to be enabled in TTT configuration
- Audio permission needs to be granted in App
- DP protocol parser needs to be registered after device initialization
-
Decoupling Suggestions:
- Encapsulate audio processing logic as independent SDK for reuse and testing
- Extract color calculation logic as utility functions for unit testing
- Use TypeScript type definitions to ensure data structure consistency
- Make music mode data configurable for easy extension and maintenance