国产音频压缩格式JLM——SDK介绍

一、背景

音频采集和播放是电子设备必要功能之一,涉及录音、通话、游戏、音乐、影视、语音识别等各个领域。目前全球使用的主流音频格式有WAV、AVI等原始音频文件格式,MP3、WMA、AAC等有损音频压缩,APE、FLAC等无损音频压缩。
随着信息化的发展,一方面用户对音频质量的要求越来越高,另一方面因传输速率的提升,高质量的音频能有效传输。其次,用户对版权保护、隐私保护等需求日益增长,给音频压缩算法提出了加密、版权管理、播放鉴权等具体功能要求。
新的音频压缩算法能有效扩展电子类产品发展方向,同时也能促进部分行业的健康有序发展,掌握更多话语权。比如当音频文件具备版权管理和播放鉴权功能后,在未获得商业授权,或播放授权下,将无法播放(或有限播放),从而从技术上管控音频版权。又比如每个用户在音频采集编码时就必须打上其唯一数字标签,任何修改或篡改都需要数字签名,那么很容易追根溯源。
为此,我公司结合自主发明的编码算法,研发了一款能针对PCM采样数据压缩、加密、签名于一体的音频压缩算法,该算法具有如下特征:
1、 对称加密,压缩的同时进行加密。
2、 支持无损、Q1和Q2两个档次的高质量有损压缩。
3、 可扩展性,提供自定义的版权、发布人、版号、数字签名、时间戳等方法。
4、 支持8位、16位和24位采样,可分块(分段)编码(分段加密)。
5、 文件格式为JLM。
6、 提供JLM与WAV互转接口。
JLM音频压缩算法基于加权概率模型(杰林码的核心数学模型)的核心算法联合应用,加权概率模型的编码算法最大的特征就是通过改变权系数能得到不同的编码结果,比如当权系数小于1时能扩展数据,当权系数为1到Rmax(杰林码理论最大权系数,详细请参考《杰林码原理及应用》)时可以无损压缩和加密数据,当权系数大于Rmax是可以有损或降熵编码,当权系数大于Rmax且设定编码输出长度时则杰林码又能有效的转换为单向散列函数(哈希函数)。关键是这些算法完全自主可控。
下载链接:JLM SDK 1.1.0

二、JLM音频压缩算法SDK说明

1、JLM SDK封装说明
程序语言:C/C++
版本号:1.1.0
系统架构:x86和x64,可支持RAM
操作系统:unix、linux和windows
SDK文件说明:

文件名 说明
JLMAudioCompression.h JLM音频压缩算法的头文件,包括了多个可调用的函数入口。
WAV.h WAV音频格式的读写头文件,包括了多个可调用的函数入口。
LIBJLMAudioCompressionAlgorithm.a Linux/unix静态库(1.0.0版本仅提供x86的库)
DLLJLMAudioCompressionAlgorithm.so Linux/unix动态库(1.0.0版本仅提供x86的库)
DLLJLMAudioCompactionAlgorithm(x64).dll Windows动态库x64(64位操作系统)
LIBJLMAudioCompactionAlgorithm(x64).lib Windows静态库x64(64位操作系统)
DLLJLMAudioCompactionAlgorithm(x86).dll Windows动态库x86(32位操作系统)
LIBJLMAudioCompactionAlgorithm(x86).lib Windows静态库x86(32位操作系统)
在DEMO中提供了linux、Windows对应的录音、播放等功能样例。

三、JLM音频和WAV互转

1、Linux(ubuntu + gcc)

#include "JLMAudioCompression.h"
#include 
#include 
#include 
#include 
#include 

using namespace std;

int main() {
	JLMAudio jlm;
	int i, errsign = 0, inputerr, q = 0;
	int sign = 0, restart = 0; // 为0表示编码,为1表示译码
	const char* passwords = nullptr;
	const char* WAV_PATH = nullptr;
	const char* JLM_PATH = nullptr;
	char pass_str[2000], wavpath_str[2000], jlmpath_str[2000];
	
RESTART:
	for (i = 0; i < 2000; ++i) {
		pass_str[i] = 0x00;
		wavpath_str[i] = 0x00;
		jlmpath_str[i] = 0x00;
	}
	printf("----------------------------------------------------------------------------------------------------------\n");
	printf("请选择是编码还是译码(输入0为“WAV转JLM”,输入1为“JLM转WAV”,每完成一个步骤需【回车】进入下一步):\n");
	inputerr = scanf("%d", &sign);
	if (sign == 0) {
		printf("您选择了【WAV转JLM】,请在下面输入WAV文件的路径(如D://文件名.wav):\n");
		inputerr = scanf("%s", wavpath_str);
		
		printf("请在下面输入JLM文件的路径(如E://文件名.jlm):\n");
		inputerr = scanf("%s", jlmpath_str);
		
		printf("请在下面输入加密密码:\n");
		inputerr = scanf("%s", pass_str);

		RESET_Q:
		printf("请输入音频压缩指标(0表示无损(默认),1表示高质量,2表示次高质量):\n");
		inputerr = scanf("%d", &q);
		if (q < 0 || q > 2) {
			printf("指标输入有误!0表示无损(默认),1表示高质量,2表示次高质量\n");
			goto RESET_Q;
		}
	}
	else {
		printf("您选择了【JLM转WAV】,请在下面输入JLM文件的路径(如D://文件名.jlm):\n");
		inputerr = scanf("%s", jlmpath_str);
		printf("请在下面输入WAV文件的路径(如E://文件名.wav):\n");
		inputerr = scanf("%s", wavpath_str);
		printf("请在下面输入解密密码:\n");
		inputerr = scanf("%s", pass_str);
	}

	// 将char[]转为const char*
	passwords = pass_str;
	WAV_PATH = wavpath_str;
	JLM_PATH = jlmpath_str;

	printf("您输入的信息如下:\n");
	if (sign == 0) {
		printf("待转码文件:%s\n", WAV_PATH);
		printf("待输出文件:%s\n", JLM_PATH);
		printf("密码:%s\n", passwords);
	}
	else {
		printf("待转码文件:%s\n", JLM_PATH);
		printf("待输出文件:%s\n", WAV_PATH);
		printf("密码:%s\n", passwords);
	}

	printf("请按【回车键】即可开始转换!请稍等...\n");
	if (sign == 0) {
		jlm.WAV_TO_JLM(WAV_PATH, JLM_PATH, passwords, q, &errsign);
		if (errsign == 0) {
			printf("WAV_TO_JLM转码正确!\n");
		}
		else {
			printf("转码失败!错误标号:%d\n", errsign);
		}
	}
	else {
		jlm.JLM_TO_WAV(JLM_PATH, WAV_PATH, passwords, &errsign);
		if (errsign == 0) {
			printf("JLM_TO_WAV转码正确!\n");
		}
		else if (errsign == 800) {
			printf("转码失败!密码错误!\n");
		}
		else {
			printf("转码失败!错误标号:%d\n", errsign);
		}
	}
	// 是否继续
	printf("输入1可继续!输入0则退出\n", errsign);
	inputerr = scanf("%d", &restart);
	if (restart) {
		goto RESTART;
	}
	else {
		exit;
	}
	return 0;
}

2、Windows(vs2019)

#include "JLMAudioCompression.h"
#include 
#include 
#include 
#include 
#include 
#include 
#ifdef WIN32
#define  inline __inline
#endif // WIN32

using namespace std;

int main() {
	long t1, t2;
	JLMAudio jlm;
	int i, errsign = 0, inputerr, q = 0;
	int sign = 0, restart = 0; // 为0表示编码,为1表示译码
	const char* passwords = nullptr;
	const char* WAV_PATH = nullptr;
	const char* JLM_PATH = nullptr;
	char pass_str[2000], wavpath_str[2000], jlmpath_str[2000];
	
RESTART:
	printf("----------------------------------------------------------------------------------------------------------\n");
	printf("请选择是编码还是译码(输入0为“WAV转JLM”,输入1为“JLM转WAV”,每完成一个步骤需【回车】进入下一步):\n");
	inputerr = scanf_s("%d", &sign);
	if (sign == 0) {
		printf("您选择了【WAV转JLM】,请在下面输入WAV文件的路径(如D://文件名.wav):\n");
		inputerr = scanf_s("%s", wavpath_str);
		
		printf("请在下面输入JLM文件的路径(如E://文件名.jlm):\n");
		inputerr = scanf_s("%s", jlmpath_str);
		
		printf("请在下面输入加密密码:\n");
		inputerr = scanf_s("%s", pass_str);

		RESET_Q:
		printf("请输入音频压缩指标(0表示无损(默认),1表示高质量,2表示次高质量):\n");
		inputerr = scanf_s("%d", &q);
		if (q < 0 || q > 2) {
			printf("指标输入有误!0表示无损(默认),1表示高质量,2表示次高质量\n");
			goto RESET_Q;
		}
	}
	else {
		printf("您选择了【JLM转WAV】,请在下面输入JLM文件的路径(如D://文件名.jlm):\n");
		inputerr = scanf_s("%s", jlmpath_str);
		printf("请在下面输入WAV文件的路径(如E://文件名.wav):\n");
		inputerr = scanf_s("%s", wavpath_str);
		printf("请在下面输入解密密码:\n");
		inputerr = scanf_s("%s", pass_str);
	}

	// 将char[]转为const char*
	passwords = pass_str;
	WAV_PATH = wavpath_str;
	JLM_PATH = jlmpath_str;

	printf("您输入的信息如下:\n");
	if (sign == 0) {
		printf("待转码文件:%s\n", WAV_PATH);
		printf("待输出文件:%s\n", JLM_PATH);
		printf("密码:%s\n", passwords);
	}
	else {
		printf("待转码文件:%s\n", JLM_PATH);
		printf("待输出文件:%s\n", WAV_PATH);
		printf("密码:%s\n", passwords);
	}

	printf("请按【回车键】即可开始转换!请稍等...\n");
	if (sign == 0) {
		t1 = GetTickCount64();
		jlm.WAV_TO_JLM(WAV_PATH, JLM_PATH, passwords, q, &errsign);
		t2 = GetTickCount64();
		if (errsign == 0) {
			printf("WAV_TO_JLM转码正确!耗时:%d ms\n", t2 - t1);
		}
		else {
			printf("转码失败!错误标号:%d\n", errsign);
		}
	}
	else {
		t1 = GetTickCount64();
		jlm.JLM_TO_WAV(JLM_PATH, WAV_PATH, passwords, &errsign);
		t2 = GetTickCount64();
		if (errsign == 0) {
			printf("JLM_TO_WAV转码正确!耗时:%d ms\n", t2 - t1);
		}
		else if (errsign == 800) {
			printf("转码失败!密码错误!\n");
		}
		else {
			printf("转码失败!错误标号:%d\n", errsign);
		}
	}
	// 是否继续
	printf("输入1可继续!输入0则退出\n", errsign);
	inputerr = scanf_s("%d", &restart);
	if (restart) {
		goto RESTART;
	}
	else {
		exit;
	}
}

你可能感兴趣的:(杰林码应用,音视频,语音识别,ffmpeg)