root/modules/sdl_out/audio.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sdl_close_audio
  2. sdl_fill_audio
  3. SDLAud_Setup
  4. SDLAud_Shutdown
  5. SDL_DeleteAudio
  6. SDLAud_ConfigureOutput
  7. SDLAud_GetAudioDelay
  8. SDLAud_GetTotalBufferTime
  9. SDLAud_SetVolume
  10. SDLAud_SetPan
  11. SDLAud_Play
  12. SDLAud_SetPriority
  13. SDLAud_QueryOutputSampleRate
  14. SDL_NewAudio

/*
 *                      GPAC - Multimedia Framework C SDK
 *
 *                      Authors: Jean Le Feuvre
 *                      Copyright (c) Telecom ParisTech 2000-2012
 *                                      All rights reserved
 *
 *  This file is part of GPAC / SDL audio and video module
 *
 *  GPAC is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU Lesser General Public License as published by
 *  the Free Software Foundation; either version 2, or (at your option)
 *  any later version.
 *
 *  GPAC is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; see the file COPYING.  If not, write to
 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */

#include "sdl_out.h"

#define SDLAUD()        SDLAudCtx *ctx = (SDLAudCtx *)dr->opaque

static void sdl_close_audio() {
        SDL_CloseAudio();
}


void sdl_fill_audio(void *udata, Uint8 *stream, int len)
{
        GF_AudioOutput *dr = (GF_AudioOutput *)udata;
        SDLAUD();
        if (ctx->volume != SDL_MIX_MAXVOLUME) {
                u32 written;
                if (ctx->alloc_size < (u32) len) {
                        ctx->audioBuff = (Uint8*)gf_realloc( ctx->audioBuff, sizeof(Uint8) * len);
                        ctx->alloc_size = len;
                }
                memset(stream, 0, len);
                written = dr->FillBuffer(dr->audio_renderer, (char *) ctx->audioBuff, (u32) len);
                if (written)
                        SDL_MixAudio(stream, ctx->audioBuff, len, ctx->volume);
        } else {
                dr->FillBuffer(dr->audio_renderer, (char *) stream, (u32) len);
        }
}


static GF_Err SDLAud_Setup(GF_AudioOutput *dr, void *os_handle, u32 num_buffers, u32 total_duration)
{
        u32 flags;
        SDL_AudioSpec want_format, got_format;
        SDLAUD();

        /*init sdl*/
        if (!SDLOUT_InitSDL()) return GF_IO_ERR;

        flags = SDL_WasInit(SDL_INIT_AUDIO);
        if (!(flags & SDL_INIT_AUDIO)) {
                if (SDL_InitSubSystem(SDL_INIT_AUDIO)<0) {
                        GF_LOG(GF_LOG_ERROR, GF_LOG_MMIO, ("[SDL] Audio output initialization error\n"));
                        SDLOUT_CloseSDL();
                        return GF_IO_ERR;
                }
        }
        /*check we can open the device*/
        memset(&want_format, 0, sizeof(SDL_AudioSpec));
        want_format.freq = 44100;
        want_format.format = AUDIO_S16SYS;
        want_format.channels = 2;
        want_format.samples = 1024;
        want_format.callback = sdl_fill_audio;
        want_format.userdata = dr;
        if ( SDL_OpenAudio(&want_format, &got_format) < 0 ) {
                sdl_close_audio();
                SDL_QuitSubSystem(SDL_INIT_AUDIO);
                SDLOUT_CloseSDL();
                GF_LOG(GF_LOG_ERROR, GF_LOG_MMIO, ("[SDL] Audio output format not supported\n"));
                return GF_IO_ERR;
        }
        sdl_close_audio();
        ctx->is_init = GF_TRUE;
        ctx->num_buffers = num_buffers;
        ctx->total_duration = total_duration;
        GF_LOG(GF_LOG_INFO, GF_LOG_MMIO, ("[SDL] Audio output setup\n"));
        return GF_OK;
}

static void SDLAud_Shutdown(GF_AudioOutput *dr)
{
        SDLAUD();
        sdl_close_audio();
        if (ctx->is_init) {
                SDL_QuitSubSystem(SDL_INIT_AUDIO);
                SDLOUT_CloseSDL();
                ctx->is_init = GF_FALSE;
        }
}

void SDL_DeleteAudio(void *ifce) {
        SDLAudCtx *ctx;
        GF_AudioOutput * dr;
        if (!ifce)
                return;
        dr = ( GF_AudioOutput *) ifce;
        ctx = (SDLAudCtx *)dr->opaque;
        if (!ctx)
                return;
        if (ctx->audioBuff)
                gf_free(ctx->audioBuff);
        ctx->audioBuff = NULL;
        gf_free( ctx );
        dr->opaque = NULL;
        gf_free( dr );
}

static GF_Err SDLAud_ConfigureOutput(GF_AudioOutput *dr, u32 *SampleRate, u32 *NbChannels, u32 *nbBitsPerSample, u32 channel_cfg)
{
        s32 nb_samples;
        SDL_AudioSpec want_format, got_format;
        SDLAUD();

        sdl_close_audio();
        ctx->is_running = GF_FALSE;

        memset(&want_format, 0, sizeof(SDL_AudioSpec));
        want_format.freq = *SampleRate;
        want_format.format = (*nbBitsPerSample==16) ? AUDIO_S16SYS : AUDIO_S8;
        want_format.channels = *NbChannels;
        want_format.callback = sdl_fill_audio;
        want_format.userdata = dr;

        if (ctx->num_buffers && ctx->total_duration) {
                nb_samples = want_format.freq * ctx->total_duration;
                nb_samples /= (1000 * ctx->num_buffers);
                if (nb_samples % 2) nb_samples++;
        } else {
                nb_samples = 1024;
        }

        /*respect SDL need for power of 2*/
        want_format.samples = 1;
        while (want_format.samples*2<nb_samples) want_format.samples *= 2;

        if ( SDL_OpenAudio(&want_format, &got_format) < 0 ) return GF_IO_ERR;
        ctx->is_running = GF_TRUE;
        ctx->delay_ms = (got_format.samples * 1000) / got_format.freq;
        ctx->total_size = got_format.samples;
        *SampleRate = got_format.freq;
        *NbChannels = got_format.channels;

        switch (got_format.format) {
        case AUDIO_S8:
        case AUDIO_U8:
                *nbBitsPerSample = 8;
                break;
        default:
                *nbBitsPerSample = 16;
                break;
        }
        /*and play*/
        SDL_PauseAudio(0);
        GF_LOG(GF_LOG_INFO, GF_LOG_MMIO, ("[SDL] Audio output setup - SampleRate %d Nb Channels %d - %d ms delay\n", got_format.freq, got_format.channels, ctx->delay_ms));
        return GF_OK;
}

static u32 SDLAud_GetAudioDelay(GF_AudioOutput *dr)
{
        SDLAUD();
        return ctx->delay_ms;
}

static u32 SDLAud_GetTotalBufferTime(GF_AudioOutput *dr)
{
        SDLAUD();
        return ctx->delay_ms;
}

static void SDLAud_SetVolume(GF_AudioOutput *dr, u32 Volume)
{
        SDLAUD();
        if (Volume == 100)
                ctx->volume = SDL_MIX_MAXVOLUME;
        else
                ctx->volume = Volume * SDL_MIX_MAXVOLUME / 100;
}

static void SDLAud_SetPan(GF_AudioOutput *dr, u32 pan)
{
        /*not supported by SDL*/
}

static void SDLAud_Play(GF_AudioOutput *dr, u32 PlayType)
{
        SDL_PauseAudio(PlayType ? 0 : 1);
}

static void SDLAud_SetPriority(GF_AudioOutput *dr, u32 priority)
{
        /*not supported by SDL*/
}

static GF_Err SDLAud_QueryOutputSampleRate(GF_AudioOutput *dr, u32 *desired_samplerate, u32 *NbChannels, u32 *nbBitsPerSample)
{
        /*cannot query supported formats in SDL...*/
        return GF_OK;
}

void *SDL_NewAudio()
{
        SDLAudCtx *ctx;
        GF_AudioOutput *dr;


        ctx = (SDLAudCtx*)gf_malloc(sizeof(SDLAudCtx));
        memset(ctx, 0, sizeof(SDLAudCtx));

        dr = (GF_AudioOutput*)gf_malloc(sizeof(GF_AudioOutput));
        memset(dr, 0, sizeof(GF_AudioOutput));
        GF_REGISTER_MODULE_INTERFACE(dr, GF_AUDIO_OUTPUT_INTERFACE, "SDL Audio Output", "gpac distribution");

        dr->opaque = ctx;

        dr->Setup = SDLAud_Setup;
        dr->Shutdown = SDLAud_Shutdown;
        dr->ConfigureOutput = SDLAud_ConfigureOutput;
        dr->SetVolume = SDLAud_SetVolume;
        dr->SetPan = SDLAud_SetPan;
        dr->Play = SDLAud_Play;
        dr->SetPriority = SDLAud_SetPriority;
        dr->GetAudioDelay = SDLAud_GetAudioDelay;
        dr->GetTotalBufferTime = SDLAud_GetTotalBufferTime;

        dr->QueryOutputSampleRate = SDLAud_QueryOutputSampleRate;
        /*always threaded*/
        dr->SelfThreaded = GF_TRUE;
        ctx->audioBuff = NULL;
        ctx->volume = SDL_MIX_MAXVOLUME;
        return dr;
}


/* [<][>][^][v][top][bottom][index][help] */