问题遇到的现象和发生背景
我已经写好一对一的客户端和服务器的实时语音传输,接下来补充就好了,希望能帮我解答
用代码块功能插入代码,请勿粘贴截图
server端
#include <stdio.h>
#include <alsa/asoundlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
int main()
{
int ret;
snd_pcm_t *handle;//pcm句柄
snd_pcm_hw_params_t *params;//pcm属性
snd_pcm_sw_params_t *swparams;
snd_pcm_uframes_t period_frames;
FILE *fp=NULL;
char comm_ret[100]={'0'};
fp=popen("amixer aset numid=17,iface=MIXER,name='Speaker Function' 0","r");//关闭扬声器,音量17
if(fp==NULL)
{
printf("shell retor\n");
return 0;
}
while(fgets(comm_ret,sizeof(comm_ret) - 1,fp)!=NULL)
printf("amixer:\n%s\n",comm_ret);
pclose(fp);
//打开设备,播放模式
int r = snd_pcm_open(&handle, "hw:1,0", SND_PCM_STREAM_PLAYBACK,0);
if(r < 0)
{
perror("snd pcm open fail");
return -1;
}
snd_pcm_hw_params_alloca(¶ms);//分配参数结构体
snd_pcm_sw_params_alloca(&swparams);
snd_pcm_hw_params_any(handle, params);//设置默认参数,初始化
//交错模式
snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
//设置双声道,小端格式,有符号16位
snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE);
snd_pcm_hw_params_set_channels(handle, params, 2);
//设置采样率
int rate = 44100;
snd_pcm_hw_params_set_rate_near(handle,params,&rate,0);
snd_pcm_prepare(handle);
//设置好的参数回写设备
r = snd_pcm_hw_params(handle, params);
if(r < 0)
{
perror("snd pcm params fail");
return -1;
}
/* unsigned buffer_time=0;
unsigned period_time=0;
//snd_pcm_hw_params_get_buffer_max(params,&buffer,0);//
if(buffer_time>500000)
buffer_time=500000;
if (period_time > 0)
ret = snd_pcm_hw_params_set_period_time_near(handle, params,&period_time, 0);
else
ret = snd_pcm_hw_params_set_period_size_near(handle, params,&period_frames, 0);
*/
//定义帧数
int frames;
//获取一个周期有多少帧数据,一个周期一个周期方式处理音频数据。
snd_pcm_hw_params_get_period_size(params,(snd_pcm_uframes_t*)&frames,0);
// snd_pcm_prepare(handle);
int size=frames*4;
unsigned char *buffer = malloc(size);
// snd_pcm_hw_params_get_buffer_size(params,(snd_pcm_uframes_t*)&buffer);
snd_pcm_sw_params_current(handle,swparams);
snd_pcm_sw_params_set_start_threshold(handle,swparams,0);//让设备立即启动
snd_pcm_sw_params_set_stop_threshold(handle,swparams,size);//读完size大小的数据后就停止
//初始化网络
struct sockaddr_in seraddr,cliaddr;
int addrlen=sizeof(struct sockaddr);
int sockfd = socket (AF_INET, SOCK_DGRAM, 0);
memset(&seraddr, 0, sizeof(seraddr));
seraddr.sin_family = AF_INET;
seraddr.sin_port = htons(8888);
seraddr.sin_addr.s_addr=INADDR_ANY;//本地IP
//绑定
ret = bind(sockfd, (struct sockaddr*)&seraddr, sizeof(seraddr));
if(ret < 0)
{
perror("bind fail");
return -1;
}
else
{
printf("bind success!\n");
}
while(1)
{
usleep(2000);
//接收数据
ret = recvfrom(sockfd, buffer, size, 0, (struct sockaddr *)&cliaddr, &addrlen);
if(ret <= 0){break;}
if(ret<frames*2)
{
printf("finish writing!\n");
break;
}
printf("recv:%d ", ret);
snd_pcm_format_set_silence(SND_PCM_FORMAT_S16_LE,&buffer,0);
usleep(2000);
ret=snd_pcm_writei(handle,buffer,frames);
if(ret<0)
{
if(ret==-EPIPE)
{
usleep(2000);
fprintf(stderr,"<<<<<<<<<<Buffer Underrun>>>>>>>>>>\n");//添加一个sleep,防止数据来不及读取,让系统有时间准备更多的数据
snd_pcm_prepare(handle);
}
else if(ret==-ESTRPIPE)
{
fprintf(stderr,"<<<<<<<<<<writei retor -ESTRPIPE>>>>>>>>>>\n");
}
else if(ret==-EBADFD)
{
fprintf(stderr,"<<<<<<<<<<writei retor -EABDFD>>>>>>>>>>\n");
}
}
printf("write ret=%d\n",ret);
bzero(buffer,sizeof(buffer));
}
//关闭
snd_pcm_drain(handle);
snd_pcm_close(handle);
free(buffer);
return 0;
}
服务端
#include <stdio.h>
#include <alsa/asoundlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <arpa/inet.h>
int main()
{
int ret=0;
snd_pcm_t *handle;//pcm句柄
snd_pcm_hw_params_t *params;//pcm属性
snd_pcm_sw_params_t *swparams;
FILE *fp=NULL;
char comm_ret[100] = {'0'};
fp=popen("amixer cset numid=10,iface=MIXER,name='Audio main mic' 1","r");
if(fp==NULL)
{
printf("shell error\n");
return 0;
}
while(fgets(comm_ret,sizeof(comm_ret) - 1,fp)!=NULL)
printf("amixer:\n%s\n",comm_ret);
pclose(fp);
//打开设备
int r = snd_pcm_open(&handle, "hw:1,0", SND_PCM_STREAM_CAPTURE,0);
if(r < 0)
{
perror("open fail");
return -1;
}
//设置参数
//初始化pcm属性
snd_pcm_hw_params_alloca(¶ms);//params申请内存
snd_pcm_sw_params_alloca(&swparams);
snd_pcm_hw_params_any(handle, params);
//交错模式
snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
//snd_pcm_hw_params_set_rate_resample(handle,);
//设置双声道,小端格式,16位
snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE);
snd_pcm_hw_params_set_channels(handle, params, 2);
//设置采样频率
int rate = 44100;
snd_pcm_hw_params_set_rate_near(handle,params,&rate,0);
//设置好的参数回写设备
r = snd_pcm_hw_params(handle, params);
if(r < 0)
{
perror("snd pcm params fail");
return -1;
}
unsigned buffer_time=0;
unsigned period_time=0;
snd_pcm_hw_params_get_buffer_time_max(params,&buffer_time,0);//
if(buffer_time>500000)
buffer_time=500000;
if(buffer_time>0)
period_time=buffer_time/4;
snd_pcm_hw_params_set_period_time_near(handle,params,&period_time,0);
//snd_pcm_hw_params_set_buffer_time_near(handle,params,&buffer_time,0);
//定义帧数
int frames=32;
//获取一个周期有多少帧数据
snd_pcm_hw_params_get_period_size(params,(snd_pcm_uframes_t*)&frames,0);
snd_pcm_hw_params_get_rate(params,&rate,0);
printf("frames=%d, rate=%d\n", frames, rate);
int size = frames*4;
unsigned char *buffer = malloc(size);
snd_pcm_sw_params_current(handle,swparams);
//snd_pcm_sw_params_set_avail_min(handle,swparams)
snd_pcm_sw_params_set_start_threshold(handle,swparams,0);
//snd_pcm_sw_params_set_stop_threshold(handle,swparams,frames+1);
//初始化网络
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
struct sockaddr_in seraddr;
memset(&seraddr, 0, sizeof(seraddr));
seraddr.sin_family = AF_INET;
seraddr.sin_port = htons(8888);
inet_pton(AF_INET,"127.0.0.1",&seraddr.sin_addr);
//int times=0;
while(1)
{
//录音
ret = snd_pcm_readi(handle,buffer,frames);
printf("read_ret=%d ",ret);
/*if(ret != frames)
{
snd_pcm_prepare(handle);
continue;
}*/
if( ret == -EPIPE )
{
snd_pcm_prepare( handle );
/*数据满了,没有被alsa读走*/
fprintf (stderr, "<<<<<<<<<<<<<<<<<<< Buffer Overrun >>>>>>>>>>>>>>>>>\n");
continue;
}
else if( ret == -EBADFD )
{
fprintf(stderr, "<<<<<<<<<<<<<<<<<<<< readi error -EBADFD >>>>>>>>>>>>>\n");
continue;
}
else if( ret == -ESTRPIPE )
{
fprintf(stderr, "<<<<<<<<<<<<<<<<<<<< readi error -ESTRPIPE >>>>>>>>>>>>>\n");
}
//udp发送
ret = sendto(sockfd, buffer, size, 0, (struct sockaddr*)&seraddr, sizeof(seraddr));
/*if(ret != frames*4)
{
break;
}*/
printf("send_ret=%d\n",ret);
bzero(buffer,sizeof(buffer));
}
close(sockfd);
//关闭
snd_pcm_drain(handle);
snd_pcm_close(handle);
free(buffer);
return 0;
}
我想要达到的结果
写出另一个客户端传输一段音乐,服务器能同时收听到人声和音乐