Search
lxdream.org :: lxdream/src/drivers/audio_alsa.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/drivers/audio_alsa.c
changeset 1073:92dfe34665ed
prev1024:c67f2d61ab97
author nkeynes
date Tue Feb 28 18:22:52 2012 +1000 (12 years ago)
permissions -rwxr-xr-x
last change Add a GL-only video driver for android usage (since the Java code is
responsible for creating the context)
file annotate diff log raw
bhaal22@643
     1
/**
nkeynes@1021
     2
 * $Id$
bhaal22@643
     3
 * 
bhaal22@643
     4
 * The asla  audio driver
bhaal22@643
     5
 *
bhaal22@643
     6
 * Copyright (c) 2008 Jonathan Muller
bhaal22@643
     7
 *
bhaal22@643
     8
 * This program is free software; you can redistribute it and/or modify
bhaal22@643
     9
 * it under the terms of the GNU General Public License as published by
bhaal22@643
    10
 * the Free Software Foundation; either version 2 of the License, or
bhaal22@643
    11
 * (at your option) any later version.
bhaal22@643
    12
 *
bhaal22@643
    13
 * This program is distributed in the hope that it will be useful,
bhaal22@643
    14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
bhaal22@643
    15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
bhaal22@643
    16
 * GNU General Public License for more details.
bhaal22@643
    17
 */
bhaal22@643
    18
#include <stdio.h>
bhaal22@643
    19
#include <unistd.h>
bhaal22@643
    20
bhaal22@643
    21
/* Use the newer ALSA API */
bhaal22@643
    22
#define ALSA_PCM_NEW_HW_PARAMS_API
bhaal22@643
    23
bhaal22@643
    24
#include <alsa/asoundlib.h>
bhaal22@643
    25
#include "config.h"
bhaal22@643
    26
#include "aica/audio.h"
bhaal22@643
    27
#include "dream.h"
bhaal22@643
    28
bhaal22@643
    29
bhaal22@643
    30
static snd_pcm_t *_soundDevice = NULL;
bhaal22@643
    31
static int frame_bytes;
bhaal22@643
    32
bhaal22@643
    33
nkeynes@1073
    34
static struct lxdream_config_group alsa_config = {
nkeynes@1073
    35
        "alsa", NULL, NULL, NULL,
nkeynes@1073
    36
        {{"device", N_("Audio output device"), CONFIG_TYPE_FILE, "default"},
nkeynes@1073
    37
        {NULL, CONFIG_TYPE_NONE}}  };
bhaal22@643
    38
bhaal22@643
    39
nkeynes@1024
    40
static gboolean audio_alsa_init(  )
bhaal22@643
    41
{
bhaal22@643
    42
    int err;
bhaal22@643
    43
    snd_pcm_hw_params_t *hw_params;
bhaal22@643
    44
    snd_pcm_sw_params_t *sw_params;
bhaal22@643
    45
    snd_pcm_uframes_t frames;
bhaal22@643
    46
    snd_pcm_uframes_t bufferSize;
nkeynes@806
    47
    unsigned int rate = DEFAULT_SAMPLE_RATE;
nkeynes@697
    48
    int format = DEFAULT_SAMPLE_FORMAT;
bhaal22@643
    49
    int dir;
bhaal22@643
    50
bhaal22@643
    51
bhaal22@643
    52
    // Open the device we were told to open.
nkeynes@1073
    53
    err = snd_pcm_open( &_soundDevice, alsa_config.params[0].value,
nkeynes@736
    54
            SND_PCM_STREAM_PLAYBACK, 0 );
bhaal22@643
    55
bhaal22@643
    56
    // Check for error on open.
bhaal22@643
    57
    if ( err < 0 ) {
bhaal22@643
    58
        ERROR( "Init: cannot open audio device %s (%s)\n",
nkeynes@1073
    59
                alsa_config.params[0].value, snd_strerror( err ) );
bhaal22@643
    60
        return FALSE;
bhaal22@643
    61
    } else {
bhaal22@643
    62
        DEBUG( "Audio device opened successfully." );
bhaal22@643
    63
    }
bhaal22@643
    64
bhaal22@643
    65
    frame_bytes = ( 2 * ( snd_pcm_format_width( SND_PCM_FORMAT_S16_LE ) / 8 ) );
bhaal22@643
    66
bhaal22@643
    67
bhaal22@643
    68
    //snd_pcm_hw_params_alloca (&hw_params);
bhaal22@643
    69
    // Allocate the hardware parameter structure.
bhaal22@643
    70
    if ( ( err = snd_pcm_hw_params_malloc( &hw_params ) ) < 0 ) {
bhaal22@643
    71
        ERROR( "Init: cannot allocate hardware parameter structure (%s)\n",
nkeynes@736
    72
                snd_strerror( err ) );
bhaal22@643
    73
        return FALSE;
bhaal22@643
    74
    }
bhaal22@643
    75
bhaal22@643
    76
    if ( ( err = snd_pcm_hw_params_any( _soundDevice, hw_params ) ) < 0 ) {
bhaal22@643
    77
        ERROR( "Init: cannot allocate hardware parameter structure (%s)\n",
nkeynes@736
    78
                snd_strerror( err ) );
bhaal22@643
    79
        return FALSE;
bhaal22@643
    80
    }
bhaal22@643
    81
    // Set access to RW interleaved.
bhaal22@643
    82
    if ( ( err = snd_pcm_hw_params_set_access( _soundDevice, hw_params,
nkeynes@736
    83
            SND_PCM_ACCESS_RW_INTERLEAVED ) )
nkeynes@736
    84
            < 0 ) {
bhaal22@643
    85
        ERROR( " Init: cannot set access type (%s)\n", snd_strerror( err ) );
bhaal22@643
    86
        return FALSE;
bhaal22@643
    87
    }
bhaal22@643
    88
bhaal22@643
    89
    if ( ( err = snd_pcm_hw_params_set_format( _soundDevice, hw_params,
nkeynes@736
    90
            SND_PCM_FORMAT_S16_LE ) ) <
nkeynes@736
    91
            0 ) {
bhaal22@643
    92
        ERROR( "Init: cannot set sample format (%s)\n", snd_strerror( err ) );
bhaal22@643
    93
        return FALSE;
bhaal22@643
    94
    }
bhaal22@643
    95
bhaal22@643
    96
    err = snd_pcm_hw_params_set_rate_near( _soundDevice, hw_params, &rate, 0 );
bhaal22@643
    97
    if ( err < 0 ) {
bhaal22@643
    98
        ERROR( "Init: Resampling setup failed for playback: %s\n",
nkeynes@736
    99
                snd_strerror( err ) );
bhaal22@643
   100
        return err;
bhaal22@643
   101
    }
bhaal22@643
   102
    // Set channels to stereo (2).
bhaal22@643
   103
    err = snd_pcm_hw_params_set_channels( _soundDevice, hw_params, 2 );
bhaal22@643
   104
    if ( err < 0 ) {
bhaal22@643
   105
        ERROR( "Init: cannot set channel count (%s)\n", snd_strerror( err ) );
bhaal22@643
   106
        return FALSE;
bhaal22@643
   107
    }
bhaal22@643
   108
bhaal22@643
   109
    // frames = 4410;
bhaal22@643
   110
    // snd_pcm_hw_params_set_period_size_near( _soundDevice, hw_params, &frames,
bhaal22@643
   111
    //                                     &dir );
bhaal22@643
   112
bhaal22@643
   113
    // Apply the hardware parameters that we've set.
bhaal22@643
   114
    err = snd_pcm_hw_params( _soundDevice, hw_params );
bhaal22@643
   115
    if ( err < 0 ) {
bhaal22@643
   116
        DEBUG( "Init: cannot set parameters (%s)\n", snd_strerror( err ) );
bhaal22@643
   117
        return FALSE;
bhaal22@643
   118
    } else {
bhaal22@643
   119
        DEBUG( "Audio device parameters have been set successfully." );
bhaal22@643
   120
    }
bhaal22@643
   121
bhaal22@643
   122
    snd_pcm_hw_params_get_period_size( hw_params, &frames, &dir );
bhaal22@643
   123
    DEBUG( "period size = %d\n", frames );
bhaal22@643
   124
bhaal22@643
   125
    // Get the buffer size.
bhaal22@643
   126
    snd_pcm_hw_params_get_buffer_size( hw_params, &bufferSize );
bhaal22@643
   127
    DEBUG("Buffer Size = %d\n", bufferSize);
bhaal22@643
   128
bhaal22@643
   129
    // If we were going to do more with our sound device we would want to store
bhaal22@643
   130
    // the buffer size so we know how much data we will need to fill it with.
bhaal22@643
   131
bhaal22@643
   132
    //cout << "Init: Buffer size = " << bufferSize << " frames." << endl;
bhaal22@643
   133
bhaal22@643
   134
    // Display the bit size of samples.
bhaal22@643
   135
    //cout << "Init: Significant bits for linear samples = " << snd_pcm_hw_params_get_sbits(hw_params) << endl;
bhaal22@643
   136
bhaal22@643
   137
    // Free the hardware parameters now that we're done with them.
bhaal22@643
   138
    snd_pcm_hw_params_free( hw_params );
bhaal22@643
   139
bhaal22@643
   140
    // Set the start threshold to reduce inter-buffer gaps
bhaal22@643
   141
    snd_pcm_sw_params_alloca( &sw_params );
bhaal22@643
   142
    snd_pcm_sw_params_current( _soundDevice, sw_params );
nkeynes@880
   143
    snd_pcm_sw_params_set_start_threshold( _soundDevice, sw_params, bufferSize );
bhaal22@643
   144
    err = snd_pcm_sw_params( _soundDevice, sw_params );
bhaal22@643
   145
    if( err < 0 ) {
nkeynes@736
   146
        ERROR("Unable to set sw params for alsa driver: %s\n", snd_strerror(err));
nkeynes@736
   147
        return FALSE;
bhaal22@643
   148
    } 
bhaal22@643
   149
bhaal22@643
   150
    err = snd_pcm_prepare( _soundDevice );
bhaal22@643
   151
    if ( err < 0 ) {
bhaal22@643
   152
        ERROR( "Init: cannot prepare audio interface for use (%s)\n",
nkeynes@736
   153
                snd_strerror( err ) );
bhaal22@643
   154
        return FALSE;
bhaal22@643
   155
    }
bhaal22@643
   156
    return TRUE;
bhaal22@643
   157
}
bhaal22@643
   158
nkeynes@1024
   159
static gboolean audio_alsa_process_buffer( audio_buffer_t buffer )
bhaal22@643
   160
{
bhaal22@643
   161
    int err;
bhaal22@643
   162
    int length;
bhaal22@643
   163
bhaal22@643
   164
bhaal22@643
   165
    length = buffer->length / frame_bytes;
bhaal22@643
   166
bhaal22@643
   167
    err = snd_pcm_writei( _soundDevice, buffer->data, length );
bhaal22@643
   168
    if( err == -EPIPE ) {
nkeynes@736
   169
        snd_pcm_prepare( _soundDevice );
bhaal22@643
   170
    } else if( err == -ESTRPIPE ) {
nkeynes@736
   171
        snd_pcm_resume( _soundDevice );
bhaal22@643
   172
    }
bhaal22@643
   173
bhaal22@643
   174
    return TRUE;
bhaal22@643
   175
}
bhaal22@643
   176
bhaal22@643
   177
nkeynes@1024
   178
static gboolean audio_alsa_shutdown(  )
bhaal22@643
   179
{
bhaal22@643
   180
    return TRUE;
bhaal22@643
   181
}
bhaal22@643
   182
bhaal22@643
   183
bhaal22@643
   184
nkeynes@1024
   185
static struct audio_driver audio_alsa_driver = { 
nkeynes@736
   186
        "alsa",
nkeynes@736
   187
        N_("Linux ALSA system driver"),
nkeynes@1024
   188
        40,
nkeynes@736
   189
        DEFAULT_SAMPLE_RATE,
nkeynes@736
   190
        DEFAULT_SAMPLE_FORMAT,
nkeynes@736
   191
        audio_alsa_init,
nkeynes@736
   192
        NULL,
nkeynes@736
   193
        audio_alsa_process_buffer,
nkeynes@736
   194
        NULL,
nkeynes@736
   195
        audio_alsa_shutdown
bhaal22@643
   196
};
nkeynes@1024
   197
nkeynes@1024
   198
static gboolean audio_alsa_static_init( void )
nkeynes@1024
   199
{
nkeynes@1073
   200
    lxdream_register_config_group( "alsa", &alsa_config );
nkeynes@1024
   201
    audio_register_driver( &audio_alsa_driver );
nkeynes@1024
   202
    return TRUE;
nkeynes@1024
   203
}
nkeynes@1024
   204
nkeynes@1024
   205
DEFINE_PLUGIN( PLUGIN_AUDIO_DRIVER, "alsa", audio_alsa_static_init );
.