----------------------------------------
author:hjjdebug
date:2022-02-15
----------------------------------------
手工创建一个原始的音频数据,见识一下音频到底是啥样的. 直接上代码. 按S16格式双声道存储.
音频本是流,但是由于总要分包,所以有每包采样点数的概念,实际上是frame_size, 这里用nb_samples 表示
其它概念: 数据采样格式,通道数,每秒采样率。
其中采样率(sample_rate),通道数(channels),数据采样格式(sample_format)构成音频流的三要素.
本例中samle_rate:44100,channels:2 sample_format:S16
具体领会请看代码.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main(int argc, char **argv)
{
if (argc != 2) {
fprintf(stderr,
"API example program to show how to create a tone \n"
"Usage: %s output_file \n\n"
, argv[0]);
exit(1);
}
char *filename = argv[1];
FILE *file = fopen(filename, "wb");
if (!file) {
fprintf(stderr, "Could not open destination file %s\n", filename);
exit(1);
}
/* encode a single tone sound */
int i,j,k;
int nb_samples = 1024;
int channels = 2;
int sample_rate=44100;
float t = 0;
//对sin函数,2pi 弧度是一个周期, 均匀圆周运动,其角频率为2*pi*f, 设f=440
int omiga = 2 * M_PI * 440.0;
//每次时间递长一个采样时间
float tincr = 1.0 / sample_rate;
typedef unsigned short uint16_t;
//分配内存,存储一个frame 的数据
uint16_t *sample_data = (uint16_t*)malloc(nb_samples * channels *sizeof(uint16_t)); //内存容量要考虑上通道个数
for (i = 0; i < 200; i++) { // create 200 个 frame, 可持续时间200 * 1024 /44100 = 4.64s
for (j = 0; j < nb_samples; j++)
{
sample_data[2*j] = (int)(sin(omiga*t) * 30000); //正负值为-30000 - +30000
for (k = 1; k < channels; k++)
sample_data[2*j + k] = sample_data[2*j];
t += tincr;
}
fwrite(sample_data, 1, nb_samples * channels *sizeof(uint16_t), file);
}
fprintf(stderr, "play the output file with the command:\n"
"ffplay -f s16le -ac 2 -ar 44100 %s\n",
filename); //指明数据采样格式,通道数,采样率就可以播放原始数据了
fclose(file);
return 0;
}