音视频开发:ffplay使用soundtouch实现倍速播放

前言

基于上一篇文章《ffplay使用sonic实现倍速播放》实现倍速播放后,想有个参照相对比下效果,所以用soundtouch也实现了ffplay的倍速播放。个人感觉效果比sonic要好。

一、soundtouch介绍

soundtouch是一个开源音频处理库,主要包含变速和变调功能,ijkplayer就是使用soundtouch实现视频变速的。
soundtouch是基于c++实现的,编译方式中提供了静态库和动态库。静态库提供c++形式的接口。动态库有c语言形式的函数包装提供,但其头文件添加了非c++错误宏,即一定要在c++环境中使用。

二、ffplay中使用soundtouch

由上述内容可知,虽然soundtouch有一套c语言接口,但soundtouch一定要在c++环境中使用。想在ffplay中使用只能再用c语言包装soundtouch,或者将ffplay改成c++实现。但是由于ffplay.c是完全基于c语言的语法,改成c++后需要修改的地方比较多,比较麻烦,故本文采用c语言包装soundtouch。

1、包装接口

下面是接口定义,实现根据具体需求,静态库则使用SoundTouch.h的类和对象,动态库则使用SoundTouchDLL.h中的c语言接口。

#ifndef CSOUNDTOUCH_H
#define CSOUNDTOUCH_H
#ifdef __cplusplus
extern "C" {
#endif
	typedef void* cSoundTouch;
	const char* cSoundTouch_getVersionString();
	int cSoundTouch_getVersionId();
	cSoundTouch cSoundTouch_create();
	void cSoundTouch_destroy(cSoundTouch soundTouch);
	void cSoundTouch_setRate(cSoundTouch soundTouch, double newRate);
	void cSoundTouch_setTempo(cSoundTouch soundTouch, double newTempo);
	void cSoundTouch_setRateChange(cSoundTouch soundTouch, double newRate);
	void cSoundTouch_setTempoChange(cSoundTouch soundTouch, double newTempo);
	void cSoundTouch_setPitch(cSoundTouch soundTouch, double newPitch);
	void cSoundTouch_setPitchOctaves(cSoundTouch soundTouch, double newPitch);
	void cSoundTouch_setPitchSemiTones(cSoundTouch soundTouch, int newPitch);
	void cSoundTouch_setChannels(cSoundTouch soundTouch, int numChannels);
	void cSoundTouch_setSampleRate(cSoundTouch soundTouch, int srate);
	double cSoundTouch_getInputOutputSampleRatio(cSoundTouch soundTouch);
	void cSoundTouch_flush(cSoundTouch soundTouch);
	void cSoundTouch_putSamples(cSoundTouch soundTouch, float* samples, int numSamples);
	void cSoundTouch_putSamples_i16(cSoundTouch soundTouch, short* samples, int numSamples);
	int cSoundTouch_receiveSamples(cSoundTouch soundTouch, float* output, int maxSamples);
	int cSoundTouch_receiveSamples_i16(cSoundTouch soundTouch, short* output, int maxSamples);
	void cSoundTouch_clear(cSoundTouch soundTouch);
	int cSoundTouch_setSetting(cSoundTouch soundTouch, int settingId, int value);
	int cSoundTouch_getSetting(cSoundTouch soundTouch, int settingId);
	int cSoundTouch_numUnprocessedSamples(cSoundTouch soundTouch);
	int cSoundTouch_numChannels(cSoundTouch soundTouch);
	int cSoundTouch_numSamples(cSoundTouch soundTouch);
#ifdef __cplusplus
};
#endif
#endif

本文福利, 免费领取C++音视频学习资料包、技术视频,内容包括(音视频开发,面试题,FFmpeg ,webRTC ,rtmp ,hls ,rtsp ,ffplay ,srs)↓↓↓↓↓↓见下面↓↓文章底部点击免费领取↓↓

2、初始化

根据上述接口直接调用cSoundTouch_create即可创建一个soundtouch对象。

(1)、定义字段

可以在VideoState中添加soundtouch 字段

cSoundTouch soundTouch;

(2)、初始化

在stream_component_open中case AVMEDIA_TYPE_AUDIO:的末尾初始化soundtouch。

is->soundTouch = cSoundTouch_create();
cSoundTouch_setSampleRate(is->soundTouch, sample_rate);
cSoundTouch_setChannels(is->soundTouch, nb_channels);

3、倍速处理

在audio_decode_frame中处理重采样后的音频数据,写回音频数据,并调整相关参数。

(1)、定义字段

倍速处理时需要一个速度参数。并且当处理后的数据过大时需要建立新的缓冲区,需要定义一个自己的缓冲区。

double speed;
char* speed_buf;
int speed_buf_size;

(2)、处理数据

在audio_decode_frame中重采样后,更新时钟之前放置如下代码

double speed = is->speed;
	if (speed != 1)
	{
		//设置倍速
		cSoundTouch_setTempo(is->soundTouch, speed);
		//写入音频数据
		cSoundTouch_putSamples_i16(is->soundTouch, is->audio_buf, af->frame->nb_samples);	
		int numSamples =2*af->frame->nb_samples / speed;
		if (speed < 1)
			//倍速小于1时使用自己的缓冲区
		{		
			int size = numSamples * is->audio_tgt.channels * av_get_bytes_per_sample(is->audio_tgt.fmt);
			if (is->speed_buf_size < size)
			{
				is->speed_buf = av_realloc(is->speed_buf, size);
				is->speed_buf_size = size;
			}
			is->audio_buf = is->speed_buf;
		}
		//读取处理后的数据
		int new_nb_samples = cSoundTouch_receiveSamples_i16(is->soundTouch, is->audio_buf, numSamples);
		//更新参数
		resampled_data_size = new_nb_samples * is->audio_tgt.channels * av_get_bytes_per_sample(is->audio_tgt.fmt);
		af->frame->nb_samples = numSamples;
	}

4、释放资源

在stream_component_close中的case AVMEDIA_TYPE_AUDIO中释放资源

if (is->speed_buf)
{
	av_free(is->speed_buf);
	is->speed_buf = NULL;
}
if (is->soundTouch)
{
	cSoundTouch_destroy(is->soundTouch);
	is->soundTouch = NULL;
}

如果你对音视频开发感兴趣,觉得文章对您有帮助,别忘了点赞、收藏哦!或者对本文的一些阐述有自己的看法,有任何问题,欢迎在下方评论区讨论! 

本文福利, 免费领取C++音视频学习资料包、技术视频,内容包括(音视频开发,面试题,FFmpeg webRTC rtmp hls rtsp ffplay srs↓↓↓↓↓↓见下面↓↓文章底部点击免费领取↓↓

猜你喜欢

转载自blog.csdn.net/m0_60259116/article/details/127463613