c - ALSA 的依赖问题(libao 和 sndfile)
问题描述
我编写了一个小程序来使用来自 github 的参考来播放 PCM 音频文件,并对我的应用程序稍作修改。该程序编译良好,但我遇到了一些关于依赖项和 ALSA 设备的运行时问题。
我收到的错误是:
ERROR: Failed to load plugin /usr/lib/x86_64-linux-gnu/ao/plugins-4/libsndio.so => dlopen() failed
ERROR: Failed to load plugin /usr/lib/x86_64-linux-gnu/ao/plugins-4/libnas.so => dlopen() failed
ao_alsa WARNING: Unable to open surround playback. Trying default device...
ALSA lib pcm_dmix.c:1089:(snd_pcm_dmix_open) unable to open slave
ao_alsa ERROR: Unable to open ALSA device 'default' for playback => No such file or directory
我一直在研究许多不同的解决方案,但似乎都没有工作,包括在 /etc/modprobe.d 中的 alsa.conf 文件中添加一行(但是,这些解决方案建议在我使用 AMD 时添加一行引用 intel设置。
这是完整的代码:
/*
*
* ao_example.c
*
* Written by Stan Seibert - July 2001
*
* Legal Terms:
*
* This source file is released into the public domain. It is
* distributed without any warranty; without even the implied
* warranty * of merchantability or fitness for a particular
* purpose.
*
* Function:
*
* This program opens the default driver and plays a 440 Hz tone for
* one second.
*
* Compilation command line (for Linux systems):
*
* gcc -o ao_example ao_example.c -lao -ldl -lm -lsndfile
*
*/
#include <stdio.h>
#include <string.h>
#include <ao/ao.h>
#include <math.h>
#include <sndfile.h>
#define BUF_SIZE 4096
static void clean(ao_device *device, SNDFILE *file){
ao_close(device);
sf_close(file);
ao_shutdown();
}
int main(int argc, char **argv)
{
ao_device *device;
ao_sample_format format;
unsigned long count;
int default_driver;
short *buffer;
int buf_size;
int sample;
int i;
//FILE *fp;
SF_INFO sfinfo;
if (argc != 2){
printf("usage: %s <filename>\n", argv[0]);
exit(1);
}
/* -- Initialize -- */
fprintf(stderr, "libao example program\n");
SNDFILE *fp = sf_open(argv[1], SFM_READ, &sfinfo);
// fp = fopen(argv[1], "rb");
if (fp == NULL){
printf("Cannot open %s.\n", argv[1]);
exit(1);
}
printf("samples: %d\n", sfinfo.frames);
printf("sample rate: %d\n", sfinfo.samplerate);
printf("Channels: %d\n", sfinfo.channels);
ao_initialize();
/* -- Setup for default driver -- */
default_driver = ao_default_driver_id();
switch(sfinfo.format & SF_FORMAT_SUBMASK){
case SF_FORMAT_PCM_16:
format.bits = 16;
break;
case SF_FORMAT_PCM_24:
format.bits = 24;
break;
case SF_FORMAT_PCM_32:
format.bits = 32;
break;
case SF_FORMAT_PCM_S8:
format.bits = 8;
break;
case SF_FORMAT_PCM_U8:
format.bits = 8;
break;
default:
format.bits = 24;
break;
}
format.channels = sfinfo.channels;
format.rate = sfinfo.samplerate;
format.byte_format = AO_FMT_LITTLE;
// format.byte_format = AO_FMT_NATIVE;
format.matrix = 0;
// memset(&format, 0, sizeof(format));
// format.bits = 24;
// format.channels = 16;
// format.rate = 48000;
// format.byte_format = AO_FMT_LITTLE;
/* -- Open driver -- */
device = ao_open_live(default_driver, &format, NULL /* no options */);
if (device == NULL) {
fprintf(stderr, "Error opening device.\n");
return 1;
}
// fseek(fp, 0, SEEK_END);
// count = ftell(fp);
// fseek(fp, 0, SEEK_SET);
// // printf("count: %ld\n", count);
buffer = calloc(BUF_SIZE, sizeof(short));
while(1){
int read = sf_read_short(fp, buffer, BUF_SIZE);
if (ao_play(device, (char *) buffer, (uint_32)(read * sizeof(short))) == 0){
printf("ao_play: failed\n");
clean(device, fp);
break;
}
}
clean(device, fp);
return 0;
}
我希望其他人也遇到过同样的麻烦,并且可以阐明解决方案。谢谢你。
解决方案
总结讨论:
问题似乎不在于代码本身,而在于libao
配置。
根据libao
文档,该库尝试按如下方式确定默认驱动程序:
在没有配置文件显式识别默认驱动程序的情况下,库将尝试检测合适的默认驱动程序。它通过测试每个可用的实时输出驱动程序(使用 ao_plugin_test())并找到具有最高优先级的驱动程序(参见 ao_info 结构)来实现这一点。优先级为 0 的驱动程序,例如 null 和文件输出驱动程序,永远不会被选为默认值。
错误消息表明已尝试了包括和nas
在内的多个驱动程序。手动选择驱动程序而不是使用可以解决问题。sndio
alsa
ao_driver_id(...)
ao_default_driver_id()
ao_open_live(...)
可以通过使用 获取相应的错误号来调查打开设备的更多问题printf("errno %d\n", errno);
。输出可以解释如下:
AO_ENODRIVER (1) - No driver corresponds to driver_id.
AO_ENOTLIVE (3) - This driver is not a live output device.
AO_EBADOPTION (4) - A valid option key has an invalid value.
AO_EOPENDEVICE (5) - Cannot open the device (for example, if /dev/dsp cannot be opened for writing).
AO_EFAIL (100) - Any other cause of failure.
除此之外,可以在~/.libao
配置文件中启用调试以获取更多信息。
推荐阅读
- firebase - Flutter FirebaseAnimatedList 查询无法正常工作
- c# - 从父类执行构造函数到子类
- android - 来自 strings.xml 的字符串在应用程序中可用但不被小部件使用
- c++ - C++ std::out_of_range 中止(核心转储)
- python - 如何在 FPDF 中同时编写返回的输出和打印的输出?
- python-3.x - 在python中将对象数据类型转换为字符串问题
- sql - T-SLQ 你可以在 on 子句中使用聚合吗?
- django - Django 不采用自定义 password_reset_form.html
- html - Angular MatDatePicker
- android - 减少 TabLayout 下 TabItem 中文本和图标之间的高度