272 lines
6.3 KiB
Markdown
272 lines
6.3 KiB
Markdown
# 信号处理JNI封装使用说明
|
||
|
||
## 概述
|
||
|
||
本项目已将C++信号处理功能封装成JNI接口,可以在Android应用中直接调用。主要功能包括:
|
||
|
||
- 各种数字滤波器(带通、低通、高通、陷波)
|
||
- 信号质量评估
|
||
- ECG信号质量指数计算
|
||
- 信号特征提取
|
||
- 信号预处理(归一化、去直流等)
|
||
- 实时信号处理
|
||
|
||
## 文件结构
|
||
|
||
```
|
||
app/src/main/
|
||
├── cpp/
|
||
│ ├── include/cpp/
|
||
│ │ └── signal_processor.h # C++头文件
|
||
│ ├── src/
|
||
│ │ └── signal_processor.cpp # C++实现文件(需要修复乱码)
|
||
│ ├── jni/
|
||
│ │ └── jni_bridge.cpp # 统一的JNI桥接文件(包含所有JNI函数)
|
||
│ └── CMakeLists.txt # 构建配置
|
||
└── java/
|
||
└── com/example/cmake_project_test/
|
||
├── SignalProcessorJNI.kt # Java JNI接口类
|
||
└── SignalProcessorExample.kt # 使用示例类
|
||
```
|
||
|
||
## 使用方法
|
||
|
||
### 1. 基本使用
|
||
|
||
```kotlin
|
||
// 创建信号处理器实例
|
||
val signalProcessor = SignalProcessorJNI()
|
||
if (signalProcessor.createProcessor()) {
|
||
// 使用各种信号处理功能
|
||
val filteredSignal = signalProcessor.bandpassFilter(
|
||
inputSignal,
|
||
sampleRate = 1000.0,
|
||
lowFreq = 40.0,
|
||
highFreq = 60.0
|
||
)
|
||
|
||
// 清理资源
|
||
signalProcessor.destroyProcessor()
|
||
}
|
||
```
|
||
|
||
### 2. 主要功能
|
||
|
||
#### 数字滤波
|
||
|
||
```kotlin
|
||
// 带通滤波
|
||
val bandpassResult = signalProcessor.bandpassFilter(
|
||
signal, sampleRate, lowFreq, highFreq
|
||
)
|
||
|
||
// 低通滤波
|
||
val lowpassResult = signalProcessor.lowpassFilter(
|
||
signal, sampleRate, cutoffFreq
|
||
)
|
||
|
||
// 高通滤波
|
||
val highpassResult = signalProcessor.highpassFilter(
|
||
signal, sampleRate, cutoffFreq
|
||
)
|
||
|
||
// 陷波滤波(去除工频干扰)
|
||
val notchResult = signalProcessor.notchFilter(
|
||
signal, sampleRate, notchFreq, qFactor
|
||
)
|
||
```
|
||
|
||
#### 信号质量评估
|
||
|
||
```kotlin
|
||
// 计算信号质量指数
|
||
val quality = signalProcessor.calculateSignalQuality(signal)
|
||
|
||
// 计算ECG信号质量指数
|
||
val ecgSQI = signalProcessor.calculateECGSQI(ecgSignal, sampleRate)
|
||
|
||
// 计算两个信号的相关性
|
||
val correlation = signalProcessor.calculateCorrelation(signal1, signal2)
|
||
```
|
||
|
||
#### 信号预处理
|
||
|
||
```kotlin
|
||
// 归一化信号幅度
|
||
signalProcessor.normalizeAmplitude(signal)
|
||
|
||
// 提取信号特征
|
||
val features = signalProcessor.extractFeatures(signal, sampleRate)
|
||
|
||
// 重置滤波器状态
|
||
signalProcessor.resetFilters()
|
||
```
|
||
|
||
#### 实时处理
|
||
|
||
```kotlin
|
||
// 实时处理数据块
|
||
val processedChunk = signalProcessor.processRealtimeChunk(
|
||
chunk, sampleRate
|
||
)
|
||
```
|
||
|
||
### 3. 完整示例
|
||
|
||
参考 `SignalProcessorExample.kt` 文件,其中包含了所有功能的演示代码:
|
||
|
||
```kotlin
|
||
val example = SignalProcessorExample()
|
||
|
||
// 运行所有演示
|
||
example.runAllDemonstrations()
|
||
|
||
// 清理资源
|
||
example.cleanup()
|
||
```
|
||
|
||
## 数据格式
|
||
|
||
### 输入数据
|
||
|
||
- 所有信号数据使用 `FloatArray` 格式
|
||
- 采样率使用 `Double` 类型
|
||
- 频率参数使用 `Double` 类型
|
||
|
||
### 输出数据
|
||
|
||
- 滤波结果返回 `FloatArray?`(可能为null表示处理失败)
|
||
- 质量指数返回 `Float` 类型(0.0-1.0)
|
||
- 相关性返回 `Float` 类型(-1.0到1.0)
|
||
|
||
### 内部转换
|
||
|
||
- Java端使用 `ByteBuffer` 进行 `FloatArray` 和 `ByteArray` 的转换
|
||
- C++端使用 `std::vector<float>` 处理数据
|
||
- 字节序使用小端序(Little Endian)
|
||
|
||
## 注意事项
|
||
|
||
### 1. 资源管理
|
||
|
||
```kotlin
|
||
// 必须在使用前创建处理器
|
||
if (!signalProcessor.createProcessor()) {
|
||
// 处理创建失败的情况
|
||
return
|
||
}
|
||
|
||
// 使用完毕后必须销毁处理器
|
||
signalProcessor.destroyProcessor()
|
||
```
|
||
|
||
### 2. 错误处理
|
||
|
||
```kotlin
|
||
val result = signalProcessor.bandpassFilter(signal, sampleRate, lowFreq, highFreq)
|
||
if (result != null) {
|
||
// 处理成功
|
||
processResult(result)
|
||
} else {
|
||
// 处理失败
|
||
Log.e("SignalProcessor", "滤波处理失败")
|
||
}
|
||
```
|
||
|
||
### 3. 性能考虑
|
||
|
||
- 滤波器初始化有一定开销,建议复用处理器实例
|
||
- 大数据量处理时考虑分块处理
|
||
- 实时处理时注意内存分配
|
||
|
||
### 4. 线程安全
|
||
|
||
- JNI函数不是线程安全的
|
||
- 多线程使用时需要适当的同步机制
|
||
- 建议在主线程或专用工作线程中使用
|
||
|
||
## 构建配置
|
||
|
||
### CMakeLists.txt
|
||
|
||
确保在 `CMakeLists.txt` 中包含了信号处理库:
|
||
|
||
```cmake
|
||
# Signal processor static library
|
||
add_library(signal_processor STATIC
|
||
src/signal_processor.cpp)
|
||
|
||
target_include_directories(signal_processor PUBLIC
|
||
${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||
|
||
# 链接到主库
|
||
target_link_libraries(${CMAKE_PROJECT_NAME}
|
||
core_math
|
||
data_parser
|
||
signal_processor
|
||
android
|
||
log)
|
||
```
|
||
|
||
**注意**:信号处理的JNI函数现在已整合到 `jni_bridge.cpp` 中,不再需要单独的 `signal_processor_jni.cpp` 文件。
|
||
|
||
### 库加载
|
||
|
||
在Java代码中确保正确加载原生库:
|
||
|
||
```kotlin
|
||
companion object {
|
||
init {
|
||
System.loadLibrary("cmake_project_test")
|
||
}
|
||
}
|
||
```
|
||
|
||
## 故障排除
|
||
|
||
### 1. 编译错误
|
||
|
||
- 检查 `CMakeLists.txt` 配置
|
||
- 确保所有源文件路径正确
|
||
- 检查头文件包含路径
|
||
|
||
### 2. 运行时错误
|
||
|
||
- 检查Logcat中的错误信息
|
||
- 确保处理器已正确创建
|
||
- 检查输入数据格式和大小
|
||
|
||
### 3. 性能问题
|
||
|
||
- 使用Android Profiler分析性能瓶颈
|
||
- 考虑减少数据转换开销
|
||
- 优化滤波器参数
|
||
|
||
## 扩展功能
|
||
|
||
### 1. 添加新的滤波器
|
||
|
||
1. 在 `signal_processor.h` 中声明新方法
|
||
2. 在 `signal_processor.cpp` 中实现
|
||
3. 在 `signal_processor_jni.cpp` 中添加JNI封装
|
||
4. 在 `SignalProcessorJNI.kt` 中添加Java接口
|
||
|
||
### 2. 自定义信号处理
|
||
|
||
可以基于现有的JNI接口构建更高级的信号处理功能:
|
||
|
||
```kotlin
|
||
class AdvancedSignalProcessor(private val jni: SignalProcessorJNI) {
|
||
fun adaptiveFilter(signal: FloatArray, sampleRate: Double): FloatArray? {
|
||
// 实现自适应滤波算法
|
||
// 使用JNI接口调用底层功能
|
||
}
|
||
}
|
||
```
|
||
|
||
## 总结
|
||
|
||
通过JNI封装,您现在可以在Android应用中直接使用C++的高性能信号处理功能。这种架构既保持了C++的性能优势,又提供了Java/Kotlin的易用性。
|
||
|
||
建议在使用前先运行示例代码,熟悉各种功能的使用方法,然后根据具体需求进行定制化开发。
|