diff --git a/.idea/deploymentTargetSelector.xml b/.idea/deploymentTargetSelector.xml
index b268ef3..53f1e2c 100644
--- a/.idea/deploymentTargetSelector.xml
+++ b/.idea/deploymentTargetSelector.xml
@@ -4,6 +4,14 @@
+
+
+
+
+
+
+
+
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..94a25f7
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/JNI_FIX_SUMMARY.md b/JNI_FIX_SUMMARY.md
new file mode 100644
index 0000000..d99a981
--- /dev/null
+++ b/JNI_FIX_SUMMARY.md
@@ -0,0 +1,141 @@
+# JNI函数名不匹配问题修复说明
+
+## 问题描述
+
+在代码重构过程中,将原生方法从`MainActivity`移动到`DataManager`类后,出现了以下错误:
+
+```
+Cannot resolve corresponding JNI function Java_com_example_cmake_1project_1test_DataManager_createStreamParser
+```
+
+## 问题原因
+
+### JNI函数命名规则
+
+JNI函数名遵循以下格式:
+```
+Java_{包名}_{类名}_{方法名}
+```
+
+其中:
+- 包名中的点(.)用下划线(_)替换
+- 类名中的下划线用`_1`替换
+
+### 具体变化
+
+**重构前的JNI函数名**(在MainActivity中):
+```
+Java_com_example_cmake_1project_1test_MainActivity_createStreamParser
+Java_com_example_cmake_1project_1test_MainActivity_destroyStreamParser
+Java_com_example_cmake_1project_1test_MainActivity_streamParserAppend
+Java_com_example_cmake_1project_1test_MainActivity_streamParserDrainPackets
+```
+
+**重构后的JNI函数名**(在DataManager中):
+```
+Java_com_example_cmake_1project_1test_DataManager_createStreamParser
+Java_com_example_cmake_1project_1test_DataManager_destroyStreamParser
+Java_com_example_cmake_1project_1test_DataManager_streamParserAppend
+Java_com_example_cmake_1project_1test_DataManager_streamParserDrainPackets
+```
+
+## 解决方案
+
+### 方案1:回调接口模式(已实现)
+
+通过创建回调接口,让`DataManager`通过`MainActivity`来调用原生方法,保持原有的JNI函数名。
+
+#### 实现步骤
+
+1. **创建回调接口**
+```kotlin
+interface NativeMethodCallback {
+ fun createStreamParser(): Long
+ fun destroyStreamParser(handle: Long)
+ fun streamParserAppend(handle: Long, chunk: ByteArray)
+ fun streamParserDrainPackets(handle: Long): List?
+}
+```
+
+2. **修改DataManager构造函数**
+```kotlin
+class DataManager(private val nativeCallback: NativeMethodCallback)
+```
+
+3. **MainActivity实现接口**
+```kotlin
+class MainActivity : AppCompatActivity(), DataManager.NativeMethodCallback
+```
+
+4. **保持原生方法在MainActivity中**
+```kotlin
+// 原生方法声明 - 保持原来的JNI函数名
+external fun createStreamParser(): Long
+external fun destroyStreamParser(handle: Long)
+external fun streamParserAppend(handle: Long, chunk: ByteArray)
+external fun streamParserDrainPackets(handle: Long): List?
+```
+
+#### 优势
+- 保持原有的JNI函数名,无需修改C++代码
+- 维持了代码重构的架构优势
+- 清晰的职责分离
+
+#### 劣势
+- 增加了接口依赖
+- 稍微增加了代码复杂度
+
+### 方案2:修改C++代码中的JNI函数名
+
+如果您有权限修改C++代码,可以将C++中的JNI函数名改为新的名称。
+
+#### 需要修改的C++函数名
+```cpp
+// 原来的函数名
+JNIEXPORT jlong JNICALL Java_com_example_cmake_1project_1test_MainActivity_createStreamParser
+
+// 改为
+JNIEXPORT jlong JNICALL Java_com_example_cmake_1project_1test_DataManager_createStreamParser
+```
+
+#### 优势
+- 完全符合重构后的架构
+- 无需额外的接口层
+
+#### 劣势
+- 需要修改C++代码
+- 可能影响其他依赖项目
+
+## 推荐方案
+
+**推荐使用方案1(回调接口模式)**,原因如下:
+
+1. **无需修改C++代码**:保持现有C++代码的稳定性
+2. **维持重构优势**:仍然保持了代码的职责分离
+3. **向后兼容**:如果将来需要,可以轻松切换到方案2
+4. **风险较低**:不会引入新的编译或链接问题
+
+## 修复后的架构
+
+```
+MainActivity (实现NativeMethodCallback)
+ ↓
+DataManager (通过回调调用原生方法)
+ ↓
+原生C++库 (保持原有JNI函数名)
+```
+
+## 注意事项
+
+1. **JNI函数名一致性**:确保Kotlin中的`external`方法名与C++中的JNI函数名完全匹配
+2. **库加载**:确保在`MainActivity`的`companion object`中正确加载原生库
+3. **接口实现**:MainActivity必须实现`NativeMethodCallback`接口的所有方法
+4. **依赖注入**:DataManager的构造函数现在需要传入回调接口实例
+
+## 验证修复
+
+修复完成后,您应该能够:
+1. 成功编译项目
+2. 不再看到JNI函数名不匹配的错误
+3. 保持原有的功能正常运行
+4. 享受重构后的代码结构优势
diff --git a/README_REFACTOR.md b/README_REFACTOR.md
new file mode 100644
index 0000000..e5d7da7
--- /dev/null
+++ b/README_REFACTOR.md
@@ -0,0 +1,136 @@
+# 代码重构说明
+
+## 重构目标
+将原本堆在一个MainActivity.kt文件中的所有逻辑分解为多个职责明确的Kotlin文件,提高代码的可读性和可维护性。
+
+## 重构后的文件结构
+
+### 1. **MainActivity.kt** - 主界面控制器
+**职责**: 主界面逻辑和生命周期管理
+- 初始化各个管理器
+- 处理按钮点击事件
+- 管理Activity生命周期
+- 协调各个管理器之间的交互
+
+**主要方法**:
+- `onCreate()`: 初始化UI和管理器
+- `onBleNotify()`: 蓝牙数据通知处理
+- `resetData()`: 重置数据
+- `reloadData()`: 重新加载数据
+
+### 2. **Constants.kt** - 常量定义
+**职责**: 集中管理应用中的所有常量
+- UI更新间隔
+- 数据分块大小
+- 缓冲区管理阈值
+- 显示限制参数
+
+**主要常量**:
+- `UPDATE_INTERVAL`: UI更新间隔(500ms)
+- `CHUNK_SIZE`: 数据分块大小(64字节)
+- `BUFFER_CLEANUP_THRESHOLD`: 缓冲区清理阈值(50)
+- `BUFFER_KEEP_COUNT`: 缓冲区保留数量(30)
+
+### 3. **DeviceTypeHelper.kt** - 设备类型工具
+**职责**: 设备类型相关的工具方法
+- 设备类型名称映射
+- 通道数据详情构建
+
+**主要方法**:
+- `getDeviceName()`: 根据数据类型获取设备名称
+- `buildChannelDetails()`: 构建通道数据详情字符串
+
+### 4. **DataManager.kt** - 数据管理器
+**职责**: 数据解析、缓冲管理和原生方法调用
+- 管理流式解析器
+- 处理数据块
+- 管理数据缓冲区
+- 调用原生C++方法
+
+**主要方法**:
+- `ensureParser()`: 确保解析器已创建
+- `onBleNotify()`: 处理蓝牙通知数据块
+- `processFileData()`: 处理文件数据
+- `cleanupBuffer()`: 智能清理缓冲区
+- `resetData()`: 重置所有数据
+
+**原生方法**:
+- `createStreamParser()`: 创建流式解析器
+- `streamParserAppend()`: 向解析器追加数据
+- `streamParserDrainPackets()`: 从解析器拉取数据包
+- `destroyStreamParser()`: 销毁解析器
+
+### 5. **UiManager.kt** - UI管理器
+**职责**: UI更新、统计信息构建和显示逻辑
+- 管理UI更新调度
+- 构建统计信息
+- 构建显示内容
+- 触发UI更新
+
+**主要方法**:
+- `scheduleUiUpdate()`: 计划UI更新,避免频繁刷新
+- `buildStatisticsString()`: 构建统计信息字符串
+- `buildDisplayContent()`: 构建完整的显示内容
+- `updateDisplay()`: 更新UI显示内容
+
+### 6. **FileHelper.kt** - 文件帮助类
+**职责**: 文件读取操作
+- 从assets文件夹读取文件
+
+**主要方法**:
+- `readAssetFile()`: 读取assets文件到字节数组
+
+## 重构优势
+
+### 1. **职责分离**
+- 每个类都有明确的单一职责
+- 降低了类之间的耦合度
+- 提高了代码的可测试性
+
+### 2. **代码复用**
+- 工具方法可以在多个地方复用
+- 减少了重复代码
+- 提高了开发效率
+
+### 3. **维护性提升**
+- 修改某个功能只需要修改对应的类
+- 代码结构更清晰,易于理解
+- 降低了修改的风险
+
+### 4. **可扩展性**
+- 新增功能可以创建新的类
+- 现有类可以独立扩展
+- 支持团队协作开发
+
+## 数据流向
+
+```
+MainActivity → DataManager → 原生解析器
+ ↓
+UiManager ← DataManager ← 数据缓冲区
+ ↓
+ UI更新
+```
+
+## 使用说明
+
+1. **MainActivity**: 作为入口点,协调各个管理器
+2. **DataManager**: 处理所有数据相关的操作
+3. **UiManager**: 负责所有UI相关的更新
+4. **DeviceTypeHelper**: 提供设备类型相关的工具方法
+5. **Constants**: 集中管理所有常量
+6. **FileHelper**: 处理文件读取操作
+
+## 注意事项
+
+1. **原生方法**: 所有原生C++方法现在都在DataManager中声明
+2. **依赖关系**: 各个类之间有明确的依赖关系,避免循环依赖
+3. **线程安全**: UI更新始终在主线程进行,数据操作在后台线程进行
+4. **错误处理**: 每个类都有适当的错误处理和日志记录
+
+## 后续优化建议
+
+1. **依赖注入**: 可以考虑使用Dagger或Koin进行依赖注入
+2. **响应式编程**: 可以考虑使用RxJava或Flow进行数据流处理
+3. **单元测试**: 重构后的代码更容易进行单元测试
+4. **文档完善**: 可以添加更详细的API文档和示例代码
diff --git a/SIGNAL_PROCESSOR_README.md b/SIGNAL_PROCESSOR_README.md
new file mode 100644
index 0000000..9732d20
--- /dev/null
+++ b/SIGNAL_PROCESSOR_README.md
@@ -0,0 +1,271 @@
+# 信号处理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` 处理数据
+- 字节序使用小端序(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的易用性。
+
+建议在使用前先运行示例代码,熟悉各种功能的使用方法,然后根据具体需求进行定制化开发。
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index b2584ef..dd61251 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -32,11 +32,11 @@ android {
}
}
compileOptions {
- sourceCompatibility = JavaVersion.VERSION_11
- targetCompatibility = JavaVersion.VERSION_11
+ sourceCompatibility = JavaVersion.VERSION_17
+ targetCompatibility = JavaVersion.VERSION_17
}
kotlinOptions {
- jvmTarget = "11"
+ jvmTarget = "17"
}
externalNativeBuild {
cmake {
diff --git a/app/src/main/assets/ecg_data_raw.dat b/app/src/main/assets/ecg_data_raw.dat
new file mode 100644
index 0000000..00e9d9f
Binary files /dev/null and b/app/src/main/assets/ecg_data_raw.dat differ
diff --git a/app/src/main/cpp/CMakeLists.txt b/app/src/main/cpp/CMakeLists.txt
index 0989916..e5fa74b 100644
--- a/app/src/main/cpp/CMakeLists.txt
+++ b/app/src/main/cpp/CMakeLists.txt
@@ -39,6 +39,27 @@ add_library(data_parser STATIC
target_include_directories(data_parser PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/include)
+# Signal processor static library
+add_library(signal_processor STATIC
+ src/signal_processor.cpp)
+
+target_include_directories(signal_processor PUBLIC
+ ${CMAKE_CURRENT_SOURCE_DIR}/include)
+
+# Data mapper static library
+add_library(data_mapper STATIC
+ src/data_mapper.cpp)
+
+target_include_directories(data_mapper PUBLIC
+ ${CMAKE_CURRENT_SOURCE_DIR}/include)
+
+# Indicator calculator static library
+add_library(indicator_calculator STATIC
+ src/indicator_cal.cpp)
+
+target_include_directories(indicator_calculator PUBLIC
+ ${CMAKE_CURRENT_SOURCE_DIR}/include)
+
# JNI shared library: expose only JNI bridge, link against core
add_library(${CMAKE_PROJECT_NAME} SHARED
jni/jni_bridge.cpp)
@@ -49,5 +70,8 @@ add_library(${CMAKE_PROJECT_NAME} SHARED
target_link_libraries(${CMAKE_PROJECT_NAME}
core_math
data_parser
+ signal_processor
+ data_mapper
+ indicator_calculator
android
log)
\ No newline at end of file
diff --git a/app/src/main/cpp/include/cpp/data_mapper.h b/app/src/main/cpp/include/cpp/data_mapper.h
new file mode 100644
index 0000000..3af87a9
--- /dev/null
+++ b/app/src/main/cpp/include/cpp/data_mapper.h
@@ -0,0 +1,58 @@
+#ifndef _DATA_MAPPER_H
+#define _DATA_MAPPER_H
+
+#include "cpp/data_praser.h"
+#include
+#include
+#include
+#include
+#include
+#include