音频编程 libsndfile

音频编程 libsndfile

libsndfile是一个专门为读写音频采样文件(如wav或者AIFF)设计的C程序库。它支持多种格式,并且有简单易用的接口。在buildroot sdk中可以非常方便的配置和使用libsndfile。
下面的sample用来生成指定频率的正弦波并封装为wav文件。
正弦信号的规格是16k 采样率,1khz频率,-6db,S16_LE format,1 channel。

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>

#include <sndfile.h>

#undef ARRAY_SIZE
#define ARRAY_SIZE(a)	(sizeof(a)/sizeof(a[0]))



struct data_info {
	unsigned int sample_rate;
	unsigned int channel;
	char *format;
};

struct output_ele {
	size_t ele_len;
	char ele[0];
};

typedef void (*output_callback)(struct output_ele *data, void *private_data);

struct sin_info {
	unsigned int amp;
	unsigned int freq;
	unsigned int time;
	struct data_info data;

	output_callback output;
	void *private_data;
};

typedef long long (*compute_total_data_func)(struct sin_info *info);
typedef int (*gen_sin_func)(struct sin_info *info);



struct formats_work {
	unsigned int format_id;
	char *format;
	unsigned int bits;
	compute_total_data_func compute_work;
	gen_sin_func work;
};


static long long total_data_s16_le(struct sin_info *info);
static int gen_sin_s16_le(struct sin_info *info);

struct formats_work format_works[] = {
	{SF_FORMAT_PCM_16, "S16_LE", sizeof(int16_t) * 8,
		total_data_s16_le, gen_sin_s16_le},
};

struct sin_info *get_sin_info(void)
{
	struct sin_info *info = NULL;

	info = malloc(sizeof(struct sin_info));
	if (!info)
		return NULL;

	memset(info, 0, sizeof(struct sin_info));


	return info;
}

int release_sin_info(struct sin_info *info)
{
	if (!info)
		return -1;

	free(info);

	return 0;
}

static long long total_data_s16_le(struct sin_info *info)
{
	return info->time * info->data.sample_rate * info->data.channel
		* sizeof(int16_t);
}

static int gen_sin_s16_le(struct sin_info *info)
{
	float angle_freq, t_delta;
	float resault;
	int16_t resault_s16;
	int i = 0, sample_bytes = 0;
	struct output_ele *p_ele = NULL;

	sample_bytes = info->data.channel * sizeof(uint16_t);
	p_ele = malloc(sizeof(struct output_ele) + sample_bytes);
	if (!p_ele)
		return -1;
	p_ele->ele_len = sample_bytes;

	angle_freq = 2 * M_PI * info->freq;
	t_delta = 1/(float)info->data.sample_rate;

	for (i = 0; i < info->data.sample_rate * info->time; i ++) {
		resault = info->amp * sin(angle_freq * i * t_delta);
		resault_s16 = (int16_t)resault;
		memcpy(p_ele->ele, &resault_s16, sizeof(int16_t));
		if (sample_bytes > sizeof(int16_t))
			memcpy((char *)(p_ele->ele + sizeof(int16_t)),
			       &resault_s16, sizeof(int16_t));
		info->output(p_ele, info->private_data);
	}

	free(p_ele);
	return 0;
}

int gen_sin_data(struct sin_info *info)
{
	int index = 0, ret = 0;

	if (!info->output)
		return -1;

	for (index = 0; index < ARRAY_SIZE(format_works); index ++) {
		if (!strcmp(info->data.format, format_works[index].format)) {
			if (format_works[index].work != NULL) {
				ret = format_works[index].work(info);
				if (ret < 0)
					return ret;
			} else
				return -1;
		}
	}

	if (index == ARRAY_SIZE(format_works))
		return -1;
}

void do_gs_work(struct output_ele *data, void *private_data)
{
	SNDFILE *fp = (SNDFILE *)private_data;
	sf_write_short(fp, (short *)data->ele,
		       (sf_count_t)(data->ele_len/sizeof(short))) ;
}

int main(int argc, char *argv[])
{
	struct sin_info *p_sin_info;
	SNDFILE *sndfile = NULL;
	SF_INFO file_info;

	file_info.samplerate = 16000;
	file_info.channels = 1;
	file_info.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16;

	p_sin_info = get_sin_info();
	if (!p_sin_info) {
		printf("get sin info fail\n");
		return -1;
	}

	if (!sf_format_check(&file_info)) {
		printf("format wrong.\n");
		goto end;
	}

	sndfile = sf_open("./sine.wav", SFM_WRITE, &file_info);
	if (!sndfile) {
		printf("%s\n", sf_strerror(sndfile));
		return -1;
	}

	p_sin_info->amp = 16384;
	p_sin_info->time = 10;
	p_sin_info->freq = 1000;
	p_sin_info->private_data = (void *)sndfile;
	p_sin_info->data.sample_rate = 16000;
	p_sin_info->data.channel = 1;
	p_sin_info->data.format = "S16_LE";
	p_sin_info->output = do_gs_work;

	gen_sin_data(p_sin_info);


	sf_close(sndfile);
end:
	release_sin_info(p_sin_info);
	return 0;

}

amplitude和db

数字音频信号的参考值是最大幅度值,定为0db。
在这里插入图片描述

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
libsndfile库是一个C语言开发的音频文件读写库,它可以进行一些常见的音频格式转换、音频文件拼接、单声道合成为立体声、立体声拆分为单声道等功能。\[3\]该库的官方网站是http://www.mega-nerd.com/libsndfile,你可以在这里找到最新的源代码和支持的音频格式列表。\[2\]如果你想在Windows平台上编译该库,你可以使用IDE打开E:\libsndfile\CMakeBuild\libsndfile.sln,并按照默认步骤进行编译。编译成功后,你可以在E:\libsndfile\CMakeBuild\Debug目录下找到生成的静态库。\[1\]如果你想在嵌入式ARM平台上移植该库,你可以在Ubuntu 16.04上使用以下命令获取源码:sudo apt-get source libsndfile1-dev。\[3\] #### 引用[.reference_title] - *1* *2* [Windows下编译libsndfile音频库](https://blog.csdn.net/caoshangpa/article/details/119682934)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [linux ——libsndfile1-dev库移植至嵌入式arm](https://blog.csdn.net/u014470361/article/details/84947962)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值