You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何优化Qt C++中24位采样数据的解压与转换耗时?

优化方案

1. 直接操作二进制数据,彻底抛弃字符串转换

原代码通过转十六进制字符串再转整数的方式,是性能瓶颈的核心——字符串拼接、转换会产生大量临时对象和冗余计算。直接读取24位二进制原始数据,完成符号扩展转32位有符号整数:

// 假设数据是大端序(高位字节在前)
signed int convertSample(const unsigned char* data) {
    // 拼接24位数据到32位整数
    int32_t sample = (static_cast<int32_t>(data[0]) << 16) | 
                     (static_cast<int32_t>(data[1]) << 8) | 
                     static_cast<int32_t>(data[2]);
    // 符号扩展:如果24位的最高位(第23位)为1,说明是负数,需要把32位的高8位设为1
    if (sample & 0x800000) {
        sample |= 0xFF000000;
    }
    return sample;
}

// 如果数据是小端序(低位字节在前),用这个版本
signed int convertSampleLittleEndian(const unsigned char* data) {
    int32_t sample = (static_cast<int32_t>(data[2]) << 16) | 
                     (static_cast<int32_t>(data[1]) << 8) | 
                     static_cast<int32_t>(data[0]);
    if (sample & 0x800000) {
        sample |= 0xFF000000;
    }
    return sample;
}

2. 避免循环中频繁创建QByteArray

原代码里chunkSamples.mid(i*3,3)会每次生成新的QByteArray对象,带来不必要的内存分配和拷贝开销。直接通过指针访问chunk的内存:

while(!file.atEnd()){
    QByteArray chunkSamples = file.read(chunkSize);
    const int sampleCount = chunkSamples.size() / 3;
    // 预分配buffer空间,避免多次扩容拷贝
    buffer.reserve(buffer.size() + sampleCount);
    
    const unsigned char* ptr = reinterpret_cast<const unsigned char*>(chunkSamples.constData());
    for (int i = 0; i < sampleCount ; ++i){
        signed int sample = convertSample(ptr + i*3);
        buffer.append(sample);
    }
}

3. 预分配QVector内存

buffer.append默认会在空间不足时自动扩容,每次扩容都要重新分配内存并拷贝已有数据。提前计算每个chunk的样本数,用reserve预留足够空间,能大幅减少内存操作开销。

4. 增大读取块尺寸(可选)

如果磁盘IO性能允许,适当调大chunkSize(比如从100万样本提升到400万样本),减少文件读取的次数,降低IO层面的开销。注意不要超过可用内存上限。

5. 内存映射文件(可选)

如果使用Qt 5.15及以上版本,可通过QFile::map将整个文件映射到内存,直接访问内存中的数据,彻底避免多次read调用的开销:

QFile file("your_file_path");
if (!file.open(QIODevice::ReadOnly)) {
    // 处理文件打开错误
}
qint64 fileSize = file.size();
const unsigned char* fileData = reinterpret_cast<const unsigned char*>(file.map(0, fileSize));
const int totalSamples = fileSize / 3;
buffer.reserve(totalSamples);

for (int i = 0; i < totalSamples; ++i) {
    buffer.append(convertSample(fileData + i*3));
}
file.unmap(fileData);

内容的提问来源于stack exchange,提问作者A.A.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 21:40:58