关于声音的变速不变调,或者只是单纯的变调,现在很多视频播放器或者音频播放器或者移动端APP都实现了此功能。诸如腾讯视频,爱奇艺视频,优酷视频。。。。。。而我们主要是以SoundTouch开源源码来实现:SoundTouch是一种非常优秀的音频处理算法,大名鼎鼎的安卓端开发开源源码ijkplayer就是用的SoundTouch的算法实现变速不变调。

但是如果同时对音视频实现变速不变调呢,这个其实说复杂也复杂,说简单也简单,如果播放器源码是自己做的,我们可以让视频去同步音频,音频速度加快,证明音频数据减少,那么视频帧也会丢弃。如果音频速度变慢,证明音频数据增多,那么视频帧间切换会变慢即可。

直接贴源码吧:

下面是我封装的头文件:

#pragma once
#include "SoundTouch.h"
using namespace soundtouch;class CSoundTouchEx
{
public:CSoundTouchEx(void);~CSoundTouchEx(void);private:int m_nChannels;float m_fTempo;float m_fRate;SoundTouch m_soundtouch;public:float GetTempo(){return m_fTempo;}bool SetTempo(float nTempo);float GetRate(){return m_fRate;}bool SetRate(float nRate);int TempoProcess(char *pOutBuf,char *pInBuf,int nInDataCount);void SetTempoFormat(int sampleRate=44100,int channels=2){ m_soundtouch.setSampleRate(sampleRate);m_soundtouch.setChannels(channels);m_nChannels=channels;m_soundtouch.setSetting(SETTING_USE_QUICKSEEK, 0);m_soundtouch.setSetting(SETTING_USE_AA_FILTER, 1);}bool shortTOfloat(const short *pShort,int nNum,float *pFloat){double fscale = 1.0 / 32768.0;// convert to floats, scale to range [-1..+1[for (int i = 0; i < nNum; i ++){pFloat[i] = (float)(fscale * (double)pShort[i]);}return true;}bool floatTOshort(const float *pFloat,int nNum,short *pShort){int iTemp=0;// convert to 16 bit integerfor (int i = 0; i < nNum; i ++){// convert to integeriTemp = (int)(32768.0f * pFloat[i]);// saturateif (iTemp < -32768) iTemp = -32768;if (iTemp > 32767)  iTemp = 32767;pShort[i] = (short)iTemp;}return true;}
};

接下来是实现的CPP源码:

#include "StdAfx.h"
#include ".\soundtouchex.h"CSoundTouchEx::CSoundTouchEx(void)
{m_fRate=1;m_fTempo=0;m_nChannels=2;
}CSoundTouchEx::~CSoundTouchEx(void)
{
}bool CSoundTouchEx::SetRate(float nRate)
{//if(nRate<-50) //  return false;//if(nRate>900)//   return false;//m_soundtouch.setRateChange(nRate);m_soundtouch.setPitch(nRate);m_fRate=nRate;return true;
}bool CSoundTouchEx::SetTempo(float nTempo)
{if(nTempo<-50)return false;if(nTempo>900)return false;//m_soundtouch.setRateChange(nTempo);m_soundtouch.setTempoChange(nTempo);m_fTempo=nTempo;return true;
}int CSoundTouchEx::TempoProcess(char *pOutBuf,char *pInBuf,int nInDataCount)
{int nChannels=m_nChannels;short *pOutBuf1=(short*)pOutBuf;int nOut=0;DWORD time1=::timeGetTime();//m_soundtouch.flush();const int tempoBUFSIZE=(1024*2);//SAMPLETYPE *pNewBuf=new SAMPLETYPE[nInDataCount];SAMPLETYPE pNewBuf[1024*64];//memset(pNewBuf,0,sizeof(SAMPLETYPE)*nInDataCount);shortTOfloat((short*)pInBuf,nInDataCount,pNewBuf);int nAllSize=0;int nPointer=0;SAMPLETYPE *pBuf=0;for(;;){int nTrueLen=0;SAMPLETYPE *pBuf=pNewBuf+nPointer;nPointer+=tempoBUFSIZE;nTrueLen=tempoBUFSIZE;if(nPointer>=nInDataCount){nTrueLen=nInDataCount-nPointer+tempoBUFSIZE;nPointer+=nTrueLen;}int buffSizeSamples=nTrueLen/nChannels;// Feed the samples into SoundTouch processorm_soundtouch.putSamples((SAMPLETYPE*)pBuf, buffSizeSamples);int nSamples=0;do {nSamples = m_soundtouch.receiveSamples((SAMPLETYPE*)pBuf, buffSizeSamples);floatTOshort(pBuf,nSamples*nChannels,(short*)(pOutBuf1+nAllSize));nAllSize+=nSamples*nChannels;} while (nSamples != 0);if(nPointer>=nInDataCount)break;}//if(pNewBuf)// delete []pNewBuf;DWORD time2=::timeGetTime()-time1;return nAllSize*2;//因为是char
}

调用代码段:

int CXiaoPlayer::OutAudio(BYTE *pPCM,int nlen,int c,int s,int b,int pts)
{
    m_soundtouch.SetTempoFormat(s,c);
    //变速不变调
    BYTE *TempoBuf=new BYTE[1024*200]; 
    int nBytes=nlen;
    if(m_soundtouch.GetTempo()!=0||m_soundtouch.GetRate()!=1)
    {
        try
        {
            nBytes=m_soundtouch.TempoProcess((char*)TempoBuf,(char*)pPCM,nlen/2);
        }
        catch(...)
        {
            TRACE0("CAudioPlay:TempoProcess错误\n");
            m_soundtouch.SetTempo(0);
        }
    }
    else
    {
        memcpy(TempoBuf,pPCM,nlen);
        nBytes=nlen;
    }

if(nBytes>0)
    {
        WAVEFORMATEX waveformat;
        memset(&waveformat, 0, sizeof(WAVEFORMATEX));
        waveformat.cbSize = sizeof(WAVEFORMATEX);
        waveformat.wFormatTag = WAVE_FORMAT_PCM; // pcm
        waveformat.nChannels = c; //
        waveformat.nSamplesPerSec = s; // 
        waveformat.wBitsPerSample = b; // 
        waveformat.nBlockAlign = waveformat.nChannels * waveformat.wBitsPerSample / 8;
        waveformat.nAvgBytesPerSec = waveformat.nSamplesPerSec * waveformat.nBlockAlign;    
        PlayAudio(TempoBuf,nBytes,(BYTE*)&waveformat,pts);
        
    }
    delete []TempoBuf;
    return nBytes;
}

OK!今天就到此为止!

如果大家有合作需求:请联系QQ35744025,10多年专业音视频开发经验,欢迎骚扰。

ffmpeg播放器声音效果2-变速不变调及变调相关推荐

  1. ffmpeg播放器声音效果1-淡入淡出

    直接上播放器: 播放器要求使用类似千千静听的淡入淡出功能,声音的淡入淡出,就是开始声音缓缓变大,不会突然很大.结束的时候声音逐渐放小,不会突然的消失.特别对于某些特别场合特别有用,比如交谊舞,舞台歌曲 ...

  2. FFmpeg音频播放器(8)-创建FFmpeg播放器

    原文地址::https://www.jianshu.com/p/73b0a0a9bb0d 相关文章 1.FFmpeg音频解码播放----https://www.jianshu.com/p/76562a ...

  3. ffmpeg播放器实现详解 - 音频同步控制

    ffplay是ffmpeg源码中一个自带的开源播放器实例,同时支持本地视频文件的播放以及在线流媒体播放,功能非常强大. FFplay: FFplay is a very simple and port ...

  4. 《Android FFmpeg 播放器开发梳理》第一章 播放器初始化与解复用流程

    <Android FFmpeg 播放器开发梳理>: 第零章 基础公共类的封装 播放器初始化与解复用流程 这一章,我们来讲解播放器解复用(从文件中读取数据包)的流程.在讲解播放器的读数据包流 ...

  5. 某牛的QT+ffmpeg 播放器 的readme

    http://download.csdn.net/source/2802201 write by :lbwave@sina.com QT+ffmpeg 大名顶顶的QT ffmpeg 我就不用说了.看看 ...

  6. android平台移植ffmpeg 播放器

    引用:http://blog.csdn.net/ouyangtianhan/article/details/7943543 IT行业是一个踩在巨人肩膀上前进的行业,否则做的事情不一定有意义,所以我也是 ...

  7. ffmpeg播放器(一) 视频解码与播放

    1.环境搭建 首先需要导入所需要的包include.armeabi-v7a. 然后跟项目建立连接,在CMakeList.txt,并做了相关的解释: cmake_minimum_required(VER ...

  8. ffmpeg播放器快进快退(七)

    指导7:快进快退 处理快进快退命令 现在我们来为我们的播放器加入一些快进和快退的功能,因为如果你不能全局搜索一部电影是很让人讨厌的.同时,这将告诉你av_seek_frame函数是多么容易使用. 我们 ...

  9. 音视频从入门到精通——FFmpeg 播放器实现音视频同步的三种方式

    老人们经常说,播放器对音频和视频的播放没有绝对的静态的同步,只有相对的动态的同步,实际上音视频同步就是一个"你追我赶"的过程. 音视频的同步方式有 3 种,即:音视频分别向系统时钟 ...

最新文章

  1. Lua和C++交互总结(很详细)
  2. 熊猫烧香源代码(转载)
  3. Mono制作安装包让C#桌面应用程序脱离net framework步骤
  4. js slice 参数为负值
  5. Java集合工具类的一些坑,Arrays.asList()、Collection.toArray()...
  6. git 创建webpack项目_使用webpack手动创建一个完整项目的全过程
  7. 软考信息系统项目管理师_信息系统安全管理---软考高级之信息系统项目管理师026
  8. Linux下PHP开启Oracle支持(oci8)
  9. 如何建立网页快捷方式linux,怎么创建linux命令”快捷方式”或”自定义命令”...
  10. vue-video-player的使用方法,vue-video-player在移动端点击画面不触发事件不能暂停播放的解决方法
  11. 视频帧数,普清,高清,超清,分辨率
  12. 2.4G RFID动物耳标解决方案 SI24R2F+
  13. 女性内分泌失调要小心
  14. 概率论--贝叶斯法则
  15. 第8讲 - C语言关键字(8)
  16. android 仿qq发动态,Android opengl 实现动态贴纸(仿QQ的拍摄)
  17. 为何要从用户角度出发来思考问题
  18. 女神说拍了一套写真集想弄成素描画?很简单,用Python就行了!
  19. 最优化理论与设计——最优化设计的基本概念
  20. 背单词软件-功能介绍

热门文章

  1. zabbix_server表面启动成功,但是没有进程
  2. linux ramdisk swap,ramdisk和initramfs比较
  3. Ubuntu16.04 + Geforce GT630 OEM安装cuda 8.0
  4. HTML中的语义化标签
  5. 【程序人生】虚拟现实(VR)版霍兰德职业兴趣岛测试
  6. Docker Compose 容器编排基础使用
  7. 工控机主板与ARM工控机主板有什么不同呢?
  8. 如何使用 Django 进行分页
  9. 导航条动态模糊效果实现原理实战
  10. 本机php环境搭建教程:windows环境下wampserver的配置教程——超级详细