【问题标题】:SDL2 audio choose output "channel"SDL2 音频选择输出“通道”
【发布时间】:2018-07-19 15:04:03
【问题描述】:

我正在尝试使用 nodejs 库 https://github.com/duobeiyun/node-sdl-speaker 在特定声卡的特定音频通道上播放声音,但我的问题并不特定于该库。这是一个 SDL 音频问题。

通过修改src/SDLSpeaker.cpp,我可以使用SDL_OpenAudioDevice而不是SDL_OpenAudio来选择声音设备。我将第 62 行替换为以下代码:

// Select second audio device
if (int errorCode = SDL_OpenAudioDevice(SDL_GetAudioDeviceName(1, 0), 0, &wanted_spec, NULL, SDL_AUDIO_ALLOW_FORMAT_CHANGE) < 0) {
[…]

现在,我想强制将声音输出仅向左。我认为我应该通过更改fill_audio 来做到这一点,但我不知道该怎么办...... :(

【问题讨论】:

  • 您是否尝试过使其使用单通道? (填充音频中的 for 循环将其设置为一次迭代)。 SDL_Audio 中的通道相当于单声道、立体声、4 和 6(5.1)。
  • 是的,我试过了。但是填充音频中的通道不是左/右通道而是一些音频流(当前播放的音频文件):每次要播放音频时,都创建一个通道。

标签: node.js sdl sdl-2


【解决方案1】:

我找到了解决方案! SDL 不适合我的需要,SDL_MIXER 是!

我正在根据我编写的这个 C 代码编写一个节点插件:

#include <SDL2/SDL.h>
#include <SDL2/SDL_mixer.h>
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
  int continuer = 1;
  SDL_Init(SDL_INIT_AUDIO);
  Mix_Init(MIX_INIT_MP3);

  int i, count = SDL_GetNumAudioDevices(0);

  printf("-----------------------------------------\n");
  printf("Available audio devices:\n");
  for (i = 0; i < count; ++i)
  {
    printf("    - Audio device %d: %s\n", i, SDL_GetAudioDeviceName(i, 0));
  }
  printf("\n");

  if (argc <= 2)
  {
    return EXIT_FAILURE;
  }

  char *deviceName = argv[1];

  if (Mix_OpenAudioDevice(44100, MIX_DEFAULT_FORMAT, MIX_DEFAULT_CHANNELS, 1024,
                          deviceName, SDL_AUDIO_ALLOW_ANY_CHANGE) == -1)
  {
    printf("[SDL ERROR] :: %s\n\n", Mix_GetError());
    return EXIT_FAILURE;
  }

  printf("Audio device \"%s\" opened with success\n", deviceName);
  printf("-----------------------------------------\n\n");

  int MAX_SOUNDS = argc - 3;
  int currentSound = 0;
  char **files; // = {"file1.wav", "ding.wav"};

  files = (char **)malloc(MAX_SOUNDS * sizeof(char *));

  for (int i = 0; i < MAX_SOUNDS; ++i)
  {
    files[i] = argv[3 + i];
  }

  Mix_AllocateChannels(1);

  if (!Mix_SetPanning(0, argv[2][0] == '1' ? 255 : 0,
                      argv[2][0] == '1' ? 0 : 255))
  {
    printf("[SDL ERROR] :: Mix_SetPanning: %s\n", Mix_GetError());
  }

  Mix_Chunk *sounds[MAX_SOUNDS];

  for (int i = 0; i < MAX_SOUNDS; ++i)
  {
    sounds[i] = Mix_LoadWAV(files[i]);
    Mix_VolumeChunk(sounds[i], MIX_MAX_VOLUME);
  }

  Mix_PlayChannel(0, sounds[0], 0);
  bool playing = true;

  while (playing)
  {
    SDL_WaitEvent(NULL);
    playing = Mix_Playing(0) != 0;

    if (!playing && currentSound < MAX_SOUNDS)
    {
      ++currentSound;
      playing = true;

      if (!Mix_SetPanning(0, argv[2][0] == '1' ? 255 : 0,
                          argv[2][0] == '1' ? 0 : 255))
      {
        printf("[SDL ERROR] :: Mix_SetPanning: %s\n", Mix_GetError());
      }

      Mix_PlayChannel(0, sounds[currentSound], 0);
    }

    printf("Channel 0: %s\r", playing ? "PLAYING" : "STOPPED");
  }

  for (int i = 0; i < MAX_SOUNDS; ++i)
  {
    Mix_FreeChunk(sounds[i]);
  }

  Mix_CloseAudio(); // Fermeture de l'API

  printf("\n");

  return EXIT_SUCCESS;
}

在 UNIX 上,要编译(SDL2 和 SDL2_Mixer 开发依赖项必须安装在您的系统上):

$ cc test-sdl-mixer.cc `sdl2-config --cflags --libs` -lsdl2_mixer

编译后,应用程序将在特定声卡的特定通道(仅限左侧或右侧)上按顺序播放声音文件。

$ ./a.out "Built-in Output" 1 chime.wav advert.wav

它工作得很好,但是在我正在编写的节点模块中,我必须使用 child_process fork() 才能在 2 个不同的通道或设备上播放 2 个声音,因为 SDL2 和 SDL2_Mixer 都没有创建播放器/混音器的实例。

节点模块即将推出。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2013-08-07
  • 2016-08-20
  • 2017-06-03
  • 1970-01-01
  • 1970-01-01
  • 2013-11-25
  • 1970-01-01
相关资源
最近更新 更多