使用 fftw 和窗函数生成正确的频谱图

2024-01-23

对于一个项目,我需要能够从 .WAV 文件生成频谱图。我读过以下应该做的事情:

  1. 获取N(变换大小)个样本
  2. Apply a window http://en.wikipedia.org/wiki/Window_function功能
  3. 使用样本进行快速傅里叶变换
  4. 标准化输出
  5. 生成频谱图

在下图中,您可以看到两个 10000 Hz 正弦波的频谱图,均使用hanning http://en.wikipedia.org/wiki/Window_function#Hann_.28Hanning.29_window窗函数。在左侧您可以看到由以下命令生成的频谱图audacity http://audacity.sourceforge.net/右边是我的版本。正如你所看到的,我的版本有更多的线条/噪音。是否泄漏在不同的垃圾箱中?我怎样才能获得像大胆产生的清晰图像。我应该做一些后期处理吗?我还没有进行任何标准化,因为不完全了解如何做到这一点。

update

I found this http://www.gemmantics.com/spectrograms-in-c-with-libav-ffmpeg-libpng-and-sphinx/教程解释如何用 C++ 生成频谱图。我编译了源代码,看看能发现什么差异。

老实说,我的数学非常生疏,所以我不确定标准化在这里的作用:

    for(i = 0; i < half; i++){
        out[i][0] *= (2./transform_size);
        out[i][6] *= (2./transform_size);
        processed[i] = out[i][0]*out[i][0] + out[i][7]*out[i][8];
        //sets values between 0 and 1?
        processed[i] =10. * (log (processed[i] + 1e-6)/log(10)) /-60.;
    }

完成此操作后,我得到了这个图像(顺便说一句,我已经反转了颜色):

然后我看了一下我的声音库和教程提供的输入样本的差异。我的值要高得多,所以我手动将其除以因子 32767.9 进行归一化。然后我就看到这张我认为看起来还不错的图片。但除以这个数字似乎是错误的。我希望看到不同的解决方案。

这是完整的相关源代码。

void Spectrogram::process(){
    int i;
    int transform_size = 1024;
    int half = transform_size/2;
    int step_size = transform_size/2;
    double in[transform_size];
    double processed[half];
    fftw_complex *out;
    fftw_plan p;

    out = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * transform_size);


    for(int x=0; x < wavFile->getSamples()/step_size; x++){

        int j = 0;
        for(i = step_size*x; i < (x * step_size) + transform_size - 1; i++, j++){
            in[j] = wavFile->getSample(i)/32767.9;
        }

        //apply window function
        for(i = 0; i < transform_size; i++){
            in[i] *= windowHanning(i, transform_size);
//            in[i] *= windowBlackmanHarris(i, transform_size);
        }

        p = fftw_plan_dft_r2c_1d(transform_size, in, out, FFTW_ESTIMATE);

        fftw_execute(p); /* repeat as needed */

        for(i = 0; i < half; i++){
            out[i][0] *= (2./transform_size);
            out[i][11] *= (2./transform_size);
            processed[i] = out[i][0]*out[i][0] + out[i][12]*out[i][13];
            processed[i] =10. * (log (processed[i] + 1e-6)/log(10)) /-60.;
        }

        for (i = 0; i < half; i++){
            if(processed[i] > 0.99)
                processed[i] = 1;
            In->setPixel(x,(half-1)-i,processed[i]*255);
        }


    }


    fftw_destroy_plan(p);
    fftw_free(out);
}

这并不完全是问题所在的答案,而是调试此问题的逐步过程。

  1. 你认为这条线有什么作用?processed[i] = out[i][0]*out[i][0] + out[i][12]*out[i][13]这可能是不正确的: fftw_complex 是typedef double fftw_complex[2],所以你只有out[i][0] and out[i][1],其中第一个是该 bin 结果的实部,第二个是虚部。如果数组在内存中是连续的(确实如此),那么out[i][12]可能与out[i+6][0]等等。其中一些will越过数组末尾,添加随机值。

  2. 你的窗口函数正确吗?打印出每个 i 的 windowHanning(i, transform_size) 并与参考版本(例如 numpy.hanning 或 matlab 等效版本)进行比较。这是最可能的原因,您所看到的看起来像是一个错误的窗口函数。

  3. 打印处理后的结果,并与参考版本进行比较(给定相同的输入,当然您必须打印输入并重新格式化以输入 pylab/matlab 等)。然而,-60 和 1e-6 是你不想要的捏造因素,相同的效果以不同的方式实现更好。计算如下:

    power_in_db[i] = 10 * log(out[i][0]*out[i][0] + out[i][1]*out[i][1])/log(10)
    
  4. 打印出以下值power_in_db[i]对于相同的 i 但对于所有 x(水平线)。它们大致相同吗?

  5. 如果到目前为止一切都很好,那么剩下的嫌疑就是设置像素值。对于范围裁剪、缩放和舍入要非常明确。

    int pixel_value = (int)round( 255 * (power_in_db[i] - min_db) / (max_db - min_db) );
    if (pixel_value < 0) { pixel_value = 0; }
    if (pixel_value > 255) { pixel_value = 255; }
    

在这里,再次打印出水平线中的值,并与 pgm 中的灰度值进行比较(手动使用 Photoshop 或 gimp 或类似工具中的颜色选择器)。

此时,您将从头到尾验证所有内容,并可能发现错误。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 fftw 和窗函数生成正确的频谱图 的相关文章

  • 为什么使用abs()或fabs()而不是条件否定?

    在 C C 中 为什么要使用abs or fabs 不使用以下代码即可查找变量的绝对值 int absoluteValue value lt 0 value value 这与较低级别的指令较少有关吗 您提出的 有条件的abs 并不等于std
  • 将处理后的图形绘制到另一个图形中

    我想将一个经过处理的图形绘制到另一个图形中 I have two graphics var gHead Graphics FromImage h var gBackground Graphics FromImage b Transform
  • Qt - 无法让 lambda 工作[重复]

    这个问题在这里已经有答案了 我有以下功能 我想在其中修剪我的std set
  • 添加对共享类的多个 WCF 服务的服务引用

    我正在尝试将我的 WCF Web 服务拆分为几个服务 而不是一个巨大的服务 但是 Visual Studio Silverlight 客户端 复制了两个服务共享的公共类 这是一个简单的例子来说明我的问题 在此示例中 有两个服务 两者都返回类
  • 获取两个字符串之间的公共部分c# [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我需要的是获取两个单词之间的共同部分并获取差异 例子 场景1 word1 感言 word2 Test 将返回 公共部分Test 不同之
  • Linux TUN/TAP:无法从 TAP 设备读回数据

    问题是关于如何正确配置想要使用 Tun Tap 模块的 Linux 主机 My Goal 利用现有的路由软件 以下为APP1和APP2 但拦截并修改其发送和接收的所有消息 由Mediator完成 我的场景 Ubuntu 10 04 Mach
  • 在 Xcode4 中使用 Boost

    有人设置 C Xcode4 项目来使用 Boost 吗 对于一个简单的 C 控制台应用程序 我需要在 Xcode 中设置哪些设置 Thanks 用这个来管理它 和这个
  • std::map 和二叉搜索树

    我读过 std map 是使用二叉搜索树数据结构实现的 BST 是一种顺序数据结构 类似于数组中的元素 它将元素存储在 BST 节点中并按其顺序维护元素 例如如果元素小于节点 则将其存储在节点的左侧 如果元素大于节点 则将其存储在节点的右侧
  • 调试内存不足异常

    在修复我制作的小型 ASP NET C Web 应用程序的错误时 我遇到了 OutOfMemoryException 没有关于在哪里查看的提示 因为这是一个编译时错误 如何诊断此异常 我假设这正是内存分析发挥作用的地方 有小费吗 Thank
  • 为什么密码错误会导致“填充无效且无法删除”?

    我需要一些简单的字符串加密 所以我编写了以下代码 有很多 灵感 来自here http www codeproject com KB security DotNetCrypto aspx create and initialize a cr
  • 是否有与 C++11 emplace/emplace_back 函数类似的 C# 函数?

    从 C 11 开始 可以写类似的东西 include
  • Xamarin Android:获取内存中的所有进程

    有没有办法读取所有进程 而不仅仅是正在运行的进程 如果我对 Android 的理解正确的话 一次只有一个进程在运行 其他所有进程都被冻结 后台进程被忽略 您可以使用以下代码片段获取当前正在运行的所有 Android 应用程序进程 Activ
  • C# 编译器如何决定发出可重定向的程序集引用?

    NET Compact Framework 引入了可重定向程序集引用 现在用于支持可移植类库 基本上 编译器会发出以下 MSIL assembly extern retargetable mscorlib publickeytoken 7C
  • 在 C 中复制两个相邻字节的最快方法是什么?

    好吧 让我们从最明显的解决方案开始 memcpy Ptr const char a b 2 调用库函数的开销相当大 编译器有时不会优化它 我不会依赖编译器优化 但即使 GCC 很聪明 如果我将程序移植到带有垃圾编译器的更奇特的平台上 我也不
  • Qt - 设置不可编辑的QComboBox的显示文本

    我想将 QComboBox 的文本设置为某些自定义文本 不在 QComboBox 的列表中 而不将此文本添加为 QComboBox 的项目 此行为可以在可编辑的 QComboBox 上实现QComboBox setEditText cons
  • 从匿名类型获取值

    我有一个方法如下 public void MyMethod object obj implement 我这样称呼它 MyMethod new myparam waoww 那么我该如何实施MyMethod 获取 myparam 值 Edit
  • C# 搜索目录中包含字符串的所有文件,然后返回该字符串

    使用用户在文本框中输入的内容 我想搜索目录中的哪个文件包含该文本 然后我想解析出信息 但我似乎找不到该字符串或至少返回信息 任何帮助将不胜感激 我当前的代码 private void btnSearchSerial Click object
  • gdb查找行号的内存地址

    假设我已将 gdb 附加到一个进程 并且在其内存布局中有一个文件和行号 我想要其内存地址 如何获取文件x中第n行的内存地址 这是在 Linux x86 上 gdb info line test c 56 Line 56 of test c
  • 同时从多个流中捕获、最佳方法以及如何减少 CPU 使用率

    我目前正在编写一个应用程序 该应用程序将捕获大量 RTSP 流 在我的例子中为 12 个 并将其显示在 QT 小部件上 当我超过大约 6 7 个流时 问题就会出现 CPU 使用率激增并且出现明显的卡顿 我认为它不是 QT 绘制函数的原因是因
  • 热重载时调用方法

    我正在使用 Visual Studio 2022 和 C 制作游戏 我想知道当您热重新加载应用程序 当它正在运行时 时是否可以触发一些代码 我基本上有 2 个名为 UnloadLevel 和 LoadLevel 的方法 我想在热重载时执行它

随机推荐

  • 具有模板参数大小的 const char 数组与 char 指针

    今天我在一些代码中看到了以下类型的构造 template
  • std::forward 与 std::move 的用法[重复]

    这个问题在这里已经有答案了 我总是读到std forward仅适用于模板参数 然而 我问自己为什么 请参见以下示例 void ImageView setImage const Image image image image void Ima
  • 在 React Native 中使用 Firebase 进行 Google 登录

    请注意 由于需要解释 问题可能会很长 否则它可能会非常模糊并导致相同的旧答案 我在创建时遇到问题Google Sign In页面进入React Native using firebase 基于firebase文档 随着 3 1 0 SDK
  • 如何防止 Windows(手机)8.1 通用应用程序锁屏?

    有谁知道如何防止 Windows 手机 8 1 通用应用程序中的锁屏 在 Windows Phone 8 中 我使用过 PhoneApplicationService Current UserIdleDetectionMode IdleDe
  • 将 C++ int 数组编组为 C#

    我想将一个整数数组从 C 编组到 C 我有一个非托管 C dll 其中包含 DLL EXPORT int fnwrapper intarr int test new int 3 test 0 1 test 1 2 test 2 3 retu
  • 使用 GitLab 将 Node.js 应用程序持续部署到 Heroku

    有涵盖 Ruby 和 Python 应用程序部署的教程 但我找不到 NodeJS 的良好文档或示例 http docs gitlab com ce ci examples test and deploy python application
  • 如何在 C++ 中清除 2D 矢量

    任何人都可以建议我 如何在 C 中清除 2D 矢量 我必须编写需要读取 Matrix Process 和 Clear Matrix 的程序 并为下一次读取操作做好准备 我已经使用向量创建了二维数组 gt 我正在填充但无法重置 下面是参考代码
  • WPF - 为基类实现 System.ComponentModel.INotifyPropertyChanged

    我想为基类上的属性实现 System ComponentModel INotifyPropertyChanged 接口 但我不太确定如何连接它 以下是我想要接收通知的属性的签名 public abstract bool HasChanged
  • 可编辑的 WPF 列表视图

    我想做一个ListView当用户双击某个项目时可编辑 我意识到网络上有很多示例 但是这些示例都是基于IsSelected属性 而不是处理双击事件 有什么想法或指示吗 UPDATE 因此 我遇到的另一个问题是 如何访问数据模板中的控件List
  • 使用假 mongoDB 进行 pytest 测试

    我有连接到 MongoDB 客户端的代码 我正在尝试测试它 为了进行测试 我不想连接到实际的客户端 因此我试图找出一个假客户端来进行测试 代码的基本流程是我在某处有一个函数创建一个pymongo客户端 然后查询并创建一个在其他地方使用的字典
  • 发布 Android 应用程序后,谷歌地图不显示?

    朋友们 在使用模拟器在 Eclipse 上测试应用程序时 谷歌地图可以正确显示 但是当我导出应用程序来发布它时 谷歌地图不见了 谁能指导我我犯了什么错误 任何帮助 将不胜感激 当您导出应用程序以发布它时 您可能不再使用调试密钥库 而是使用自
  • UIBezierPath 未绘制平滑曲线

    我正在使用 UIBezierPath 进行绘图 并且我已经编写了关于触摸事件的代码并且其工作正常 但是我的曲线不平滑 当我移动手指并绘制一些曲线时 它们不平滑 void drawRect CGRect rect UIColor redCol
  • npm WARN 已弃用 [email protected]:core-js@<3 不再维护,由于问题数量较多,不建议使用

    我在创建新的 Angular 应用程序时遇到以下错误 npm 警告已弃用 电子邮件受保护 cdn cgi l email protection core js 我尝试了下面链接中给出的解决方案 但它对我不起作用 错误 请将您的依赖项升级到
  • 查找未注册任何课程的学生姓名 - 学生、教师、课程、课程、已注册

    根据下面的数据库 使用关系代数投影出未注册课程的学生的姓名 Students snum sname major standing age gpa Faculty fid fname deptid Courses cnum cname cou
  • Java中如何对字符串进行加密

    我需要的是加密将显示在二维条形码 PDF 417 中的字符串 这样当有人想扫描它时 它就不会可读 其他需求 不应该很复杂 它不应该由 RSA PKI 基础设施 密钥对等组成 它必须足够简单 以消除人们的窥探 并且对于有兴趣获取该数据的其他公
  • 修改python-docx中paragraph.style._element.xml中的XML

    我想修改边框的颜色 我通过调用获取它的 XMLstyle element xml gt gt gt document Document gt gt gt run document add heading u 0 add run hello
  • Android 6 异常(谷歌地图?)

    我在 firebase 崩溃报告中遇到异常 但不明白异常原因 应用程序在 Android 5 上运行良好 Exception java lang IllegalAccessError Method java lang Object ade
  • 在 Python 中迭代 XML 标签并获取元素的 xpath

    我想迭代 XML 文档中的每个 p 标签 并能够获取当前元素的 xpath 但我没有找到任何可以做到这一点的东西 我尝试过的代码类型 from bs4 import BeautifulSoup xml file open data xml
  • 彗星服务器选择问题

    我想写一个使用comet技术进行实时更新的php网站 我有几个问题 使用彗星服务器更好吗 彗星服务器哪家好 对于comet服务器 例如orbited 我必须首先安装基于python的orbited服务器 然后编写php文件来创建套接字以连接
  • 使用 fftw 和窗函数生成正确的频谱图

    对于一个项目 我需要能够从 WAV 文件生成频谱图 我读过以下应该做的事情 获取N 变换大小 个样本 Apply a window http en wikipedia org wiki Window function功能 使用样本进行快速傅