Search
lxdream.org :: lxdream/src/drivers/audio_sdl.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/drivers/audio_sdl.c
changeset 1161:d3511e94c29f
prev1049:e723f379ec88
author nkeynes
date Sat Mar 03 15:52:59 2012 +1000 (12 years ago)
permissions -rw-r--r--
last change Swap between run + pause icons when pressed
file annotate diff log raw
nkeynes@989
     1
/**
nkeynes@1021
     2
 * $Id$
nkeynes@1049
     3
 *
nkeynes@989
     4
 * The SDL sound driver
nkeynes@989
     5
 *
nkeynes@989
     6
 * Copyright (c) 2009 wahrhaft
nkeynes@989
     7
 *
nkeynes@989
     8
 * This program is free software; you can redistribute it and/or modify
nkeynes@989
     9
 * it under the terms of the GNU General Public License as published by
nkeynes@989
    10
 * the Free Software Foundation; either version 2 of the License, or
nkeynes@989
    11
 * (at your option) any later version.
nkeynes@989
    12
 *
nkeynes@989
    13
 * This program is distributed in the hope that it will be useful,
nkeynes@989
    14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
nkeynes@989
    15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
nkeynes@989
    16
 * GNU General Public License for more details.
nkeynes@989
    17
 */
nkeynes@989
    18
#include <stdio.h>
nkeynes@989
    19
#include <unistd.h>
nkeynes@1161
    20
#include <SDL.h>
nkeynes@1161
    21
#include <SDL_audio.h>
nkeynes@989
    22
#include "aica/audio.h"
nkeynes@989
    23
#include "lxdream.h"
nkeynes@989
    24
nkeynes@989
    25
#define SDL_SAMPLES 512        //tweaking this value may help with audio dropouts
nkeynes@989
    26
#define BYTES_PER_SAMPLE 4     //should be changed if samples are not S16 stereo
nkeynes@989
    27
nkeynes@989
    28
#define BUFFER_MIN_SIZE SDL_SAMPLES * BYTES_PER_SAMPLE * 4
nkeynes@989
    29
#define BUFFER_MAX_SIZE SDL_SAMPLES * BYTES_PER_SAMPLE * 16
nkeynes@989
    30
nkeynes@1024
    31
static char *audio_buffer;
nkeynes@1024
    32
static int buffer_pos;
nkeynes@989
    33
nkeynes@1024
    34
static void mix_audio(void *userdata, Uint8 *stream, int len);
nkeynes@989
    35
nkeynes@1024
    36
static gboolean audio_sdl_init( )
nkeynes@989
    37
{
nkeynes@989
    38
    int rate = DEFAULT_SAMPLE_RATE;
nkeynes@989
    39
    int format = DEFAULT_SAMPLE_FORMAT;
nkeynes@1049
    40
nkeynes@989
    41
    SDL_AudioSpec fmt;
nkeynes@989
    42
    fmt.freq = rate;
nkeynes@1049
    43
    if (format & AUDIO_FMT_16BIT)
nkeynes@989
    44
        fmt.format = AUDIO_S16;
nkeynes@989
    45
    else
nkeynes@989
    46
        fmt.format = AUDIO_U8;
nkeynes@989
    47
    if (format & AUDIO_FMT_STEREO)
nkeynes@989
    48
        fmt.channels = 2;
nkeynes@989
    49
    else
nkeynes@989
    50
        fmt.channels = 1;
nkeynes@1049
    51
nkeynes@989
    52
    fmt.samples = SDL_SAMPLES;
nkeynes@989
    53
    fmt.callback = mix_audio;
nkeynes@989
    54
    fmt.userdata = NULL;
nkeynes@1049
    55
nkeynes@989
    56
    if (SDL_OpenAudio(&fmt, NULL) < 0)
nkeynes@989
    57
    {
nkeynes@989
    58
        ERROR("Unable to open audio output (SDL)");
nkeynes@989
    59
        return FALSE;
nkeynes@989
    60
    }
nkeynes@989
    61
    buffer_pos = 0;
nkeynes@989
    62
    audio_buffer = (char*)malloc(BUFFER_MAX_SIZE * sizeof(char));
nkeynes@989
    63
    if (audio_buffer == NULL)
nkeynes@989
    64
    {
nkeynes@989
    65
        ERROR("Could not allocate audio buffer (SDL)");
nkeynes@989
    66
        return FALSE;
nkeynes@989
    67
    }
nkeynes@1049
    68
nkeynes@989
    69
    return TRUE;
nkeynes@989
    70
}
nkeynes@989
    71
nkeynes@989
    72
gboolean audio_sdl_process_buffer( audio_buffer_t buffer )
nkeynes@989
    73
{
nkeynes@989
    74
    SDL_LockAudio();
nkeynes@989
    75
    if (buffer_pos + buffer->length >= BUFFER_MAX_SIZE)
nkeynes@989
    76
    {
nkeynes@1049
    77
        DEBUG("Audio buffer full, dropping a chunk\n");
nkeynes@989
    78
    }
nkeynes@989
    79
    else
nkeynes@989
    80
    {
nkeynes@989
    81
        memcpy(audio_buffer, buffer->data, buffer->length);
nkeynes@989
    82
        buffer_pos += buffer->length;
nkeynes@989
    83
    }
nkeynes@989
    84
    SDL_UnlockAudio();
nkeynes@989
    85
nkeynes@1049
    86
    return TRUE;
nkeynes@989
    87
}
nkeynes@989
    88
nkeynes@1024
    89
static void mix_audio(void *userdata, Uint8 *stream, int len)
nkeynes@989
    90
{
nkeynes@989
    91
    if (len < buffer_pos)
nkeynes@989
    92
    {
nkeynes@989
    93
        memcpy(stream, audio_buffer, len);
nkeynes@989
    94
    }
nkeynes@989
    95
    if (buffer_pos > BUFFER_MIN_SIZE)
nkeynes@989
    96
    {
nkeynes@989
    97
        memcpy(audio_buffer, &audio_buffer[len], buffer_pos - len);
nkeynes@989
    98
        buffer_pos -= len;
nkeynes@989
    99
    }
nkeynes@989
   100
    else
nkeynes@989
   101
    {
nkeynes@1049
   102
        DEBUG("Audio buffer low, repeating a chunk\n");
nkeynes@989
   103
    }
nkeynes@989
   104
}
nkeynes@989
   105
nkeynes@1024
   106
static gboolean audio_sdl_shutdown()
nkeynes@989
   107
{
nkeynes@989
   108
    SDL_CloseAudio();
nkeynes@989
   109
    free(audio_buffer);
nkeynes@989
   110
    return TRUE;
nkeynes@989
   111
}
nkeynes@989
   112
nkeynes@1024
   113
static void audio_sdl_start()
nkeynes@989
   114
{
nkeynes@989
   115
    SDL_PauseAudio(0);
nkeynes@989
   116
}
nkeynes@989
   117
nkeynes@1024
   118
static void audio_sdl_stop()
nkeynes@989
   119
{
nkeynes@989
   120
    SDL_PauseAudio(1);
nkeynes@989
   121
}
nkeynes@989
   122
nkeynes@1049
   123
static struct audio_driver audio_sdl_driver = {
nkeynes@989
   124
    "sdl",
nkeynes@989
   125
    N_("SDL sound driver"),
nkeynes@1024
   126
    20,
nkeynes@989
   127
    DEFAULT_SAMPLE_RATE,
nkeynes@989
   128
    DEFAULT_SAMPLE_FORMAT,
nkeynes@989
   129
    audio_sdl_init,
nkeynes@989
   130
    audio_sdl_start,
nkeynes@989
   131
    audio_sdl_process_buffer,
nkeynes@989
   132
    audio_sdl_stop,
nkeynes@989
   133
    audio_sdl_shutdown
nkeynes@989
   134
};
nkeynes@989
   135
nkeynes@1024
   136
AUDIO_DRIVER( "sdl", audio_sdl_driver );
.