gpt4 book ai didi

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

转载 作者:IT王子 更新时间:2023-10-29 00:27:21 30 4
gpt4 key购买 nike

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

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

有什么建议吗?

最佳答案

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

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

关于c - 什么是轻量级跨平台WAV播放库?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/379353/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com