New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support libsndfile for WAV playback #859

Closed
Ghabry opened this Issue Apr 8, 2016 · 2 comments

Comments

Projects
None yet
2 participants
@Ghabry
Member

Ghabry commented Apr 8, 2016

This is not really required for SDL, except for a few corner cases like 24 bit PCM but would be useful for non-SDL ports.

OpenAL already uses it.

  • Windows
  • macOS
  • Android
  • Wii

@Ghabry Ghabry added this to the 0.5.0 milestone Apr 8, 2016

@fdelapena

This comment has been minimized.

Show comment
Hide comment
@fdelapena

fdelapena Apr 8, 2016

Contributor

👍 this would fix Ara Fell demo playback as it uses some 24-bit PCM Microsoft WAV files (unsupported by SDL).

Contributor

fdelapena commented Apr 8, 2016

👍 this would fix Ara Fell demo playback as it uses some 24-bit PCM Microsoft WAV files (unsupported by SDL).

@fdelapena

This comment has been minimized.

Show comment
Hide comment
@fdelapena

fdelapena Apr 28, 2016

Contributor

Here is a proof of concept with loop support. Not widely tested, it fails with some wave file types yet (e.g. 96 khz 24 bit multichannel wave). Of course it needs some work for the audio format mapping (everything will play to 44100 in this test).

You can use sf_readf_* (note the "f") instead of sf_read_* to read frames (for 2 channels it reads twice) instead and adjust the len calculation.

#include "SDL.h"
#include "SDL_mixer.h"
#include <sndfile.h>
#include <stdio.h>

int musicPlaying;
SNDFILE *wavfile = NULL;
SF_INFO wavinfo;

void musicFinished() {
    printf("Music finished\n");
    /*Mix_HookMusic(NULL, NULL);*/
    /*musicPlaying = 0;*/
}

void play_wav(void *udata, Uint8 *stream, int len) {
    Uint8 *buffer = malloc(len);
    (void)udata; /* Unused yet, silence the compiler */

    if (!sf_read_short(wavfile, (short*)buffer, len / 2)) {
        sf_seek(wavfile, 0, SEEK_SET);
        musicFinished();
    }
    SDL_MixAudio(stream, buffer, len, SDL_MIX_MAXVOLUME);

    free(buffer);
}

int main(int argc, char *argv[]) {
    if (argc < 2) {
        printf("Usage: %s filename.wav\n", argv[0]);
        return 1;
    }
    SDL_Init(SDL_INIT_AUDIO);
    Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 2048);

    wavfile = sf_open(argv[1], SFM_READ, &wavinfo);
    sf_command(wavfile, SFC_SET_SCALE_FLOAT_INT_READ, NULL, SF_TRUE);
    Mix_HookMusic(play_wav, NULL);

    musicPlaying = 1;
    while (musicPlaying) {
        SDL_Delay(200);
    }

    sf_close(wavfile);
    Mix_Quit();
    SDL_Quit();
    return 0;
}

Build with:

gcc wavplayer.c -o wavplayer `pkg-config --cflags --libs sndfile SDL2_mixer`
Contributor

fdelapena commented Apr 28, 2016

Here is a proof of concept with loop support. Not widely tested, it fails with some wave file types yet (e.g. 96 khz 24 bit multichannel wave). Of course it needs some work for the audio format mapping (everything will play to 44100 in this test).

You can use sf_readf_* (note the "f") instead of sf_read_* to read frames (for 2 channels it reads twice) instead and adjust the len calculation.

#include "SDL.h"
#include "SDL_mixer.h"
#include <sndfile.h>
#include <stdio.h>

int musicPlaying;
SNDFILE *wavfile = NULL;
SF_INFO wavinfo;

void musicFinished() {
    printf("Music finished\n");
    /*Mix_HookMusic(NULL, NULL);*/
    /*musicPlaying = 0;*/
}

void play_wav(void *udata, Uint8 *stream, int len) {
    Uint8 *buffer = malloc(len);
    (void)udata; /* Unused yet, silence the compiler */

    if (!sf_read_short(wavfile, (short*)buffer, len / 2)) {
        sf_seek(wavfile, 0, SEEK_SET);
        musicFinished();
    }
    SDL_MixAudio(stream, buffer, len, SDL_MIX_MAXVOLUME);

    free(buffer);
}

int main(int argc, char *argv[]) {
    if (argc < 2) {
        printf("Usage: %s filename.wav\n", argv[0]);
        return 1;
    }
    SDL_Init(SDL_INIT_AUDIO);
    Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 2048);

    wavfile = sf_open(argv[1], SFM_READ, &wavinfo);
    sf_command(wavfile, SFC_SET_SCALE_FLOAT_INT_READ, NULL, SF_TRUE);
    Mix_HookMusic(play_wav, NULL);

    musicPlaying = 1;
    while (musicPlaying) {
        SDL_Delay(200);
    }

    sf_close(wavfile);
    Mix_Quit();
    SDL_Quit();
    return 0;
}

Build with:

gcc wavplayer.c -o wavplayer `pkg-config --cflags --libs sndfile SDL2_mixer`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment