Skip to content

Conversation

@kgbook
Copy link
Owner

@kgbook kgbook commented May 31, 2024

Summary by CodeRabbit

  • 新功能

    • 添加了多个新C++文件以实现各种功能,包括音频处理、文件读取、词频统计、学生数据管理、二分搜索、银行账户管理、购物车管理、图书馆系统、线程管理、事件处理和配置文件显示。
  • 优化

    • 更新了多个CMakeLists.txt文件以包含新的子目录和可执行文件目标,从而更好地组织和构建项目。
  • 其他

    • .idea目录添加到.gitignore文件中,避免其被版本控制系统跟踪。

@coderabbitai
Copy link

coderabbitai bot commented May 31, 2024

Walkthrough

这次更新主要涉及在多个子目录中添加新的C++源文件和CMakeLists.txt文件。新增的功能包括音频处理、文件读取和分析、学生成绩管理、二分搜索、银行账户管理、购物车管理、图书馆系统、线程管理、epoll事件处理、配置文件读取、以及非线性数据转换等。还对.gitignore文件进行了更新,排除了.idea目录。

Changes

文件路径 变更摘要
.gitignore 添加.idea目录以排除版本控制。
c++/misc/CMakeLists.txt 更新以包含三个新的子目录:ChenPengYuanXuShaoQiuKangDengli
c++/misc/.../CMakeLists.txt 在各子目录中添加CMake项目设置文件。
c++/misc/.../*.cpp 新增多个C++源文件,分别实现音频处理、文件读取与分析、学生成绩管理、二分搜索、银行账户管理、购物车管理、图书馆系统、线程管理、epoll事件处理、配置文件读取、非线性数据转换等功能。

Poem

在代码的世界里,
兔子跳跃如飞,
新增功能多姿多彩,
音频处理,文本分析,
学生成绩,购物车欢喜,
银行账户,图书馆藏,
线程管理,事件处理,
配置读取,数据转换,
代码更新,精彩纷呈。
🐰✨📚💻


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

Share
Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai generate interesting stats about this repository and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (invoked as PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Additionally, you can add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Configration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@kgbook kgbook self-assigned this May 31, 2024
@kgbook
Copy link
Owner Author

kgbook commented May 31, 2024

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented May 31, 2024

Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 0eb5bbf and a69670e.

Files selected for processing (20)
  • .gitignore (1 hunks)
  • c++/misc/CMakeLists.txt (1 hunks)
  • c++/misc/ChenPengYuan/CMakeLists.txt (1 hunks)
  • c++/misc/ChenPengYuan/cpy_0_001.cpp (1 hunks)
  • c++/misc/ChenPengYuan/cpy_1_001.cpp (1 hunks)
  • c++/misc/ChenPengYuan/cpy_1_002.cpp (1 hunks)
  • c++/misc/ChenPengYuan/cpy_1_003.cpp (1 hunks)
  • c++/misc/ChenPengYuan/cpy_1_004.cpp (1 hunks)
  • c++/misc/ChenPengYuan/cpy_1_005.cpp (1 hunks)
  • c++/misc/ChenPengYuan/cpy_1_006.cpp (1 hunks)
  • c++/misc/KangDengli/CMakeLists.txt (1 hunks)
  • c++/misc/KangDengli/KangDengli01.cpp (1 hunks)
  • c++/misc/XuShaoQiu/CMakeLists.txt (1 hunks)
  • c++/misc/XuShaoQiu/XuShaoQiu001.cpp (1 hunks)
  • c++/misc/XuShaoQiu/XuShaoQiu002.cpp (1 hunks)
  • c++/misc/XuShaoQiu/XuShaoQiu003.cpp (1 hunks)
  • c++/misc/XuShaoQiu/XuShaoQiu004.cpp (1 hunks)
  • c++/misc/XuShaoQiu/XuShaoQiu005.cpp (1 hunks)
  • c++/misc/XuShaoQiu/XuShaoQiu006.cpp (1 hunks)
  • c++/misc/XuShaoQiu/XuShaoQiu007.cpp (1 hunks)
Files skipped from review due to trivial changes (8)
  • .gitignore
  • c++/misc/CMakeLists.txt
  • c++/misc/ChenPengYuan/CMakeLists.txt
  • c++/misc/ChenPengYuan/cpy_1_001.cpp
  • c++/misc/ChenPengYuan/cpy_1_003.cpp
  • c++/misc/ChenPengYuan/cpy_1_005.cpp
  • c++/misc/KangDengli/CMakeLists.txt
  • c++/misc/XuShaoQiu/CMakeLists.txt
Additional comments not posted (29)
c++/misc/XuShaoQiu/XuShaoQiu001.cpp (2)

4-9: 打印列表函数实现正确,无需修改。


31-34: 主函数实现正确,调用了listOpt函数并返回0。

c++/misc/XuShaoQiu/XuShaoQiu005.cpp (2)

9-24: 显示配置文件内容的函数实现正确,但建议注意getConfigPath().c_str()可能存在的内存问题。


26-29: 主函数实现正确,调用了showConfigContent函数并返回0。

c++/misc/XuShaoQiu/XuShaoQiu003.cpp (1)

33-37: 主函数实现正确,正确地创建并等待线程结束。

c++/misc/XuShaoQiu/XuShaoQiu007.cpp (1)

5-42: 显示配置文件内容的函数实现正确,正确处理了多行配置和空白字符。但该函数较为复杂,建议在文档中详细说明其行为。

c++/misc/ChenPengYuan/cpy_0_001.cpp (3)

3-9: 音频回调构造函数实现正确,正确地初始化了音频参数和缓冲区。但建议检查malloc的返回值以处理内存分配失败的情况。


11-13: 音频回调析构函数实现正确,正确地释放了分配的内存。


15-34: 处理音频数据的函数实现正确,正确地使用互斥锁确保线程安全,并妥善处理了数据移动。建议添加错误处理逻辑以应对潜在的问题。

c++/misc/ChenPengYuan/cpy_1_002.cpp (2)

4-15: 学生类实现正确,提供了获取学生姓名和成绩的方法。


17-46: 教室类实现正确,提供了添加学生、计算平均分和查找最高分学生的方法。建议添加对除以零的错误处理。

c++/misc/ChenPengYuan/cpy_1_006.cpp (3)

4-17: 代码实现了书籍的基本属性和获取方法,逻辑清晰,没有发现问题。


19-46: 图书馆类实现了添加书籍、按标题查找书籍和按作者统计书籍数量的功能,使用了标准C++库,代码结构合理。


48-63: 主函数中演示了图书馆类和书籍类的使用,包括添加书籍、查找书籍和统计作者的书籍数量,输出语句正确地展示了这些操作的结果。

c++/misc/ChenPengYuan/cpy_1_004.cpp (3)

6-38: 银行账户类实现了存款、取款和获取余额的功能,对存取款的金额进行了有效性检查,逻辑正确。


40-64: 银行类管理一系列的银行账户,提供了开户、销户和计算总存款的功能,使用了现代C++特性如emplace_back,提高了效率。


66-84: 主函数中演示了银行类和银行账户类的使用,包括开户、进行交易和销户,输出语句正确地展示了这些操作的结果。

c++/misc/KangDengli/KangDengli01.cpp (3)

10-41: 线程类提供了线程管理的框架,包括启动、停止、暂停和恢复线程的方法,使用了现代C++的并发特性。


106-115: MyThread类是Thread的简单扩展,重写了threadLoop方法以执行特定任务,实现简单且正确。


117-127: 主函数中演示了MyThread类的使用,包括启动线程、暂停、恢复和停止,输出语句正确地展示了这些操作的结果。

c++/misc/XuShaoQiu/XuShaoQiu006.cpp (4)

3-9: NLAData结构简单且正确地定义了非线性转换点的字段。


13-36: mw2SdkNonLinear函数根据输入使用定义的转换点计算非线性输出,实现正确,使用了适当的数学运算。


38-77: sdk2MwNonLinear函数执行mw2SdkNonLinear转换的逆变换。它正确处理斜率可能为零的情况,以避免除零错误。


79-100: 主函数演示了mw2SdkNonLinearsdk2MwNonLinear函数的使用。它执行转换并检查是否可以检索原始值,这对于验证转换的正确性至关重要。

c++/misc/XuShaoQiu/XuShaoQiu002.cpp (2)

12-89: EPoll类管理epoll事件,提供了插入文件描述符和运行事件循环的方法。实现处理了错误,并使用了现代C++特性,如std::threadstd::atomic


91-127: 主函数演示了EPoll类用于处理UDP套接字事件的使用。它正确地设置了套接字,进行了绑定,并使用EPoll实例来管理传入数据。

c++/misc/XuShaoQiu/XuShaoQiu004.cpp (3)

10-13: EventListener类是事件监听器的接口,正确地定义了纯虚函数onEvent


15-92: EventHub类管理事件监听器和事件。它提供了添加、删除和清除监听器的方法,以及同步和异步发布事件的方法。实现有效地使用了现代C++的并发特性。


129-146: 主函数演示了EventHubEventListener类用于事件处理的使用。它设置了监听器,发布了事件,并清理了资源。实现正确,有效地演示了功能。

Comment on lines +22 to +26
for (auto iter = list.begin(); iter != list.end(); iter++) {
if (*iter == 2) {
list.erase(iter);
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

在循环中删除列表元素可能会导致迭代器失效。建议使用std::remove_if来安全地移除元素。

-    for (auto iter = list.begin(); iter != list.end(); iter++) {
-        if (*iter == 2) {
-            list.erase(iter);
-        }
-    }
+    list.remove_if([](int value) { return value == 2; });

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
for (auto iter = list.begin(); iter != list.end(); iter++) {
if (*iter == 2) {
list.erase(iter);
}
}
list.remove_if([](int value) { return value == 2; });

Comment on lines +28 to +31
char filePath[256] = {0};
sprintf(filePath, "/home/qiushao/config.ini");
thread = std::thread(theadLoop, filePath);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

创建线程的函数中,filePath作为局部变量可能会在线程函数访问时已经被销毁。建议将其声明为静态变量。

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 14

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 0eb5bbf and a69670e.

Files selected for processing (20)
  • .gitignore (1 hunks)
  • c++/misc/CMakeLists.txt (1 hunks)
  • c++/misc/ChenPengYuan/CMakeLists.txt (1 hunks)
  • c++/misc/ChenPengYuan/cpy_0_001.cpp (1 hunks)
  • c++/misc/ChenPengYuan/cpy_1_001.cpp (1 hunks)
  • c++/misc/ChenPengYuan/cpy_1_002.cpp (1 hunks)
  • c++/misc/ChenPengYuan/cpy_1_003.cpp (1 hunks)
  • c++/misc/ChenPengYuan/cpy_1_004.cpp (1 hunks)
  • c++/misc/ChenPengYuan/cpy_1_005.cpp (1 hunks)
  • c++/misc/ChenPengYuan/cpy_1_006.cpp (1 hunks)
  • c++/misc/KangDengli/CMakeLists.txt (1 hunks)
  • c++/misc/KangDengli/KangDengli01.cpp (1 hunks)
  • c++/misc/XuShaoQiu/CMakeLists.txt (1 hunks)
  • c++/misc/XuShaoQiu/XuShaoQiu001.cpp (1 hunks)
  • c++/misc/XuShaoQiu/XuShaoQiu002.cpp (1 hunks)
  • c++/misc/XuShaoQiu/XuShaoQiu003.cpp (1 hunks)
  • c++/misc/XuShaoQiu/XuShaoQiu004.cpp (1 hunks)
  • c++/misc/XuShaoQiu/XuShaoQiu005.cpp (1 hunks)
  • c++/misc/XuShaoQiu/XuShaoQiu006.cpp (1 hunks)
  • c++/misc/XuShaoQiu/XuShaoQiu007.cpp (1 hunks)
Files skipped from review due to trivial changes (8)
  • .gitignore
  • c++/misc/CMakeLists.txt
  • c++/misc/ChenPengYuan/CMakeLists.txt
  • c++/misc/ChenPengYuan/cpy_1_001.cpp
  • c++/misc/ChenPengYuan/cpy_1_002.cpp
  • c++/misc/ChenPengYuan/cpy_1_003.cpp
  • c++/misc/KangDengli/CMakeLists.txt
  • c++/misc/XuShaoQiu/CMakeLists.txt
Additional comments not posted (15)
c++/misc/XuShaoQiu/XuShaoQiu001.cpp (2)

4-9: 打印列表功能实现正确,使用了C风格的输入输出,与包含的头文件一致。


31-34: 主函数实现简单明了,正确调用了listOpt函数。

c++/misc/XuShaoQiu/XuShaoQiu005.cpp (3)

5-7: 获取配置文件路径的函数实现正确,但路径硬编码,建议增加灵活性。


9-24: 显示配置文件内容的函数正确处理了文件打开错误,并使用了C风格的输入输出。


26-29: 主函数实现简单明了,正确调用了showConfigContent函数。

c++/misc/XuShaoQiu/XuShaoQiu003.cpp (1)

33-37: 主函数实现简单明了,正确创建了线程并等待其完成。

c++/misc/ChenPengYuan/cpy_0_001.cpp (1)

11-13: 音频处理类的析构函数正确地释放了分配的内存。

c++/misc/ChenPengYuan/cpy_1_005.cpp (3)

4-14: 商品类提供了获取商品名称和价格的方法,实现正确。


17-45: 购物车类正确实现了添加商品、计算总价和查找最贵商品的方法。


47-58: 主函数正确创建了购物车,添加了商品,并显示了总成本和最贵的商品。

c++/misc/ChenPengYuan/cpy_1_006.cpp (1)

4-17: 代码实现了一个简单的书籍信息封装,没有发现问题。

c++/misc/ChenPengYuan/cpy_1_004.cpp (1)

6-37: 银行账户类实现了存款和取款功能,包含基本的验证,没有发现问题。

c++/misc/KangDengli/KangDengli01.cpp (1)

106-115: 自定义线程类正确地重写了 threadLoop 方法,没有发现问题。

c++/misc/XuShaoQiu/XuShaoQiu006.cpp (1)

3-9: 非线性转换数据点的结构定义简单明了,没有发现问题。

c++/misc/XuShaoQiu/XuShaoQiu004.cpp (1)

10-13: 事件监听器接口定义了虚拟方法 onEvent 用于事件处理,没有发现问题。

Comment on lines +19 to +42
class Library {
public:
void AddBook(const Book& book) {
books_.push_back(book);
}

Book* FindBookByTitle(const std::string& title) {
for (auto& book : books_) {
if (book.GetTitle() == title) {
return &book;
}
}
return nullptr;
}

size_t CountBooksByAuthor(const std::string& author) {
size_t count = 0;
for (auto& book : books_) {
if (book.GetAuthor() == author) {
++count;
}
}
return count;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

建议将 FindBookByTitle 方法返回的指针设置为常量,以防止外部修改书籍对象。

- Book* FindBookByTitle(const std::string& title) {
+ const Book* FindBookByTitle(const std::string& title) const {

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
class Library {
public:
void AddBook(const Book& book) {
books_.push_back(book);
}
Book* FindBookByTitle(const std::string& title) {
for (auto& book : books_) {
if (book.GetTitle() == title) {
return &book;
}
}
return nullptr;
}
size_t CountBooksByAuthor(const std::string& author) {
size_t count = 0;
for (auto& book : books_) {
if (book.GetAuthor() == author) {
++count;
}
}
return count;
}
class Library {
public:
void AddBook(const Book& book) {
books_.push_back(book);
}
const Book* FindBookByTitle(const std::string& title) const {
for (auto& book : books_) {
if (book.GetTitle() == title) {
return &book;
}
}
return nullptr;
}
size_t CountBooksByAuthor(const std::string& author) {
size_t count = 0;
for (auto& book : books_) {
if (book.GetAuthor() == author) {
++count;
}
}
return count;
}

Comment on lines +40 to +64
class Bank {
public:
BankAccount* OpenAccount(std::string owner, double initial_balance) {
accounts_.emplace_back(owner, initial_balance);
return &accounts_.back();
}

bool CloseAccount(BankAccount* account) {
for (auto it = accounts_.begin(); it != accounts_.end(); ++it) {
if (&(*it) == account) {
accounts_.erase(it);
return true;
}
}
return false;
}

double GetTotalDeposits() const {
return std::accumulate(accounts_.begin(), accounts_.end(), 0.0,
[](double sum, const BankAccount& account) { return sum + account.GetBalance(); });
}

private:
std::vector<BankAccount> accounts_;
};
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

对于大量账户的情况,当前的关闭账户方法效率较低。建议使用更高效的数据结构,如 std::map,来管理账户。

- std::vector<BankAccount> accounts_;
+ std::map<std::string, BankAccount> accounts_;

Committable suggestion was skipped due low confidence.

Comment on lines +10 to +104
class Thread {
public:
explicit Thread(std::string threadName);
virtual ~Thread() = default;

virtual void start();

virtual void stop();

virtual void pause();

virtual void resume();

protected:
virtual bool threadLoop() = 0;
virtual bool prepare();
virtual void destroy();

private:
void interrupt(bool);

void run();

protected:
std::thread thread_;
std::atomic<bool> interrupted_;
std::atomic<bool> started_;
std::atomic<bool> paused_;
std::condition_variable cond_;
std::mutex mutex_;
std::string threadName_;
};

Thread::Thread(std::string threadName) :
interrupted_(false),
started_(false),
paused_(false),
threadName_(std::move(threadName)) {
}

void Thread::start() {
interrupt(false);
thread_ = std::thread(&Thread::run, this);
started_ = true;
}

void Thread::stop() {
if (!started_) {
return;
}
if (paused_) {
resume();
}
interrupt(true);
destroy();
}

void Thread::pause() {
paused_ = true;
}

void Thread::resume() {
paused_ = false;
cond_.notify_one();
}

void Thread::destroy() {
if(!started_) {
return;
}
started_ = false;
if (thread_.joinable()) {
thread_.join();
}
}

void Thread::interrupt(bool flag) {
interrupted_ = flag;
}

void Thread::run() {
do {
if (paused_) {
std::unique_lock<std::mutex> lock(mutex_);
cond_.wait(lock, [&] {
return !paused_;
});
}

if (!threadLoop()) {
started_ = false;
break;
}
} while (!interrupted_);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

线程管理类提供了全面的功能。建议将 interrupt 方法重命名为 setInterrupted,以提高代码的可读性。

- void interrupt(bool);
+ void setInterrupted(bool);

Committable suggestion was skipped due low confidence.

Comment on lines +11 to +28
void listOpt() {
std::list<int> list;
list.push_back(1);
list.push_back(2);
list.push_back(2);
list.push_back(3);
list.push_back(4);
list.push_back(2);

printList(list);

for (auto iter = list.begin(); iter != list.end(); iter++) {
if (*iter == 2) {
list.erase(iter);
}
}

printList(list);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

在循环中删除列表元素时未正确管理迭代器,可能导致未定义行为。

- for (auto iter = list.begin(); iter != list.end(); iter++) {
-     if (*iter == 2) {
-         list.erase(iter);
-     }
- }
+ for (auto iter = list.begin(); iter != list.end(); ) {
+     if (*iter == 2) {
+         iter = list.erase(iter);
+     } else {
+         ++iter;
+     }
+ }

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
void listOpt() {
std::list<int> list;
list.push_back(1);
list.push_back(2);
list.push_back(2);
list.push_back(3);
list.push_back(4);
list.push_back(2);
printList(list);
for (auto iter = list.begin(); iter != list.end(); iter++) {
if (*iter == 2) {
list.erase(iter);
}
}
printList(list);
void listOpt() {
std::list<int> list;
list.push_back(1);
list.push_back(2);
list.push_back(2);
list.push_back(3);
list.push_back(4);
list.push_back(2);
printList(list);
for (auto iter = list.begin(); iter != list.end(); ) {
if (*iter == 2) {
iter = list.erase(iter);
} else {
++iter;
}
}
printList(list);

Comment on lines +38 to +77
void sdk2MwNonLinear(uint32_t input, uint32_t *output) {
double slopValue;
uint32_t diffValue;
uint32_t baseValue;
if (nlaData.u32Point75 < input) {
if (nlaData.u32Point100 != nlaData.u32Point75) {
slopValue = 25.0 / (int32_t) (nlaData.u32Point100 - nlaData.u32Point75);
} else {
slopValue = 0;
}
diffValue = input - nlaData.u32Point75;
baseValue = 75;
} else if (nlaData.u32Point50 < input) {
if (nlaData.u32Point75 != nlaData.u32Point50) {
slopValue = 25.0 / (int32_t) (nlaData.u32Point75 - nlaData.u32Point50);
} else {
slopValue = 0;
}
diffValue = input - nlaData.u32Point50;
baseValue = 50;
} else if (nlaData.u32Point25 < input) {
if (nlaData.u32Point50 != nlaData.u32Point25) {
slopValue = 25.0 / (int32_t) (nlaData.u32Point50 - nlaData.u32Point25);
} else {
slopValue = 0;
}
diffValue = input - nlaData.u32Point25;
baseValue = 25;
} else {
if (nlaData.u32Point25 != nlaData.u32Point0) {
slopValue = 25.0 / (int32_t) (nlaData.u32Point25 - nlaData.u32Point0);
} else {
slopValue = 0;
}
diffValue = input - nlaData.u32Point0;
baseValue = 0;
}

*output = baseValue + (int32_t) (slopValue * diffValue);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

函数执行反向分段线性转换。同样存在不必要的强制类型转换问题。

-        slopValue = 25.0 / (int32_t) (nlaData.u32Point100 - nlaData.u32Point75);
+        slopValue = 25.0 / (nlaData.u32Point100 - nlaData.u32Point75);

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
void sdk2MwNonLinear(uint32_t input, uint32_t *output) {
double slopValue;
uint32_t diffValue;
uint32_t baseValue;
if (nlaData.u32Point75 < input) {
if (nlaData.u32Point100 != nlaData.u32Point75) {
slopValue = 25.0 / (int32_t) (nlaData.u32Point100 - nlaData.u32Point75);
} else {
slopValue = 0;
}
diffValue = input - nlaData.u32Point75;
baseValue = 75;
} else if (nlaData.u32Point50 < input) {
if (nlaData.u32Point75 != nlaData.u32Point50) {
slopValue = 25.0 / (int32_t) (nlaData.u32Point75 - nlaData.u32Point50);
} else {
slopValue = 0;
}
diffValue = input - nlaData.u32Point50;
baseValue = 50;
} else if (nlaData.u32Point25 < input) {
if (nlaData.u32Point50 != nlaData.u32Point25) {
slopValue = 25.0 / (int32_t) (nlaData.u32Point50 - nlaData.u32Point25);
} else {
slopValue = 0;
}
diffValue = input - nlaData.u32Point25;
baseValue = 25;
} else {
if (nlaData.u32Point25 != nlaData.u32Point0) {
slopValue = 25.0 / (int32_t) (nlaData.u32Point25 - nlaData.u32Point0);
} else {
slopValue = 0;
}
diffValue = input - nlaData.u32Point0;
baseValue = 0;
}
*output = baseValue + (int32_t) (slopValue * diffValue);
}
void sdk2MwNonLinear(uint32_t input, uint32_t *output) {
double slopValue;
uint32_t diffValue;
uint32_t baseValue;
if (nlaData.u32Point75 < input) {
if (nlaData.u32Point100 != nlaData.u32Point75) {
slopValue = 25.0 / (nlaData.u32Point100 - nlaData.u32Point75);
} else {
slopValue = 0;
}
diffValue = input - nlaData.u32Point75;
baseValue = 75;
} else if (nlaData.u32Point50 < input) {
if (nlaData.u32Point75 != nlaData.u32Point50) {
slopValue = 25.0 / (nlaData.u32Point75 - nlaData.u32Point50);
} else {
slopValue = 0;
}
diffValue = input - nlaData.u32Point50;
baseValue = 50;
} else if (nlaData.u32Point25 < input) {
if (nlaData.u32Point50 != nlaData.u32Point25) {
slopValue = 25.0 / (nlaData.u32Point50 - nlaData.u32Point25);
} else {
slopValue = 0;
}
diffValue = input - nlaData.u32Point25;
baseValue = 25;
} else {
if (nlaData.u32Point25 != nlaData.u32Point0) {
slopValue = 25.0 / (nlaData.u32Point25 - nlaData.u32Point0);
} else {
slopValue = 0;
}
diffValue = input - nlaData.u32Point0;
baseValue = 0;
}
*output = baseValue + (int32_t) (slopValue * diffValue);
}

Comment on lines +5 to +41
void showConfigContent() {
constexpr int LINE_MAX_LEN = 4096;
const char *filePath = "/home/qiushao/config.ini";
char line[LINE_MAX_LEN] = {0};
printf("file path = %s\n", filePath);
FILE *fp = fopen(filePath, "r");
if (fp == nullptr) {
perror("Error opening file");
return;
}

size_t last = 0;
while (fgets(line + last, 256, fp) != nullptr) {
int len = (int)strlen(line) - 1; // 去掉字符串结束符 '\0'

while ((len>=0) && ((line[len]=='\n') || (isspace(line[len])))) {
// 去除行尾空白字符(空格,TAB, 换行), trim
line[len]=0 ;
len-- ;
}

if (len < 0) {
// 空行
continue;
}

if (line[len] == '\\') {
// 多行配置
last = len;
continue;
}
printf("%s\n", line);
last = 0;
memset(line, 0, LINE_MAX_LEN);
}

fclose(fp);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

处理配置文件内容的函数正确实现了多行条目的读取。但是,在处理字符串时使用了潜在不安全的方法,建议改进。

-    while (fgets(line + last, 256, fp) != nullptr) {
+    while (fgets(line + last, LINE_MAX_LEN - last, fp) != nullptr) {

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
void showConfigContent() {
constexpr int LINE_MAX_LEN = 4096;
const char *filePath = "/home/qiushao/config.ini";
char line[LINE_MAX_LEN] = {0};
printf("file path = %s\n", filePath);
FILE *fp = fopen(filePath, "r");
if (fp == nullptr) {
perror("Error opening file");
return;
}
size_t last = 0;
while (fgets(line + last, 256, fp) != nullptr) {
int len = (int)strlen(line) - 1; // 去掉字符串结束符 '\0'
while ((len>=0) && ((line[len]=='\n') || (isspace(line[len])))) {
// 去除行尾空白字符(空格,TAB, 换行), trim
line[len]=0 ;
len-- ;
}
if (len < 0) {
// 空行
continue;
}
if (line[len] == '\\') {
// 多行配置
last = len;
continue;
}
printf("%s\n", line);
last = 0;
memset(line, 0, LINE_MAX_LEN);
}
fclose(fp);
void showConfigContent() {
constexpr int LINE_MAX_LEN = 4096;
const char *filePath = "/home/qiushao/config.ini";
char line[LINE_MAX_LEN] = {0};
printf("file path = %s\n", filePath);
FILE *fp = fopen(filePath, "r");
if (fp == nullptr) {
perror("Error opening file");
return;
}
size_t last = 0;
while (fgets(line + last, LINE_MAX_LEN - last, fp) != nullptr) {
int len = (int)strlen(line) - 1; // 去掉字符串结束符 '\0'
while ((len>=0) && ((line[len]=='\n') || (isspace(line[len])))) {
// 去除行尾空白字符(空格,TAB, 换行), trim
line[len]=0 ;
len-- ;
}
if (len < 0) {
// 空行
continue;
}
if (line[len] == '\\') {
// 多行配置
last = len;
continue;
}
printf("%s\n", line);
last = 0;
memset(line, 0, LINE_MAX_LEN);
}
fclose(fp);
}

Comment on lines +3 to +9
MyCallback::MyCallback(AudioParam param) : audioParam_(param) {
frameDiv_ = sizeof(int16_t) * audioParam_.channelCount;
//公式:数据率=采样频率(Hz)×量化位数(bit)×声道数(bit/s),在48000 Hz采样率下,如果是16位立体声,数据率将是 1536 kbps。
audioDataRate = (audioParam_.sampleRate * audioParam_.AudioFormat * audioParam_.channelCount)/1000;
bufferSize_ = audioDataRate * 50;
frameBuffer_ = static_cast<uint8_t *>(malloc(bufferSize_));
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

音频处理类的构造函数正确计算了数据率并分配了缓冲区。建议添加内存分配失败的检查。

-    frameBuffer_ = static_cast<uint8_t *>(malloc(bufferSize_));
+    frameBuffer_ = static_cast<uint8_t *>(malloc(bufferSize_));
+    if (!frameBuffer_) {
+        throw std::bad_alloc();
+    }

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
MyCallback::MyCallback(AudioParam param) : audioParam_(param) {
frameDiv_ = sizeof(int16_t) * audioParam_.channelCount;
//公式:数据率=采样频率(Hz)×量化位数(bit)×声道数(bit/s),在48000 Hz采样率下,如果是16位立体声,数据率将是 1536 kbps。
audioDataRate = (audioParam_.sampleRate * audioParam_.AudioFormat * audioParam_.channelCount)/1000;
bufferSize_ = audioDataRate * 50;
frameBuffer_ = static_cast<uint8_t *>(malloc(bufferSize_));
}
MyCallback::MyCallback(AudioParam param) : audioParam_(param) {
frameDiv_ = sizeof(int16_t) * audioParam_.channelCount;
//公式:数据率=采样频率(Hz)×量化位数(bit)×声道数(bit/s),在48000 Hz采样率下,如果是16位立体声,数据率将是 1536 kbps。
audioDataRate = (audioParam_.sampleRate * audioParam_.AudioFormat * audioParam_.channelCount)/1000;
bufferSize_ = audioDataRate * 50;
frameBuffer_ = static_cast<uint8_t *>(malloc(bufferSize_));
if (!frameBuffer_) {
throw std::bad_alloc();
}
}

Comment on lines +12 to +89
class EPoll {
public:
EPoll(int maxEvents, std::function<void(int fd)> readAvailableCallback);
~EPoll();

bool insertFd(int fd) const;

private:
void eventLoop();
private:
const int maxEvents_;
int epollFd_ = -1;
int exitEventFd_ = -1;
std::function<void(int fd)> readAvailableCallback_;
std::thread thread_;
std::atomic<bool> interrupted_{};
};

EPoll::EPoll(const int maxEvents, std::function<void(int)> readAvailableCallback) : maxEvents_(maxEvents) {
readAvailableCallback_ = std::move(readAvailableCallback);
epollFd_ = epoll_create1(0);
if (epollFd_ <= 0) {
printf("epoll_create error: %s\n", strerror(errno));
return;
}

exitEventFd_ = eventfd(0, 0);
if (exitEventFd_ <= 0) {
printf("create eventfd error: %s\n", strerror(errno));
return;
}
insertFd(exitEventFd_);

interrupted_.store(false);
thread_ = std::thread(&EPoll::eventLoop, this);
}

EPoll::~EPoll() {
interrupted_.store(true);
auto ret = eventfd_write(exitEventFd_, 0);
if (ret != 0) {
printf("eventfd_write error : ret = %d, error: %s\n", ret, strerror(errno));
}
thread_.join();
close(exitEventFd_);
close(epollFd_);
}

bool EPoll::insertFd(int fd) const {
struct epoll_event event{};
event.events = EPOLLIN;
event.data.fd = fd;
if (epoll_ctl(epollFd_, EPOLL_CTL_ADD, fd, &event) < 0) {
printf("epoll_ctl add error: %s\n", strerror(errno));
return false;
}

return true;
}

void EPoll::eventLoop() {
while (!interrupted_.load()) {
struct epoll_event events[maxEvents_];
int count = epoll_wait(epollFd_, events, maxEvents_, -1);
if (count == -1) {
printf("epoll_wait error: %s\n", strerror(errno));
continue;
}

for (int i = 0; i < count; ++i) {
if (events[i].data.fd == exitEventFd_) {
printf("exit event loop\n");
return;
}
readAvailableCallback_(events[i].data.fd);
}
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

EPoll 类用于管理 epoll 事件,结构良好。建议在错误处理中抛出异常,而不是仅打印错误信息,以使代码更加健壮。

-        printf("epoll_create error: %s\n", strerror(errno));
+        throw std::runtime_error("epoll_create error: " + std::string(strerror(errno)));

Committable suggestion was skipped due low confidence.

Comment on lines +15 to +34
oboe::DataCallbackResult
MyCallback::onAudioReady(oboe::AudioStream *audioStream, void *audioData, int32_t numFrames) {
auto *outputData = static_cast<int16_t *>(audioData);
size_t waitLen = numFrames * frameDiv_;
if ((frameCount_++ & 0xff) == 0) {
LOGV("waitLen = %d, cachedSize_ = %d", waitLen, cachedSize_);
}

std::lock_guard<std::mutex> lock(mutex_);
if (cachedSize_ < waitLen) {
memset(outputData, 0, waitLen);
memcpy(outputData, &frameBuffer_, cachedSize_);
cachedSize_ = 0;
} else {
memcpy(outputData, &frameBuffer_, waitLen);
cachedSize_ -= waitLen;
memmove(frameBuffer_, frameBuffer_ + waitLen, cachedSize_);
}
return oboe::DataCallbackResult::Continue;
} No newline at end of file
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

处理音频数据的方法正确管理了缓冲区。但是,使用了潜在不安全的方法访问缓冲区,建议改进。

-        memcpy(outputData, &frameBuffer_, cachedSize_);
+        memcpy(outputData, frameBuffer_, cachedSize_);
-        memcpy(outputData, &frameBuffer_, waitLen);
+        memcpy(outputData, frameBuffer_, waitLen);
-        memmove(frameBuffer_, frameBuffer_ + waitLen, cachedSize_);
+        memmove(frameBuffer_, frameBuffer_ + waitLen, cachedSize_);

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
oboe::DataCallbackResult
MyCallback::onAudioReady(oboe::AudioStream *audioStream, void *audioData, int32_t numFrames) {
auto *outputData = static_cast<int16_t *>(audioData);
size_t waitLen = numFrames * frameDiv_;
if ((frameCount_++ & 0xff) == 0) {
LOGV("waitLen = %d, cachedSize_ = %d", waitLen, cachedSize_);
}
std::lock_guard<std::mutex> lock(mutex_);
if (cachedSize_ < waitLen) {
memset(outputData, 0, waitLen);
memcpy(outputData, &frameBuffer_, cachedSize_);
cachedSize_ = 0;
} else {
memcpy(outputData, &frameBuffer_, waitLen);
cachedSize_ -= waitLen;
memmove(frameBuffer_, frameBuffer_ + waitLen, cachedSize_);
}
return oboe::DataCallbackResult::Continue;
}
oboe::DataCallbackResult
MyCallback::onAudioReady(oboe::AudioStream *audioStream, void *audioData, int32_t numFrames) {
auto *outputData = static_cast<int16_t *>(audioData);
size_t waitLen = numFrames * frameDiv_;
if ((frameCount_++ & 0xff) == 0) {
LOGV("waitLen = %d, cachedSize_ = %d", waitLen, cachedSize_);
}
std::lock_guard<std::mutex> lock(mutex_);
if (cachedSize_ < waitLen) {
memset(outputData, 0, waitLen);
memcpy(outputData, frameBuffer_, cachedSize_);
cachedSize_ = 0;
} else {
memcpy(outputData, frameBuffer_, waitLen);
cachedSize_ -= waitLen;
memmove(frameBuffer_, frameBuffer_ + waitLen, cachedSize_);
}
return oboe::DataCallbackResult::Continue;
}

Comment on lines +15 to +92
class EventHub {
public:
EventHub() {
eventThead_ = std::thread(&EventHub::eventThread, this);
}

~EventHub() {
interrupted_.store(true);
eventQueueCondition_.notify_one();
eventThead_.join();
}

void eventThread() {
while (!interrupted_.load()) {
eventLoop();
}
}

void eventLoop() {
std::unique_lock<std::mutex> lock(eventQueueMutex_);
while (eventQueue_.empty()) {
if (interrupted_.load()) {
return;
}
eventQueueCondition_.wait(lock);
}

auto event = eventQueue_.front();
eventQueue_.pop_front();
publishEventSync(event);
}

void addEventListener(EventListener *listener) {
std::lock_guard<std::mutex> lock(listenerMutex_);
printf("addEventListener %p\n", listener);
listenerList_.push_back(listener);
}

void removeEventListener(EventListener *listener) {
std::lock_guard<std::mutex> lock(listenerMutex_);
printf("removeEventListener %p\n", listener);
for (auto it = listenerList_.begin(); it != listenerList_.end();) {
if (*it == listener) {
it = listenerList_.erase(it);
} else {
++it;
}
}
}

void clearEventListener() {
listenerList_.clear();
}

void publishEventSync(int event) {
std::lock_guard<std::mutex> lock(listenerMutex_);
for (auto const &listener : listenerList_) {
listener->onEvent(event);
}
}

void publishEventAsync(int event) {
std::lock_guard<std::mutex> lock(eventQueueMutex_);
eventQueue_.push_back(event);
eventQueueCondition_.notify_one();
}

private:
std::mutex listenerMutex_;
std::list<EventListener*> listenerList_;

std::mutex eventQueueMutex_;
std::condition_variable eventQueueCondition_;
std::list<int> eventQueue_;

std::thread eventThead_;
std::atomic<bool> interrupted_{false};
};
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

事件中心类管理事件监听器列表和事件队列。建议在 publishEventAsync 方法中添加线程安全注释,以阐明其线程安全性。

+ // 确保此方法在多线程环境中安全调用
void publishEventAsync(int event) {

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
class EventHub {
public:
EventHub() {
eventThead_ = std::thread(&EventHub::eventThread, this);
}
~EventHub() {
interrupted_.store(true);
eventQueueCondition_.notify_one();
eventThead_.join();
}
void eventThread() {
while (!interrupted_.load()) {
eventLoop();
}
}
void eventLoop() {
std::unique_lock<std::mutex> lock(eventQueueMutex_);
while (eventQueue_.empty()) {
if (interrupted_.load()) {
return;
}
eventQueueCondition_.wait(lock);
}
auto event = eventQueue_.front();
eventQueue_.pop_front();
publishEventSync(event);
}
void addEventListener(EventListener *listener) {
std::lock_guard<std::mutex> lock(listenerMutex_);
printf("addEventListener %p\n", listener);
listenerList_.push_back(listener);
}
void removeEventListener(EventListener *listener) {
std::lock_guard<std::mutex> lock(listenerMutex_);
printf("removeEventListener %p\n", listener);
for (auto it = listenerList_.begin(); it != listenerList_.end();) {
if (*it == listener) {
it = listenerList_.erase(it);
} else {
++it;
}
}
}
void clearEventListener() {
listenerList_.clear();
}
void publishEventSync(int event) {
std::lock_guard<std::mutex> lock(listenerMutex_);
for (auto const &listener : listenerList_) {
listener->onEvent(event);
}
}
void publishEventAsync(int event) {
std::lock_guard<std::mutex> lock(eventQueueMutex_);
eventQueue_.push_back(event);
eventQueueCondition_.notify_one();
}
private:
std::mutex listenerMutex_;
std::list<EventListener*> listenerList_;
std::mutex eventQueueMutex_;
std::condition_variable eventQueueCondition_;
std::list<int> eventQueue_;
std::thread eventThead_;
std::atomic<bool> interrupted_{false};
};
class EventHub {
public:
EventHub() {
eventThead_ = std::thread(&EventHub::eventThread, this);
}
~EventHub() {
interrupted_.store(true);
eventQueueCondition_.notify_one();
eventThead_.join();
}
void eventThread() {
while (!interrupted_.load()) {
eventLoop();
}
}
void eventLoop() {
std::unique_lock<std::mutex> lock(eventQueueMutex_);
while (eventQueue_.empty()) {
if (interrupted_.load()) {
return;
}
eventQueueCondition_.wait(lock);
}
auto event = eventQueue_.front();
eventQueue_.pop_front();
publishEventSync(event);
}
void addEventListener(EventListener *listener) {
std::lock_guard<std::mutex> lock(listenerMutex_);
printf("addEventListener %p\n", listener);
listenerList_.push_back(listener);
}
void removeEventListener(EventListener *listener) {
std::lock_guard<std::mutex> lock(listenerMutex_);
printf("removeEventListener %p\n", listener);
for (auto it = listenerList_.begin(); it != listenerList_.end();) {
if (*it == listener) {
it = listenerList_.erase(it);
} else {
++it;
}
}
}
void clearEventListener() {
listenerList_.clear();
}
void publishEventSync(int event) {
std::lock_guard<std::mutex> lock(listenerMutex_);
for (auto const &listener : listenerList_) {
listener->onEvent(event);
}
}
// 确保此方法在多线程环境中安全调用
void publishEventAsync(int event) {
std::lock_guard<std::mutex> lock(eventQueueMutex_);
eventQueue_.push_back(event);
eventQueueCondition_.notify_one();
}
private:
std::mutex listenerMutex_;
std::list<EventListener*> listenerList_;
std::mutex eventQueueMutex_;
std::condition_variable eventQueueCondition_;
std::list<int> eventQueue_;
std::thread eventThead_;
std::atomic<bool> interrupted_{false};
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants