基于FFmpeg的视频播放器开发系列教程(六):FFmpeg视频音量调节

       在声音物理学中,音量的变化是对数关系,在代码里,暂时我没有这样处理,简单的用线性关系表示,在主进程进行设置,解码时设置进pcm数据,再用声卡播放。

       这段代码的实现也是参考了别人的,代码如下:

/*
* @Func   : SetVolume
* @brief  : 音量调节
* @author : linghuzhangmen
* @[in]   : buf 为需要调节音量的音频数据块首地址指针
* @[in]   : size为长度
* @[in]   : uRepeat为重复次数,通常设为1
* @[in]   : vol为增益倍数,可以小于1
*/
void MyFFmpeg::SetVolume(char* buf, UINT32 size, UINT32 uRepeat, double vol)
{
	if (!size)
	{
		return;
	}
	for (int i = 0; i < size; i += 2)
	{
		short wData;
		wData = MAKEWORD(buf[i], buf[i + 1]);
		long dwData = wData;
		for (int j = 0; j < uRepeat; j++)
		{
			dwData = dwData * vol;
			if (dwData < -0x8000)
			{
				dwData = -0x8000;
			}
			else if (dwData > 0x7FFF)
			{
				dwData = 0x7FFF;
			}
		}
		wData = LOWORD(dwData);
		buf[i] = LOBYTE(wData);
		buf[i + 1] = HIBYTE(wData);
	}
}

 在转成pcm数据时,加上音量的调节

int MyFFmpeg::ToPCM(char *out)
{
	m_mutex.lock();
	if (!m_afc || !m_pcm || !out)
	{
		m_mutex.unlock();
		return 0;
	}

	AVCodecContext *ctx = m_afc->streams[m_audioStream]->codec;
	if (m_aCtx == NULL)
	{
		m_aCtx = swr_alloc();

		//可能会出问题, 16位音频
		swr_alloc_set_opts(m_aCtx, ctx->channel_layout, 
			AV_SAMPLE_FMT_S16,
			ctx->sample_rate, 
			ctx->channels, 
			ctx->sample_fmt,
			ctx->sample_rate, 
			0, 0);

		swr_init(m_aCtx); //初始化样本转换
	}

	uint8_t *data[1];
	data[0] = (uint8_t *)out;
	int len = swr_convert(m_aCtx, data, 10000, (const uint8_t **)m_pcm->data, m_pcm->nb_samples);
	if (len <= 0)
	{
		m_mutex.unlock();
		return 0;
	}
	int outsize = av_samples_get_buffer_size(NULL, ctx->channels, m_pcm->nb_samples, AV_SAMPLE_FMT_S16, 0);

	//音量调节
	SetVolume(out, outsize, 1, m_VolumeRatio);

	m_mutex.unlock();

	return outsize;
}

  播放时,拖动slider就能调节声音的变化

//调节音量
void FFVideoPlayer::volumeAdjust()
{
	MyFFmpeg::Get()->m_VolumeRatio = (ui.sliderVolume->value()) * 1.00 / 100;
}

静音的设置就直接把增益参数设为0,即可,同时把图标也换掉,代码如下:

//静音设置
void FFVideoPlayer::setMute()
{
	m_isMute = !m_isMute;
	if (m_isMute)
	{
		MyFFmpeg::Get()->m_VolumeRatio = 0;
		setButtonBackImage(ui.btnSetVolume, "./Resources/mute.png");
	}
	else
	{
		MyFFmpeg::Get()->m_VolumeRatio = 0.5;
		setButtonBackImage(ui.btnSetVolume, "./Resources/volume.png");
	}
}

      其实这种设置有问题,目前我没想到更好的办法,以后解决了再更新。

      本教程专栏地址:https://blog.csdn.net/yao_hou/category_9275800.html

      源码链接在第五篇。

发布了124 篇原创文章 · 获赞 84 · 访问量 16万+

猜你喜欢

转载自blog.csdn.net/yao_hou/article/details/103790617