soundtouch变速主要采用WSOLA算法来进行变速。

http://www.surina.net/soundtouch/

https://blog.csdn.net/suhetao/article/details/5863477

The principle of WSOLA refer to following figure:

There are three important parameter: SequenceMs, overlapMs, seekWindowMs.

These parameters affect to the time-stretch algorithm as follows:

    • DEFAULT_SEQUENCE_MS: This is the default length of a single processing sequence in milliseconds which determines the how the original sound is chopped in the time-stretch algorithm. Larger values mean fewer sequences are used in processing. In principle a larger value sounds better when slowing down the tempo, but worse when increasing the tempo and vice versa.

      By default, this setting value is calculated automatically according to tempo value.

    • DEFAULT_SEEKWINDOW_MS: The seeking window default length in milliseconds is for the algorithm that seeks the best possible overlapping location. This determines from how wide a sample "window" the algorithm can use to find an optimal mixing location when the sound sequences are to be linked back together.

      The bigger this window setting is, the higher the possibility to find a better mixing position becomes, but at the same time large values may cause a "drifting" sound artifact because neighboring sequences can be chosen at more uneven intervals. If there's a disturbing artifact that sounds as if a constant frequency was drifting around, try reducing this setting.

      By default, this setting value is calculated automatically according to tempo value.

    • DEFAULT_OVERLAP_MS: Overlap length in milliseconds. When the sound sequences are mixed back together to form again a continuous sound stream, this parameter defines how much the ends of the consecutive sequences will overlap with each other.

      This shouldn't be that critical parameter. If you reduce the DEFAULT_SEQUENCE_MS setting by a large amount, you might wish to try a smaller value on this.

function out = check_limits(in, min, max)

if in < min

  out = min;

else if in > max

  out = max;

else

  out = in;

end

end

function [seekWindowLength, seekLength, overlapLength] = calcSeqParams(fs, tempo)

overlapMs = 8;

autoseq_tempo_low = 0.5;

autoseq_tempo_top = 2.0;

autoseq_at_min = 90;

autoseq_at_max = 40;

autoseq_k =(autoseq_at_max - autoseq_at_min) / (autoseq_temp_top - auto_temp_low);

autoseq_c = autoseq_at_min -autoseq_k * autoseq_temp_low;

autoseek_at_min = 20;

autoseek_at_max = 15;

autoseek_k =(autoseek_at_max - autoseek_at_min) / (autoseq_temp_top - auto_temp_low);

autoseek_c = autoseek_at_min -autoseek_k * autoseq_temp_low;

%calc sequenceMs

seq = autoseq_c + autoseq_k * tempo;

seq = check_limits(seq, autoseq_at_max, autoseq_at_min);

sequenceMs = round(seq);

seek= autoseek_c + autoseek_k * tempo;

seek= check_limits(seek, autoseek_at_max, autoseek_at_min);

seekMs = round(seek)

seekWindowLength = sequenceMs * fs / 1000;

seekLength = seekMs * fs /1000;

overlapLength = overlapMs * fs / 1000;

overlapLength  = overlapLength - mod(overlapLength, 8);

end

function corr = calcCrossCorr(mixingSeg, compareSeg)

len = length(compareSeg(:,1));

corr = 0;

norm = 0;

for i = 1: 1 : len

  corr = corr + mixingSeg(i) * compareSeg(i);

  norm = norm + mixingSeg(i) * mixingSeg(i);

end

corr = corr / sqrt(norm);

end

function offset = seekBestOverlapPosition(seekWindow, compareSeg, overlapLength, seekLength)

bestCorr = calcCrossCorr(seekWindow(1:overlapLength, 1), compareSeg);

offset = 1;

for i = 2 : 1 : seekLength

  corr = calcCrossCorr(seekWindow(i:i + overlapLength, 1), compareSeg);

  if corr > bestCorr

    bestCorr = corr;

    offset = i;

  end

end

end

function output = overlap(rampUp, rampDown)

len=length(rampDown);

for i = 1:1:len

  output(i,1) = rampUp(i) * i / len + rampDown(i) * (len - i) / len;

end

end

function [output, outpos, lastCompare, inpos] = processSamples(input, inputLen, expectOutputLen, compareSeg, overlapLength, seekLength, seekWindowLength, tempo, isBeginning)

nominalSkip = tempo * (seekWindowLength - overlapLength);

sampleReq  = max(round(nominalSkip) + overlapLength, seekWindow);

inpos = 1;

outpos = 1;

offset = 0;

skipFract = 0;

while inputLen - inpos >= sampleReq

  if isBeginning == 0

    offset = seekBestOverlapPosition(input(inpos : inpos + overlapLength + seekLength - 1, 1), compareSeg, overlapLength, seekLength);

    output(outpos:outpos + overlapLength - 1, 1) = overlap(input(inpos + offset : inpos + offset + overlapLength - 1, 1), compareseg);

    ouputpos = outpos + overlapLength;

    offset = offset  + overlapLength;

  else

    isBeginning = 0;

    skip = round(tempo * overlapLength);

    skipFract = skipFract - skip;

  end

  temp = (seekWindowLength - 2 * overlapLength);

  if outpos + tmep < expectOutputLen

    output(outpos : outpos + temp - 1, 1) = input (inpos + offset : inpos + offset + temp - 1, 1);

    outpos = outpos + temp;

  else   

    output(outpos : expectOutputLen, 1) = input (inpos + offset : inpos + offset + expectOutputLen- outpos, 1);

    outpos = expectOutputLen;

    beak;

  end

  compareSeg = input (inpos + offset + temp: inpos + offset + temp +overlapLength - 1, 1);

  skipFract = skipFract + nominalSkip;

  ovlSkip = floor(skipFract);

  skipFract = skipFract - ovlSkip;

  inpos = inpos  + ovlSkip;

end

lastCompare = compareSeg;

end

function output = changeTempo(input, fs, tempo)

inputLen = length(input(:,1));

outputLen = round(inputLen / tempo);

output = zeros(outputLen, 1);

[seekWindowLength, seekLength, overlapLength] = calcSeqParams(fs, tempo);

isBeginning = 1;

compareBuf = zeros(overlapLength, 1);

expectOutLen = outputLen;

[output, outpos, compareBuf, inpos] = processSamples(input, inputLen, expectOutLen, compareBuf, overlapLength, seekLength, seekWindowLength, tempo, isBeginning);

remainningSamples = inputLen - inpos;

%append zeros to the remainning data

remainningLen = remainningSamples + 200 * 128;

remainningInput = zeros(remainningLen, 1);

remainningInput(1:remainningSamples, 1) = input(inpos:inpos + remainningSamples - 1, 1);

if outputLen > outpos

  expectOutLen = outputLen - outpos + 1;

  isBeginning = 0;

  [tempOutput, tempOutpos, compareBuf, inpos] = processSamples(remainingInput, remainingInputLen, expectOutLen, compareBuf, overlapLength, seekLength, seekWindowLength, tempo, isBeginning);

  output(outpos:outputLen, 1) = tempOutput(1: tempOutpos);

end

end

main.m:

clc;

clear all;

[input fs] = wavread('test.wav');

tempo = 2;

output = changeTempo(input, fs, tempo);

wavwrite(output, fs, 'output.wav');

soundtouch 变速算法matlab实现的更多相关文章

  1. soundtouch变速wsola算法之改进

    soundtouch变速算法很类似sola算法,细看才知道是wsola算法. 上个星期有个需求,将该变速应用到直播的包处理,有点类似于webrtc的netEQ处理机制. 直接使用soundtouch, ...

  2. OLA音频变速算法的仿真与剖析

    前段时间,在尝试音乐节拍数的提取时,终于有了突破性的进展,效果基本上比市面上的许多商业软件还要好,在作节拍数检测时,高频信息作用不大, 通过重采样减小运算量.重采样让我想起了在学校里面做的变速变调算法 ...

  3. 标准差分进化算法matlab程序实现(转载)

    标准差分进化算法matlab程序实现 自适应差分演化算法方面的Matlab和C++代码及论文 差分进化算法 DE-Differential Evolution matlab练习程序(差异演化DE) [ ...

  4. 密度峰值聚类算法MATLAB程序

    密度峰值聚类算法MATLAB程序 凯鲁嘎吉 - 博客园 http://www.cnblogs.com/kailugaji/ 密度峰值聚类算法简介见:[转] 密度峰值聚类算法(DPC) 数据见:MATL ...

  5. GWO(灰狼优化)算法MATLAB源码逐行中文注解(转载)

    以优化SVM算法的参数c和g为例,对GWO算法MATLAB源码进行了逐行中文注解. tic % 计时器 %% 清空环境变量 close all clear clc format compact %% ...

  6. 每天进步一点点------Alpha半透明图形叠加算法Matlab+Verilog实现

    Alpha图形叠加算法Matlab+Verilog实现 1.1. Alpha算法的研究 Alpha通道是一个8位的灰度通道,该通道用256级灰度来记录图像中的透明度信息,定义透明.不透明和半透明区域, ...

  7. 医学CT图像特征提取算法(matlab实现)

    本科毕设做的是医学CT图像特征提取方法研究,主要是肺部CT图像的特征提取.由于医学图像基本为灰度图像,因此我将特征主要分为三类:纹理特征,形态特征以及代数特征,每种特征都有对应的算法进行特征提取. 如 ...

  8. 蚁群算法matlab实现

    大家好,我是小鸭酱,博客地址为:http://www.cnblogs.com/xiaoyajiang 以下用matlab实现蚁群算法:   %蚂蚁算法test   %用产生的一个圆上的十个点来检验蚂蚁 ...

  9. 多源最短路Floyd 算法————matlab实现

    弗洛伊德(Floyd)算法是一种用于寻找给定的加权图中顶点间最短路径的算法.该算法名称以创始人之一.1978年图灵奖获得者.斯坦福大学计算机科学系教授罗伯特·弗洛伊德命名. 基本思想 通过Floyd计 ...

随机推荐

  1. 一起学Vue之条件判断

    在Vue进行前端开发中,条件判断主要用于根据不同的条件来决定显示或隐藏,或者进行视图之间的切换,本文以一个简单的小例子简述v-if的常见用法,仅供学习分享使用,如有不足之处,还请指正. v-if 指令 ...

  2. .net core 3.0配置跨域

    1.ConfigureServices services.AddCors(c => { // 配置策略 c.AddPolicy("Policy", policy => ...

  3. 使用高精度计算斐波那契数列 c++

    使用高精度计算斐波那契数列 非高精度 Code(Non-high accuracy) 这是不用高精度的代码 #include<bits/stdc++.h> using namespace ...

  4. SP10707 COT2 - Count on a tree II [树上莫队学习笔记]

    树上莫队就是把莫队搬到树上-利用欧拉序乱搞.. 子树自然是普通莫队轻松解决了 链上的话 只能用树上莫队了吧.. 考虑多种情况 [X=LCA(X,Y)] [Y=LCA(X,Y)] else void d ...

  5. P1345 [USACO5.4]奶牛的电信Telecowmunication【最小割】【最大流】

    题目描述 农夫约翰的奶牛们喜欢通过电邮保持联系,于是她们建立了一个奶牛电脑网络,以便互相交流.这些机器用如下的方式发送电邮:如果存在一个由c台电脑组成的序列a1,a2,...,a(c),且a1与a2相 ...

  6. 洛谷 P4708 画画

    题意 在所以置换下,本质不同的各个极大连通子图均含有欧拉闭迹的\(n\)阶图个数 做法 务必先做完这题再看此题解,因为会省略大部分分析了 仍是从边入手,隔外限制:各个点度数是偶数 某个因子内\((m= ...

  7. cli4适配移动端

    1.首先在项目中安装以下依赖 npm install px2rem-loader --savenpm install amfe-flexible --savenpm install postcss-p ...

  8. centos 安装桌面

    centos7.*安装 1,安装 yum groupinstall "KDE Plasma Workspaces" 2.启动 startx

  9. xmind修改默认配置

    XMIND使用过程中,输入英文字符的时候,第1.2层级的英文字母总是默认大写,手动修改很繁琐.默认字体,想切换成其他类型,也是要手动一个个去修改. 网上找了下相关的问题,找到一些解决办法,整理到文档中 ...

  10. 【你不知道的javaScript 上卷 笔记5】javaScript中的this词法

    function foo() { console.log( a ); } function bar() { var a = 3; foo(); } var a = 2; bar(); 上面这段代码为什 ...