Linuux-alsa-左右声道处理

Linuux-alsa-左右声道处理


前言

基于alsa实现实现左右声道的分离与合并。此处为对双声道处理的简单示例,


提示:以下是本篇文章正文内容,下面案例可供参考

一、具体处理部分

1.头文件

头文件:

/*************************************************************************
    > File Name: pcm.h
    > Author: ***
    > Mail: 1301751355@qq.com 
    > Created Time: 2021年04月20日 星期二 14时33分50秒
 ************************************************************************/
#ifndef __PCM_H__
#define __PCM_H_


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <sys/stat.h>
#include <time.h>
//#include <tinyalsa/asoundlib.h>

#include "include/tinyalsa/asoundlib.h"
//#include <alsa/asoundlib.h>

struct pcm* i_pcm_open(int direction);
void i_pcm_close(int direction);
int LefeAndRightChannel(char* LefeChannelFile, char* RightChannelFile); //左声道文件路径、右声道文件路径

#endif

2.声卡初始化

代码如下(示例):

/*************************************************************************
    > File Name: pcm.c
    > Author: ***
    > Mail: 1301751355@qq.com 
    > Created Time: 2021年04月20日 星期二 14时35分55秒
 ************************************************************************/

#include<stdio.h>
#include<assert.h>
#include"pcm.h"

static struct pcm *pcm_in =	NULL;
static struct pcm *pcm_out = NULL;
static struct pcm* _i_pcm_open(int direction){
	struct pcm* pcm;
	unsigned int card = 0;
	unsigned int device = 0;
	unsigned int channels = 2;
	unsigned int rate = 48000;
	enum pcm_format format = PCM_FORMAT_S16_LE;
	unsigned int period_size = 320;//320*4;
	unsigned int period_count = 4;//4;
	struct pcm_config config;
	memset(&config,0,sizeof(config));

	config.channels = channels;
	config.rate = rate;
	config.period_size = period_size;
	config.period_count = period_count;
	config.format = format;
	config.stop_threshold = 0;
	config.start_threshold = 0;
	config.silence_threshold = 0;

	pcm = pcm_open(card, device, direction, &config);
	if(!pcm || !pcm_is_ready(pcm)){
		printf("Unable open PCM DEVICE (%s)\n",pcm_get_error(pcm));
		return ;
	}
	return pcm;
}
struct pcm* i_pcm_open(int direction){
	struct pcm *pcm;
	switch(direction){
		case PCM_IN:
			if(pcm_in == NULL)
				pcm_in = _i_pcm_open(PCM_IN);
			pcm = pcm_in;
			break;
		case PCM_OUT:
			if(pcm_out == NULL)
				pcm_out = _i_pcm_open(PCM_OUT);
			pcm = pcm_out;
			break;
		default:
			break;
	}
	return pcm;
}
void i_pcm_close(int direction){
	if(direction == PCM_IN){
		if(pcm_in != NULL)
			pcm_close(pcm_in);
		pcm_in = NULL;
	}
	if(direction == PCM_OUT){
		if(pcm_out != NULL)
			pcm_close(pcm_out);
		pcm_out = NULL;
	}
}

3.接口封装

/*************************************************************************
    > File Name: pcm-play.c
    > Author: ***
    > Mail: 1301751355@qq.com 
    > Created Time: 2021年04月20日 星期二 15时59分14秒
 ************************************************************************/

#include<stdio.h>
#include"pcm.h"

#define MAXSIZE(a,b) ((a>b)?a:b)

static void LefeChannel(char * buffer, char *lefeChannel, int MAXBUFFERSIZE)
{
      int i = 0;
#if 0
      for (i = 0; i < MAXBUFFERSIZE/2; i+=2)
      {
        *(lefeChannel+i*2) = *(buffer +  i);
        *(lefeChannel+i*2+1) = *(buffer +  i + 1);
      }
#endif
      for (i = 0; i < MAXBUFFERSIZE; i+=4){
        *(lefeChannel+i) = *(buffer +  i);
        *(lefeChannel+i+1) = *(buffer +  i + 1);
	  }

}

static void RightChannel(char * buffer, char *rightChannel, int MAXBUFFERSIZE)
{
      int i = 0;
      for (i = 0; i < MAXBUFFERSIZE; i+=4)
      {
        *(rightChannel+i+2) = *(buffer +  i + 2);
        *(rightChannel+i+3) = *(buffer +  i + 3);
	  }

}

static void SoundContent(char* soundBuf, char* lefeChannel, char* rightChannel, int size){
	int i = 0;
	for(i = 0; i < size; i+=4){
		*(soundBuf+i) = *(lefeChannel+i);
	 	*(soundBuf+i+1) = *(lefeChannel+i+1);
		*(soundBuf+i+2) = *(rightChannel+i+2);
		*(soundBuf+i+3) = *(rightChannel+i+3);
	}
}

int LefeAndRightChannel(char* LefeChannelFile, char* RightChannelFile) /*左声道文件路径、右声道文件路径  成功返回:1 失败返回 0*/ 
																	   /*成功:播放结合后的立体声*/
{
	/*获取文件大小*/
	struct stat statbuf;
	stat(LefeChannelFile, &statbuf);
	int LefeSize = statbuf.st_size;   /*左声道文件大小*/

	memset(&statbuf,0,sizeof(statbuf));

	stat(RightChannelFile, &statbuf);
	int RightSize = statbuf.st_size;  /*右声道文件大小*/
#ifdef DEBUG_SOUND
	printf("LefeSize = %d, RightSize = %d\n",LefeSize, RightSize);
#endif
	char *LefeFileBuf;		/*左声道文件内容*/
	LefeFileBuf = malloc(LefeSize);
	if(LefeFileBuf == NULL){
		fprintf(stderr,"malloc failed \n");
	}
	FILE* Lefe_fp = fopen(LefeChannelFile,"rb");
	if(Lefe_fp == NULL){
		printf("fopen LefeFile failed\n");
		return 0;
	}

	LefeSize = fread(LefeFileBuf,1,LefeSize,Lefe_fp);

	char *RightFileBuf;		/*右声道文件内容*/
	RightFileBuf = malloc(RightSize);
	if(RightFileBuf == NULL){
		fprintf(stderr,"malloc failed\n");
		return 0;
	}
	FILE* Right_fp = fopen(RightChannelFile,"rb");
	if(Right_fp == NULL){
		printf("fopen RightFile failed\n");
		return 0;
	}
	RightSize = fread(RightFileBuf,1,RightSize,Right_fp);

	struct pcm *pcm;
	pcm = i_pcm_open(PCM_OUT);
	if(pcm == NULL)
		return 0;

	char *lefeChannel; /*提取左声道数据*/
	lefeChannel = malloc(LefeSize);
	memset(lefeChannel,0,LefeSize);
	LefeChannel(LefeFileBuf,lefeChannel,LefeSize);

	char *rightChannel; /*提取右声道数据*/
	rightChannel = malloc(RightSize);
	memset(rightChannel,0,RightSize);
	RightChannel(RightFileBuf,rightChannel,RightSize);

	char *soundBuf;		/*立体声数据:左右声道内容结合*/
	soundBuf = malloc(MAXSIZE(LefeSize,RightSize));
	memset(soundBuf,0,MAXSIZE(LefeSize,RightSize));
#ifdef DEBUG_SOUND
	printf("soundBuf size %d\n",MAXSIZE(LefeSize,RightSize));
#endif
	SoundContent(soundBuf,lefeChannel,rightChannel,MAXSIZE(LefeSize,RightSize));
	pcm_write(pcm,soundBuf,MAXSIZE(LefeSize,RightSize));

	i_pcm_close(PCM_OUT);

	free(LefeFileBuf);
	free(RightFileBuf);
	free(lefeChannel);
	free(rightChannel);
	free(soundBuf);

	fclose(Lefe_fp);
	fclose(Right_fp);
	return 1;
}

总结

以上处理方式需要对I2S协议有一些基础的了解。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值