我正在寻找一种轻量级的方法来使我的程序(用C语言编写)能够在Windows或Linux上播放音频文件。我目前正在使用Windows本机调用,这实际上只是一个传递文件名的调用。我想在linux上运行类似的东西。
音频文件是Microsoft PCM,单通道,22Khz
任何建议?
答案 0 :(得分:10)
由于我也在寻找问题的答案,我做了一些研究,而且我没有找到任何简单的(简单的称为调用一个函数)方式来播放音频文件。但是使用一些代码行,甚至可以使用已经提到的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。如果您的采样率或通道数也不同,那将变得非常困难。
因此,如果您不想同时播放多个文件,这可能是一个解决方案,或者至少是您的开始。
答案 1 :(得分:4)
SDL_Mixer,虽然不是很轻量级,但它有一个简单的界面来播放WAV文件。我相信,就像SDL一样,SDL_Mixer也是LGPL。
OpenAL是另一个跨平台音频库,更适合3D音频。
您可能想要查看的另一个开源音频库是PortAudio
答案 2 :(得分:2)
我使用OpenAL在空中交通管制系统中播放wav文件作为警报/警告
我发现的优势是
答案 3 :(得分:1)
您可以试试这个:libao
答案 4 :(得分:0)
答案 5 :(得分:0)
您也可以尝试Audiere。最新版本发布于2006年,但它是开源的,并在LGPL下获得许可。
答案 6 :(得分:0)