文章中的示例音频
音频文件
信号就是某一特定量随时间变化。对于音频来说,这个特定的变化量就是气压。那我们如何去数字化地捕获这些信息呢?我们可以在某个时间段内对气压进行采样。我们采集数据的采样率是可以变化的,但是最常用的是44.1kHz(每秒采集44100个样)。我们采集到的信号叫做波形(waveform),并且它可以通过计算机软件进行解释,修改和分析。
import librosa
import librosa.display
import matplotlib.pyplot as plt
y, sr = librosa.load('CantinaBand3.wav')
plt.plot(y)
plt.title('Signal')
plt.xlabel('Time (samples)')
plt.ylabel('Amplitude')
plt.savefig('音频频率图.png')

好棒!我们现在拥有了一个可以处理的语音信号数字表示。欢迎来到信号处理的领域!然后,你可能会想,那我们如何从这里提取中有用的信息的?目前看起来是一团乱麻。别担心,我们的朋友傅立叶变换正在款款走来!
一个音频信号由多个单频声波组成。当我们随着时间对信号进行采样时,我们仅仅能够捕获到最终叠加后的振幅(amplitude)。傅立叶变换是一个数学工具,它能够帮助我们将一个信号分解为多个频率以及频率对应的振幅。换句话说,它可以将信号从时域转化为频域。最终的结果成为谱(spectrum)。

这是可能的,因为每一个信号都能分解为一些列正弦波和余弦波的叠加。这就是著名的傅立叶定理。
快速傅立叶变换(fast Fourier transform, FFT)是一种可以高效计算傅立叶变换的算法。被广泛运用于信号处理领域。我们在音频的加窗段上使用这个算法。
import numpy as np
n_fft = 2048
ft = np.abs(librosa.stft(y[: n_fft], hop_length = n_fft + 1))
plt.plot(ft)
plt.title('Spectrum')
plt.xlabel('Frequency Bin')
plt.ylabel('Amplitude')
plt.savefig('spectrum.png')

快速傅立叶变换时让我们分析信号内容中频率含量的有力工具,但是如果我们的信号中频率含量含量时随时间变化的呢?例如音乐,讲话。它们又叫做非周期信号。你可能会想:“我们不能通过对多个信号加窗段进行FFT,从而得到多个谱吗?”是的,这就是我们在做的,我们称为短时傅里叶变换(short-time Fourier transform,STFT),FFT信号在信号的重叠加窗段上计算,我们就得到了所谓的频谱图(spectrogram)。

你可以把频谱图当作一堆FFTs彼此叠加的结果。这是一种信号响度,或者频率的视觉表现,因为它随着时间在不同频率上进行变化。除此之外,在计算频谱图的时候还有一些额外的细节。如下图所示,y轴,也就是频率轴以log为尺度(你可以认为是频率取log),并且颜色维度用于表示分贝。这是因为人类只能感知非常小而集中的频率和振幅的范围。
spec = np.abs(librosa.stft(y, hop_length=512))
spec = librosa.amplitude_to_db(spec, ref=np.max)
librosa.display.specshow(spec, sr=sr, x_axis='time', y_axis='log')
plt.colorbar(format='%+2.0f dB')
plt.title('Spectrogram')
plt.savefig('spectrogram.png')

研究表明人们对频率的感知不是线性的,相较于高频率我们对低频率的感知更加好一些。例如我们可以轻松地分辨出500Hz和1000Hz的区别,但是我们很难分辨出10000Hz和10500Hz的区别,尽管这两对频率的差距是相同的。
在1937年,Stevens,Volkmann,和Newmann提出了一种音高单位,这种单位中相同的差距对听者来说也是相等的。我们称为梅尔刻度。我们对频率进行数学操作使其变为梅尔刻度。

梅尔频谱是频率转换为梅尔刻度的频谱。他可以通过几行代码实现。
spect = librosa.feature.melspectrogram(y=y, sr=sr, n_fft=2048, hop_length=1024)
mel_spect = librosa.power_to_db(spect, ref=np.max)
librosa.display.specshow(mel_spect, y_axis='mel', fmax=8000, x_axis='time')
plt.title('Mel Spectrogram')
plt.colorbar(format='%+2.f dB')
plt.savefig('mel_spectrogram.png')

最近在学习CAN,记录一下,也供大家参考交流。推荐几个我觉得很好的CAN学习,本文也是在看了他们的好文之后做的笔记首先是瑞萨的CAN入门,真的通透;秀!靠这篇我竟然2天理解了CAN协议!实战STM32F4CAN!原文链接:https://blog.csdn.net/XiaoXiaoPengBo/article/details/116206252CAN详解(小白教程)原文链接:https://blog.csdn.net/xwwwj/article/details/105372234一篇易懂的CAN通讯协议指南1一篇易懂的CAN通讯协议指南1-知乎(zhihu.com)视频推荐CAN总线个人知识总
Transformers开始在视频识别领域的“猪突猛进”,各种改进和魔改层出不穷。由此作者将开启VideoTransformer系列的讲解,本篇主要介绍了FBAI团队的TimeSformer,这也是第一篇使用纯Transformer结构在视频识别上的文章。如果觉得有用,就请点赞、收藏、关注!paper:https://arxiv.org/abs/2102.05095code(offical):https://github.com/facebookresearch/TimeSformeraccept:ICML2021author:FacebookAI一、前言Transformers(VIT)在图
关闭。这个问题不符合StackOverflowguidelines.它目前不接受答案。我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。关闭3年前。Improvethisquestion我正处于学习Ruby的阶段,我想查看一些小型库的源代码以了解它们是如何构建的。我不知道什么是小型图书馆,但希望SO能推荐一些易于理解的图书馆来学习。因此,如果有人知道一两个非常小的库,这是新手Rubyists学习的好例子,请推荐!我想使用Manveru'sInnatelib,因为它试图保持在2000LOC以下,但我还不熟悉其中经常使用的Ruby速记。也许大约100-5
由于匿名block和散列block看起来大致相同。我正在玩它。我做了一些严肃的观察,如下所示:{}.class#=>Hash好的,这很酷。空block被视为Hash。print{}.class#=>NilClassputs{}.class#=>NilClass为什么上面的代码和NilClass一样,下面的代码又显示了Hash?puts({}.class)#Hash#=>nilprint({}.class)#Hash=>nil谁能帮我理解上面发生了什么?我完全不同意@Lindydancer的观点你如何解释下面几行:print{}.class#NilClassprint[].class#A
我很难理解Ruby中sender和receiver的实际含义。它们一般是什么意思?到目前为止,我只是将它们理解为方法调用和获取其返回值的调用。但是,我知道我的理解还远远不够。谁能给我一个Ruby中发送者和接收者的具体解释? 最佳答案 面向对象中的一个核心概念是消息传递和早期概念化,这在很大程度上借鉴了计算的Actor模型。艾伦·凯(AlanKay)创造了面向对象一词并发明了最早的OO语言之一SmallTalk,他拥有voicedregretatusingatermwhichputthefocusonobjectsinsteadofo
rails新手。只是想了解\assests目录中的这两个文件。例如,application.js文件有如下行://=requirejquery//=requirejquery_ujs//=require_tree.我理解require_tree。只是将所有JS文件添加到当前目录中。根据上下文,我可以看出requirejquery添加了jQuery库。但是它从哪里得到这些jQuery库呢?我没有在我的Assets文件夹中看到任何jquery.js文件——或者直接在我的整个应用程序中没有看到任何jquery.js文件?同样,我正在按照一些说明安装TwitterBootstrap(http:
我在某些代码中遇到了三元组,但我无法理解条件:str.split(/',\s*'/).mapdo|match|match[0]==?,?match:"somestring"end.join我确实理解我是在某些点上拆分字符串并将总结果转换为数组,然后依次处理数组的每个元素。除此之外,我不知道发生了什么。 最佳答案 一种(稍微)不那么令人困惑的写法是:str.split(/',\s*'/).mapdo|match|ifmatch[0]==?,matchelse"somestring"endend.join我认为多行三元语句很糟糕,尤其是
有没有人成功地将S3存储桶读取为子文件夹?文件夹1--子文件夹2----文件3----文件4--文件1--文件2文件夹2--子文件夹3--文件5--文件6我的任务是读取文件夹1。我希望看到子文件夹2、文件1和文件2,但看不到文件3或文件4。现在,因为我将存储桶键限制为prefix=>'folder1/',你仍然会得到file3和4,因为它们在技术上具有folder1前缀。似乎真正做到这一点的唯一方法是吸收folder1下的所有键,然后使用字符串搜索从结果数组中实际排除file3和file4。有没有人有过这方面的经验?我知道像Transmit和Cyberduck这样的FTP风格的S3
关于yolov5训练时参数workers和batch-size的理解yolov5训练命令workers和batch-size参数的理解两个参数的调优总结yolov5训练命令python.\train.py--datamy.yaml--workers8--batch-size32--epochs100yolov5的训练很简单,下载好仓库,装好依赖后,只需自定义一下data目录中的yaml文件就可以了。这里我使用自定义的my.yaml文件,里面就是定义数据集位置和训练种类数和名字。workers和batch-size参数的理解一般训练主要需要调整的参数是这两个:workers指数据装载时cpu所使
我在理解GrapeAPI时遇到很多困难,特别是route_param以及它如何仅使用params。考虑这段代码:desc"Returnastatus."paramsdorequires:id,type:Integer,desc:"Statusid."endroute_param:iddogetdoStatus.find(param[:id])endend这个街区产生什么路线?我知道这是一个get请求,但为什么它被包裹在route_paramblock中?为什么它不能在paramsblock中? 最佳答案 你的block产生这条路线: