手机号码进来变音频处理软件怎么处理

17590人阅读
C/C++(19)
算法系列(37)
编程语言(17)
年月的时候,一个南京的大学生从电视台播放的一段记者采访总裁周鸿祎的视频中破解了周鸿祎的手机号码,一时间被网络热炒。后来,又听说某人买车的时候使用电话银行付款,结果被人录下声音,破解了银行卡号和密码,导致存款被盗。最近居委会在小区里散发传单,提醒一种新的诈骗方式:电话听音破密码诈骗。各种网络和媒体对这些事情炒作的很热闹,但是趋于两种极端,要么将其说的出神入化,要么将其贬的一钱不值,唯独缺少理性的声音解释一下到底是什么原理。猫猫一直想说,“其实就是离散傅立叶变换(DFT)嘛,至于吗?”,这次就借着这种所谓的新型诈骗方式,一并说道说道。&&&&&&& 在动笔写这篇文章之前,猫猫上网Google了一下“电话号码破解”,居然发现某宝上有人叫卖“电话拨号音破解器”,价格从几百到上千大洋的都有,猫猫不说了,只笑笑。本文就准备从理论上解释一些破解电话拨号音的数学原理,看了本文的同学,你有福了,只需要依照本文给出的百十行演示代码,稍加改造,再加上一个麦克风,你就可以拥有自己的“电话拨号音破解器”了,废话少说,现在就开始吧。&&&&&&& 首先要说的是,根据电话拨号音破解电话号码,只适用于使用“双音多频技术(DTMF)”的电话设备,老式的拨号盘电话(脉冲式电话机)您就别试了(估计您也没有这玩意了)。双音多频技术是贝尔实验室的发明,就是将电话机的拨号键盘分成4X4的矩阵,每一行对应一个低频信号,每一列对应一个高频信号,如图(1)所示:图(1)电话键盘双音频对照表&其中低频信号和高频信号的频率都在人耳可以识别的频率范围之内。打电话拨号的时候,每按下一个键,就产生一个高频信号和低频信号的正弦信号组合,局端的电话交换机从这个组合信号中解出两个频率,就知道是那个按键被按下了。说到这里,您可能已经猜到了,只要从按键音中解析出这两个频率,就能根据上表查出是对应的哪个按键了。&&&&&&& 现在该离散傅立叶变换(DFT)隆重登场了!关于离散傅立叶变换算法的来龙去脉,请上网Google之,这里只简单介绍一下它的基本原理,以及它在电话号码破解的过程中能做什么。&&&&&&& 傅里叶是一位法国数学家和物理学家的名字,他于年在法国科学学会上发表了一篇论文,提到了一个观点:任何连续周期信号可以由一组适当的正弦曲线组合而成,换言之,满足一定条件的连续函数(周期函数)都可以表示成一系列三角函数(正弦和或余弦函数)或者它们的积分的线性组合形式,这个转换就被称为“傅立叶转换”。一般情况下,若“傅里叶变换”一词的前面未加任何限定语,则指的是“连续傅里叶变换”,与之对应的自然就是“离散傅立叶变换”。事实上,变换原始信号可以是周期的,也可以不是周期的,根据原始信号类型的不同,傅立叶变换可以分成四种形式,分别是“非周期性连续信号傅立叶变换”、“周期性连续信号傅立叶变换”、“非周期性离散信号傅立叶变换”和“周期性离散信号傅立叶变换”,其中“周期性连续信号傅立叶变换”实际上就是傅里叶级数的推广,因为积分其实是一种极限形式的求和算子而已。&&&&&&& 一维傅立叶变换的数学意义就是将时域信号转换为频域信号,当然,也存在称为傅立叶逆变换的变换,可以将频域信号转换成时域信号。连续时域信号以及对应的连续傅里叶变换都是连续函数(且是无限长度的时域信号),但是用计算机进行数字处理只能处理有限长度的离散信号,所以必须将原始信号离散化,同时建立对应的离散信号傅里叶变换。所谓的“离散傅里叶变换(,缩写为)”,是指傅里叶变换在时域和频域上都以离散的形式呈现。原始信号离散化的过程其实就是以一定的周期对原始信号进行采样的过程,至于如何从连续傅立叶变换推导出离散傅立叶变换,不是本文的重点,您可以之。因为离散傅立叶变换计算量相当大,有很多提高效率的算法理论,其中应用最广泛的就是快速傅立叶变换(),关于快速傅立叶变换的理论依据,也不是本文的重点,您可以之。总之,您只需要知道,存在一种方法,可以将基于时间轴的时域信号,转换成基于频率的频域信号即可,本文的重点是这种转换的物理意义,以及如何应用这种转换带给我们的结果。图()正弦波在时域和频域的形态&&&&&&& 现在看几个转换对比图,理解一下这种转换的物理意义。首先看图(),图()是的正弦波在时域中的形态,采样率是。图()就是通过离散傅立叶转换后得到的频域中的形态,理想状态下,图()应该在处一条直线,其他位置的值都是,但是受原始信号杂波和转换后的频域分辨率影响,实际显示的是一个呈金字塔形状的图形,不过还是可以明显地看到在的时候功率(相对强度)值最大,其他位置的值都明显小于位置的值。图()按键“”对应的音频在时域和频域的形态&&&&&&& 图()是电话按键“”对应的音频波形,图()是离散傅立叶转换后得到的频域形态,虽然受录音杂波影响很大,但是还是可以很明显看到在和位置上,相对能量强度达到了最大值。&&&&&&& 前面提到过,原始信号离散化的过程其实就是以一定的周期对原始信号进行采样的过程,这里就提到了一个很重要的参数,就是采样率。因为这个采样率决定了转换成频域信号后的分辨率,另外,每次进行转换的时域信号的个数(也称为离散傅立叶变换的点数)不能小于,否则无法完整映射到频域信号。实际上,是和共同决定了转换后的频域信号的分辨率。以本文要用到的声音信号为例,转换前的数据是每个采样点上的声波的振幅(各个频率叠加后的振幅),横坐标轴是周期的时间点,纵坐标轴是振幅。转换成频域信号后,横坐标轴就是频率,纵坐标轴就是该频率的产生强度,通过适当的转换,可以理解为该频率的功率。刚才提到,时域信号的采样率和参与转换的信号点数决定了频域信号的分辨率,这是因为离散傅立叶转换会将时域信号一对一的转换为频域信号,也就是说,个时域信号转换后会得到个频域信号。但是傅立叶转换有个特点,就是时域信号的周期性和频域信号的对称性,所谓频域信号的对称性,是指转换后的个频域信号在位置呈现轴对称特征,对信号分析有用的实际频域信号点只有个。其中第一个点对应的是,也就是时域信号中直流分量强度,其他个点分别对应之间的频率,频率分辨率是。由此可见,增加可以提高频域信号的分辨率,但是增加会显著增加每次傅立叶变换的计算量,因此对的选择需要做一个折衷。&&&&&&& 使用离散傅立叶变换进行信号分析的时候,一般都会采用快速傅立叶变换(FFT)算法,网上有很多高效的快速傅立叶变换算法,包括基于实数的快速傅立叶算法,大家可以参考。本文给出的算法是猫猫上学时写的一个快速傅立叶变换算法,输入和输出参数都是复数,算不上高效,但是很简单,只有二十几行代码,适合研究原理使用。另外,这个算法采用原位变换的方式,可以减少傅立叶转换算法使用过程中的数据复制操作。&42&/*&43&window = 1 -& hanning window&44&*/&45&bool InitFft(FFT_HANDLE *hfft, int count, int window)&46&{&47&&&& int i;&48&&49&&&& hfft-&count = count;&50&&&& hfft-&win = new float[count];&51&&&& if(hfft-&win == NULL)&52&&&& {&53&&&& &&& return false;&54&&&& }&55&&&& hfft-&wt = new COMPLEX[count];&56&&&& if(hfft-&wt == NULL)&57&&&& {&58&&&& &&& delete[] hfft-&win;&59&&&& &&& return false;&60&&&& }&61&&&& for(i = 0; i & count; i++)&62&&&& {&63&&&& &&& hfft-&win[i] = float(0.50 - 0.50 * cos(2 * M_PI * i / (count - 1)));&64&&&& }&65&&&& for(i = 0; i & count; i++)&66&&&& {&67&&&& &&& float angle = -i * M_PI * 2 / count;&68&&&& &&& hfft-&wt[i].re = cos(angle);&69&&&& &&& hfft-&wt[i].im = sin(angle);&70&&&& }&71&&72&&&& return true;&73&}&74&&75&void FFT(FFT_HANDLE *hfft, COMPLEX *TD2FD)&76&{&77&&&& int i,j,k,butterfly,p;&78&&79&&&& int power = NumberOfBits(hfft-&count);&80&&81&&&& /*蝶形运算*/&82&&&& for(k = 0; k & power; k++)&83&&&& {&84&&&& &&& for(j = 0; j & 1&&k; j++)&85&&&& &&& {&86&&&& &&& &&& butterfly = 1&&(power-k);&87&&&& &&& &&& for(i = 0; i & butterfly/2; i++)&88&&&& &&& &&& {&89&&&& &&& &&& &&& p=j * butterfly;&90&&&& &&& &&& &&& COMPLEX t = TD2FD[i + p] + TD2FD[i + p + butterfly/2];&91&&&& &&& &&& &&& TD2FD[i + p + butterfly/2] = (TD2FD[i + p] - TD2FD[i + p + butterfly/2]) * hfft-&wt[i*(1&&k)];&92&&&& &&& &&& &&& TD2FD[i + p] = t;&93&&&& &&& &&& }&94&&&& &&& }&95&&&& }&96&&97&&&& /*重新排序*/&98&&&& for(i = 1,j = hfft-&count/2;i &= hfft-&count-2; i++)&99&&&& {100&&&& &&& if(i & j)101&&&& &&& {102&&&& &&& &&& COMPLEX t = TD2FD[j];103&&&& &&& &&& TD2FD[j] = TD2FD[i];104&&&& &&& &&& TD2FD[i] = t;105&&&& &&& }106&&&& &&& k = hfft-&count/2;107&&&& &&& while(k &= j)108&&&& &&& {109&&&& &&& &&& j = j - k;110&&&& &&& &&& k = k / 2;111&&&& &&& }112&&&& &&& j = j + k;113&&&& }114&}&&&&&&&& InitFft()函数初始化一个傅立叶转换句柄,包括正/余弦系数表(wt)和窗口系数表(win),count参数是傅立叶转换的点数,就是一次能转换的最大信号个数,windows参数是决定使用什么窗函数,这段代码只支持汉宁窗(hanning window)。有关离散傅立叶变换中窗函数的作用将在后面介绍。FFT()函数就是快速傅立叶变换的实现,TD2FD是个复数数组,每调用一次FFT()函数可以转换count个数据。对于音频数据这样的实数,只需使用COMPLEX结构的实数分量,虚数分量可以置0。COMPLEX数据结构定义如下:&8&struct COMPLEX&9&{10&&&& float re;11&&&& float im;12&};13&COMPLEX数据结构重载了+、-和*运算符,所以FFT()函数的代码看起来很简练。&&&&&&& 前文提到过,计算机不能处理无限长度的数据,离散傅立叶变换算法只能对数据一批一批地进行变换,每次只能对限时间长度的信号片段进行分析。具体的做法就是从信号中截取一段时间的片段(比如本文对按键音频文件的分析,从音频文件中读取的数据就可以看做是从无限长度信号中截取的一秒钟音频信号),然后对这个片段的信号数据进行周期延拓处理,得到虚拟的无限长度的信号,再对这个虚拟的无限长度信号进行傅立叶变换。但是信号被按照时间片截取成片段后,其频谱就会发生畸变,这种情况也被称之为频谱能量泄露。&&&&&&& 为了减少能量泄露,人们研究了很多截断函数对信号进行截取操作,这些截断函数就被称为窗函数。窗函数w(t)被设计成频带无限的函数,所以即使原始信号是有限带宽信号,被窗函数截取后得到的片段也会变成无限带宽,也就是说,信号经过窗函数处理后,在频域的能量与分布都被扩展了,有效地减少了频谱能量泄露。&&&&&&& 不同的窗函数对信号频谱的影响是不一样的,比如最简单的矩形窗,实际上就是对信号不做任何处理,简单地按照时间片段截取一定长度的信号进行处理。本文的演示算法选用了汉宁窗(hanning window),汉宁窗的数学定义如下:其中R(t)是原始信号,t的范围是 0 &= t & N-1,对于其他范围的值,w(t) = 0。图(4)显示了汉宁窗对信号截取的示意图,以及对频域转换结果的影响,蓝色区域是窗口覆盖的数据部分。汉宁窗的作用是分析带宽加宽,但是降低了频率分辨率,不过拨号音的低频和高频组中,任意两个频率之间的间隔都超过了70Hz,所以牺牲这点分辨率对按键声音的识别没有影响。图()汉宁窗信号截取示意图&&&&&&& 使用了窗口,就需要讨论窗口的滑动问题,也就是窗口重叠的处理。用汉宁窗截取的信号片段,可以看出来窗口中部分信号被削弱了(造成衰减),为了抵消部分窗口对信号造成的衰减,各种窗函数都需要对信号进行相应的重叠处理。本文选择的重叠处理方式是选取信号时每次滑动半个窗口位置,使得每个窗口的后半个窗口的衰减在下个窗口的前半个窗口中的到一定的补偿,这个在计算一段时间信号总的功率谱时会有相应的体现。计算一段时域信号的总功率谱的函数代码如下:31&bool PowerSpectrumT(FFT_HANDLE *hfft, short *sampleData, int totalSamples, int channels, float *power)32&{33&&&& int i,j;34&35&&&& for(i = 0; i & hfft-&count; i++)36&&&& &&& power[i] = (float)0.0;37&38&&&& COMPLEX *inData = new COMPLEX[hfft-&count];39&&&& if(inData == NULL)40&&&& &&& return false;41&42&&&& int procSamples = 0;43&&&& short *procData = sampleData;44&&&& while((totalSamples - procSamples) &= hfft-&count)45&&&& {46&&&& &&& procData = sampleData + procSamples * channels;47&&&& &&& for(j = 0; j & hfft-&count; j++)48&&&& &&& {49&&&& &&& &&& SampleDataToComplex(procData, channels, &inData[j]);50&&&& &&& &&& procData += channels;51&&&& &&& }52&&&& &&& procSamples += (hfft-&count / 2); /*每次向后移动半个窗口*/53&54&&&& &&& FftWindowFunction(hfft, inData);55&&&& &&& FFT(hfft, inData);56&57&&&& &&& for(i = 0; i & hfft-&count; i++)58&&&& &&& {59&&&& &&& &&& power[i] += float(20.0 * log10(sqrt(inData[i].re * inData[i].re + inData[i].im * inData[i].im) / (hfft-&count / 2)));60&&&& &&& }61&&&& }62&63&&&& delete[] inData;64&65&&&& return true;66&}&&&&&&& PowerSpectrumT()函数要做的事情很简单,就是每次从采样数据中选择count个,对其进行窗口处理,然后用傅立叶转换得到频域信号,最后计算并累加各个频率的相对功率。处理完一批采样数据后,向后偏移 count/2 个采样数据(相当于滑动半个窗口),重复上述过程,直到剩余的采样数据全部完成为止(剩余数据不足一个窗口时也退出计算)。sampleData参数是采样数据,本文处理的是16位音频数据,因此每个采样的大小是两个字节,totalSamples是总的采样数据的个数,totalSamples必须大于count才能得到有意义的功率频谱。channels是采样数据的声道数,对于有两个声道的立体声采样数据,则取两个声道的平均值做为采样数据进行傅立叶转换。SampleDataToComplex()函数将采样数据赋值给复数对象的实数部分,虚数部分置0,对于双声道,则取左右声道的平均值赋值给复数对象的实数部分,其实现如下:17&static void SampleDataToComplex(short *sampleData, int channels, COMPLEX *cd)18&{19&&&& if(channels == 1)20&&&& {21&&&& &&& cd-&re = float(*sampleData / 32768.0);22&&&& &&& cd-&im = 0.0;23&&&& }24&&&& else25&&&& {26&&&& &&& cd-&re = float(*sampleData + *(sampleData + 1) / 65536.0);27&&&& &&& cd-&im = 0.0;28&&&& }29&}&&&&&&& 现在来讲一下对PowerSpectrumT()函数转换结果的处理,PowerSpectrumT()函数的power参数返回最终计算好的功率谱,其分辨率是T/N。每个点对应的频率可使用以下公式计算:&Freq = n * (T / N)&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& (公式2)&以音频信号采样率8000Hz,傅立叶转换的count是2048为例,其频谱分辨率是3.90625Hz,power[0]是频率0的相对功率,也就是直流信号的功率,power[1]是频率3.9Hz对应的相对功率,power[2]是频率7.8Hz对应的相对功率,对应关系以此类推。如果在power[240]处出现频率最大值,则其对应的频率应该是()*240=937Hz。&&&&&&& 双音频电话按键音中有两个主频率,因此转换后的power数组中应该存在两个相对极大值,需要从power数组中找出这两个相对极大值。从M个数中选最大的N个数是一个很常见的算法,其主要思想就是维护一个大小是N的有序组,然后从剩下的M-N个数中逐个与有序组中的最小值比较,如果小于有序组中的最小值,则继续比较下一个数,如果大于有序组中的最小值,则替换有序组中的最小值,并对有序组进行适当的变换,使其保持有序。使用堆来维护有序组被认为是最高效的方式,大家有兴趣可以从网上找相关的代码学习。本文设计的从power数组中选出最大的两个值的算法也采用这种思想,但是有序表只有两个元素,因此对有序表的维护不需要复杂的排序处理,如果有序性失效,只要交换两个元素的位置即可,其具体算法如下:290&void ExchangeIndex(int *index, float *power)291&{292&&&& if(power[index[1]] & power[index[0]])293&&&& {294&&&& &&& int t = index[0];295&&&& &&& index[0] = index[1];296&&&& &&& index[1] = t;297&&&& }298&}299&300&void SearchMax2FreqIndex(float *power, int count, int& first, int& second)301&{302&&&& int max2Idx[2] = { 0 };303&304&&&& ExchangeIndex(max2Idx, power);305&&&& for(int i = 2; i & count; i++)306&&&& {307&&&& &&& if(power[i] & power[max2Idx[1]])308&&&& &&& {309&&&& &&& &&& max2Idx[1] = i;310&&&& &&& &&& ExchangeIndex(max2Idx, power);311&&&& &&& }312&&&& }313&314&&&& first = min(max2Idx[0], max2Idx[1]);315&&&& second = max(max2Idx[0], max2Idx[1]);316&}&&&&&&& SearchMax2FreqIndex()函数从power数组中选择最大的两个值,并返回它们在power数组中的位置(power数组的下标),并根据频率排序,first总是较小的那个频率的位置,second总是较大的那个频率的位置。根据first和second指示的位置,利用“公式2”就可以计算出两个频率,但是因为频谱分辨率的关系,这两个计算出来的频率不会刚好就是图(1)中所示的标准频率,但是没关系,它们与标准频率差的不多,通过查表就可以确定是哪个标准频率。&&&&&&& 至此,所有的核心代码都完成了,创建一个例子试试吧,我的例子很简单,如图()所示,就是打开按键音频文件,然后显示是哪个按键。您可以做的更复杂一些,直接从麦克风获得音频数据,实时分析按键声音,这样就可以实时破解电话号码了。图()按键音识别实例程序&
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:1208956次
积分:12911
积分:12911
排名:第717名
原创:104篇
译文:12篇
评论:1136条
阅读:58967
文章:31篇
阅读:654308
(2)(1)(1)(2)(1)(2)(1)(1)(1)(1)(1)(2)(1)(1)(2)(1)(1)(5)(2)(4)(1)(1)(5)(1)(1)(2)(3)(1)(1)(1)(1)(1)(3)(1)(1)(5)(1)(1)(1)(1)(3)(1)(1)(2)(1)(1)(2)(3)(1)(3)(2)(3)(8)(8)(1)(2)(2)(1)(5)人人网 - 抱歉
哦,抱歉,好像看不到了
现在你可以:
看看其它好友写了什么
北京千橡网景科技发展有限公司:
文网文[号··京公网安备号·甲测资字
文化部监督电子邮箱:wlwh@··
文明办网文明上网举报电话: 举报邮箱:&&&&&&&&&&&&手机直播音频专业处理方法_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
手机直播音频专业处理方法
上传于||文档简介
&&手​机​直​播​音​频​专​业​处​理​方​法​,​和​一​些​知​识​点
阅读已结束,如果下载本文需要使用1下载券
想免费下载本文?
定制HR最喜欢的简历
你可能喜欢扫描下载MIUI论坛APP
经验4083 米
在线时间54 小时
版本6.10.25
机型小米手机5
签到次数30
MIUI版本6.10.25
建议通话录音文件按联系人(电话号码)进行分类,这样查找管理起来会方便很多,可以参考“匹诺曹通话录音软件”。
分享到微信朋友圈
打开微信,点击底部的“发现”,使用 “扫一扫” 即可将网页分享到我的朋友圈。
经验1310 米
在线时间67 小时
版本6.10.17
机型小米手机3/4 WCDMA版
MIUI版本6.10.17
如果按照联系人查看的话是不是可以直接去通话记录查看?
计算器用户反馈QQ群:
录音机用户反馈QQ群:
悬浮球用户反馈QQ群:
经验4083 米
在线时间54 小时
版本6.10.25
机型小米手机5
签到次数30
MIUI版本6.10.25
如果按照联系人查看的话是不是可以直接去通话记录查看?
在录音机里如果也可以按电话号码分类,岂不是更方便吗?
经验4083 米
在线时间54 小时
版本6.10.25
机型小米手机5
签到次数30
MIUI版本6.10.25
如果按照联系人查看的话是不是可以直接去通话记录查看?
在通话录音软件中分类,比如我要删除某个人的录音而不想删除通话记录,岂不是更方便?我觉得有改进的必要
经验122473 米
威望1625 米
在线时间17722 小时
版本6.10.27
我是大水逼
机型红米手机2 联通版/电信版
签到次数154
MIUI版本6.10.27
MIUI 300周
MIUI 300周更新纪念勋章
MIUI 3000万
MIUI 3000万发烧友纪念勋章
MIUI 2000万
MIUI 2000万发烧友纪念勋章
MIUI 7纪念勋章
小米商城购买纪念勋章
论坛APP购买小米商品获得
小米平板2 Win10 荣誉内测
小米平板2 Win10 荣誉内测
MIUI五周年
MIUI五周年纪念勋章
已关注极客秀微信
已关注微信
关注腾讯微博
已关注腾讯微博
关注新浪微博
已关注新浪微博
MIUI六周年
MIUI六周年纪念勋章
Copyright (C) 2016 MIUI
京ICP备号 | 京公网安备34号 | 京ICP证110507号昨天不知道怎么弄得,手机里面的电话号码图片视频音乐全部删除了,额? - 爱问知识人
(window.slotbydup=window.slotbydup || []).push({
id: '2491531',
container: s,
size: '150,90',
display: 'inlay-fix'
里面的电话号码图片视频音乐全部删除了,额的神吖,肿么办
里面曾经安装过QQ同步助手的,这个同步助手只要弄过一次,以后换什么手机,什么卡掉了都没问题,有QQ号登陆QQ同步助手,把自己的联系人,重要的短信都可以同步到新卡或者新手机里面的。试试,如果可以请点有用。
您的举报已经提交成功,我们将尽快处理,谢谢!
长按图标,拖动,再出现的垃圾桶上,拖动垃圾桶盖就删除了。朋友您好,我致力于努力认真的回答您的每一个问题,所以请您高抬贵手将我的答案设置【好评】,您的肯定将是对我...
看看你是什么手机了,把手机插在电脑上也不能开机么?如果能链接电脑,可以用蜡笔同步这款软件来导出通讯录。
肯定是不行的你没有备份
手机QQ音乐3.7及以上版本有批量删除功能,在歌曲列表界面的右上角,有个管理,点击即可出现批量操作界面。
除后手机又丢失,可以使用以下方法恢复:&br /&1、在微信朋友圈中找到该好友发布过的信息,这个信息是不随着删除该好友进行删除的。&br /&2、如果该好友没有...
大家还关注

我要回帖

更多关于 数字音频处理器 的文章

 

随机推荐