libao 示例在编译为 python 模块时不起作用

发布于 2024-12-28 17:24:40 字数 3289 浏览 1 评论 0原文

我试图用Python做一点PCM声音,但是我尝试过的所有包都太多了,或者没有文档记录,或者已经死了,所以我决定用libao做一个简单的。

我使用 xiph 的 this source code 作为起点.org 播放 440Hz 1 秒,我用 gcc -o ao_example ao_example.c -lao -ldl -lm 编译它,我成功运行了这段代码,立即听到 440Hz两个通道都正弦 1 秒。

到目前为止,一切都很好。

因此,我 $ cp ao_exemple.c mySoundAo.c 并编辑了 mySoundAo.c 以编译为 Python 模块。完整代码如下:

 #include <math.h>
 #include <stdio.h>
 #include <string.h>
 #include <ao/ao.h>
 #include <Python.h>
 #define BUF_SIZE 4096

 static PyObject* py_soundAo(PyObject* self, PyObject* args)
 {
     ao_device *device;
     ao_sample_format format;
     int default_driver;
     char *buffer;
     int buf_size;
     int sample;
     float freq = 440.0;
     int i;
     /* -- Initialize -- */
     fprintf(stderr, "libao example program\n");
     ao_initialize();
     /* -- Setup for default driver -- */
     default_driver = ao_default_driver_id();
     memset(&format, 0, sizeof(format));
     format.bits = 16;
     format.channels = 2;
     format.rate = 44100;
     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 Py_BuildValue("", 0);
     }
     /* -- Play some stuff -- */
     buf_size = format.bits/8 * format.channels * format.rate;
     buffer = calloc(buf_size,
             sizeof(char));
     for (i = 0; i < format.rate; i++) {
         sample = (int)(0.75 * 32768.0 * sin(2 * M_PI * freq * ((float) i/format.rate)));
         /* Put the same stuff in left and right channel */
         buffer[4*i] = buffer[4*i+2] = sample & 0xff;
         buffer[4*i+1] = buffer[4*i+3] = (sample >> 8) & 0xff;
     }
     ao_play(device, buffer, buf_size);
     /* -- Close and shutdown -- */
     ao_close(device);
     ao_shutdown();
  return Py_BuildValue("", 0);
 }

 static PyMethodDef mySoundAo_methods[] = {
    {"soundAo", py_soundAo, METH_VARARGS},
    {NULL, NULL}
 };

 void initmySoundAo()
 {
    (void) Py_InitModule("mySoundAo", mySoundAo_methods);
 }

所以我编译为 gcc -shared -I/usr/include/python2.7/ -o mySoundAo.so mySoundAo.c -lpython2.7 -lm -lsndfile -lao -ldl我收到了这样的警告:

In file included from /usr/include/python2.7/Python.h:8:0,
             from mySoundAo.c:5:
/usr/include/python2.7/pyconfig.h:1158:0: warning: "_POSIX_C_SOURCE" redefined [enabled by default]
/usr/include/features.h:214:0: note: this is the location of the previous definition

听起来不太危险,所以我继续前进。

在 python 中,我执行了以下操作:

$ python
Python 2.7.2+ (default, Oct  4 2011, 20:03:08) 
[GCC 4.6.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import mySoundAo
>>> mySoundAo.soundAo()
libao example program
Error opening device.
>>> 

没有声音。稍微检查一下代码,我发现函数 ao_initialize(); 挂起大约 4 秒,下面的行 default_driver = ao_default_driver_id(); 将此变量设置为 -1 (错误)。

这种行为很奇怪,因为它几乎是相同的代码。

那么,有什么想法可以让这项工作成功吗?

谢谢你!

I was trying to PCM sound a little bit in Python, but all the packages I've tried were too much or were undocumented or dead, so I decided to make a simple one with libao.

I used as start point this source code by xiph.org that plays 440Hz for 1 second, and I compiled it with gcc -o ao_example ao_example.c -lao -ldl -lm and I run successfully this code, immediately hearing a 440Hz sine for 1 second in both channels.

So far, so good.

So I $ cp ao_exemple.c mySoundAo.c and I edited mySoundAo.c to be compiled as Python module. The full code follows:

 #include <math.h>
 #include <stdio.h>
 #include <string.h>
 #include <ao/ao.h>
 #include <Python.h>
 #define BUF_SIZE 4096

 static PyObject* py_soundAo(PyObject* self, PyObject* args)
 {
     ao_device *device;
     ao_sample_format format;
     int default_driver;
     char *buffer;
     int buf_size;
     int sample;
     float freq = 440.0;
     int i;
     /* -- Initialize -- */
     fprintf(stderr, "libao example program\n");
     ao_initialize();
     /* -- Setup for default driver -- */
     default_driver = ao_default_driver_id();
     memset(&format, 0, sizeof(format));
     format.bits = 16;
     format.channels = 2;
     format.rate = 44100;
     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 Py_BuildValue("", 0);
     }
     /* -- Play some stuff -- */
     buf_size = format.bits/8 * format.channels * format.rate;
     buffer = calloc(buf_size,
             sizeof(char));
     for (i = 0; i < format.rate; i++) {
         sample = (int)(0.75 * 32768.0 * sin(2 * M_PI * freq * ((float) i/format.rate)));
         /* Put the same stuff in left and right channel */
         buffer[4*i] = buffer[4*i+2] = sample & 0xff;
         buffer[4*i+1] = buffer[4*i+3] = (sample >> 8) & 0xff;
     }
     ao_play(device, buffer, buf_size);
     /* -- Close and shutdown -- */
     ao_close(device);
     ao_shutdown();
  return Py_BuildValue("", 0);
 }

 static PyMethodDef mySoundAo_methods[] = {
    {"soundAo", py_soundAo, METH_VARARGS},
    {NULL, NULL}
 };

 void initmySoundAo()
 {
    (void) Py_InitModule("mySoundAo", mySoundAo_methods);
 }

So I compiled as gcc -shared -I/usr/include/python2.7/ -o mySoundAo.so mySoundAo.c -lpython2.7 -lm -lsndfile -lao -ldl and I had this warning:

In file included from /usr/include/python2.7/Python.h:8:0,
             from mySoundAo.c:5:
/usr/include/python2.7/pyconfig.h:1158:0: warning: "_POSIX_C_SOURCE" redefined [enabled by default]
/usr/include/features.h:214:0: note: this is the location of the previous definition

Doesn't sound much dangerous, so I moved on.

In python, I did the following:

$ python
Python 2.7.2+ (default, Oct  4 2011, 20:03:08) 
[GCC 4.6.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import mySoundAo
>>> mySoundAo.soundAo()
libao example program
Error opening device.
>>> 

With no sound. Inspecting the code a little bit, I discovered the function ao_initialize(); hangs for about 4 second and the following line default_driver = ao_default_driver_id(); sets this variable to -1 (error).

This behavior is strange, since it's almost the same code.

So, any ideas to make this work?

Thank you!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

一世旳自豪 2025-01-04 17:24:40

您收到的警告是无害的,只需将 #include 移至顶部即可让标准库正确识别已定义的宏。

该问题可能是由于 /usr/lib/ao/plugins-4/libalsa.so 编译错误造成的(如果在 中设置了 debug 就会提到这个文件~ /.libao.conf)。由于ao的alsa插件加载失败,ao尝试了所有其他选项,并耗尽了4秒的nas超时(这就是延迟的原因)。

要检查错误编译(或错误链接)的 libalsa.so 是否是问题所在,请运行

$ ldd -r /usr/lib/ao/plugins-4/libalsa.so > /dev/null
undefined symbol: ao_is_big_endian      (/usr/lib/ao/plugins-4/libalsa.so)

输出中的错误应该指出符号存在问题。您可以简单地自己下载libao,并修补libao-*/src/plugins/alsa/ao_alsa.c中的行,或者复制ao_is_big_endian中的定义,或者修复的链接。

The warning you get is harmless, simply moving #include <Python.h> to the top should let the standard library correctly recognize the macro is already defined.

The problem is probably caused by a miscompiled /usr/lib/ao/plugins-4/libalsa.so (this file is mentioned if you set debug in ~/.libao.conf). Since the ao's alsa plugin fails to load, ao tries all other options, and exhausts the nas timeout of 4 seconds (that's the cause for the delay).

To check whether the miscompiled (or mislinked) libalsa.so is the problem, run

$ ldd -r /usr/lib/ao/plugins-4/libalsa.so > /dev/null
undefined symbol: ao_is_big_endian      (/usr/lib/ao/plugins-4/libalsa.so)

The error in the output should points to a problem with the symbol. You can simply download libao yourself, and patch out the line in libao-*/src/plugins/alsa/ao_alsa.c, or copy the definition from ao_is_big_endian, or fix the linking.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文