做Linux录音时碰到问题 寻求帮助

toongyu_zty 2017-10-14 02:44:59
我写了这么个小测试程序,开2个线程,A线程播放音乐,B线程录音并保存,测试时用的耳机,麦克风基本是采集不到耳机的声音的。结果播放B线程保存的录音文件时可以很清晰地听到A线程音乐的声音,这是为什么呢?这好像有点像Windows上立体声混音的效果,如果不想要这种效果应该怎么做?

//播放线程
void *StartPlay(void *arg)
{
int dsp_arg = 0;
int fd_wav = open("music.wav", O_RDONLY);

int fd_dsp_w = open("/dev/dsp", O_WRONLY);
if(fd_dsp_w < 0)
{
printf("[Error] Failed to open soundcard in play thread.\n");
}
else
{
printf("[Info] Play dsp file descriptor: %d.\n", fd_dsp_w);
}

//设置位数
dsp_arg = AFMT_S16_LE;
if(ioctl(fd_dsp_w, SNDCTL_DSP_SETFMT, &dsp_arg) == -1)
{
printf("[Error] Failed to set SNDCTL_DSP_SETFMT in play thread.\n");
}

//设置声道数
dsp_arg = 1;
if(ioctl(fd_dsp_w, SNDCTL_DSP_CHANNELS, &dsp_arg) == -1)
{
printf("[Error] Failed to set SNDCTL_DSP_CHANNELS in play thread.\n");
}

//设置采样率
dsp_arg = 11025;
if(ioctl(fd_dsp_w, SNDCTL_DSP_SPEED, &dsp_arg) == -1)
{
printf("[Error] Failed to set SNDCTL_DSP_SPEED in play thread.\n");
}

char buf[2048];
int buf_len = sizeof(buf);
memset(buf, 0, buf_len);

while(1)
{
read(fd_pcm, buf, buf_len); //读取音频文件
write(fd_dsp_w, buf, buf_len); //写入声卡进行播放
}

close(fd_wav);
close(fd_dsp_w);
}

//录音线程
void *StartRecord(void *arg)
{
int dsp_arg = 0;

int fd_rec = open("rec.pcm", O_WRONLY | O_TRUNC);

int fd_dsp_r = open("/dev/dsp", O_RDONLY);
if(fd_dsp_r < 0)
{
printf("[Error] Failed to open soundcard in record thread.\n");
}
else
{
printf("[Info] Record dsp file descriptor: %d.\n", fd_dsp_r);
}

//设置位数
dsp_arg = AFMT_S16_LE;
if(ioctl(fd_dsp_r, SNDCTL_DSP_SETFMT, &dsp_arg) == -1)
{
printf("[Error] Failed to set SNDCTL_DSP_SETFMT in record thread.\n");
}

//设置声道数
dsp_arg = 1;
if(ioctl(fd_dsp_r, SNDCTL_DSP_CHANNELS, &dsp_arg) == -1)
{
printf("[Error] Failed to set SNDCTL_DSP_CHANNELS in record thread.\n");
}

//设置采样率
dsp_arg = 11025;
if(ioctl(fd_dsp_r, SNDCTL_DSP_SPEED, &dsp_arg) == -1)
{
printf("[Error] Failed to set SNDCTL_DSP_SPEED in record thread.\n");
}

char buf[2048];
int buf_len = sizeof(buf);
memset(buf, 0, buf_len);

while(1)
{
//memset(&buf, 0, sizeof(buf));
read(fd_dsp_r, buf, buf_len);
write(fd_rec, buf, buf_len);
}

close(fd_rec);
close(fd_dsp_r);
}

int main(int argc, char const *argv[])
{
pthread_t thd_play;
pthread_t thd_record;

if(pthread_create(&thd_play, NULL, StartPlay, NULL))
{
printf("Failed to create play thread.\n");
exit(1);
}
if(pthread_create(&thd_record, NULL, StartRecord, NULL))
{
printf("Failed to create record thread.\n");
exit(2);
}

while(1)
{
sleep(1);
}

return 0;
}
...全文
372 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
toongyu_zty 2017-10-23
  • 打赏
  • 举报
回复
引用 4 楼 lgbxyz 的回复:
我觉得你录到了 播放的声音+外界的声音 是正常的现象.声卡又不会为你滤除掉播放的声音. 不知道你需要做什么功能才有这种奇怪的需求.
我测试时用的耳机,正常情况下基本录不到播放的声音吧。 主要是奇怪按道理来说放音和录音功能应该是不同的数据通道吧,默认怎么会混到一起去。我朋友用WinCE开发就没有这情况,可能就像Windows上要开立体声混音才有这种效果。 这是想做双向对讲时碰到的问题,结果就是对讲通话时总能听到自己的声音,有些延迟,大概是从对方播放时又给录下然后发送回来的 = =
LubinLew 2017-10-23
  • 打赏
  • 举报
回复
我觉得你录到了 播放的声音+外界的声音 是正常的现象.声卡又不会为你滤除掉播放的声音. 不知道你需要做什么功能才有这种奇怪的需求.
toongyu_zty 2017-10-23
  • 打赏
  • 举报
回复
引用 2 楼 lgbxyz 的回复:
你读写设备都是同一个 是对的吗? 我觉得录音的话 肯定还另有设备吧. 按照linux下皆文件的理论, 你就是一个线程写文件,另一个线程读文件. 所以B录的音其实就是在A写的,所以是差不多一样的, 我觉得你最好尝试下 只录音的情况跑一下,看看能否录得到声音. 记得之前的项目中linux上录音/播放 都是用的 pluseaudio库来做的.
终于有人回复了,感动。。。 Linux下的录音是可以这样实现的呀,我查了一些资料后才开始写代码的。Linux的音频驱动框架有OSS和ALSA,OSS就是这种写法,往声卡文件写数据就是放音,从声卡文件读数据就是录音。这个测试代码任意关掉一条线程都是能正常工作的,只是一起运行时录音采集了外界声音的同时又有了内录的效果。 ALSA的代码稍微复杂些,我后来基于ALSA框架也写了测试代码,问题依旧,没辙了,猜想是驱动的问题。 PulseAudio之前也有稍微了解,这是更上一层的封装库了,底层好像也是靠ALSA来驱动的,因为程序是在板子上跑的,移植PulseAudio有些麻烦,所以没试过。
LubinLew 2017-10-20
  • 打赏
  • 举报
回复
你读写设备都是同一个 是对的吗? 我觉得录音的话 肯定还另有设备吧. 按照linux下皆文件的理论, 你就是一个线程写文件,另一个线程读文件. 所以B录的音其实就是在A写的,所以是差不多一样的, 我觉得你最好尝试下 只录音的情况跑一下,看看能否录得到声音. 记得之前的项目中linux上录音/播放 都是用的 pluseaudio库来做的.
toongyu_zty 2017-10-14
  • 打赏
  • 举报
回复
一开始是在ARM开发板上测试的。宿主机Ubuntu采用ALSA框架已经没有dsp声卡设备文件,不过我重新编译了内核打开了ALSA的OSS兼容,这代码倒也能运行起来了,不过问题依旧。有没有大神指点一下啊。

23,121

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧