Karplus-Strong 算法简单介绍和实现

  • 本文为Coursera数字信号处理课程第一周内容,对相关课程刚兴趣的同学,请参看这里
  • 为了有更好的交互性,本文所有代码均上传至Microsoft Azure Notebooks,你可以在上面试听所有输出的音频,具体代码在这里

什么是Karplus-Strong算法

Karplus-Strong算法简单的说就是一种合成声音的算法,它不断的循环重复MMM个采样点,从而生成一段音频

是的,它非常简单,我们用一段代码(KS_1)来直观的描述它。

import numpy as np
import matplotlib.pyplot as plt
import IPython
%matplotlib inlinedef KS_1(x, N):'''x: 初始序列N: 输出序列的最大长度'''y = xwhile len(y) < N:y = np.append(y, x)y = y[0:N+1]return yFs = 16000 # 设置采样频率,16Khz

当设定了采样频率,那么我们就可以就算用KS算法生成音频的频率了。例如,如果初始序列x的长度为50,采样频率Fs=16000,那么生成音频在每秒内将会重复
16000/50 = 320次x,也就是说生成音频的频率为320Hz,这刚好是钢琴中E4的音。

接下来我们讨论初始序列x的值应该是怎样的,这是KS算法中最coool的地方,因为算法的发明者推荐我们使用高斯白噪声作为初始化序列,虽然我们可以使用任意值的初始化序列,但实验表明,随机的序列效果通常最好

b = np.random.randn(50) # 一个随机的初始化序列
plt.stem(b)

让我们用KS_1来生成一段2s的音频

y = KS_1(b, Fs*2)plt.figure(figsize=(10,3))
plt.stem(y[0:Fs*2:111])
plt.show()

IPython.display.Audio(y, rate=Fs) # 真的很难听!!
 # 生成另一段音频,但是初始序列更长,意味着输出音频的频率更小
IPython.display.Audio(KS_1(np.random.rand(100), Fs*2), rate=Fs)

很棒!KS算法至少能够运行了。我们可以用下面的图来描述这个信号处理系统

输出信号可以表示为(暂时忽略那个α\alphaα)
y[n]=x[n]+y[n−M]y[n] = x[n] + y[n-M] y[n]=x[n]+y[n−M]
并假设x是 finite-support 信号
x[n]={0n&lt;0bn0≤n&lt;M0n≥Mx[n] = \begin{cases} 0 &amp; n&lt; 0\\ b_n &amp; 0 \le n &lt; M \\ 0 &amp; n \ge M\\ \end{cases} x[n]=⎩⎪⎨⎪⎧​0bn​0​n<00≤n<Mn≥M​

让我们上面的式子来实现KS(不是高效的做法)

def KS_2(x, N):y = np.zeros(N)M = len(x)for n in range(N):y[n] = (x[n] if n < M else 0) + (y[n-M] if n-M>=0 else 0)return y
IPython.display.Audio(KS_2(np.random.randn(50), Fs*2), rate=Fs)

我们只要添加一个α\alphaα就能让输出的音频听上去更真实,α\alphaα设置为比1小那么一丢丢,那么生成的音频听上去就像吉他一样

def KS_3(x, N, alpha=0.99):y = np.zeros(N)M = len(x)for n in range(N):y[n] = (x[n] if n < M else 0) + alpha*(y[n-M] if n-M>=0 else 0)return y
y = KS_3(b, Fs*2, 0.99)plt.figure(figsize=(15,4))
plt.stem(y[0:Fs*2:43])
plt.show()

IPython.display.Audio(y, rate=Fs) # 听着不错

KS算法中的还有一个重要的细节。每次循环初始序列都会乘上α\alphaα,那么我们可以将KS写成:
y[n]=α⌊n/M⌋x[nmod&ThinSpace;&ThinSpace;M]y[n] = \alpha^{\lfloor n/M \rfloor}x[n \mod M] y[n]=α⌊n/M⌋x[nmodM]
也就是说当N固定时(输出音频长度固定),输出音频的减弱速度与α\alphaα和M有关系。换句话说,如果α\alphaα固定,M越小(音调越高),那么输出的音频减弱的越快

IPython.display.Audio(KS_3(np.random.rand(50), Fs*2), rate=Fs)
y = KS_3(np.random.randn(50), Fs*2) #衰退速率较慢plt.figure(figsize=(15,4))
plt.stem(y[0:Fs*2:33])
<Container object of 3 artists>

IPython.display.Audio(KS_3(np.random.rand(10), Fs*2), rate=Fs)
y = KS_3(np.random.randn(10), Fs*2) # 衰退速率快plt.figure(figsize=(15,4))
plt.stem(y[0:Fs*2:33])
<Container object of 3 artists>

这样是不好的,我们需要进行改进。我们希望当α\alphaα一样时,减弱的速率也是一样的。于是,我们最终版的KS算法来了

def KS(x, N, alpha=0.99, REF_LEN=50):# REF_LEN 越大衰减越慢(感觉尾音越长),# 例如REF_LEN=50,表示当 alpha 固定时,你希望衰减速率同M=50一样M = len(x)beta = alpha ** (float(M) / REF_LEN) # 表示 \beta^n = \alpha,其中n=REF_LEN/M,求得betay = np.zeros(N)for n in range(N):y[n] = (x[n] if n < M else 0) + beta*(y[n-M] if n-M >= 0 else 0)return y
y = KS(np.random.rand(50), Fs*2, REF_LEN=50)
IPython.display.Audio(y, rate=Fs)
y = KS(np.random.rand(10), Fs*2, REF_LEN=50)
IPython.display.Audio(y, rate=Fs)

上面的KS算法效率较低,用上numpy,可以大大提高效率

def KS_with_np(x, N, alpha=0.99, REF_LEN=50):M = len(x)beta = alpha ** (M / REF_LEN)a = betay = xwhile len(y) < N:y = np.append(y, a*x)a *= betareturn y[0:N+1]
y_np = KS_with_np(b, Fs*2, REF_LEN=50)
IPython.display.Audio(y_np, rate=Fs)
y_np = KS_with_np(c, Fs*2, REF_LEN=150)
IPython.display.Audio(y_np, rate=Fs)

音乐,走起!

让我们用KS算法来生成一段甲壳虫乐队著名的 opening chord of “A Hard Day’s Night”

在很多文献中,这段音乐的音为D3,F3,G3,F4,A4,C5D_3, F_3, G_3, F_4, A_4, C_5D3​,F3​,G3​,F4​,A4​,C5​,为了让音乐听上去更“深”,我们添加了一个D2D_2D2​音

在西方音乐中,A4A_4A4​音的频率为440Hz,其他的音的频率可以根据A4A_4A4​计算得到 f(n)=A4×2n/12f(n) = A4 \times 2^{n/12}f(n)=A4×2n/12,其中n为目标音与A4的半音符差距个数,如果比A4高,那么n为整数,否则为负数。

我们将不同的音赋予不同的增益,就能生成一段类型的音乐啦。下面的代码需要懂一些乐理知识(我不会啊!),但是大致能够明白在干什么。freq根据音的字符串得到音的频率。

def freq(note):# general purpose function to convert a note  in standard notation #  to corresponding frequencyif len(note) < 2 or len(note) > 3 or \note[0] < 'A' or note[0] > 'G':return 0if len(note) == 3:if note[1] == 'b':acc = -1elif note[1] == '#':acc = 1else:return 0octave = int(note[2])else:acc = 0octave = int(note[1])SEMITONES = {'A': 0, 'B': 2, 'C': -9, 'D': -7, 'E': -5, 'F': -4, 'G': -2}n = 12 * (octave - 4) + SEMITONES[note[0]] + accf = 440 * (2 ** (float(n) / 12.0))#print note, freturn fdef ks_chord(chord, N, alpha):y = np.zeros(N)# the chord is a dictionary: pitch => gainfor note, gain in chord.items():# create an initial random-filled KS buffer the notex = np.random.randn(int(np.round(float(Fs) / freq(note))))y = y + gain * KS(x, N, alpha)return y
# A Hard Day's Night's chord
hdn_chord = {'D2' : 2.2, 'D3' : 3.0, 'F3' : 1.0, 'G3' : 3.2, 'F4' : 1.0, 'A4' : 1.0, 'C5' : 1.0, 'G5' : 3.5,
}IPython.display.Audio(ks_chord(hdn_chord, Fs * 4, 0.995), rate=Fs)
# 另一段音乐
hdn_chord = {'C3' : 1.2, 'F#3' : 1.0, 'Bb3' : 1.0, 'E4' : 1.2, 'A4' : 1.0, 'D5' : 1.0,
}IPython.display.Audio(ks_chord(hdn_chord, Fs * 2, 0.995), rate=Fs)

重申一遍:以上所有代码和输出音频都可以在这个在线notebook进行下载和播放。

Karplus-Strong 算法简单介绍和实现相关推荐

  1. 【转载】Relief 特征选择算法简单介绍

    Relief 特征选择算法简单介绍 原创 2017年03月11日 16:56:11 标签: 机器学习 4279 相关文章  特征选择  LVW(Las Vegas Wrapper)特征选择算法简单介绍 ...

  2. LRU(Least Recently Used)算法简单介绍

    文章目录 LRU算法简介 使用场景 简单实现 简单介绍 LRU算法简介 LRU英文翻译过来就是least recently used,字面意思就是最近最少使用,说白了就是一种淘汰算法,当有新的元素插入 ...

  3. RSYNC及其算法简单介绍

    现在的存储系统,本身都具备很强的迁移以及备份策略,虽然还是基于网络传输,有相对延迟,但是方便了不少.另外,现在使用的存储系统,读写瓶颈的问题,也大都改为对象存储. 而我们那时候做文件存储,最头疼的就是 ...

  4. 文本分析算法简单介绍-1

    以下内容是基于李博<机器学习实践应用>,邹博小象学院<机器学习课程>以及李航书籍<统计学习方法>加上自己的理解提炼而成 文本分析算法大致可以分成3种方法:机械分词, ...

  5. 垃圾回收算法简单介绍——JVM读书笔记lt;二gt;

    垃圾回收的过程主要包含两部分:找出已死去的对象.移除已死去的对象. 确定哪些对象存活有两种方式:引用计数算法.可达性分析算法. 方案一:引用计数算法 给对象中加入一个引用计数器.每当有一个地方引用它时 ...

  6. 神经网络之感知器算法简单介绍和MATLAB简单实现

    Perceptron Learning Algorithm 感知机学习算法,在1943年被生物学家MeCulloch和数学家Pitts提出以后,面临一个问题:参数需要依靠人工经验选定,十分麻烦.因此人 ...

  7. Annoy算法简单介绍

    Annoy算法 与Faiss相比,Annoy搜索,速度更快一点,主要目的是建立一个数据结构快速找到任何查询点的最近点.通过牺牲查询准确率来换取查询速度,这个速度比faiss速度还要快. 是什么 Ann ...

  8. Dijkstra算法简单介绍

    一.概念 Dijkstra算法解决的是带权重的有向图上单源最短路径问题,该算法要求所有边的权重都为非负值.        二.伪代码实现 三.算法说明及例题图解 算法重复从结点集V-S中选择最短路径估 ...

  9. 神经网络中的BPTT算法简单介绍

    首先来看下RNN的一个循环网络结构图: RNN(Recurrent Neural Network) 在时间维度上,我们将RNN进行展开,以便能够更好地来观察: 主要的参数就是三部分:在RNN中每一个时 ...

最新文章

  1. deepin启动盘无法引导安装_深度启动盘制作工具(Deepin Boot Maker)怎么安装kubuntu?Deepin Boot Maker图文教程...
  2. python程序结构有哪几种_三、python程序结构之分支结构
  3. Kafka 安装和搭建 (一)
  4. create-react-app 使用代理做 mock
  5. 从零开始通过 Artifactory 搭建公网的 maven 仓库
  6. Unity3d之Http通讯GET方法和POST方法
  7. 你的核心竞争力真的是技术么?
  8. wait,notify,notifyAll用法解析
  9. zip gbk java,java 解压 ZIP 中文 乱码 GBK UTF-8 完美解决方案
  10. 2013Esri全球用户大会QA之Web GIS
  11. 从BIM行业看中国工业软件的困境及出路
  12. MacBook常用快捷键有哪些?
  13. excel计算机快捷键大全,常用的Excel快捷键大全
  14. argmin ,argmax函数
  15. BZOJ_4199_[Noi2015]品酒大会_后缀自动机
  16. 正交db小波 图像处理 matlab,基于matlab小波工具箱的数字图像处理及小波分析
  17. 虹科-将人工智能引入电子组装检测
  18. C# 7.0 SPANS
  19. 第十八届中日韩三国IT局长OSS会议暨东北亚开源软件推进论坛在韩国首尔成功举办...
  20. 部署Adobe Reader 9.41

热门文章

  1. Java中使用JNA实现全局监听Windows键盘事件
  2. mysql并行加载机制_Mysql表引擎优化
  3. python ipaddr库_用Python脚本查询纯真IP库QQWry.dat(Demon修改版)
  4. python len命令_python命令行参数
  5. Linux(四):虚拟机Ubuntu 卸载
  6. WARNING: IPv4 forwarding is disabled. Networking will not work.
  7. allure的安装和使用(windows环境)
  8. Description Resource Path Location Type Project configuration is not up-to-date with pom.xml. Select
  9. 职称计算机 高级会计,高级会计《职称计算机》网络应用:Windows防火墙
  10. 博客系统的设计与实现_企业车辆管理系统设计与实现