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 669:ab344e42bca9
prev643:653b0a70f173
next697:479b8c213f61
author nkeynes
date Mon May 12 10:00:13 2008 +0000 (13 years ago)
permissions -rwxr-xr-x
last change Cleanup most of the -Wall warnings (getting a bit sloppy...)
Convert FP code to use fixed banks rather than indirect pointer
(3-4% faster this way now)
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", CONFIG_TYPE_FILE, "default"},
    36     {NULL, CONFIG_TYPE_NONE}
    37 };
    40 gboolean audio_alsa_init(  )
    41 {
    42     return TRUE;
    43 }
    46 gboolean audio_alsa_set_format( uint32_t rate, uint32_t format )
    47 {
    48     int err;
    49     snd_pcm_hw_params_t *hw_params;
    50     snd_pcm_sw_params_t *sw_params;
    51     snd_pcm_uframes_t frames;
    52     snd_pcm_uframes_t bufferSize;
    53     int dir;
    56     // Open the device we were told to open.
    57     err = snd_pcm_open( &_soundDevice, alsa_config[0].value,
    58                         SND_PCM_STREAM_PLAYBACK, 0 );
    60     // Check for error on open.
    61     if ( err < 0 ) {
    62         ERROR( "Init: cannot open audio device %s (%s)\n",
    63                alsa_config[0].value, snd_strerror( err ) );
    64         return FALSE;
    65     } else {
    66         DEBUG( "Audio device opened successfully." );
    67     }
    69     frame_bytes = ( 2 * ( snd_pcm_format_width( SND_PCM_FORMAT_S16_LE ) / 8 ) );
    72     //snd_pcm_hw_params_alloca (&hw_params);
    73     // Allocate the hardware parameter structure.
    74     if ( ( err = snd_pcm_hw_params_malloc( &hw_params ) ) < 0 ) {
    75         ERROR( "Init: cannot allocate hardware parameter structure (%s)\n",
    76                snd_strerror( err ) );
    77         return FALSE;
    78     }
    80     if ( ( err = snd_pcm_hw_params_any( _soundDevice, hw_params ) ) < 0 ) {
    81         ERROR( "Init: cannot allocate hardware parameter structure (%s)\n",
    82                snd_strerror( err ) );
    83         return FALSE;
    84     }
    85     // Set access to RW interleaved.
    86     if ( ( err = snd_pcm_hw_params_set_access( _soundDevice, hw_params,
    87                                                SND_PCM_ACCESS_RW_INTERLEAVED ) )
    88          < 0 ) {
    89         ERROR( " Init: cannot set access type (%s)\n", snd_strerror( err ) );
    90         return FALSE;
    91     }
    93     if ( ( err = snd_pcm_hw_params_set_format( _soundDevice, hw_params,
    94                                                SND_PCM_FORMAT_S16_LE ) ) <
    95          0 ) {
    96         ERROR( "Init: cannot set sample format (%s)\n", snd_strerror( err ) );
    97         return FALSE;
    98     }
   100     err = snd_pcm_hw_params_set_rate_near( _soundDevice, hw_params, &rate, 0 );
   101     if ( err < 0 ) {
   102         ERROR( "Init: Resampling setup failed for playback: %s\n",
   103                snd_strerror( err ) );
   104         return err;
   105     }
   106     // Set channels to stereo (2).
   107     err = snd_pcm_hw_params_set_channels( _soundDevice, hw_params, 2 );
   108     if ( err < 0 ) {
   109         ERROR( "Init: cannot set channel count (%s)\n", snd_strerror( err ) );
   110         return FALSE;
   111     }
   113     // frames = 4410;
   114     // snd_pcm_hw_params_set_period_size_near( _soundDevice, hw_params, &frames,
   115     //                                     &dir );
   117     // Apply the hardware parameters that we've set.
   118     err = snd_pcm_hw_params( _soundDevice, hw_params );
   119     if ( err < 0 ) {
   120         DEBUG( "Init: cannot set parameters (%s)\n", snd_strerror( err ) );
   121         return FALSE;
   122     } else {
   123         DEBUG( "Audio device parameters have been set successfully." );
   124     }
   126     snd_pcm_hw_params_get_period_size( hw_params, &frames, &dir );
   127     DEBUG( "period size = %d\n", frames );
   129     // Get the buffer size.
   130     snd_pcm_hw_params_get_buffer_size( hw_params, &bufferSize );
   131     DEBUG("Buffer Size = %d\n", bufferSize);
   133     // If we were going to do more with our sound device we would want to store
   134     // the buffer size so we know how much data we will need to fill it with.
   136     //cout << "Init: Buffer size = " << bufferSize << " frames." << endl;
   138     // Display the bit size of samples.
   139     //cout << "Init: Significant bits for linear samples = " << snd_pcm_hw_params_get_sbits(hw_params) << endl;
   141     // Free the hardware parameters now that we're done with them.
   142     snd_pcm_hw_params_free( hw_params );
   144     // Set the start threshold to reduce inter-buffer gaps
   145     snd_pcm_sw_params_alloca( &sw_params );
   146     snd_pcm_sw_params_current( _soundDevice, sw_params );
   147     snd_pcm_sw_params_set_start_threshold( _soundDevice, sw_params, bufferSize/2 );
   148     err = snd_pcm_sw_params( _soundDevice, sw_params );
   149     if( err < 0 ) {
   150 	ERROR("Unable to set sw params for alsa driver: %s\n", snd_strerror(err));
   151 	return FALSE;
   152     } 
   154     err = snd_pcm_prepare( _soundDevice );
   155     if ( err < 0 ) {
   156         ERROR( "Init: cannot prepare audio interface for use (%s)\n",
   157                snd_strerror( err ) );
   158         return FALSE;
   159     }
   160     return TRUE;
   161 }
   163 gboolean audio_alsa_process_buffer( audio_buffer_t buffer )
   164 {
   165     int err;
   166     int length;
   169     length = buffer->length / frame_bytes;
   171     err = snd_pcm_writei( _soundDevice, buffer->data, length );
   172     if( err == -EPIPE ) {
   173 	snd_pcm_prepare( _soundDevice );
   174     } else if( err == -ESTRPIPE ) {
   175 	snd_pcm_resume( _soundDevice );
   176     }
   178     return TRUE;
   179 }
   182 gboolean audio_alsa_close(  )
   183 {
   184     return TRUE;
   185 }
   189 struct audio_driver audio_alsa_driver = { 
   190     "alsa",
   191     audio_alsa_init,
   192     audio_alsa_set_format,
   193     audio_alsa_process_buffer,
   194     audio_alsa_close
   195 };
.