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

如何获取原函数*data值并将文件读取改为USB流实现FFT变换?

问题解答

1. 如何获取原始函数中*data的值?

data是int16_t*类型的动态数组,获取其值的方式如下:

  • 单个元素访问:通过下标直接读取,例如int16_t firstSample = data[0];即可拿到第一个采样值,下标范围是0到numSamples-1。
  • 遍历所有元素:用循环逐个读取,示例代码:
for (uint32_t i = 0; i < numSamples; ++i) {
    int16_t currentSample = data[i];
    // 对当前采样值进行处理
}
  • 指针直接访问:使用*(data + i),效果和data[i]完全等价,比如int16_t sample = *(data + 5);可以获取第6个元素的值。

2. USB流数据接入FFT变换的实现方案

核心思路

原代码是一次性读取完整的numSamples个int16_t采样点,USB流是分批传输数据,因此需要先缓存流数据,直到凑够所需的采样点数,再转换为int16_t类型接入FFT逻辑。

修改后的完整代码

#include <cstdint>
#include <vector>
#include <iostream>
#include <fftw3.h>

void usbStream2FFT()
{
    const uint32_t numSamples = 1920018;
    const size_t totalBytesNeeded = numSamples * sizeof(int16_t);
    // 用vector做动态缓存,自动管理内存
    std::vector<uint8_t> dataBuffer;
    dataBuffer.reserve(totalBytesNeeded);

    // 提前创建FFT计划和缓冲区,避免循环内重复创建浪费资源
    fftw_complex* in = reinterpret_cast<fftw_complex*>(fftw_malloc(sizeof(fftw_complex) * numSamples));
    fftw_plan plan = fftw_plan_dft_1d(numSamples, in, in, FFTW_FORWARD, FFTW_ESTIMATE);

    // 缓存足够的字节数据
    while (dataBuffer.size() < totalBytesNeeded)
    {
        uint32_t rxSize = 0;
        if (FT4222_SPISlave_GetRxStatus(ftHandle, &rxSize) == FT_OK && rxSize > 0)
        {
            uint8_t* pRead_data = reinterpret_cast<uint8_t*>(malloc(rxSize));
            if (!pRead_data) continue;

            // 补充实际读数据的API调用,替换为FT4222_SPISlave_Read的真实逻辑
            uint32_t actualReadSize = rxSize;
            // FT4222_SPISlave_Read(ftHandle, pRead_data, rxSize, &actualReadSize);

            // 将读取的字节加入缓存
            dataBuffer.insert(dataBuffer.end(), pRead_data, pRead_data + actualReadSize);
            free(pRead_data);
        }
    }

    // 将缓存的字节转换为int16_t数组(注意字节序,若设备与主机字节序不同需做转换)
    int16_t* data = reinterpret_cast<int16_t*>(dataBuffer.data());

    // 填充FFT输入缓冲区
    for (uint32_t i = 0; i < numSamples; ++i) {
        in[i][0] = static_cast<double>(data[i]);
        in[i][1] = 0.0; // 实信号虚部设为0
    }

    // 执行FFT变换
    fftw_execute(plan);

    // 输出FFT结果
    for (uint32_t i = 0; i < numSamples / 2; ++i) {
        double realPart = in[i][0];
        double imagPart = in[i][1];
        double magnitude = sqrt(realPart * realPart + imagPart * imagPart);

        std::cout << "Frequency bin " << i << ": Magnitude=" << magnitude << std::endl;
    }

    // 清理资源
    fftw_destroy_plan(plan);
    fftw_free(in);
}

关键注意事项

  • 字节序处理:如果USB设备传输的int16_t数据字节序与主机端不一致(比如设备是大端、主机是小端),需要手动转换字节序,示例转换函数:
int16_t swapByteOrder(uint8_t highByte, uint8_t lowByte) {
    return static_cast<int16_t>((highByte << 8) | lowByte);
}
// 使用时替换data[i]的赋值:
data[i] = swapByteOrder(dataBuffer[2*i], dataBuffer[2*i+1]);
  • 内存管理:fftw_plan和fftw_complex缓冲区创建开销大,必须提前初始化,避免在循环内重复创建。
  • 实际读数据逻辑:代码中actualReadSize为占位,需替换为FT4222_SPISlave_Read返回的真实读取字节数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 22:00:12