Что такое легкая кроссплатформенная библиотека WAV? - PullRequest
13 голосов
/ 19 декабря 2008

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

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

Есть предложения?

Ответы [ 7 ]

10 голосов
/ 28 декабря 2008

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

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

4 голосов
/ 19 декабря 2008

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

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

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

2 голосов
/ 21 декабря 2008

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

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

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

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

0 голосов
/ 22 июня 2012

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

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

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

0 голосов
/ 23 февраля 2011

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

0 голосов
/ 22 декабря 2008

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...