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 880:214979b3bc80
prev806:6ef1ce4a9dbc
next1021:848db285a184
author nkeynes
date Sat Feb 28 06:26:48 2009 +0000 (15 years ago)
permissions -rwxr-xr-x
last change Add SDL audio driver, thanks to Wahrhaft!
view annotate diff log raw
     1 /**
     2  * $Id: audio_esd.c 602 2008-01-15 20:50:23Z nkeynes $
     3  * 
     4  * The asla  audio driver
     5  *
     6  * Copyright (c) 2008 Jonathan Muller
     7  *
     8  * This program is free software; you can redistribute it and/or modify
     9  * it under the terms of the GNU General Public License as published by
    10  * the Free Software Foundation; either version 2 of the License, or
    11  * (at your option) any later version.
    12  *
    13  * This program is distributed in the hope that it will be useful,
    14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    16  * GNU General Public License for more details.
    17  */
    18 #include <stdio.h>
    19 #include <unistd.h>
    21 /* Use the newer ALSA API */
    22 #define ALSA_PCM_NEW_HW_PARAMS_API
    24 #include <alsa/asoundlib.h>
    25 #include "config.h"
    26 #include "aica/audio.h"
    27 #include "dream.h"
    30 static snd_pcm_t *_soundDevice = NULL;
    31 static int frame_bytes;
    34 struct lxdream_config_entry alsa_config[] = {
    35         {"device", N_("Audio output device"), CONFIG_TYPE_FILE, "default"},
    36         {NULL, CONFIG_TYPE_NONE}
    37 };
    40 gboolean audio_alsa_init(  )
    41 {
    42     int err;
    43     snd_pcm_hw_params_t *hw_params;
    44     snd_pcm_sw_params_t *sw_params;
    45     snd_pcm_uframes_t frames;
    46     snd_pcm_uframes_t bufferSize;
    47     unsigned int rate = DEFAULT_SAMPLE_RATE;
    48     int format = DEFAULT_SAMPLE_FORMAT;
    49     int dir;
    52     // Open the device we were told to open.
    53     err = snd_pcm_open( &_soundDevice, alsa_config[0].value,
    54             SND_PCM_STREAM_PLAYBACK, 0 );
    56     // Check for error on open.
    57     if ( err < 0 ) {
    58         ERROR( "Init: cannot open audio device %s (%s)\n",
    59                 alsa_config[0].value, snd_strerror( err ) );
    60         return FALSE;
    61     } else {
    62         DEBUG( "Audio device opened successfully." );
    63     }
    65     frame_bytes = ( 2 * ( snd_pcm_format_width( SND_PCM_FORMAT_S16_LE ) / 8 ) );
    68     //snd_pcm_hw_params_alloca (&hw_params);
    69     // Allocate the hardware parameter structure.
    70     if ( ( err = snd_pcm_hw_params_malloc( &hw_params ) ) < 0 ) {
    71         ERROR( "Init: cannot allocate hardware parameter structure (%s)\n",
    72                 snd_strerror( err ) );
    73         return FALSE;
    74     }
    76     if ( ( err = snd_pcm_hw_params_any( _soundDevice, hw_params ) ) < 0 ) {
    77         ERROR( "Init: cannot allocate hardware parameter structure (%s)\n",
    78                 snd_strerror( err ) );
    79         return FALSE;
    80     }
    81     // Set access to RW interleaved.
    82     if ( ( err = snd_pcm_hw_params_set_access( _soundDevice, hw_params,
    83             SND_PCM_ACCESS_RW_INTERLEAVED ) )
    84             < 0 ) {
    85         ERROR( " Init: cannot set access type (%s)\n", snd_strerror( err ) );
    86         return FALSE;
    87     }
    89     if ( ( err = snd_pcm_hw_params_set_format( _soundDevice, hw_params,
    90             SND_PCM_FORMAT_S16_LE ) ) <
    91             0 ) {
    92         ERROR( "Init: cannot set sample format (%s)\n", snd_strerror( err ) );
    93         return FALSE;
    94     }
    96     err = snd_pcm_hw_params_set_rate_near( _soundDevice, hw_params, &rate, 0 );
    97     if ( err < 0 ) {
    98         ERROR( "Init: Resampling setup failed for playback: %s\n",
    99                 snd_strerror( err ) );
   100         return err;
   101     }
   102     // Set channels to stereo (2).
   103     err = snd_pcm_hw_params_set_channels( _soundDevice, hw_params, 2 );
   104     if ( err < 0 ) {
   105         ERROR( "Init: cannot set channel count (%s)\n", snd_strerror( err ) );
   106         return FALSE;
   107     }
   109     // frames = 4410;
   110     // snd_pcm_hw_params_set_period_size_near( _soundDevice, hw_params, &frames,
   111     //                                     &dir );
   113     // Apply the hardware parameters that we've set.
   114     err = snd_pcm_hw_params( _soundDevice, hw_params );
   115     if ( err < 0 ) {
   116         DEBUG( "Init: cannot set parameters (%s)\n", snd_strerror( err ) );
   117         return FALSE;
   118     } else {
   119         DEBUG( "Audio device parameters have been set successfully." );
   120     }
   122     snd_pcm_hw_params_get_period_size( hw_params, &frames, &dir );
   123     DEBUG( "period size = %d\n", frames );
   125     // Get the buffer size.
   126     snd_pcm_hw_params_get_buffer_size( hw_params, &bufferSize );
   127     DEBUG("Buffer Size = %d\n", bufferSize);
   129     // If we were going to do more with our sound device we would want to store
   130     // the buffer size so we know how much data we will need to fill it with.
   132     //cout << "Init: Buffer size = " << bufferSize << " frames." << endl;
   134     // Display the bit size of samples.
   135     //cout << "Init: Significant bits for linear samples = " << snd_pcm_hw_params_get_sbits(hw_params) << endl;
   137     // Free the hardware parameters now that we're done with them.
   138     snd_pcm_hw_params_free( hw_params );
   140     // Set the start threshold to reduce inter-buffer gaps
   141     snd_pcm_sw_params_alloca( &sw_params );
   142     snd_pcm_sw_params_current( _soundDevice, sw_params );
   143     snd_pcm_sw_params_set_start_threshold( _soundDevice, sw_params, bufferSize );
   144     err = snd_pcm_sw_params( _soundDevice, sw_params );
   145     if( err < 0 ) {
   146         ERROR("Unable to set sw params for alsa driver: %s\n", snd_strerror(err));
   147         return FALSE;
   148     } 
   150     err = snd_pcm_prepare( _soundDevice );
   151     if ( err < 0 ) {
   152         ERROR( "Init: cannot prepare audio interface for use (%s)\n",
   153                 snd_strerror( err ) );
   154         return FALSE;
   155     }
   156     return TRUE;
   157 }
   159 gboolean audio_alsa_process_buffer( audio_buffer_t buffer )
   160 {
   161     int err;
   162     int length;
   165     length = buffer->length / frame_bytes;
   167     err = snd_pcm_writei( _soundDevice, buffer->data, length );
   168     if( err == -EPIPE ) {
   169         snd_pcm_prepare( _soundDevice );
   170     } else if( err == -ESTRPIPE ) {
   171         snd_pcm_resume( _soundDevice );
   172     }
   174     return TRUE;
   175 }
   178 gboolean audio_alsa_shutdown(  )
   179 {
   180     return TRUE;
   181 }
   185 struct audio_driver audio_alsa_driver = { 
   186         "alsa",
   187         N_("Linux ALSA system driver"),
   188         DEFAULT_SAMPLE_RATE,
   189         DEFAULT_SAMPLE_FORMAT,
   190         audio_alsa_init,
   191         NULL,
   192         audio_alsa_process_buffer,
   193         NULL,
   194         audio_alsa_shutdown
   195 };
.