ADPCM C语音示例
时间: 2023-10-30 09:05:06 浏览: 136
编程例子(C语音)
下面是一个简单的 ADPCM C语音示例,它可以将一个 WAV 文件压缩为 ADPCM 格式:
```c
#include <stdio.h>
#include <stdlib.h>
#define BLOCK_SIZE 256
typedef struct adpcm_state {
short valprev;
char index;
} adpcm_state;
static short int stepsizeTable[] = {
7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28, 31,
34, 37, 41, 45, 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 130, 143
};
static char indexTable[] = {
-1, -1, -1, -1, 2, 4, 6, 8, -1, -1, -1, -1, 2, 4, 6, 8
};
void adpcm_coder(short int *indata, char *outdata, int len, adpcm_state *state)
{
int valprev = state->valprev;
int index = state->index;
int sign, delta, step, vpdiff, outputbuffer = 0, bufferstep = 1;
for (int i = 0; i < len; i++) {
/* Step 1 - compute difference with previous value */
delta = indata[i] - valprev;
sign = (delta < 0) ? 8 : 0;
if (sign) delta = (-delta);
/* Step 2 - divide and clamp */
step = stepsizeTable[index];
vpdiff = step >> 3;
if (delta > step) {
outputbuffer |= sign | 7;
if ((delta >>= 1) > step) {
outputbuffer |= 8;
vpdiff += step;
} else {
vpdiff += delta;
}
} else {
if ((delta >>= 1) > step) {
outputbuffer |= sign;
vpdiff -= step;
} else {
vpdiff -= delta;
}
}
/* Step 3 - update previous value */
valprev += (sign) ? -vpdiff : vpdiff;
/* Step 4 - clamp previous value to 16 bits */
if (valprev > 32767) {
valprev = 32767;
} else if (valprev < -32768) {
valprev = -32768;
}
/* Step 5 - update step value */
index += indexTable[outputbuffer & 0x0f];
if (index < 0) {
index = 0;
} else if (index > 15) {
index = 15;
}
/* Step 6 - output value */
if (bufferstep) {
outputbuffer = (outputbuffer << 4) & 0xf0;
} else {
*outdata++ = outputbuffer | ((outputbuffer >> 4) & 0x0f);
}
bufferstep = !bufferstep;
}
/* Output last step, if needed */
if (!bufferstep) {
*outdata++ = outputbuffer | ((outputbuffer >> 4) & 0x0f);
}
/* Save state */
state->valprev = valprev;
state->index = index;
}
int main(int argc, char *argv[])
{
if (argc != 3) {
printf("Usage: %s input_file output_file\n", argv[0]);
return 1;
}
FILE *fin = fopen(argv[1], "rb");
if (!fin) {
printf("Cannot open input file %s\n", argv[1]);
return 1;
}
fseek(fin, 0L, SEEK_END);
int input_size = ftell(fin);
fseek(fin, 0L, SEEK_SET);
short int *input_data = (short int *) malloc(input_size);
if (!input_data) {
printf("Out of memory\n");
return 1;
}
fread(input_data, 1, input_size, fin);
fclose(fin);
adpcm_state state;
state.valprev = 0;
state.index = 0;
char *output_data = (char *) malloc(input_size / 4);
if (!output_data) {
printf("Out of memory\n");
return 1;
}
int blocks = input_size / BLOCK_SIZE;
for (int i = 0; i < blocks; i++) {
adpcm_coder(input_data + i * BLOCK_SIZE, output_data + i * BLOCK_SIZE / 4, BLOCK_SIZE, &state);
}
FILE *fout = fopen(argv[2], "wb");
if (!fout) {
printf("Cannot open output file %s\n", argv[2]);
return 1;
}
fwrite(output_data, 1, input_size / 4, fout);
fclose(fout);
free(input_data);
free(output_data);
return 0;
}
```
此示例使用了一个 adpcm_state 结构体来保存编码器的状态。adpcm_coder() 函数将输入数据块压缩为 ADPCM 格式,并更新状态。main() 函数读取 WAV 文件,将其分成块,压缩每个块并将结果写入输出文件。注意,此示例仅处理单声道 16 位 PCM WAV 文件。
阅读全文