4

Python实用工具,PyQt5模块,Python实现不用声卡就能让电脑自己哼起歌

 3 years ago
source link: https://segmentfault.com/a/1190000040324744
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Python实用工具,PyQt5模块,Python实现不用声卡就能让电脑自己哼起歌

发布于 今天 16:18

周末了给大家整点有趣的东西吧,在不借助电脑声卡的情况下,只利用电脑主板上的蜂鸣器,就能让电脑自己哼起歌来,感觉还挺好玩的呢~
废话不多说,让我们愉快地开始吧~

Python版本:3.6.4

相关模块:

PyQt5模块;

以及一些python自带的模块。

安装python并添加到环境变量,pip安装需要的相关模块即可。

原理其实挺简单的,主要就是利用python来控制电脑主板上的蜂鸣器以不同的频率发出声音从而模拟人哼歌时的效果~

具体而言,我们小学就学过,声音是由物体震动产生的,它包括以下几个部分:

1. 音调: 声音的高低,由发声体的振动频率决定,频率越高,音调越高;
2. 响度: 人耳感觉到的声音的大小,它跟发声体的振幅有关.振幅越大,响度越大;振幅越小,响度越小;
3. 音色: 发声体的声音品质,由发声体本身的特征决定.是区别声音的重要标志.

这是考点,麻烦还在念初中的粉丝记一下,考试要考的,别一到周末了就只玩手机不学习~
对于电脑主板上的蜂鸣器来说,音色和响度基本上已经确定没法改了,所以我们只能在频率上动脑筋,从而让蜂鸣器哼出我们想要听的歌来~

具体而言,我们可以调用这个函数来让蜂鸣器哼歌:

1 import ctypes
2 beep_player = ctypes.windll.kernel32
3 beep_player.Beep(freq, beats)

其中freq代表频率,beats代表节拍(就是当前音符播放的时长)。好的,看到这里可能有人懵了,别急,让我来举个例子说明我们到底应该怎么做。

首先,我们去网上找一首喜欢的歌的音乐简谱,这里以小幸运为例:

image.png

可以发现简谱上有数字1234567这7个基本音符,唱作:

1 1: do
2 2: re
3 3: mi
4 4: fa
5 5: sol
6 6: la
7 7: si

每个基本音符代表声音的一个频率,在基本音符上方标记"·"时,则代表该音升高一个八度,称为高音,反之则代表该音降低一个八度,称为低音(这里就不考虑倍高音和倍低音的情况了):

图片

一般而言,我们可以假设高音do的频率是do的两倍,是低音do的四倍,其他音符类似。再根据十二平均律:

1 一种音乐的定律方法,将一个八度平均分成十二等份,
2 每等分称为半音,是最主要的调音法。
3 音高八度音指的是频率加倍(即二倍频率)。
4 八度音的频率分为十二等分,即是分为十二项的等比数列,
5 也就是每个音的频率为前一个音的2的12次方根:
6 其近似值约为2^(1/12) = 1.06

我们只需要知道do的频率,就可以推算出其他音符的频率了(比如do的频率是1,那么re的频率就是11.061.06)。一般而言,do的频率和简谱中的调号的对应关系如下:

1 'C': 523, 
2 'D': 587, 
3 'E': 659, 
4 'F': 698, 
5 'G': 784, 
6 'A': 880, 
7 'B': 988

ok,至此,我们搞定了freq,现在再来看beats。在简谱中,一般通过加"·"和短横线"-"来表示音的长短:

1 1. 在基本音符右侧加记一条短横线, 表示增长一个四分音符的时值
(就是这个音的长度*2)
2 2. 在基本音符下方加记一条短横线, 表示缩短原音符时值的一半
3 3. 音符X右侧加·时代表增长原音符时值的一半
4 4. 在简谱中, 大于四分音符的单纯音符通常不加记·,即用X--来表示X-·

盗个图更直观一点说明吧:

图片

OK,如此一来,我们就可以很轻松地确定上面的音乐简谱中每个音符的freq和beats,从而调用函数让蜂鸣器哼出这个音符来了,所以音符连起来哼不就等于让蜂鸣器哼歌了嘛~

为了方便程序确定每个音符的freq和beats,我们把简谱重写一下,就像这样:

图片

即每个音符由三个元素组成:

[基本音符][低音/中音/高音][音的长度]

然后写过函数解析一下:

1 '''解析'''
2 def parse(self, filepath):
3     song_info = open(filepath, 'r').read().replace('\n', '').split(',')
4     tone = song_info[0]
5     song_info = song_info[1:]
6     return tone, song_info

并根据解析结果播放就ok啦:

1 '''播放'''
2 def play(self):
3     filepath = self.musicfilepath_edit.text()
4     if not os.path.isfile(filepath):
5         return
6     tone, song_info = self.parse(filepath)
7     do = self.tone2freq_dict[tone]
8     re = int(do * self.tone_scale * self.tone_scale)
9     mi = int(re * self.tone_scale * self.tone_scale)
10    fa = int(mi * self.tone_scale * self.tone_scale)
11    sol = int(fa * self.tone_scale * self.tone_scale)
12    la = int(sol * self.tone_scale * self.tone_scale)
13    si = int(la * self.tone_scale * self.tone_scale)
14    notes = [0, do, re, mi, fa, sol, la, si]
15    for item in song_info:
16         if notes[int(item[0])] == 0:
17          time.sleep(self.beats / 1000)
18        else:
19 self.beep_player.Beep(int(notes[int(item[0])]*self.pitchs_dict[item[1]]), int(self.beats * float(item[2:])))

文章到这里就结束了,感谢你的观看,关注我每天分享Python小工具系列,下篇文章根据中文姓名猜测对方性别

为了感谢读者们,我想把我最近收藏的一些编程干货分享给大家,回馈每一个读者,希望能帮到你们。

干货主要有:

① 2000多本Python电子书(主流和经典的书籍应该都有了)

② Python标准库资料(最全中文版)

③ 项目源码(四五十个有趣且经典的练手项目及源码)

④ Python基础入门、爬虫、web开发、大数据分析方面的视频(适合小白学习)

⑤ Python学习路线图(告别不入流的学习)

⑥ 两天的Python爬虫训练营直播权限

All done~完整源代码+干货详见个人简介或者私信获取相关文件。。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK