ST的插值算法

转载 2013年12月04日 09:30:13
  我们都知道,当播放速度改变的时候,会带来一个副作用,那就是音调也会随着播放的速度而改 
变。播放速度加快,声音将升调,变得尖锐,播放速度减慢,声音将降调,变得低沉,当然这是题 
外之话。改变音频播放速度的方法有很多,我只针对ST变速算法的核心,也就是线性插值算法的实 
现。对于ST的插值算法前面已经提到。 
  k = (y - y0)/(y1-y0) 
->y=(1-k) * y0+k * y1 
k值也就是现在声音播放速度和原始声音播放速度的比。也就是加快/减慢的比率。从这个公式上看 
,k为比率已知,y1为当前已知的一个采样值,y值和原来的位置y0有关,如何理解呢?假如你把一 
连串的采样分成若干段,每次拿一段出来处理,在某段的结尾和紧接的一段之间做插值算法,就要 
保存前一段结尾的采样点。这下子好理解了吧。因此针对16位双声道的音频输入,我们需要先定义 
两个变量(左右声道)来保存前面的值。 
short sPrevSampleL = 0,sPrevSampleR = 0; 
然后算法实现如下: 
第一个参数表示比率,可以理解为插值的间距,越小帧插得越多,播放速度也就越慢,越大帧插得 
少或者直接跳过,播放速度也就越快。 
uint InterpolationStereo(float fRate,short *dest,short *src,uint nSamples) 

    uint srcPos = 0, i = 0, used = 0; 
 float fSlopeCount = 0.0f; 
  
    if (nSamples == 0) return 0; 
    while (fSlopeCount <= 1.0f) 
    { 
        dest[2 * i] = (short)((1.0f - fSlopeCount) * sPrevSampleL + fSlopeCount * src 
[0]); 
        dest[2 * i + 1] = (short)((1.0f - fSlopeCount) * sPrevSampleR + fSlopeCount * 
src[1]); 
        i++; 
        fSlopeCount += fRate; 
    } 
    fSlopeCount -= 1.0f;  
    if (nSamples > 1) 
    { 
        while (1) 
        { 
            while (fSlopeCount > 1.0f) 
            { 
                fSlopeCount -= 1.0f; 
                used ++; 
                if (used >= nSamples - 1) goto end; 
            } 
            srcPos = 2 * used;  
            dest[2 * i] = (short)((1.0f - fSlopeCount) * src[srcPos] 
                + fSlopeCount * src[srcPos + 2]); 
            dest[2 * i + 1] = (short)((1.0f - fSlopeCount) * src[srcPos + 1] 
                + fSlopeCount * src[srcPos + 3]);  
            i++; 
            fSlopeCount += fRate; 
        } 
    } 
end: 
    sPrevSampleL = src[2 * nSamples - 2]; 
    sPrevSampleR = src[2 * nSamples - 1];  
    return i; 

完整的例程: 
//对16位双声道pcm编码的wav文件插值。 
//作者:核桃 
//修改main函数中float rate变量的值可以改变播放速度 
//取值范围最好在0.5~2之间 
#include <stdio.h> 
#include <stdlib.h> 
#define BUFF_SIZE 4096 
#define SCALE 3 
#ifndef uint 
typedef unsigned int uint; 
#endif 
typedef struct 

    char riff_char[4]; 
    int  package_len; 
    char wave[4]; 
} WavRiff; 
typedef struct 

    char  fmt[4]; 
    int   format_len; 
    short fixed; 
    short channel_number; 
    int   sample_rate; 
    int   byte_rate; 
    short byte_per_sample; 
    short bits_per_sample; 
} WavFormat; 
typedef struct 

    char  data_field[4]; 
    uint  data_len; 
} WavData; 
typedef struct 

    WavRiff   riff; 
    WavFormat format; 
    WavData   data; 
} WavHeader; 
short inbuffer[BUFF_SIZE]; 
short outbuffer[SCALE*BUFF_SIZE]; 
short sPrevSampleL = 0,sPrevSampleR = 0; 
uint InterpolationStereo(float fRate,short *dest,short *src,uint nSamples); 
uint InterpolationStereo(float fRate,short *dest,short *src,uint nSamples) 

    uint srcPos = 0, i = 0, used = 0; 
 float fSlopeCount = 0.0f; 
  
    if (nSamples == 0) return 0; 
    while (fSlopeCount <= 1.0f) 
    { 
        dest[2 * i] = (short)((1.0f - fSlopeCount) * sPrevSampleL + fSlopeCount * src 
[0]); 
        dest[2 * i + 1] = (short)((1.0f - fSlopeCount) * sPrevSampleR + fSlopeCount * 
src[1]); 
        i++; 
        fSlopeCount += fRate; 
    } 
    fSlopeCount -= 1.0f;  
    if (nSamples > 1) 
    { 
        while (1) 
        { 
            while (fSlopeCount > 1.0f) 
            { 
                fSlopeCount -= 1.0f; 
                used ++; 
                if (used >= nSamples - 1) goto end; 
            } 
            srcPos = 2 * used;  
            dest[2 * i] = (short)((1.0f - fSlopeCount) * src[srcPos] 
                + fSlopeCount * src[srcPos + 2]); 
            dest[2 * i + 1] = (short)((1.0f - fSlopeCount) * src[srcPos + 1] 
                + fSlopeCount * src[srcPos + 3]);  
            i++; 
            fSlopeCount += fRate; 
        } 
    } 
end: 
    sPrevSampleL = src[2 * nSamples - 2]; 
    sPrevSampleR = src[2 * nSamples - 1];  
    return i; 

int main(int arg, char **argc) 

 FILE *pIn = NULL,*pOut = NULL; 
 WavHeader *wheader = NULL; 
 uint isamples = 0,numBytes = 0,totalBytes = 0; 
 float rate = 0.8f; 
 if (arg < 3) 
 { 
  printf("usage: %s input.wav output.wav/n",argc[0]); 
  return -1; 
 } 
 wheader = (WavHeader *)malloc(sizeof(WavHeader)); 
 pIn = fopen(argc[1], "rb"); 
 pOut = fopen(argc[2], "wb"); 
 numBytes = fread(wheader,1,sizeof(WavHeader),pIn); 
 fwrite(wheader,1,sizeof(WavHeader),pOut); 
  
 while(!feof(pIn)) 
 { 
  numBytes = fread(inbuffer,1,BUFF_SIZE,pIn); 
  numBytes = numBytes >> 2; 
  isamples = InterpolationStereo(rate,outbuffer,inbuffer,numBytes); 
  isamples = isamples << 2; 
  fwrite(outbuffer,1,isamples,pOut); 
  totalBytes += isamples; 
 } 
 fseek(pOut, 0, SEEK_SET); 
 wheader->data.data_len = totalBytes; 
 wheader->riff.package_len = totalBytes + sizeof(WavHeader)-4*sizeof(char)- 
   
  sizeof(int); 
 fwrite(wheader,1,sizeof(WavHeader),pOut); 
 free(wheader); 
 fclose(pIn); 
 fclose(pOut); 
 return 0; 

  PS:根据某某人的采样定理,采样频率一定要等于或者大于信号中最高频率的2倍。我们可以理解 
为,最快播放速度不宜超过2倍,最慢播放速度不宜低于原来信号的1/2也就是0.5倍,如果不是声 
音失真会非常严重。
 

RMQ--ST表算法理解

RMQ(Range Minimum/Maximum Query),即区间最值查询,是指这样一个问题:对于长度为n的数列A,回答若干询问RMQ(A,i,j)(i,j ST算法(Sparse Tabl...
  • qq1169091731
  • qq1169091731
  • 2016年07月21日 11:59
  • 1106

st的输入输出模式

1、上拉输入:上拉就是把电位拉高,比如拉到Vcc。上拉就是将不确定的信号通过一个电阻嵌位在高电平!电阻同时起限流作用!弱强只是上拉电阻的阻值不同,没有什么严格区分。 2、下拉输入:就是把电压拉低...
  • dongdong0071
  • dongdong0071
  • 2016年01月26日 16:12
  • 497

测试过程之UT-IT-ST的区别

本文转载至:http://www.51testing.com/html/15/384415-233345.html   测试过程 区别 UT IT ...
  • robertsong2004
  • robertsong2004
  • 2015年11月20日 15:20
  • 3884

如何使用st官网的库文件开发项目详细教程

结合st官方库文件开发STM32
  • CHAMIYOUYAN
  • CHAMIYOUYAN
  • 2014年11月16日 18:50
  • 1341

svn st小解(以偶工作中遇到问题为例)

==[82]==jeanyu@debian:~/online/trunk$svn st ? libpaipai.d ? tags ? gen_svn_ci ? ...
  • xiaoxiaoniaoer1
  • xiaoxiaoniaoer1
  • 2013年01月24日 11:16
  • 2884

BZOJ 1047 [HAOI2007]理想的正方形 二维ST表+压维

Description   有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值 的差最小。 Input   第一行为3个整数,分别表示a,b,...
  • ThinFatty
  • ThinFatty
  • 2017年07月02日 22:28
  • 309

【基础学习】Avalon-ST接口协议

Avalon-ST接口是一种单向点对点的高速接口,主要针对的是高速数据流的传输,减少数据流处理中的瓶颈。...
  • zenglichuanjia
  • zenglichuanjia
  • 2014年09月10日 12:01
  • 2656

利用ST提供的USB例程实现USB IAP功能

我们知道ST推出的Cortex-M3平台STM32内部有两个Flash区域,一是System Flash,ST官方保留的一个区域,用于存放IAP代码。该区域不对用户开放,仅提供UART的通讯接口用于I...
  • f907279313
  • f907279313
  • 2014年02月09日 22:50
  • 987

R语言 - 基于[狗熊会]“财务报表分析与ST预测”数据的逻辑回归

本案例是狗熊会基础案例“财务报表分析与ST预测”的作业,一方面总结自己所学,一方面希望惠及初学者,当然,很多东西自己也在探索学习,难免班门弄斧,如有错误,欢迎指正。欢迎转载,转载请注明原文地址http...
  • max_cola
  • max_cola
  • 2017年12月08日 14:01
  • 617

CAS票据之ST与TGT过期策略详细说明

CAS的核心就是Ticket中文称之为票据,以及在Ticket之上的一系列逻辑处理操作。CAS的主要包含票据有TGT、ST、PGT、PGTIOU、PT,其中TGT、ST是CAS1.0协议中就有的票据,...
  • afreon
  • afreon
  • 2016年11月16日 09:26
  • 5760
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:ST的插值算法
举报原因:
原因补充:

(最多只允许输入30个字)