2019独角兽企业重金招聘Python工程师标准>>>
这几天在单位研究使用libspeex对原始音频文件(PCM文件)进行编解码。在linux下原始音频文件可以通过arecord命令进行采集,使用的采样率是8kHz,量化位数为有符号16位整数(小端存储),单通道模式。在linux下播放原始音频文件可以通过使用aplay命令进行播放,在播放的时候需要给出量化位数参数,因为aplay默认使用8位无符号数进行量化取样。
下面分别是编码和解码的源代码,注意linux编译环境需要有speex(speex运行库包)和speex_devel(speex开发包)。
声音录制和编码源代码:
/*
* =====================================================================================
*
* Filename: record_spx.c
*
* Description:
*
* Version: 1.0
* Created: 12/01/2011 12:49:48 PM
* Revision: none
* Compiler: gcc
*
* Author: YOUR NAME (),
* Company:
*
* =====================================================================================
*/
#include
#include
#include
#include
#include
#include
#include
#include
#define DEFAULT_RATE 8000
#define DEFAULT_RECORD_DURING 60
#define DEFAULT_ALSA_REC_FILE "/tmp/xk_rec.wav"
#define FRAME_SIZE 160
#define RECORD_CMD_LENGTH 128
#define DEBUG_ON 1
#if DEBUG_ON
#define DEBUG_FILE "/tmp/xk_recorder.log"
#define DEBUG_TOOL(flag, fmt...) \
do { \
if (flag) { \
FILE *fp; \
fp = fopen(DEBUG_FILE, "a"); \
fprintf(fp, "%s[%d]", __FILE__, __LINE__); \
fprintf(fp, fmt); \
fclose(fp); \
} \
} \
while(0)
#else
#define DEBUG_TOOL(flag, fmt...)
#endif
static int flag = 0;
void print_usage(void)
{
printf("usage: speex_recorder
return;
}
int run_command(const char *cmd)
{
int retval;
retval = system(cmd);
if (retval == 127) {
DEBUG_TOOL(DEBUG_ON, "command not available\n");
} else if (retval == -1) {
DEBUG_TOOL(DEBUG_ON, "system() error.\n");
} else if (retval != 0) {
DEBUG_TOOL(DEBUG_ON, "command return %d\n", retval);
} else {
DEBUG_TOOL(DEBUG_ON, "system(\"%s\") successful.\n", cmd);
}
return retval;
}
int record_alsa(const char *wave_file)
{
char cmd[RECORD_CMD_LENGTH];
int child, status, wait_child;
memset(cmd, 0, sizeof(cmd));
snprintf(cmd, sizeof(cmd), "arecord -t raw -f S16_LE -c 1 -r %d -d %d %s 1>/dev/null 2>&1",DEFAULT_RATE, DEFAULT_RECORD_DURING, wave_file);
if ((child = fork()) < 0 ) {
DEBUG_TOOL(DEBUG_ON, "fork() error.\n");
return -1;
} else if (child == 0) {
run_command(cmd);
return 0;
} else {
while(1) {
if (flag) {
DEBUG_TOOL(DEBUG_ON, "pause arecord process\n");
system("killall arecord");
break;
}
usleep(1000);
wait_child = waitpid(child, &status, WNOHANG||WUNTRACED);
if (wait_child == child) {
DEBUG_TOOL(DEBUG_ON, "arecord completed\n");
break;
}
}
return 0;
}
}
int build_spx_from_wave(const char *wave_file, const char *spx_file)
{
#if 0
char cmd[RECORD_CMD_LENGTH];
int retval;
memset(cmd, 0, sizeof(cmd));
snprintf(cmd, sizeof(cmd), "speexenc --wideband --vbr --rate %d --le --16bit %s %s 1>/dev/null 2>&1", DEFAULT_RATE, wave_file, spx_file);
retval = run_command(cmd);
return retval;
#else
const char *inFile, *outFile;
FILE *fin, *fout;
short in[FRAME_SIZE];
short input[FRAME_SIZE];
char cbits[200];
int nbBytes;
/*Holds the state of the encoder*/
void *state;
/*Holds bits so they can be read and written to by the Speex routines*/
SpeexBits bits;
int i, tmp;
/*Create a new encoder state in narrowband mode*/
state = speex_encoder_init(&speex_nb_mode);
/*Set the quality to 8 (15 kbps)*/
tmp=8;
speex_encoder_ctl(state, SPEEX_SET_QUALITY, &tmp);
inFile = wave_file;
outFile = spx_file;
fin = fopen(inFile, "r");
fout = fopen(outFile, "w");
/*Initialization of the structure that holds the bits*/
speex_bits_init(&bits);
while (1)
{
/*Read a 16 bits/sample audio frame*/
fread(in, sizeof(short), FRAME_SIZE, fin);
if (feof(fin))
break;
/*Copy the 16 bits values to float so Speex can work on them*/
for (i=0;i input[i]=in[i]; /*Flush all the bits in the struct so we can encode a new frame*/ speex_bits_reset(&bits); /*Encode the frame*/ speex_encode_int(state, input, &bits); /*Copy the bits to an array of char that can be written*/ nbBytes = speex_bits_write(&bits, cbits, 200); /*Write the size of the frame first. This is what sampledec expects but it's likely to be different in your own application*/ fwrite(&nbBytes, sizeof(int), 1, fout); /*Write the compressed data*/ fwrite(cbits, 1, nbBytes, fout); } /*Destroy the encoder state*/ speex_encoder_destroy(state); /*Destroy the bit-packing struct*/ speex_bits_destroy(&bits); fclose(fin); fclose(fout); return 0; #endif } int record_spx(const char *spx_file) { int retval; retval = record_alsa(DEFAULT_ALSA_REC_FILE); if (retval == 127 || retval < 0) { DEBUG_TOOL(DEBUG_ON, "record_alsa() error.\n"); return -1; } retval = build_spx_from_wave(DEFAULT_ALSA_REC_FILE, spx_file); if (retval == 127 || retval < 0) { DEBUG_TOOL(DEBUG_ON, "build_spx_from_wave() error.\n"); return -2; } unlink(DEFAULT_ALSA_REC_FILE); return 0; } void pause_record(int signal) { flag = 1; return; } int main(int argc, char **argv) { int retval; const char *speex_file; if (argc != 2) { print_usage(); return -1; } speex_file = argv[1]; signal(SIGTERM, pause_record); retval = record_spx(speex_file); return retval; } 转载于:https://my.oschina.net/linuxhunter/blog/36751