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

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

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

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

Ответы на вопрос(2)

Решение Вопроса

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

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

 Seth Taddiken04 дек. 2017 г., 07:31
Потрясающая маленькая программа! Один вопрос, я не реализовал метод для чтения данных из отдельного потока, и мне было интересно, если вы думаете, что это, вероятно, является причиной низкого качества звука, так как обратный вызов потока немного утомлен SNDFILE * file = data; Спасибо!

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

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

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

Ваш ответ на вопрос