【问题标题】:What is a lightweight cross platform WAV playing library?什么是轻量级跨平台WAV播放库?
【发布时间】:2010-09-27 14:51:48
【问题描述】:

我正在寻找一种轻量级的方法来使我的程序(用 C 编写)能够在 windows 或 linux 上播放音频文件。我目前正在使用 Windows 本机调用,它本质上只是一个传递文件名的调用。我想要在 linux 上工作的类似的东西。

音频文件为 Microsoft PCM,单声道,22Khz

有什么建议吗?

【问题讨论】:

    标签: c windows linux audio cross-platform


    【解决方案1】:

    我用过 irrKlang !

    “irrKlang 是一个适用于 C++、C# 和所有 .NET 语言的跨平台声音库”

    http://www.ambiera.com/irrklang/

    【讨论】:

    【解决方案2】:

    你也可以试试Audiere。最后一个版本是 2006 年发布的,但它是开源的,并根据 LGPL 获得许可。

    【讨论】:

      【解决方案3】:

      因为我也在寻找问题的答案,所以我做了一些研究,但我没有找到任何简单的(简单的,比如调用一个函数)播放音频文件的方法。但是通过一些代码行,甚至可以以可移植的方式使用已经提到的 portaudio 和 libsndfile (LGPL)。

      这是我为测试两个库而编写的一个小测试用例:

      
      #include <portaudio.h>
      #include <sndfile.h>
      
      static int
      output_cb(const void * input, void * output, unsigned long frames_per_buffer,
              const PaStreamCallbackTimeInfo *time_info,
              PaStreamCallbackFlags flags, void * data)
      {
          SNDFILE * file = data;
      
          /* this should not actually be done inside of the stream callback
           * but in an own working thread 
           *
           * Note although I haven't tested it for stereo I think you have
           * to multiply frames_per_buffer with the channel count i.e. 2 for
           * stereo */
          sf_read_short(file, output, frames_per_buffer);
          return paContinue;
      }
      
      static void
      end_cb(void * data)
      {
          printf("end!\n");
      }
      
      #define error_check(err) \
          do {\
              if (err) { \
                  fprintf(stderr, "line %d ", __LINE__); \
                  fprintf(stderr, "error number: %d\n", err); \
                  fprintf(stderr, "\n\t%s\n\n", Pa_GetErrorText(err)); \
                  return err; \
              } \
          } while (0)
      
      int
      main(int argc, char ** argv)
      {
          PaStreamParameters out_param;
          PaStream * stream;
          PaError err;
          SNDFILE * file;
          SF_INFO sfinfo;
      
          if (argc < 2)
          {
              fprintf(stderr, "Usage %s \n", argv[0]);
              return 1;
          }
      
          file = sf_open(argv[1], SFM_READ, &sfinfo);
          printf("%d frames %d samplerate %d channels\n", (int)sfinfo.frames,
                  sfinfo.samplerate, sfinfo.channels);
      
          /* init portaudio */
          err = Pa_Initialize();
          error_check(err);
      
          /* we are using the default device */
          out_param.device = Pa_GetDefaultOutputDevice();
          if (out_param.device == paNoDevice)
          {
              fprintf(stderr, "Haven't found an audio device!\n");
              return -1;
          }
      
          /* stero or mono */
          out_param.channelCount = sfinfo.channels;
          out_param.sampleFormat = paInt16;
          out_param.suggestedLatency = Pa_GetDeviceInfo(out_param.device)->defaultLowOutputLatency;
          out_param.hostApiSpecificStreamInfo = NULL;
      
          err = Pa_OpenStream(&stream, NULL, &out_param, sfinfo.samplerate,
                  paFramesPerBufferUnspecified, paClipOff,
                  output_cb, file);
          error_check(err);
      
          err = Pa_SetStreamFinishedCallback(stream, &end_cb);
          error_check(err);
      
          err = Pa_StartStream(stream);
          error_check(err);
      
          printf("Play for 5 seconds.\n");
          Pa_Sleep(5000);
      
          err = Pa_StopStream(stream);
          error_check(err);
      
          err = Pa_CloseStream(stream);
          error_check(err);
      
          sf_close(file);
      
          Pa_Terminate();
      
          return 0;
      }
      

      示例的一些注释。在流回调中进行数据加载不是一个好习惯,而是在自己的加载线程中进行。如果您需要播放多个音频文件,则变得更加困难,因为并非所有 portaudio 后端都支持一台设备的多个流,例如 OSS 后端不支持,但 ALSA 后端支持。我不知道windows上的情况如何。由于您所有的输入文件都是相同类型的,您可以自己混合它们,这会使代码更加复杂,但是您也可以支持 OSS。如果您也有不同的采样率或通道数,那将变得非常困难。

      因此,如果您不想同时播放多个文件,这可能是一个解决方案,或者至少是您的一个开始。

      【讨论】:

      • 很棒的小程序!一个问题,我还没有实现从单独线程读取数据的方法,我想知道您是否认为这可能是导致音频质量低的原因,因为流回调有点陷入 SNDFILE * file = data; 的困境。谢谢!
      【解决方案4】:

      我喜欢FMODlicense 供个人免费使用,对于小型共享软件或商业项目非常合理

      【讨论】:

        【解决方案5】:

        我使用 OpenAL 在空中交通管制系统中播放 wav 文件作为警报/警告

        我发现的优点是

        1. 它是跨平台的
        2. 与 C 一起工作(以及其他,但您的问题是关于 C)
        3. 重量轻
        4. 网络上提供了很好的文档
        5. 许可证为 LGPL,因此您调用 API 时不会出现许可证问题

        【讨论】:

          【解决方案6】:

          SDL_Mixer,虽然不是很轻巧,但确实有一个简单的界面来播放 WAV 文件。我相信,和SDL一样,SDL_Mixer 也是 LGPL。

          OpenAL 是另一个更适合 3D 音频的跨平台音频库。

          另一个您可能想要查看的开源音频库是PortAudio

          【讨论】:

            【解决方案7】:

            你可以试试这个:libao

            【讨论】:

            • libao 看起来不错,可惜它在 GPL 下。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-08-26
            • 1970-01-01
            • 2010-09-21
            相关资源
            最近更新 更多