C++ 中的 ALSA - 制作最小的工作代码

ALSA in C++ - Making the minimal working code

话题

我想使用 C++ 中的 ALSALinux 生成任何类型的 PCM 声音计算机。

设置

我在 C++Ubuntu 20.04Code::Blocks 编码。

背景

我曾经制作简单的 Arduino UNO 程序进行 声音处理 并且只需要播放 原始 PCM 样本 .

问题

ALSA Project's Website不太好理解

我查看了 c - ALSA tutorial required 发现很多链接都已过期。

我将 minimal PCM example in C 的代码直接复制粘贴到一个空的 Code::Blocks 项目中,但出现了错误:

||=== Build: Release in Test (compiler: GNU GCC Compiler) ===|
Test/main.cpp|5|fatal error: ../include/asoundlib.h: No such file or directory|
||=== Build failed: 1 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===|

就在第一行代码中#include "../include/asoundlib.h"。 我猜这个问题可能是因为我必须 下载一些东西或为编译器添加一个链接器 .
但我也认为它 可能是 C 到 C++ 转换的问题 这意味着这在 C 中有效但在 C++ 中无效。

我是否必须为编译器添加链接器或下载一些东西才能使 the code 正常工作?

然后我在 ALSA library 上查看并下载了 alsa-lib-1.2.3.tar.bz2
我得到了一个看起来有正确内容的档案,但我不知道如何处理它。

然后我在我的电脑上找到了usr/include/sound/asound.h。它看起来是 ALSA 的一部分,但是当我更改代码以使用它时,它在使用时吐出一堆错误。
代码现在如下所示:

/*
 *  This extra small demo sends a random samples to your speakers.
 */
#include <sound/asound.h>
#include <cstdio>
static char *device = "default";            /* playback device */
unsigned char buffer[16*1024];              /* some random data */
int main(void)
{
    int err;
    unsigned int i;
    snd_pcm_t *handle;
    snd_pcm_sframes_t frames;
    for (i = 0; i < sizeof(buffer); i++)
        buffer[i] = random() & 0xff;
    if ((err = snd_pcm_open(&handle, device, SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
        printf("Playback open error: %s\n", snd_strerror(err));
        exit(EXIT_FAILURE);
    }
    if ((err = snd_pcm_set_params(handle,
                      SND_PCM_FORMAT_U8,
                      SND_PCM_ACCESS_RW_INTERLEAVED,
                      1,
                      48000,
                      1,
                      500000)) < 0) {   /* 0.5sec */
        printf("Playback open error: %s\n", snd_strerror(err));
        exit(EXIT_FAILURE);
    }
        for (i = 0; i < 16; i++) {
        frames = snd_pcm_writei(handle, buffer, sizeof(buffer));
        if (frames < 0)
            frames = snd_pcm_recover(handle, frames, 0);
        if (frames < 0) {
            printf("snd_pcm_writei failed: %s\n", snd_strerror(frames));
            break;
        }
        if (frames > 0 && frames < (long)sizeof(buffer))
            printf("Short write (expected %li, wrote %li)\n", (long)sizeof(buffer), frames);
    }
    /* pass the remaining samples, otherwise they're dropped in close */
    err = snd_pcm_drain(handle);
    if (err < 0)
        printf("snd_pcm_drain failed: %s\n", snd_strerror(err));
    snd_pcm_close(handle);
    return 0;
}

错误是这样的:

||=== Build: Release in Test (compiler: GNU GCC Compiler) ===|
Test/main.cpp|6|warning: ISO C++ forbids converting a string constant to ‘char*’ [-Wwrite-strings]|
Test/main.cpp||In function ‘int main()’:|
Test/main.cpp|12|error: ‘snd_pcm_t’ was not declared in this scope; did you mean ‘snd_pcm_info’?|
Test/main.cpp|12|error: ‘handle’ was not declared in this scope|
Test/main.cpp|16|error: ‘SND_PCM_STREAM_PLAYBACK’ was not declared in this scope; did you mean ‘SNDRV_PCM_STREAM_PLAYBACK’?|
Test/main.cpp|16|error: ‘snd_pcm_open’ was not declared in this scope; did you mean ‘snd_pcm_info’?|
Test/main.cpp|17|error: ‘snd_strerror’ was not declared in this scope|
||error: %s\n", snd_strerror(err));|
Test/main.cpp|21|error: ‘SND_PCM_FORMAT_U8’ was not declared in this scope; did you mean ‘SNDRV_PCM_FORMAT_U8’?|
Test/main.cpp|22|error: ‘SND_PCM_ACCESS_RW_INTERLEAVED’ was not declared in this scope; did you mean ‘SNDRV_PCM_ACCESS_RW_INTERLEAVED’?|
Test/main.cpp|20|error: ‘snd_pcm_set_params’ was not declared in this scope; did you mean ‘snd_pcm_sw_params’?|
Test/main.cpp|27|error: ‘snd_strerror’ was not declared in this scope|
||error: %s\n", snd_strerror(err));|
Test/main.cpp|31|error: ‘snd_pcm_writei’ was not declared in this scope|
Test/main.cpp|33|error: ‘snd_pcm_recover’ was not declared in this scope|
Test/main.cpp|35|error: ‘snd_strerror’ was not declared in this scope|
Test/main.cpp|42|error: ‘snd_pcm_drain’ was not declared in this scope|
Test/main.cpp|44|error: ‘snd_strerror’ was not declared in this scope|
Test/main.cpp|45|error: ‘snd_pcm_close’ was not declared in this scope|
||=== Build failed: 17 error(s), 1 warning(s) (0 minute(s), 0 second(s)) ===|

按照以下步骤操作:

  1. 安装ALSA开发包,或者确保它已经安装。名称取决于您的发行版。就我而言 (OpenSUSE Tumbleweed),它是 alsa-devel。这将在目录 /usr/include/alsa.
  2. 下安装文件 asoundlib.h
  3. 将代码中的行从 #include "../include/asoundlib.h" 更改为 #include <alsa/asoundlib.h>。请注意 angular 括号而不是引号。
  4. 你想要link反对的库被命名为libsound.so,所以用gcc -Wall pcm_min.c -lasound -o pcm_min
  5. 这样的命令编译程序
  6. 运行 程序:./pcm_min