1.单声道转双声道
每隔一个采样插入一个采样
if(rhwparams.format == SND_PCM_FORMAT_S16_LE){
for(tempi=0;tempi<Readlen;tempi++)
{
*((short *)audiobuf+tempi*2)=*((short *)pstAiFrame->ps32PcmBuffer+tempi);
*((short *)audiobuf+tempi*2+1)=*((short *)pstAiFrame->ps32PcmBuffer+tempi);
}
}
else if(rhwparams.format = SND_PCM_FORMAT_S32_LE){
for(tempi=0;tempi<Readlen;tempi++)
{
*((long *)audiobuf+tempi*2)=*((long *)pstAiFrame->ps32PcmBuffer+tempi);
*((long *)audiobuf+tempi*2+1)=*((long *)pstAiFrame->ps32PcmBuffer+tempi);
}
}
2.双声道转单声道
先获取每个声道中数据字节数,去掉右声道的数据
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int judge(char filename[]) //判断是否为双声道文件
{
FILE *fp;
int j=0;
// char *c,c1;
if((fp=fopen(filename,"rb"))==NULL)
{
printf("error!\n");
exit(0);
}
fseek(fp,22L,0); //定位到文件的第23个字节
fread(&j,1,1,fp); //读取储存音频声道数的信息
// printf("%d\n",j);
if(j==1)
{
printf("this is mono file!\n"); //如果是单声道文件,则退出
exit (0);
}
fseek(fp,34L,0); //定位到第35个字节
fread(&j,1,1,fp); //读取音频文件的每个声道中各个样本的数据位数。
return (j/8);
fclose(fp);
}
void change(char file1name[],char file2name[],int i) //进行声道覆盖
{
FILE *in,*out;
long int *c = new long int[i]; //开辟以每个声道中各个样本的数据位数的数组空间
int j;
if((in=fopen(file1name,"rb"))==NULL)
{
printf("error!\n");
exit(0);
}
// in=fopen(file1name,"r");
if((out=fopen(file2name,"wb"))==NULL) //判断输出的文件是否能打开
{
printf("error!\n");
exit(0);
}
for(j = 0;j < 44;j++)
fputc(fgetc(in),out); //先将WAV文件头44字节写到输出的文件中
j = 0;
while(!feof(in))
{
c[j]=fgetc(in);
fputc(c[j],out);
j++;
if(j==i)
{
for(j = 0; j<i; j++) 把左声道的数据赋给右声道
{
fgetc(in);
//fputc(c[j],out);
}
j=0;
}
}
fclose(in);
fclose(out);
}
int main()
{
int i;
char file1name[20],file2name[20];
printf("Enter the file name which you want to change,please!\n");
gets(file1name);
i = judge(file1name);
printf("Byte per channel is %d\n",i);
gets(file2name);
change(file1name,file2name,i);
printf("succeed!\n");
return 0;
}
3.采样率转换
Speex开源库(也可以用自己的算法如16000转8000可以每隔一个采样扔掉一个采样的数据,但是测试效果不是很好)
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <alsa/asoundlib.h>
#include <speex/speex_resampler.h>
static const int divs_8000[] = { 5, 6, 6, 5 };
static const int divs_11025[] = { 4 };
static const int divs_22050[] = { 2 };
static const int divs_44100[] = { 1 };
int downsample(const int16_t *in, int16_t *out, int len, int *consumed,
const int *divs, int divs_len,
int out_stereo)
{
int i, j, lsum, rsum;
int di, div;
int oi;
i = 0;
oi = 0;
di = 0;
div = divs[0];
while (i + div * 2 <= len) {
// printf("div %d, i %d, oi %d\n", div, i, oi);
for (j = 0, lsum = 0, rsum = 0; j < div; j++) {
lsum += in[i + j * 2];
rsum += in[i + j * 2 + 1];
}
if (!out_stereo)
out[oi] = (lsum + rsum) / (div * 2);
else {
out[oi] = lsum / div;
out[oi + 1] = rsum / div;
}
oi += out_stereo + 1;
i += div * 2;
div = divs[++di % divs_len];
}
// printf("done: i %d, len %d, oi %d\n", i, len, oi);
*consumed = i;
return oi;
}
#define FAILIF(x, ...) do if (x) { \
fprintf(stderr, __VA_ARGS__); \
exit(EXIT_FAILURE); \
} while (0)
int main(int argc, char **argv)
{
int opt, ifd, ofd;
int new_rate = -1;
int quality = 3;
int read_size = 2048;
const int *divs;
int divs_len;
int consumed;
int channels = -1;
char *input = NULL;
char *output = NULL;
int nr, nr_out, nw;
int put_header = 0;
int total = 0;
int ierr = 0;
int ret;
const int bits_per_sample = 16;
SpeexResamplerState *st = NULL;
int16_t buf[2048];
int16_t out[2048];
while ((opt = getopt(argc, argv, "o:s:c:q:r:w")) != -1) {
switch (opt) {
case 'o':
FAILIF(output != NULL, "Multiple output files not supported\n");
output = strdup(optarg);
break;
case 's':
new_rate = atoi(optarg);
break;
case 'c':
channels = atoi(optarg);
break;
case 'q':
quality = atoi(optarg);
break;
case 'r':
read_size = atoi(optarg);
break;
case 'w':
put_header = 1;
break;
default: /* '?' */
fprintf(stderr, "usage: %s -o<outfile> -s<sampling> -c<channels> -q<quality> -r<read block size>\n",
*argv);
exit(EXIT_FAILURE);
}
}
FAILIF(channels != 1 && channels != 2, "-c value must be 1 or 2\n");
switch(new_rate) {
case 8000:
divs = divs_8000;
divs_len = 4;
break;
case 16000:
break;
case 11025:
divs = divs_11025;
divs_len = 1;
break;
case 22050:
divs = divs_22050;
divs_len = 1;
break;
case 44100:
divs = divs_44100;
divs_len = 1;
break;
case 48000:
break;
default:
FAILIF(1, "rate %d is not supported\n", new_rate);
}
FAILIF(!output, "Expecting an output file name\n");
FAILIF(optind >= argc, "Expecting an input file name\n");
input = argv[optind];
printf("input file [%s]\n", input);
printf("output file [%s]\n", output);
printf("new rate: [%d]\n", new_rate);
printf("quality: [%d]\n", quality);
ifd = open(input, O_RDONLY);
FAILIF(ifd < 0, "Could not open %s: %s\n", input, strerror(errno));
ofd = open(output, O_WRONLY | O_CREAT | O_TRUNC, 0666);
FAILIF(ofd < 0, "Could not open %s: %s\n", output, strerror(errno));
st = speex_resampler_init(1, new_rate, 8000, quality, &ierr);
do{
//readlen = read(in, sizeof(short), 1024, fin);
nr = read(ifd, buf, read_size);
if (nr > 0)
{
nw = nr/2; //因为每个采样占两个字节
//nr_out = (new_rate == 44100)?(nw/5.5)):(nw/2);
nr_out = (nw/(new_rate/8000));
ret = speex_resampler_process_int(st, 0, buf, &nw, out, &nr_out);
if (ret == RESAMPLER_ERR_SUCCESS)
{
//fwrite(out, sizeof(short), outlen, fout);
write(ofd, out, nr_out*2);
}
}
}while(nr == read_size);
speex_resampler_destroy(st);
close(ifd);
close(ofd);
return 0;
}