代码之家  ›  专栏  ›  技术社区  ›  Loki

什么是轻量级跨平台WAV播放库?

  •  13
  • Loki  · 技术社区  · 16 年前

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

    有什么建议吗?

    7 回复  |  直到 14 年前
        1
  •  12
  •   quinmars    16 年前

    因为我也在为这个问题寻找答案,所以我做了一些研究,但我还没有找到任何简单的(像调用一个函数一样简单)播放音频文件的方法。但对于某些代码行,甚至可以使用前面提到的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。如果你也有不同的采样率或通道数,这将变得非常困难。

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

        2
  •  5
  •   codelogic    16 年前

    SDL_Mixer SDL SDL_混频器也是LGPL。

    OpenAL

    PortAudio

        3
  •  3
  •   hhafez    16 年前

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

    我发现的优点是

    1. 它是跨平台的
    2. 与C一起工作(和其他人,但您的问题是关于C的)
    3. 轻量
    4. 许可证是LGPL,因此您调用API时没有许可证问题
        4
  •  1
  •   Marc    16 年前

    你可以试试这个: libao

        5
  •  0
  •   AShelly    16 年前

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

        6
  •  0
  •   ySgPjx    13 年前

    你也可以试试 Audiere

        7
  •  0
  •   Emadpres    12 年前

    我用了艾尔克朗!

    “RikLangon是C++、C语言和所有.NET语言的跨平台声音库”

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