Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >WAV-文件分析C (libsndfile,fftw3)

WAV-文件分析C (libsndfile,fftw3)
EN

Stack Overflow用户
提问于 2012-05-16 14:15:21
回答 1查看 8.6K关注 0票数 10

我正在尝试开发一个简单的C应用程序,它可以在WAV文件中给定时间戳的某个频率范围内给出0到100的值。

示例:我的频率范围为44.1kHz (典型的MP3文件),我希望将该范围拆分为n个范围(从0开始)。然后我需要得到每个范围的振幅,从0到100。

到目前为止我所做的:

使用libsndfile,我现在能够读取WAV-文件的数据。

代码语言:javascript
运行
AI代码解释
复制
infile = sf_open(argv [1], SFM_READ, &sfinfo);

float samples[sfinfo.frames];

sf_read_float(infile, samples, 1);

然而,我对FFT的理解是相当有限的。但我知道要在我需要的范围内获得振幅是必需的。但我该怎么从这里开始呢?我找到了FFTW-3图书馆,它似乎适合这个用途。

我在这里找到了一些帮助:https://stackoverflow.com/a/4371627/1141483

在这里查看FFTW教程:2.html

但是,由于我不确定自由工联的行为,我不知道从这里取得什么进展。

还有另一个问题,假设您使用libsndfile:如果您强迫读取单通道(使用立体声文件),然后读取示例。那么,您实际上只读取了整个文件的一半样本吗?其中一半来自第一频道,还是自动过滤掉?

非常感谢你的帮助。

编辑:我的代码可以在这里看到:

代码语言:javascript
运行
AI代码解释
复制
double blackman_harris(int n, int N){
double a0, a1, a2, a3, seg1, seg2, seg3, w_n;
a0 = 0.35875;
a1 = 0.48829;
a2 = 0.14128;
a3 = 0.01168;

seg1 = a1 * (double) cos( ((double) 2 * (double) M_PI * (double) n) / ((double) N - (double) 1) );
seg2 = a2 * (double) cos( ((double) 4 * (double) M_PI * (double) n) / ((double) N - (double) 1) );
seg3 = a3 * (double) cos( ((double) 6 * (double) M_PI * (double) n) / ((double) N - (double) 1) );

w_n = a0 - seg1 + seg2 - seg3;
return w_n;
}

int main (int argc, char * argv [])
{   char        *infilename ;
SNDFILE     *infile = NULL ;
FILE        *outfile = NULL ;
SF_INFO     sfinfo ;


infile = sf_open(argv [1], SFM_READ, &sfinfo);

int N = pow(2, 10);

fftw_complex results[N/2 +1];
double samples[N];

sf_read_double(infile, samples, 1);


double normalizer;
int k;
for(k = 0; k < N;k++){
    if(k == 0){

        normalizer = blackman_harris(k, N);

    } else {
        normalizer = blackman_harris(k, N);
    }

}

normalizer = normalizer * (double) N/2;



fftw_plan p = fftw_plan_dft_r2c_1d(N, samples, results, FFTW_ESTIMATE);

fftw_execute(p);


int i;
for(i = 0; i < N/2 +1; i++){
    double value = ((double) sqrtf(creal(results[i])*creal(results[i])+cimag(results[i])*cimag(results[i]))/normalizer);
    printf("%f\n", value);

}



sf_close (infile) ;

return 0 ;
} /* main */
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-05-17 14:00:13

这完全取决于你所追求的频率范围。FFT的工作原理是获取2^n样本,并为你提供2^(n-1)实数和虚数。我不得不承认,我对这些价值观到底代表了什么(我有一个朋友承诺要和我一起度过这一切,而不是在他有财务问题时我给他的一笔贷款),我很模糊),而不是一个圆圈的角度。有效地,他们提供了一个arccos的角度参数的正弦和余弦的每一个频率宾,其中原始的2^n样本,可以完美地,重建。

无论如何,这有一个巨大的优势,你可以通过取实部和虚部(sqrtf( (实*实)+ (imag * imag ) )的欧几里得距离来计算震级。这为您提供了一个未规范化的距离值。然后,该值可用于为每个频带构建一个幅度。

因此,让我们采用10 FFT (2^10)的顺序。你输入了1024个样本。您可以对这些样本进行FFT处理,得到512个假想值和实数(这些值的特殊顺序取决于您使用的FFT算法)。这意味着,对于一个44.1Khz音频文件,每个bin代表44100/512 Hz或~86 Hz/ bin。

有一点值得注意的是,如果您使用更多的样本(在处理多维信号(如图像)时,使用更多的样本(从所谓的时间域或空间域),则可以获得更好的频率表示(在所谓的频域中)。不管你为了另一个牺牲一个。事情就是这样进行的,你必须接受它。

基本上,您将需要调整频率箱和时间/空间分辨率,以获得您需要的数据。

首先来点命名。我前面提到的1024个时域示例称为“您的窗口”。通常,在执行这类处理时,您需要在窗口上滑动一定数量的窗口,以获得下一个1024个样本(您的FFT )。最明显的做法是取样本0->1023,然后1024->2047,以此类推。不幸的是,这并没有给出最好的结果。理想情况下,您希望在一定程度上重叠窗口,以便随着时间的推移,您的频率变化会更平稳。最常见的情况是,人们把窗户滑动到半个窗口大小。你的第一个窗口是0->1023,第二个512->1535等等。

现在,这就引出了另一个问题。虽然这一信息提供了完美的逆FFT信号重建,它给你留下了一个问题,频率泄漏到环抱箱在一定程度上。为了解决这个问题,一些数学家(比我聪明得多)提出了窗口函数的概念。窗口函数在频域中提供了更好的频率隔离,尽管它会导致时域信息的丢失(即在使用窗口函数AFAIK之后不可能完美地重新构造信号)。

现在有各种类型的窗口函数,从矩形窗口(实际上对信号没有任何作用)到提供更好频率隔离的各种功能(尽管有些函数还可能扼杀您可能感兴趣的周围频率!!)唉,没有一个尺寸适合所有的人,但我是一个狂热的球迷(谱图)的黑曼-哈里斯窗口功能。我认为它能给出最好看的结果!

然而,正如我前面提到的,FFT为你提供了一个未正常化的光谱。要使光谱正常化(在欧几里德距离计算之后),您需要将所有值除以一个归一化因子(我将详细介绍这里)。

这种标准化将为您提供一个介于0到1之间的值。因此,您可以轻松地将此值乘以100,以获得0到100的比例。

然而,这并不是它的终点。你从这得到的光谱是相当不令人满意的。这是因为你用线性尺度来观察震级。不幸的是,人类耳朵听到的是对数音阶。这就导致了光谱图/光谱的外观问题。

为了解决这个问题,您需要将这0到1的值(我称之为'x')转换为分贝标度。标准转换是log10f( X)。然后,这将为您提供一个值,其中1已转换为0,0已转换为-infinity。你的震级现在在适当的对数尺度上。然而,这并不总是那么有帮助。

此时,您需要查看原始示例位深度。在16位抽样时,得到一个介于32767到-32768之间的值。这意味着您的动态范围为fabsf( 20.0f * log10f( 1.0f / 65536.0f ))或~96.33dB。所以现在我们有了这个价值。

取我们从上面的dB计算中得到的值。加上这个-96.33的价值。显然,最大振幅(0)现在是96.33。现在除以相同的值,您就没有一个从-infinity到1.0f的值。夹紧下端到0,你现在有一个范围从0到1,乘以100,你就有了最后的0到100范围。

这是一个怪物的帖子,比我原来的打算,但应该给你一个良好的基础如何产生一个良好的光谱/光谱图的输入信号。

呼吸

进一步阅读(供已发现原海报的人参考):

将FFT转换为平面图

编辑:顺便提一下,我发现kiss使用起来容易得多,我执行前向FFT的代码如下:

代码语言:javascript
运行
AI代码解释
复制
CFFT::CFFT( unsigned int fftOrder ) :
    BaseFFT( fftOrder )
{
    mFFTSetupFwd    = kiss_fftr_alloc( 1 << fftOrder, 0, NULL, NULL );
}

bool CFFT::ForwardFFT( std::complex< float >* pOut, const float* pIn, unsigned int num )
{
    kiss_fftr( mFFTSetupFwd, pIn, (kiss_fft_cpx*)pOut );
    return true;
}
票数 14
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10627517

复制
相关文章
vue中在父组件点击按钮触发子组件的事件
1、父组件的button元素绑定click事件,该事件指向notify方法 2、给子组件注册一个ref=“child” 3、父组件的notify的方法在处理时,使用了$refs.child把事件传递给子组件的parentMsg方法,同时携带着父组件中的参数msg 4、子组件接收到父组件的事件后,调用了parentMsg方法,把接收到的msg放到message数组中
江一铭
2022/06/16
6.5K0
vue.js 父组件如何触发子组件中的方法
组件 (Component) 是 Vue.js 最强大的功能之一。组件可以扩展 HTML 元素,封装可重用的代码。在较高层面上,组件是自定义元素,Vue.js 的编译器为它添加特殊功能。在有些情况下,组件也可以表现为用 is 特性进行了扩展的原生 HTML 元素。
IT工作者
2022/02/17
4.8K0
vue 父组件调用子组件的函数_vue子组件触发父组件方法
项目里将element-ui的el-upload写成公共组件方便调用,官方的before-upload方法用于处理上传前要做的事,如:比较文件大小,限制文件类型等,通过返回true 或 false 控制是否上传。 当该组件调用父组件方法,并且要能获取到父组件方法的返回值,如何实现?
全栈程序员站长
2022/11/10
3K0
vue子组件传值给父组件_子组件调用父组件中的方法
大家好,又见面了,我是你们的朋友全栈君。 参考视频 : https://www.bilibili.com/video/av32790541/?spm_id_from=trigger_reload 原
全栈程序员站长
2022/10/04
4.3K0
vue子组件传值给父组件_子组件调用父组件中的方法
Vuejs中父组件主动调用子组件的方法
我们都知道,vue是单向流,但是有时候我们需要在父组件中主动通知子组件一些信息,使其做出一些响应变化,那么如何在父组件中去主动调用子组件的方法呢?Vue当然给我们提供了方法,如下:
飞奔去旅行
2019/06/13
5.1K0
Vue父组件调用子组件事件
Vue父组件向子组件传递事件/调用事件 不是传递数据(props)哦,适用于 Vue 2.0 方法一:子组件监听父组件发送的方法 方法二:父组件调用子组件方法 子组件: export default { mounted: function () { this.$nextTick(function () { this.$on('childMethod', function () { console.log('监听成功') })
大鹅
2021/06/11
7490
Vue父组件与子组件传递事件/调用事件
如上:通过this.$emit()来触发父组件的方法。具体就是子组件触发$emit绑定的事件watchChild,然后父组件监听watchChild,一旦watchChild被触发便会触发父组件的parentReceive方法。
IT工作者
2022/02/17
3.5K0
输入框在输入中文时回车误触发输入的回车事件
这个问题出现在:chatx.me的输入框 最近反应的人比较多,然后还是问了下前前端同事,解决了。
SingYi
2023/08/23
3500
阻止中文输入时触发input事件
做限制输入框可输入最大的长度和实时匹配输入框数据时遇到了坑 —— 当中文输入时input事件也会被触发,即假设限制的是2个字符,你要输入社会人的“社(she)”,就会直接被截取,输入框填充文本sh。或者是在中文输入法时也会一直去调接口,匹配数据,影响了页面的性能!代码如下:
全栈程序员站长
2022/09/01
1.2K0
vue 父组件调用子组件的方法_vue子组件修改父组件值
我们都知道通过$ref可以获取到某个DOM,但是它也可以用来获取子组件的实例,调用子组件的方法
全栈程序员站长
2022/11/09
2.1K0
React父组件调用子组件的方法
React组件化开发中子组件可以通过传递变量或者父组件的方法来实现和父组件的通信或者调用函数传值,但是父组件如何调用子组件的方法呢?很多介绍Hooks的文章并没有讲到useImperativeHandle,我以使用React18+TypeScript开发的项目为例,组件使用Hooks。以下是我精简过后的代码。
用户6256742
2022/07/06
5.8K0
Vue子组件调用父组件的方法
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
多凡
2019/11/01
2.2K0
子组件派发事件和值给父组件
父组件通过v-on绑定子组件派发的事件,并触发一个新的事件,新的事件内可以接收传来的值
小小杰啊
2022/12/21
3040
vue父组件引入子组件_vue子组件传递方法给父组件
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
全栈程序员站长
2022/11/09
1.1K0
vue父组件操作子组件的方法_vue父组件获取子组件数据
我们经常分不清什么是父组件,什么是子组件。现在来简单总结下:我们将某段代码封装成一个组件,而这个组件又在另一个组件中引入,而引入该封装的组件的文件叫做父组件,被引入的组件叫做子组件。具体代码如下
全栈程序员站长
2022/09/19
7.1K0
vue父组件操作子组件的方法_vue父组件获取子组件数据
vue父组件调用子组件方法
抱怨身处黑暗,不如提灯前行。——刘同 首先是官方文档 这里使用ref属性去访问子元素 <hello-world ref="helloWorld" msg="Hello World"></hello-world> 然后打印一下 console.log(this.$refs.helloWorld); 可以看到成功获取到 再到子组件定义一个方法: 父组件访问: 效果:
阿超
2022/08/17
1.8K0
vue父组件调用子组件方法
vue子组件调用父组件方法
强迫学习的东西是不会保存在心里的。——《柏拉图论教育》 首先我们在子组件中这样定义 <template> <div> <el-button @click="callSuper">123</el-button> </div> </template> <script> export default { methods: { callSuper() { this.$emit('parentEvent', '我的'); } } }; </script> 这里的组件就只有一个el-
阿超
2022/08/16
2.1K0
vue子组件调用父组件方法
input输入中文时,拼音触发input事件
在上一篇文章中写到了函数防抖,在使用函数防抖来进行搜索框优化的时候会遇到一个问题,就是监听文本输入框的input事件,在拼写汉字(输入法)但汉字并未实际填充到文本框中时会触发input事件,会出现下图的效果
OECOM
2020/07/01
8.3K1
vue父组件调用子组件方法
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
多凡
2019/11/01
2.6K0
vue父组件中获取子组件中的数据
<FormItem label="上传头像" prop="image"> <uploadImg :width="150" :height="150" :name="'avatar'" size="150px*150px" ref="avatar"></uploadImg> </FormItem> <FormItem label="上传营业执照" prop="businessLicence"> <uploadImg :width="350" :heigh
蓓蕾心晴
2018/04/12
7K0

相似问题

触发父组件父节点方法的子组件输出事件

38

监听VueJs中父组件触发的事件

110

如何从角2中的子组件事件触发父组件中的局部引用?

25

子组件中父组件的触发方法-- react

14

角键事件不会在子组件上触发,而只在父组件上触发。

13
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档