dtmf_fsk音频数据测试
文章目录
- 音频测试
- 1.dtmf调制成音频数据
- test.c
- sound forge打开
- 2.使用fsk调成音频数据
- test.c
- 相关知识:
- dtmf:
- 响度:
- 采样率:
- 振幅:
- 正弦波:
- 振幅:
- 正弦波:
音频测试
1.dtmf调制成音频数据
- 输入任意按键值,输出是该按键对应的dtmf调制的音频信号,输出结果保存到文件中。
- 要求dtmf使用的基波响度为-12dB,采样率为16000Hz,生成的音频长度为100ms。
test.c
#include <stdio.h>
#include <stdlib.h>
#include <math.h>#define FILE_NAME_SIZE_MAX 50
#define SAMPLE_RATE 16000
#define AMPLITUDE 32767
#define PI 3.14159265358979323846
#define AUDIO_TIME_SEC_LEN (0.1)
#define AUDIO_LOUDNESS_DBFS (-12) typedef struct {char key;int freq1;int freq2;
} dtmf_st;static const dtmf_st dtmf_table[] = {{'1', 697, 1209}, {'2', 697, 1336}, {'3', 697, 1477}, {'A', 697, 1633},{'4', 770, 1209}, {'5', 770, 1336}, {'6', 770, 1477}, {'B', 770, 1633},{'7', 852, 1209}, {'8', 852, 1336}, {'9', 852, 1477}, {'C', 852, 1633},{'#', 941, 1209}, {'0', 941, 1336}, {'D', 941, 1477}
};static const int dtmf_table_size = sizeof(dtmf_table) / sizeof(dtmf_st);int main(void) {char key = 0;short *audio_data = NULL;int num_samples = 0;int freq1 = -1, freq2 = -1;double dtmf_amp = 0;double time_in_sec = 0;double sin_wave1 = 0, sin_wave2 = 0;char filename[FILE_NAME_SIZE_MAX] = {0};FILE *fp = NULL;int i = 0;while(1) {printf("\nPlease input key:");if(scanf("%c", &key) != 1) {while(getchar() != '\n');printf("Input error! \nPlease input (0-9,A-D,#,*)\n");continue;}for(i=0;i<dtmf_table_size; i++) {if(key == dtmf_table[i].key) {break;}}if(i < dtmf_table_size) {freq1 = dtmf_table[i].freq1;freq2 = dtmf_table[i].freq2;// printf("%d %d\n",freq1,freq2);break;} else {printf("Invalid key!\n");}}num_samples = SAMPLE_RATE * AUDIO_TIME_SEC_LEN;audio_data = malloc(sizeof(short) * num_samples);if(audio_data == NULL) {goto ERROR;}dtmf_amp = pow(10, AUDIO_LOUDNESS_DBFS/20.0) * AMPLITUDE;for (int i = 0; i < num_samples; i++) {time_in_sec = i / (double) SAMPLE_RATE;sin_wave1 = sin(2 * PI * freq1 * time_in_sec);sin_wave2 = sin(2 * PI * freq2 * time_in_sec);audio_data[i] = dtmf_amp * (sin_wave1 + sin_wave2);}sprintf(filename, "key_%c.raw", key);fp = fopen(filename, "wb");if (!fp) {perror("fopen");goto ERROR;}if(fwrite(audio_data, sizeof(short), num_samples, fp) < 0){perror("fwrite");goto ERROR;}ERROR:if (fp) {fclose(fp);fp = NULL;}if (audio_data) {free(audio_data);audio_data = NULL;}return 0;
}
sound forge打开
2.使用fsk调成音频数据
使用C语言编写一段程序,程序可以实现将输入的16进制数据使用fsk调制成音频数据。
1.输入为一个16进制数,输出为一个音频文件。例如输入0x55,对应的二进制为01010101,fsk调制后的频率组合为 低频-高频-低频-高频-低频-高频-低频-高频。
2.音频采样率为16000Hz。
3.fsk调制时使用的两个信号分别为1209Hz和697Hz。
4.fsk使用的调制信号的幅值为-12dB。
5.fsk调制时每个频率的信号长度为10ms。
6.两个不同频率的信号拼接时要注意保持相位上的连续性。
在linux系统中,数据保存为raw格式
test.c
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <ctype.h>
#include <stdint.h>
#include <stdbool.h>#define AMPLITUDE 32767.0
#define SAMPLE_RATE (16000.0)
#define LOW_FREQ 697
#define HIGH_FREQ 1209
#define AUDIO_LOUDNESS_DBFS (-12.0)
#define SIGNAL_LENGTH 0.01
#define BIN_STR_SIZE_MAX 64
#define PI 3.14159265358979323846
#define OUTPUT_FILE "output.raw"struct wave {int freq; double amplitude;
};
static const struct wave waves[2] = {{LOW_FREQ, pow(10, AUDIO_LOUDNESS_DBFS / 20.0)*AMPLITUDE}, {HIGH_FREQ, pow(10, AUDIO_LOUDNESS_DBFS / 20.0)*AMPLITUDE}};static const char *hex_table[] = {"0000", "0001", "0010", "0011", "0100","0101", "0110", "0111", "1000", "1001","1010", "1011", "1100", "1101", "1110","1111"};void hex_to_bin(char *hex_string, char *bin_string)
{int i = 0;char hex_digit = 0;for (i = 0; hex_string[i] != '\0'; i++) {hex_digit = hex_string[i];if (hex_digit >= '0' && hex_digit <= '9') {strcat(bin_string, hex_table[hex_digit - '0']);} else if (hex_digit >= 'A' && hex_digit <= 'F') {strcat(bin_string, hex_table[hex_digit - 'A' + 10]);} else if (hex_digit >= 'a' && hex_digit <= 'f') {strcat(bin_string, hex_table[hex_digit - 'a' + 10]);} else {printf("error invalid digit '%c'\n", hex_digit);goto ERROR;}}if (strlen(bin_string) == 0) {printf("error input is null\n");goto ERROR;}if (strlen(bin_string) % 4 != 0) {printf("error:invalid len %d\n", (int)strlen(bin_string));goto ERROR;}
ERROR:return ;
}double generate_fsk_signal(int fi,int freq,int amplitude,int num_samples,short *audio_data)
{static int pos = 0;double t = 0;for (int i = 0; i < num_samples; i++){audio_data[pos++] = (short)(amplitude * sin(2 * PI * freq * t + fi));t += 1/SAMPLE_RATE;}return (2 * PI * freq * (t+1/SAMPLE_RATE) + fi); //相位对齐
}void generate_sin_wave(int n,char *bin_string,short *audio_data,int num_samples)
{int len = strlen(bin_string);int i=0 ,j=0;double fi = 0;int index = 0;for(i=0;i<len;i++){index = bin_string[i] - '0';if(index == 0) {fi = generate_fsk_signal(fi,waves[index].freq,waves[index].amplitude,num_samples,audio_data);} else if(index == 1) {fi = generate_fsk_signal(fi,waves[index].freq,waves[index].amplitude,num_samples,audio_data);}}
}char *get_hex_str(char *str)
{int len = strlen(str);if(str == NULL) {goto ERROR;}if (len == 0 || len > BIN_STR_SIZE_MAX / 4) {goto ERROR;}if(strstr(str,"0x") || strstr(str,"0X") ) {str += 2;}for(int i=0; i<strlen(str); i++){if(!isxdigit(str[i])){printf("error: invalid hex_string\n");goto ERROR;}}return str;
ERROR:return NULL;
}int main(int argc, char **argv)
{int i = 0, j = 0;int index = 0;int num_samples = 0;FILE *fp = NULL;int signal_length = 0;char *hex_str = NULL;double last_fi = 0;char bin_string[BIN_STR_SIZE_MAX] = {0};short *audio_data = NULL;if (argc < 2) {printf("Usage: %s hex_string\n", argv[0]);goto ERROR;}hex_str = get_hex_str(argv[1]);if(hex_str == NULL){goto ERROR;}hex_to_bin(hex_str, bin_string);num_samples = SIGNAL_LENGTH * SAMPLE_RATE;signal_length = strlen(bin_string) * num_samples;audio_data = malloc(sizeof(short) * signal_length);memset(audio_data,0,sizeof(short) * signal_length);generate_sin_wave(signal_length,bin_string,audio_data,num_samples);fp = fopen(OUTPUT_FILE, "wb");if (fp == NULL) {perror("fopen");goto ERROR;}if(fwrite(audio_data, sizeof(short), signal_length, fp) < 0) {perror("fwrite");goto ERROR;}
ERROR:if (fp) {fclose(fp);fp = NULL;}if (audio_data) {free(audio_data);audio_data = NULL;}return 0;
}
相关知识:
dtmf:
响度:
响度常用的单位是dBSPL、dBFS、dBpa、dBm0。
dB计算:对于功率,dB = 10 * lg(A/B)。对于电压或电流,dB= 20 * lg(A/B)。此处A,B代表参与比较的功率值或者电流、电压值。
以dBfs举例说明:
dBfs = 20 * lg(x/32767)。
其中32767是16bit采样精度时最大的值,x取值0 ~ 32767。所以dBfs的最大值为当x取值为32767时的值,即0dBfs。
采样率:
采样率是指对模拟音频信号进行取样的每秒次数,通常以赫兹 (Hz) 为单位表示。当我们要将模拟音频信号转换成数字形式时(例如录制音频或将其从 CD 转换成数字格式),需要对其进行采样,即在时间轴上不断地对音频信号进行抽样,获取一系列数字值。采样率越高,每秒中采集到的样本数量就越多,这可以提供更精确的音频表示,但同时也会增加所需的存储空间和处理能力。
振幅:
振幅是指波形的最大偏移量,通常用单位分贝 (dB) 或电平(以电压为单位)来表示。在音频信号中,振幅描述了声音的响度或强度。例如,在一段声音信号中,振幅越高,则声音会听起来更响亮、更强烈,振幅越低,则声音会听起来更柔和、更安静。与采样率不同,振幅是代表音频信号能量的单一数值,其大小与声音响度直接相关。
正弦波:
y = A * sin(ωt + ϕ)
其中,A代表振幅,即波形的最大偏移量;
ω代表角频率,即单位时间内的变化角度;
t代表时间;
ϕ代表初相位,即初始状态下正弦波图像的左右平移位置
φ = arcsin(y/A) - wt
每秒中采集到的样本数量就越多,这可以提供更精确的音频表示,但同时也会增加所需的存储空间和处理能力。
振幅:
振幅是指波形的最大偏移量,通常用单位分贝 (dB) 或电平(以电压为单位)来表示。在音频信号中,振幅描述了声音的响度或强度。例如,在一段声音信号中,振幅越高,则声音会听起来更响亮、更强烈,振幅越低,则声音会听起来更柔和、更安静。与采样率不同,振幅是代表音频信号能量的单一数值,其大小与声音响度直接相关。
正弦波:
y = A * sin(ωt + ϕ)
其中,A代表振幅,即波形的最大偏移量;
ω代表角频率,即单位时间内的变化角度;
t代表时间;
ϕ代表初相位,即初始状态下正弦波图像的左右平移位置
φ = arcsin(y/A) - wt
dtmf_fsk音频数据测试相关推荐
- 睡眠音频分割及识别问题(九)--Android下的YAMNet
部署PANNs模型面临的问题 加载模型出错 在使用PANNs模型时,在PC端可以较好的运行,可是在Android端运行的时候,编译过程提示缺少libpytorch_jni.so文件,导致无法加载模型, ...
- 【电路_音频】一些关于音频功放的小秘密,你都知道吗?
一个手机的音乐效果的好坏,取决于喇叭(包括喇叭单体.音腔结构.出音孔.防尘网等),音频功放,音效算法调试(平台音效或第三方音效等),这三者有效,合理配合,才能实现最终满意的音乐效果.本文主要从一些基础 ...
- Python爬虫教程,Python采集喜马拉雅音频
目录 项目需求:抓取专辑所有音频文件. 1. 项目截图 2. 找数据 3. 项目难点讲解 4. 源代码 很多人学习python,不知道从何学起. 很多人学习python,掌握了基本语法过后,不知道在哪 ...
- 音频编解码器以50%的功耗提供两倍的音频质量
音频编解码器以50%的功耗提供两倍的音频质量 Audio codecs deliver twice the audio quality at 50% less power Dialog的DA740x音 ...
- 新十年嵌入式音频的五大趋势
新十年嵌入式音频的五大趋势 Five embedded audio trends for the new decade 很难相信正在进入一个新的十年.十年前,像Alexa这样的语音技术甚至还没有成为现 ...
- 人工智能在音频链中找到自己的声音
人工智能在音频链中找到自己的声音 AI finds its voice in audio chain 硅基silicon-based麦克风的出现重塑了音频领域.但在未来几年,市场研究公司Yole Dé ...
- 处理器嵌入室内校正数字音频平台
处理器嵌入室内校正数字音频平台 Processors to embed room correction digital audio platform 家庭影院的目的是给家带来一种影院般的体验.对于发烧 ...
- 用matlab怎么画视电阻率拟断面图,在MATLAB平台上实现可控源音频大地电磁反演数据三维可视化显示...
第29卷 增刊 物探化探计算技术 2007年10月 收稿日期6文章编号:1001-1749(2007)增刊(1)-0068-04 在MAT LAB 平台上实现可控源音频大地 电磁反演数据三维可视化显示 ...
- FFmpeg学习4:音频格式转换
前段时间,在学习试用FFmpeg播放音频的时候总是有杂音,网上的很多教程是基于之前版本的FFmpeg的,而新的FFmepg3中audio增加了平面(planar)格式,而SDL播放音频是不支持平面格式 ...
最新文章
- [JS] 如何判断一个对象是否为空
- 计算机视觉与图像处理、模式识别、机器学习学科之间的关系
- uva 10047 the monocyle (四维bfs)
- 科大星云诗社动态20210210
- numpy genfromtxt 读取字符_numpy组队学习1: 输入输出
- phpcmsV9留言插件提交后返回上一页实现方法
- 软考信息安全工程师学习笔记四(1.4 信息安全标准化知识)
- DataGrid控件(可以实现不刷新增加删除等操作)
- java.lang.NoClassDefFoundError: weblogic/rmi/extensions/DisconnectListener
- web之nginx相关配置二
- Pyinstaller打包过程中报错“AttributeError: module 'enum' has no attribute 'IntFlag'”问题解决
- Linux中使用SSH服务远程连接Linux系统
- 2020年度全球人工智能十大事件
- pyTest官方手册(Release 4.2)之蹩脚翻译(6)
- 聚币网行情与套利分析
- 数据分析-思维分析逻辑day02
- 夏令时和时区最佳实践
- Web网页如何实现QQ好友,QQ空间,微博分享
- 【统计学】【2018.05】【含源码】时间序列:以密度预测评价方法为中心的预测与评价方法
- 深入学习理解(1):java:ExecutorService invokeAll 任务的批量提交invokeAll两种方法的区别