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 643:653b0a70f173
next669:ab344e42bca9
author nkeynes
date Fri Mar 28 12:32:25 2008 +0000 (16 years ago)
permissions -rwxr-xr-x
last change Merge lxdream-render branch (643:670) to trunk
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 frames;
    32 static int frame_bytes;
    35 struct lxdream_config_entry alsa_config[] = {
    36     {"device", CONFIG_TYPE_FILE, "default"},
    37     {NULL, CONFIG_TYPE_NONE}
    38 };
    41 gboolean audio_alsa_init(  )
    42 {
    43     int err;
    45     return TRUE;
    46 }
    49 gboolean audio_alsa_set_format( uint32_t rate, uint32_t format )
    50 {
    51     int i;
    52     int err;
    53     snd_pcm_hw_params_t *hw_params;
    54     snd_pcm_sw_params_t *sw_params;
    55     snd_pcm_uframes_t frames;
    56     unsigned int resample = 1;
    57     unsigned int actualRate = rate;
    58     snd_pcm_uframes_t bufferSize;
    59     int dir;
    62     // Open the device we were told to open.
    63     err = snd_pcm_open( &_soundDevice, alsa_config[0].value,
    64                         SND_PCM_STREAM_PLAYBACK, 0 );
    66     // Check for error on open.
    67     if ( err < 0 ) {
    68         ERROR( "Init: cannot open audio device %s (%s)\n",
    69                alsa_config[0].value, snd_strerror( err ) );
    70         return FALSE;
    71     } else {
    72         DEBUG( "Audio device opened successfully." );
    73     }
    75     frame_bytes = ( 2 * ( snd_pcm_format_width( SND_PCM_FORMAT_S16_LE ) / 8 ) );
    78     //snd_pcm_hw_params_alloca (&hw_params);
    79     // Allocate the hardware parameter structure.
    80     if ( ( err = snd_pcm_hw_params_malloc( &hw_params ) ) < 0 ) {
    81         ERROR( "Init: cannot allocate hardware parameter structure (%s)\n",
    82                snd_strerror( err ) );
    83         return FALSE;
    84     }
    86     if ( ( err = snd_pcm_hw_params_any( _soundDevice, hw_params ) ) < 0 ) {
    87         ERROR( "Init: cannot allocate hardware parameter structure (%s)\n",
    88                snd_strerror( err ) );
    89         return FALSE;
    90     }
    91     // Set access to RW interleaved.
    92     if ( ( err = snd_pcm_hw_params_set_access( _soundDevice, hw_params,
    93                                                SND_PCM_ACCESS_RW_INTERLEAVED ) )
    94          < 0 ) {
    95         ERROR( " Init: cannot set access type (%s)\n", snd_strerror( err ) );
    96         return FALSE;
    97     }
    99     if ( ( err = snd_pcm_hw_params_set_format( _soundDevice, hw_params,
   100                                                SND_PCM_FORMAT_S16_LE ) ) <
   101          0 ) {
   102         ERROR( "Init: cannot set sample format (%s)\n", snd_strerror( err ) );
   103         return FALSE;
   104     }
   106     err = snd_pcm_hw_params_set_rate_near( _soundDevice, hw_params, &rate, 0 );
   107     if ( err < 0 ) {
   108         ERROR( "Init: Resampling setup failed for playback: %s\n",
   109                snd_strerror( err ) );
   110         return err;
   111     }
   112     // Set channels to stereo (2).
   113     err = snd_pcm_hw_params_set_channels( _soundDevice, hw_params, 2 );
   114     if ( err < 0 ) {
   115         ERROR( "Init: cannot set channel count (%s)\n", snd_strerror( err ) );
   116         return FALSE;
   117     }
   119     // frames = 4410;
   120     // snd_pcm_hw_params_set_period_size_near( _soundDevice, hw_params, &frames,
   121     //                                     &dir );
   123     // Apply the hardware parameters that we've set.
   124     err = snd_pcm_hw_params( _soundDevice, hw_params );
   125     if ( err < 0 ) {
   126         DEBUG( "Init: cannot set parameters (%s)\n", snd_strerror( err ) );
   127         return FALSE;
   128     } else {
   129         DEBUG( "Audio device parameters have been set successfully." );
   130     }
   132     snd_pcm_hw_params_get_period_size( hw_params, &frames, &dir );
   133     DEBUG( "period size = %d\n", frames );
   135     // Get the buffer size.
   136     snd_pcm_hw_params_get_buffer_size( hw_params, &bufferSize );
   137     DEBUG("Buffer Size = %d\n", bufferSize);
   139     // If we were going to do more with our sound device we would want to store
   140     // the buffer size so we know how much data we will need to fill it with.
   142     //cout << "Init: Buffer size = " << bufferSize << " frames." << endl;
   144     // Display the bit size of samples.
   145     //cout << "Init: Significant bits for linear samples = " << snd_pcm_hw_params_get_sbits(hw_params) << endl;
   147     // Free the hardware parameters now that we're done with them.
   148     snd_pcm_hw_params_free( hw_params );
   150     // Set the start threshold to reduce inter-buffer gaps
   151     snd_pcm_sw_params_alloca( &sw_params );
   152     snd_pcm_sw_params_current( _soundDevice, sw_params );
   153     snd_pcm_sw_params_set_start_threshold( _soundDevice, sw_params, bufferSize/2 );
   154     err = snd_pcm_sw_params( _soundDevice, sw_params );
   155     if( err < 0 ) {
   156 	ERROR("Unable to set sw params for alsa driver: %s\n", snd_strerror(err));
   157 	return FALSE;
   158     } 
   160     err = snd_pcm_prepare( _soundDevice );
   161     if ( err < 0 ) {
   162         ERROR( "Init: cannot prepare audio interface for use (%s)\n",
   163                snd_strerror( err ) );
   164         return FALSE;
   165     }
   166     return TRUE;
   167 }
   169 gboolean audio_alsa_process_buffer( audio_buffer_t buffer )
   170 {
   171     int err;
   172     int length;
   175     length = buffer->length / frame_bytes;
   177     err = snd_pcm_writei( _soundDevice, buffer->data, length );
   178     if( err == -EPIPE ) {
   179 	snd_pcm_prepare( _soundDevice );
   180     } else if( err == -ESTRPIPE ) {
   181 	snd_pcm_resume( _soundDevice );
   182     }
   184     return TRUE;
   185 }
   188 gboolean audio_alsa_close(  )
   189 {
   190     int err;
   192     return TRUE;
   193 }
   197 struct audio_driver audio_alsa_driver = { 
   198     "alsa",
   199     audio_alsa_init,
   200     audio_alsa_set_format,
   201     audio_alsa_process_buffer,
   202     audio_alsa_close
   203 };
.