Что такое легкая кроссплатформенная библиотека WAV?

Я ищу легкий способ сделать так, чтобы моя программа (написанная на C) могла воспроизводить аудиофайлы в Windows или Linux. В настоящее время я использую родные вызовы Windows, которые по сути являются просто одним вызовом, которому передается имя файла. Я хотел бы что-то подобное, что работает на Linux.

Аудио файлы: Microsoft PCM, одноканальный, 22 кГц

Какие-либо предложения?

7 ответов

Решение

Поскольку я также ищу ответ на вопрос, я провел небольшое исследование и не нашел простого (простого, например, вызова одной функции) способа воспроизведения аудиофайла. Но с некоторыми строками кода это возможно даже портативным способом с использованием уже упомянутых 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 делает. Я не знаю, как обстоят дела с окнами. Поскольку все ваши входные файлы имеют одинаковый тип, вы можете смешивать их самостоятельно, что немного усложняет код, но тогда у вас также будет поддержка OSS. Если бы у вас также были разные частоты дискретизации или количество каналов, это стало бы очень сложно.

Так что если вы не хотите воспроизводить несколько файлов одновременно, это может быть решением или, по крайней мере, началом для вас.

SDL_Mixer, хотя и не очень легкий, имеет простой интерфейс для воспроизведения WAV-файлов. Я считаю, что, как и SDL, SDL_Mixer также является LGPL.

OpenAL - еще одна кроссплатформенная аудиотека, которая больше ориентирована на 3D-аудио.

Еще одна аудио библиотека с открытым исходным кодом, которую вы, возможно, захотите проверить, это PortAudio

Я использовал OpenAL для воспроизведения файлов WAV в качестве предупреждений / предупреждений в системе управления воздушным движением

Преимущества, которые я нашел,

  1. это кроссплатформенный
  2. работает с C (и другими, но ваш вопрос о C)
  3. легкий вес
  4. хорошая документация доступна в сети
  5. лицензия LGPL, поэтому вы вызываете API без проблем с лицензией

Вы можете попробовать с этим: libao

Я использовал irrKlang!

"irrKlang - это кроссплатформенная звуковая библиотека для C++, C# и всех языков.NET"

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

Вы также можете попробовать Audiere. Последний выпуск датирован 2006 годом, но он с открытым исходным кодом и лицензирован LGPL.

Мне нравится FMOD. Лицензия бесплатна для личного использования и очень разумна для небольших условно-бесплатных или коммерческих проектов

Другие вопросы по тегам