PCM 16BIT幅度调节

由于芯片硬件AO的音量控制封装,无法灵活调节音量,故添加软件调节音量。

调节建议:在调节音量之前将AO设备音量设置为较大,然后再使用软件调节pcm输出。

代码:


#include <stdbool.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#define PCM_SIZE_MAX			4*1024 

/*
*	设置16BIT的PCM音量,转换一次的最大size不能超过PCM_SIZE_MAX
*
*	src:pcm源数据
*	
*	size:pcm数据的长度,比如80将音量设置为之前的80%
*
*	设置音量-百分比
*/
static bool pcm_16bit_volume_cover(char * src, int size, int volume)
{
	int 			i	= 0;
	char			dst[PCM_SIZE_MAX] =
	{
		0
	};

	if (size > PCM_SIZE_MAX)
	{
		return false;
	}

	if (volume == 100)
	{
		return true;
	}

	if (volume == 0)
	{
		memset(src, 0, size);
		return true;
	}

	memset(dst, 0, PCM_SIZE_MAX);

	struct timeval tv1, tv2;
	gettimeofday(&tv1, NULL);

	float			bar = volume * 1.0 / 100;

	for (i = 0; i < size; i += 2)
	{
		short 			src_data = (src[i + 1] << 8) | (src[i] &0xFF);

		src_data			= src_data * bar;

		if (src_data > 32767)
		{
			src_data			= 32767;
		}
		else if (src_data < -32768)
		{
			src_data			= -32768;
		}

		dst[i]				= src_data & 0xFF;
		dst[i + 1]			= (src_data >> 8) & 0xFF;

	}

	memcpy(src, dst, size);

	gettimeofday(&tv2, NULL);

	printf("cover volume%d time:%d ms \n", volume, 
		tv2.tv_sec * 1000 + tv2.tv_usec / 1000 - tv1.tv_sec * 1000 - tv1.tv_usec / 1000);
	return true;
}


/*测试代码*/
int main(int argc, char * *argv)
{
	if (argc != 2)
	{
		printf("input file name \n");
		return 0;
	}

	/*获取源文件的大小*/
	char *			src_name = argv[1];
	int 			src_fd = open(src_name, O_RDONLY);

	if (src_fd < 0)
	{
		printf("open %s fail \n", argv[1]);
		return 0;
	}

	int 			src_size = lseek(src_fd, 0, SEEK_END);

	lseek(src_fd, 0, SEEK_SET);

	/*读取源文件数据*/
	char *			src_data = (char *) malloc(src_size);

	read(src_fd, src_data, src_size);
	close(src_fd);
	printf("read %s %dkb \n", src_name, src_size / 1024);


	/*复制一个副本*/
	char *			dst_data = (char *) malloc(src_size);

	memcpy(dst_data, src_data, src_size);

	/*转换音量为80的数据*/
	pcm_16bit_volume_cover(dst_data, src_size, 80);


	/*写入音量为80的数据*/
	char *			p	= strrchr(src_name, '.');

	if (p)
	{
		p[0]				= '\0';
	}

	char			dst_name[128] =
	{
		0
	};
	sprintf(dst_name, "%s-%d%%.pcm", src_name, 50);
	int 			dst_fd = open(dst_name, O_WRONLY | O_CREAT);

	write(dst_fd, dst_data, src_size);
	close(dst_fd);


	free(dst_data);
	free(src_data);
	return 0;
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值