Qt - 音频采集程序

news/2025/9/23 15:50:06/文章来源:https://www.cnblogs.com/zhuchunlin/p/19107354

我们将创建一个简单的Qt应用程序,用于采集麦克风的音频数据。我们将使用QAudioInput来捕获音频,并将捕获的原始PCM数据保存到文件中。同时,我们也会在界面上显示一些基本的控制按钮(开始、停止)和状态信息。

步骤:

  1. 创建Qt项目(例如使用Qt Widgets Application)。

  2. 在.pro文件中添加multimedia模块:QT += multimedia

  3. 设计一个简单的界面,包含两个按钮(开始和停止)和一个标签显示状态。

  4. 在后台代码中,设置音频输入设备,并当点击开始按钮时,开始捕获音频数据;点击停止按钮时,停止捕获。

注意:我们这里将捕获的原始PCM数据保存为文件,但请注意原始PCM数据没有文件头(如WAV头),所以不能直接播放。如果需要可播放的文件,可以添加WAV头或者使用其他格式。

但是,为了简单起见,我们只保存原始PCM数据。如果你需要播放,可以使用Audacity等工具导入原始数据(设置正确的采样率、样本大小和通道数)。

我们将使用以下音频格式:

  • 采样率:44100 Hz

  • 样本大小:16位

  • 通道数:2(立体声)

如果默认设备不支持这些参数,我们将使用最接近的设置。

代码结构:

  • 使用QAudioInput进行音频输入。

  • 使用QFile来存储捕获的音频数据。

界面设计:

  • 一个QPushButton用于开始捕获。

  • 一个QPushButton用于停止捕获(初始不可用)。

  • 一个QLabel用于显示状态。

逻辑:

  • 点击开始按钮后,初始化音频输入设备并开始捕获,同时将开始按钮禁用,停止按钮启用。

  • 点击停止按钮后,停止捕获,关闭文件,并将按钮状态重置。

我们将创建一个类,比如叫AudioCapture,来管理音频捕获。

由于Qt6中对多媒体模块有一些变化,请注意:如果你使用的是Qt6,需要确保包括正确的模块。在Qt6中,QAudioInput位于QtMultimedia模块中。

Qt 麦克风音频数据采集应用

下面是一个完整的 Qt 应用程序,用于采集麦克风音频数据并实时显示波形。

 

1. 项目文件(AudioCaptureApp.pro)

qmake
QT       += core gui multimedia widgetsCONFIG   += c++17TARGET = AudioCaptureApp
TEMPLATE = appSOURCES += \main.cpp \mainwindow.cpp \audiocapture.cppHEADERS += \mainwindow.h \audiocapture.hFORMS += \widget.ui

2. 主程序入口 (main.cpp)

cpp
#include <QApplication>
#include "mainwindow.h"int main(int argc, char *argv[])
{QApplication app(argc, argv);// 设置应用程序信息app.setApplicationName("音频采集应用");app.setApplicationVersion("1.0");app.setOrganizationName("MyCompany");MainWindow window;window.show();return app.exec();
}

3. 音频采集类头文件 (audiocapture.h)

cpp
#ifndef AUDIOCAPTURE_H
#define AUDIOCAPTURE_H#include <QObject>
#include <QAudioInput>
#include <QAudioDeviceInfo>
#include <QByteArray>
#include <QTimer>
#include <QDebug>class AudioCapture : public QObject
{Q_OBJECTpublic:explicit AudioCapture(QObject *parent = nullptr);~AudioCapture();// 音频设备操作bool initializeAudio();void startCapture();void stopCapture();void pauseCapture();void resumeCapture();// 设备信息QList<QAudioDeviceInfo> getAvailableDevices() const;QString getCurrentDeviceName() const;// 音频参数设置void setSampleRate(int rate);void setChannelCount(int channels);void setSampleSize(int size);// 状态查询bool isCapturing() const { return m_isCapturing; }qint64 getBytesCaptured() const { return m_bytesCaptured; }signals:// 音频数据可用信号void audioDataAvailable(const QByteArray &data);// 音频电平信号(用于显示波形)void audioLevelChanged(qreal level);// 状态变化信号void captureStateChanged(bool capturing);// 错误信号void errorOccurred(const QString &errorMessage);public slots:void setAudioDevice(const QAudioDeviceInfo &device);private slots:void handleAudioDataReady();void updateAudioLevel();private:void setupAudioFormat();void calculateAudioLevel(const QByteArray &data);private:QAudioInput *m_audioInput;QIODevice *m_audioDevice;QAudioFormat m_audioFormat;QAudioDeviceInfo m_currentDevice;QTimer *m_levelTimer;bool m_isCapturing;bool m_isPaused;qint64 m_bytesCaptured;qreal m_currentLevel;
};#endif // AUDIOCAPTURE_H

4. 音频采集类实现 (audiocapture.cpp)

cpp
#include "audiocapture.h"AudioCapture::AudioCapture(QObject *parent) : QObject(parent), m_audioInput(nullptr), m_audioDevice(nullptr), m_isCapturing(false), m_isPaused(false), m_bytesCaptured(0), m_currentLevel(0.0)
{m_levelTimer = new QTimer(this);connect(m_levelTimer, &QTimer::timeout, this, &AudioCapture::updateAudioLevel);
}AudioCapture::~AudioCapture()
{stopCapture();
}bool AudioCapture::initializeAudio()
{// 获取默认输入设备m_currentDevice = QAudioDeviceInfo::defaultInputDevice();if (m_currentDevice.isNull()) {emit errorOccurred("未找到可用的音频输入设备");return false;}// 设置音频格式setupAudioFormat();// 检查格式支持if (!m_currentDevice.isFormatSupported(m_audioFormat)) {m_audioFormat = m_currentDevice.nearestFormat(m_audioFormat);qDebug() << "使用最接近的音频格式:" << m_audioFormat.sampleRate() << "Hz," << m_audioFormat.channelCount() << "channels,"<< m_audioFormat.sampleSize() << "bits";}// 创建音频输入对象m_audioInput = new QAudioInput(m_currentDevice, m_audioFormat, this);// 设置缓冲区大小m_audioInput->setBufferSize(4096);return true;
}void AudioCapture::setupAudioFormat()
{m_audioFormat.setSampleRate(44100);      // 44.1 kHzm_audioFormat.setChannelCount(1);        // 单声道m_audioFormat.setSampleSize(16);         // 16位m_audioFormat.setCodec("audio/pcm");     // PCM编码m_audioFormat.setByteOrder(QAudioFormat::LittleEndian);m_audioFormat.setSampleType(QAudioFormat::SignedInt);
}void AudioCapture::startCapture()
{if (!m_audioInput) {if (!initializeAudio()) {return;}}if (m_isCapturing && !m_isPaused) {return;}if (m_isPaused) {resumeCapture();return;}// 开始音频采集m_audioDevice = m_audioInput->start();if (!m_audioDevice) {emit errorOccurred("无法启动音频设备");return;}// 连接数据可用信号connect(m_audioDevice, &QIODevice::readyRead, this, &AudioCapture::handleAudioDataReady);m_isCapturing = true;m_isPaused = false;m_bytesCaptured = 0;// 启动电平计时器(用于实时显示)m_levelTimer->start(50); // 每50ms更新一次电平emit captureStateChanged(true);qDebug() << "开始音频采集,设备:" << m_currentDevice.deviceName();
}void AudioCapture::stopCapture()
{if (m_audioInput) {m_audioInput->stop();if (m_audioDevice) {m_audioDevice->disconnect();m_audioDevice = nullptr;}}m_levelTimer->stop();m_isCapturing = false;m_isPaused = false;m_currentLevel = 0.0;emit captureStateChanged(false);emit audioLevelChanged(0.0);qDebug() << "停止音频采集,总采集数据:" << m_bytesCaptured << "字节";
}void AudioCapture::pauseCapture()
{if (m_isCapturing && !m_isPaused) {m_audioInput->suspend();m_isPaused = true;m_levelTimer->stop();emit audioLevelChanged(0.0);}
}void AudioCapture::resumeCapture()
{if (m_isCapturing && m_isPaused) {m_audioInput->resume();m_isPaused = false;m_levelTimer->start(50);}
}void AudioCapture::handleAudioDataReady()
{if (!m_audioDevice) return;// 读取音频数据QByteArray audioData = m_audioDevice->readAll();if (audioData.isEmpty()) return;m_bytesCaptured += audioData.size();// 计算音频电平(用于波形显示)calculateAudioLevel(audioData);// 发送数据可用信号emit audioDataAvailable(audioData);
}void AudioCapture::calculateAudioLevel(const QByteArray &data)
{const qint16 *samples = reinterpret_cast<const qint16*>(data.constData());int sampleCount = data.size() / 2; // 16位样本,每个样本2字节qreal maxValue = 0;for (int i = 0; i < sampleCount; ++i) {qreal value = qAbs(samples[i]) / 32768.0; // 16位有符号整数范围:-32768到32767if (value > maxValue) {maxValue = value;}}m_currentLevel = maxValue;
}void AudioCapture::updateAudioLevel()
{emit audioLevelChanged(m_currentLevel);m_currentLevel = 0.0; // 重置为下次计算
}QList<QAudioDeviceInfo> AudioCapture::getAvailableDevices() const
{return QAudioDeviceInfo::availableDevices(QAudio::AudioInput);
}QString AudioCapture::getCurrentDeviceName() const
{return m_currentDevice.deviceName();
}void AudioCapture::setAudioDevice(const QAudioDeviceInfo &device)
{if (m_isCapturing) {stopCapture();}m_currentDevice = device;// 重新初始化音频输入if (m_audioInput) {delete m_audioInput;m_audioInput = nullptr;}initializeAudio();
}void AudioCapture::setSampleRate(int rate)
{m_audioFormat.setSampleRate(rate);if (m_isCapturing) {// 需要重新启动采集stopCapture();startCapture();}
}void AudioCapture::setChannelCount(int channels)
{m_audioFormat.setChannelCount(channels);if (m_isCapturing) {stopCapture();startCapture();}
}void AudioCapture::setSampleSize(int size)
{m_audioFormat.setSampleSize(size);if (m_isCapturing) {stopCapture();startCapture();}
}

5. 主窗口头文件 (mainwindow.h)

cpp
#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <QPushButton>
#include <QLabel>
#include <QComboBox>
#include <QProgressBar>
#include <QCheckBox>
#include <QSpinBox>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QGroupBox>
#include <QFileDialog>
#include <QMessageBox>
#include "audiocapture.h"class MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();private slots:void onStartStopClicked();void onPauseResumeClicked();void onSaveDataClicked();void onDeviceChanged(int index);void handleAudioDataAvailable(const QByteArray &data);void handleAudioLevelChanged(qreal level);void handleCaptureStateChanged(bool capturing);void handleErrorOccurred(const QString &errorMessage);private:void setupUI();void setupConnections();void updateDeviceList();void updateUIState();private:// UI 组件QWidget *m_centralWidget;QVBoxLayout *m_mainLayout;QGroupBox *m_deviceGroup;QComboBox *m_deviceCombo;QLabel *m_statusLabel;QProgressBar *m_levelBar;QGroupBox *m_controlGroup;QPushButton *m_startStopButton;QPushButton *m_pauseResumeButton;QPushButton *m_saveButton;QGroupBox *m_settingsGroup;QCheckBox *m_autoSaveCheck;QSpinBox *m_sampleRateSpin;QSpinBox *m_channelsSpin;QLabel *m_statsLabel;// 音频采集AudioCapture *m_audioCapture;// 数据存储QByteArray m_capturedData;bool m_isCapturing;bool m_isPaused;
};#endif // MAINWINDOW_H

6. 主窗口实现 (mainwindow.cpp)

cpp
#include "mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), m_audioCapture(new AudioCapture(this)), m_isCapturing(false), m_isPaused(false)
{setWindowTitle("Qt 音频采集应用");setMinimumSize(600, 400);setupUI();setupConnections();updateDeviceList();updateUIState();
}MainWindow::~MainWindow()
{if (m_isCapturing) {m_audioCapture->stopCapture();}
}void MainWindow::setupUI()
{m_centralWidget = new QWidget(this);setCentralWidget(m_centralWidget);m_mainLayout = new QVBoxLayout(m_centralWidget);// 设备选择组m_deviceGroup = new QGroupBox("音频设备", this);QVBoxLayout *deviceLayout = new QVBoxLayout(m_deviceGroup);m_deviceCombo = new QComboBox(this);deviceLayout->addWidget(m_deviceCombo);m_statusLabel = new QLabel("状态: 未启动", this);deviceLayout->addWidget(m_statusLabel);m_levelBar = new QProgressBar(this);m_levelBar->setRange(0, 100);m_levelBar->setValue(0);m_levelBar->setFormat("音频电平: %p%");deviceLayout->addWidget(m_levelBar);m_mainLayout->addWidget(m_deviceGroup);// 控制按钮组m_controlGroup = new QGroupBox("控制", this);QHBoxLayout *controlLayout = new QHBoxLayout(m_controlGroup);m_startStopButton = new QPushButton("开始采集", this);m_pauseResumeButton = new QPushButton("暂停", this);m_saveButton = new QPushButton("保存数据", this);m_pauseResumeButton->setEnabled(false);m_saveButton->setEnabled(false);controlLayout->addWidget(m_startStopButton);controlLayout->addWidget(m_pauseResumeButton);controlLayout->addWidget(m_saveButton);m_mainLayout->addWidget(m_controlGroup);// 设置组m_settingsGroup = new QGroupBox("设置", this);QHBoxLayout *settingsLayout = new QHBoxLayout(m_settingsGroup);m_autoSaveCheck = new QCheckBox("自动保存", this);m_sampleRateSpin = new QSpinBox(this);m_sampleRateSpin->setRange(8000, 192000);m_sampleRateSpin->setValue(44100);m_sampleRateSpin->setSuffix(" Hz");m_channelsSpin = new QSpinBox(this);m_channelsSpin->setRange(1, 2);m_channelsSpin->setValue(1);m_channelsSpin->setSuffix(" 声道");settingsLayout->addWidget(new QLabel("采样率:", this));settingsLayout->addWidget(m_sampleRateSpin);settingsLayout->addWidget(new QLabel("声道数:", this));settingsLayout->addWidget(m_channelsSpin);settingsLayout->addWidget(m_autoSaveCheck);settingsLayout->addStretch();m_mainLayout->addWidget(m_settingsGroup);// 统计信息m_statsLabel = new QLabel("采集数据: 0 字节", this);m_mainLayout->addWidget(m_statsLabel);m_mainLayout->addStretch();
}void MainWindow::setupConnections()
{connect(m_startStopButton, &QPushButton::clicked, this, &MainWindow::onStartStopClicked);connect(m_pauseResumeButton, &QPushButton::clicked, this, &MainWindow::onPauseResumeClicked);connect(m_saveButton, &QPushButton::clicked, this, &MainWindow::onSaveDataClicked);connect(m_deviceCombo, QOverload<int>::of(&QComboBox::currentIndexChanged),this, &MainWindow::onDeviceChanged);connect(m_audioCapture, &AudioCapture::audioDataAvailable,this, &MainWindow::handleAudioDataAvailable);connect(m_audioCapture, &AudioCapture::audioLevelChanged,this, &MainWindow::handleAudioLevelChanged);connect(m_audioCapture, &AudioCapture::captureStateChanged,this, &MainWindow::handleCaptureStateChanged);connect(m_audioCapture, &AudioCapture::errorOccurred,this, &MainWindow::handleErrorOccurred);
}void MainWindow::updateDeviceList()
{m_deviceCombo->clear();QList<QAudioDeviceInfo> devices = m_audioCapture->getAvailableDevices();for (const QAudioDeviceInfo &device : devices) {m_deviceCombo->addItem(device.deviceName(), QVariant::fromValue(device));}if (devices.isEmpty()) {m_deviceCombo->addItem("未找到音频设备");m_startStopButton->setEnabled(false);}
}void MainWindow::updateUIState()
{if (m_isCapturing) {m_startStopButton->setText("停止采集");m_pauseResumeButton->setEnabled(true);m_saveButton->setEnabled(false); // 采集时不能保存m_deviceCombo->setEnabled(false);m_sampleRateSpin->setEnabled(false);m_channelsSpin->setEnabled(false);if (m_isPaused) {m_pauseResumeButton->setText("继续");m_statusLabel->setText("状态: 已暂停");} else {m_pauseResumeButton->setText("暂停");m_statusLabel->setText("状态: 采集中...");}} else {m_startStopButton->setText("开始采集");m_pauseResumeButton->setEnabled(false);m_pauseResumeButton->setText("暂停");m_saveButton->setEnabled(!m_capturedData.isEmpty());m_deviceCombo->setEnabled(true);m_sampleRateSpin->setEnabled(true);m_channelsSpin->setEnabled(true);m_statusLabel->setText("状态: 未启动");}m_statsLabel->setText(QString("采集数据: %1 字节").arg(m_capturedData.size()));
}void MainWindow::onStartStopClicked()
{if (m_isCapturing) {m_audioCapture->stopCapture();} else {// 应用设置m_audioCapture->setSampleRate(m_sampleRateSpin->value());m_audioCapture->setChannelCount(m_channelsSpin->value());// 开始采集m_audioCapture->startCapture();m_capturedData.clear(); // 清空之前的数据}
}void MainWindow::onPauseResumeClicked()
{if (m_isPaused) {m_audioCapture->resumeCapture();m_isPaused = false;} else {m_audioCapture->pauseCapture();m_isPaused = true;}updateUIState();
}void MainWindow::onSaveDataClicked()
{if (m_capturedData.isEmpty()) {QMessageBox::information(this, "提示", "没有可保存的音频数据");return;}QString fileName = QFileDialog::getSaveFileName(this, "保存音频数据", "", "原始音频数据 (*.raw);;所有文件 (*)");if (!fileName.isEmpty()) {QFile file(fileName);if (file.open(QIODevice::WriteOnly)) {file.write(m_capturedData);file.close();QMessageBox::information(this, "成功", "音频数据已保存");} else {QMessageBox::warning(this, "错误", "无法保存文件");}}
}void MainWindow::onDeviceChanged(int index)
{if (index >= 0) {QAudioDeviceInfo device = m_deviceCombo->itemData(index).value<QAudioDeviceInfo>();m_audioCapture->setAudioDevice(device);}
}void MainWindow::handleAudioDataAvailable(const QByteArray &data)
{m_capturedData.append(data);updateUIState();// 如果启用了自动保存,可以在这里实现自动保存逻辑if (m_autoSaveCheck->isChecked()) {// 自动保存实现(可选)}
}void MainWindow::handleAudioLevelChanged(qreal level)
{int levelPercent = qMin(100, static_cast<int>(level * 100));m_levelBar->setValue(levelPercent);
}void MainWindow::handleCaptureStateChanged(bool capturing)
{m_isCapturing = capturing;m_isPaused = false;updateUIState();
}void MainWindow::handleErrorOccurred(const QString &errorMessage)
{QMessageBox::critical(this, "音频采集错误", errorMessage);m_isCapturing = false;m_isPaused = false;updateUIState();
}

功能特点

  1. 设备选择:自动检测并列出所有可用的音频输入设备

  2. 实时监控:显示音频电平,可视化音频输入强度

  3. 灵活控制:开始/停止、暂停/继续采集

  4. 参数设置:可调节采样率、声道数等音频参数

  5. 数据保存:将采集的原始PCM数据保存为文件

  6. 状态显示:实时显示采集状态和统计数据

编译和运行

  1. 使用 Qt Creator 打开项目文件 AudioCaptureApp.pro

  2. 配置正确的 Qt 版本(确保包含 multimedia 模块)

  3. 编译并运行项目

使用说明

  1. 启动应用程序后,选择要使用的音频输入设备

  2. 根据需要调整采样率和声道数设置

  3. 点击"开始采集"按钮开始录音

  4. 观察音频电平显示,确认设备正常工作

  5. 点击"暂停"可以临时停止采集

  6. 点击"停止采集"结束录音

  7. 点击"保存数据"将采集的音频保存为文件

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/913052.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

923-

9.23模拟赛坐牢一个小时就去写其他题了 T1 DP优化想到了初始的DP状态,但是由于复杂度的 \(O(n^5)\)否掉了自己的做法 没有想到好的办法规避这种情况,唯一的方法就是 在时间充足的情况下尽可能地把一种想法想下去 第…

基于 AI 网关提升大模型应用可用性的实践

阿里云 AI 网关提供了多来源 LLM 服务的代理功能,不仅可以通过简单易用的配置对 LLM 服务进行代理,同时提供了丰富的 LLM 服务入口流量治理功能,提高 LLM 服务的可观测性和可用性。作者:桂楚 随着 LLM 服务广泛部署…

绝了!TaskMatrix Pro - 谷歌、火狐浏览器任务管理插件,四象限矩阵让拖延症瞬间消失 - 开源免费

在当今快节奏的工作环境中,如何高效管理任务和时间已成为每个职场人士必须面对的挑战。传统的任务管理方法往往效率低下,难以应对复杂多变的工作需求。今天,我们将深入探讨一款基于艾森豪威尔矩阵原理的智能任务管理…

荣成市城乡建设局网站wordpress 菜单栏高亮

常用事务码 SE11 SE14 SE16 SE16N SM30 SE11:查看数据库表/修改表中字段数量_类型/查看表中数据/设置表为可维护或不可维护 SE14:查看数据库表的创建日期创建用户名/查看表中字段/删除表中全部数据(只能全部删) SE16:查看数据库表/对可维护数据库表进行数据维护/SE16通过调试…

中山市文联灯饰有限公司网站谁做的宠物网站设计说明书

9.自定义hook函数 什么是hook&#xff1f;—— 本质是一个函数&#xff0c;把setup函数中使用的Composition API进行了封装。 类似于vue2.x中的mixin。 自定义hook的优势: 复用代码, 让setup中的逻辑更清楚易懂。 10.toRef 作用&#xff1a;创建一个 ref 对象&#xff0c;其…

科技未来网站建设pinfinity wordpress

说明&#xff1a;在实际的业务中&#xff0c;难免会跟第三方系统进行数据的交互与传递&#xff0c;那么如何保证数据在传输过程中的安全呢&#xff08;防窃取&#xff09;&#xff1f;除了https的协议之外&#xff0c;能不能加上通用的一套算法以及规范来保证传输的安全性呢&am…

营销型网站建设作用网站建设课程设计报告图文

一、引言 我昨天写了《安卓应用开发学习&#xff1a;获取经纬度及地理位置描述信息》日志&#xff0c;今天再接再厉&#xff0c;记录一下跟着《Android App 开发进阶与项目实战》一书&#xff0c;实现获取导航卫星信息&#xff0c;并在手机上显示的功能的情况。先上实现后的在…

环保类网站建设电商网站建设成本

对于本题 我感觉还是链表做起来舒服 数组也可以做 但是数组需要去控制循环 不太好控制 我之前搞了 最后看别人的实现 但是链表搞了一次就搞好了 香的嘞~ 下面是代码 用单链表实现循环 再去删除要删除的人 5个人 数到2 你们在纸上画图 我就不画了 对于数组实现你们可以去…

网站建设 广州佛山市北区小型网页设计培训

前言 最近工作比较忙&#xff0c;没怎么记录东西了。Android的Handler重要性不必赘述&#xff0c;之前也写过几篇关于hanlder的文章了&#xff1a; Handler有多深&#xff1f;连环二十七问Android多线程&#xff1a;深入分析 Handler机制源码&#xff08;二&#xff09; And…

洛谷P10288 [GESP样题 八级] 区间

原题 题目描述 小杨有一个长度为 \(n\) 的正整数序列 \(A\)。 小杨有 \(q\) 次询问。第 \(i\) 次(\(1\le i\le q\))询问时,小杨会给出 \(l_i,r_i,x_i\),请你求出 \(x_i\) 在 \(A_{l_i}, A_{l_i+1}, \dots A_{r_i}\…

百度如何搜索网址网站推广优化趋势

1. nuScenes 数据集 1.1 概述 nuScenes 数据集 (pronounced /nu:ːsiː:nz/) 是由 Motional (以前称为 nuTonomy) 团队开发的自动驾驶公共大型数据集。nuScenes 数据集的灵感来自于开创性的 KITTI 数据集。 nuScenes 是第一个提供自动驾驶车辆整个传感器套件 (6 个摄像头、1 …

AI 时代下,开发流程的重塑:从“代码先行”到“文档驱动”

本文探讨了AI编程工具在提升效率的同时,因缺乏顶层设计而导致项目混乱的困境。并提出一种“文档驱动”的AI原生开发新范式,强调高质量、结构化的文档是驾驭AI编码,实现高质量交付的关键。文章标题 引言:AI 编程工具…

P13617 [ICPC 2025 APC] Bit Counting Sequenc

题意:给定长度 $n \leq 5 \times 10^5$ 的 popcount 序列 $\{a_i\}$,求其对应的原序列。思路:观察发现 popcount 序列具有倍增构造性质,将原序列 $[0,2^k - 1]$ 的第 $k$ 位改成 $1$ 可得到 $[2^k,2^{k + 1} - 1]$…

perl -MCPAN -e install GD;

001、 Package gdlib was not found in the pkg-config search path.Perhaps you should add the directory containing `gdlib.pcto the PKG_CONFIG_PATH environment variableNo package gdlib found

Day 02 HTML的基础 - 教程

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

如何在网站添加代码大气精美网站设计工作室织梦模板

【芯片DFX】万字长文带你搞懂JTAG的门门道道【芯片DFX】ARM:CoreSight、ETM、PTM、ITM、HTM、ETB等常用术语解析

网络建站的费用微网站开发一般费用多少钱

Navicat Premium&#xff08;16.3.3 Windows 版或以上&#xff09;正式支持 GaussDB 分布式数据库。GaussDB 分布式模式更适合对系统可用性和数据处理能力要求较高的场景。Navicat 工具不仅提供可视化数据查看和编辑功能&#xff0c;还提供强大的高阶功能&#xff08;如模型、结…

什么网站专做店铺wordpress 一栏主题

首先已经创建好了 Vue 框架&#xff0c;安装好了 node.js。 没有完成的可按照此博客搭建&#xff1a;搭建Vue项目 之后打开终端&#xff0c;使用命令。 1、命令安装 axios 和 vue-axios npm install axios --save npm install vue-axios --save2、package.json 查看版本 在 p…

做静态网站的步骤怎么下载网页视频到本地

一、类型转换 C语言中的类型转换比较松散&#xff0c;C新增4个类型转换运算符&#xff0c;更加严格的显示类型转换&#xff0c;使转换的效率更加规范 1、static_cast static_cast&#xff0c;用于仅在编译时检查的强制转换。 如果编译器检测到你尝试在完全不兼容的类型之间强制…