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