单双声道及采样率转换

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开源库(也可以用自己的算法如160008000可以每隔一个采样扔掉一个采样的数据,但是测试效果不是很好)

#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;

}

 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值