Search
lxdream.org :: lxdream/src/drivers/audio_alsa.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/drivers/audio_alsa.c
changeset 643:653b0a70f173
next669:ab344e42bca9
author bhaal22
date Tue Feb 26 01:10:48 2008 +0000 (12 years ago)
permissions -rw-r--r--
last change Commit initial ALSA audio driver
Add init/shutdown stubs to audio driver structure
file annotate diff log raw
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/src/drivers/audio_alsa.c Tue Feb 26 01:10:48 2008 +0000
1.3 @@ -0,0 +1,203 @@
1.4 +/**
1.5 + * $Id: audio_esd.c 602 2008-01-15 20:50:23Z nkeynes $
1.6 + *
1.7 + * The asla audio driver
1.8 + *
1.9 + * Copyright (c) 2008 Jonathan Muller
1.10 + *
1.11 + * This program is free software; you can redistribute it and/or modify
1.12 + * it under the terms of the GNU General Public License as published by
1.13 + * the Free Software Foundation; either version 2 of the License, or
1.14 + * (at your option) any later version.
1.15 + *
1.16 + * This program is distributed in the hope that it will be useful,
1.17 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.19 + * GNU General Public License for more details.
1.20 + */
1.21 +#include <stdio.h>
1.22 +#include <unistd.h>
1.23 +
1.24 +/* Use the newer ALSA API */
1.25 +#define ALSA_PCM_NEW_HW_PARAMS_API
1.26 +
1.27 +#include <alsa/asoundlib.h>
1.28 +#include "config.h"
1.29 +#include "aica/audio.h"
1.30 +#include "dream.h"
1.31 +
1.32 +
1.33 +static snd_pcm_t *_soundDevice = NULL;
1.34 +static int frames;
1.35 +static int frame_bytes;
1.36 +
1.37 +
1.38 +struct lxdream_config_entry alsa_config[] = {
1.39 + {"device", CONFIG_TYPE_FILE, "default"},
1.40 + {NULL, CONFIG_TYPE_NONE}
1.41 +};
1.42 +
1.43 +
1.44 +gboolean audio_alsa_init( )
1.45 +{
1.46 + int err;
1.47 +
1.48 + return TRUE;
1.49 +}
1.50 +
1.51 +
1.52 +gboolean audio_alsa_set_format( uint32_t rate, uint32_t format )
1.53 +{
1.54 + int i;
1.55 + int err;
1.56 + snd_pcm_hw_params_t *hw_params;
1.57 + snd_pcm_sw_params_t *sw_params;
1.58 + snd_pcm_uframes_t frames;
1.59 + unsigned int resample = 1;
1.60 + unsigned int actualRate = rate;
1.61 + snd_pcm_uframes_t bufferSize;
1.62 + int dir;
1.63 +
1.64 +
1.65 + // Open the device we were told to open.
1.66 + err = snd_pcm_open( &_soundDevice, alsa_config[0].value,
1.67 + SND_PCM_STREAM_PLAYBACK, 0 );
1.68 +
1.69 + // Check for error on open.
1.70 + if ( err < 0 ) {
1.71 + ERROR( "Init: cannot open audio device %s (%s)\n",
1.72 + alsa_config[0].value, snd_strerror( err ) );
1.73 + return FALSE;
1.74 + } else {
1.75 + DEBUG( "Audio device opened successfully." );
1.76 + }
1.77 +
1.78 + frame_bytes = ( 2 * ( snd_pcm_format_width( SND_PCM_FORMAT_S16_LE ) / 8 ) );
1.79 +
1.80 +
1.81 + //snd_pcm_hw_params_alloca (&hw_params);
1.82 + // Allocate the hardware parameter structure.
1.83 + if ( ( err = snd_pcm_hw_params_malloc( &hw_params ) ) < 0 ) {
1.84 + ERROR( "Init: cannot allocate hardware parameter structure (%s)\n",
1.85 + snd_strerror( err ) );
1.86 + return FALSE;
1.87 + }
1.88 +
1.89 + if ( ( err = snd_pcm_hw_params_any( _soundDevice, hw_params ) ) < 0 ) {
1.90 + ERROR( "Init: cannot allocate hardware parameter structure (%s)\n",
1.91 + snd_strerror( err ) );
1.92 + return FALSE;
1.93 + }
1.94 + // Set access to RW interleaved.
1.95 + if ( ( err = snd_pcm_hw_params_set_access( _soundDevice, hw_params,
1.96 + SND_PCM_ACCESS_RW_INTERLEAVED ) )
1.97 + < 0 ) {
1.98 + ERROR( " Init: cannot set access type (%s)\n", snd_strerror( err ) );
1.99 + return FALSE;
1.100 + }
1.101 +
1.102 + if ( ( err = snd_pcm_hw_params_set_format( _soundDevice, hw_params,
1.103 + SND_PCM_FORMAT_S16_LE ) ) <
1.104 + 0 ) {
1.105 + ERROR( "Init: cannot set sample format (%s)\n", snd_strerror( err ) );
1.106 + return FALSE;
1.107 + }
1.108 +
1.109 + err = snd_pcm_hw_params_set_rate_near( _soundDevice, hw_params, &rate, 0 );
1.110 + if ( err < 0 ) {
1.111 + ERROR( "Init: Resampling setup failed for playback: %s\n",
1.112 + snd_strerror( err ) );
1.113 + return err;
1.114 + }
1.115 + // Set channels to stereo (2).
1.116 + err = snd_pcm_hw_params_set_channels( _soundDevice, hw_params, 2 );
1.117 + if ( err < 0 ) {
1.118 + ERROR( "Init: cannot set channel count (%s)\n", snd_strerror( err ) );
1.119 + return FALSE;
1.120 + }
1.121 +
1.122 + // frames = 4410;
1.123 + // snd_pcm_hw_params_set_period_size_near( _soundDevice, hw_params, &frames,
1.124 + // &dir );
1.125 +
1.126 + // Apply the hardware parameters that we've set.
1.127 + err = snd_pcm_hw_params( _soundDevice, hw_params );
1.128 + if ( err < 0 ) {
1.129 + DEBUG( "Init: cannot set parameters (%s)\n", snd_strerror( err ) );
1.130 + return FALSE;
1.131 + } else {
1.132 + DEBUG( "Audio device parameters have been set successfully." );
1.133 + }
1.134 +
1.135 + snd_pcm_hw_params_get_period_size( hw_params, &frames, &dir );
1.136 + DEBUG( "period size = %d\n", frames );
1.137 +
1.138 + // Get the buffer size.
1.139 + snd_pcm_hw_params_get_buffer_size( hw_params, &bufferSize );
1.140 + DEBUG("Buffer Size = %d\n", bufferSize);
1.141 +
1.142 + // If we were going to do more with our sound device we would want to store
1.143 + // the buffer size so we know how much data we will need to fill it with.
1.144 +
1.145 + //cout << "Init: Buffer size = " << bufferSize << " frames." << endl;
1.146 +
1.147 + // Display the bit size of samples.
1.148 + //cout << "Init: Significant bits for linear samples = " << snd_pcm_hw_params_get_sbits(hw_params) << endl;
1.149 +
1.150 + // Free the hardware parameters now that we're done with them.
1.151 + snd_pcm_hw_params_free( hw_params );
1.152 +
1.153 + // Set the start threshold to reduce inter-buffer gaps
1.154 + snd_pcm_sw_params_alloca( &sw_params );
1.155 + snd_pcm_sw_params_current( _soundDevice, sw_params );
1.156 + snd_pcm_sw_params_set_start_threshold( _soundDevice, sw_params, bufferSize/2 );
1.157 + err = snd_pcm_sw_params( _soundDevice, sw_params );
1.158 + if( err < 0 ) {
1.159 + ERROR("Unable to set sw params for alsa driver: %s\n", snd_strerror(err));
1.160 + return FALSE;
1.161 + }
1.162 +
1.163 + err = snd_pcm_prepare( _soundDevice );
1.164 + if ( err < 0 ) {
1.165 + ERROR( "Init: cannot prepare audio interface for use (%s)\n",
1.166 + snd_strerror( err ) );
1.167 + return FALSE;
1.168 + }
1.169 + return TRUE;
1.170 +}
1.171 +
1.172 +gboolean audio_alsa_process_buffer( audio_buffer_t buffer )
1.173 +{
1.174 + int err;
1.175 + int length;
1.176 +
1.177 +
1.178 + length = buffer->length / frame_bytes;
1.179 +
1.180 + err = snd_pcm_writei( _soundDevice, buffer->data, length );
1.181 + if( err == -EPIPE ) {
1.182 + snd_pcm_prepare( _soundDevice );
1.183 + } else if( err == -ESTRPIPE ) {
1.184 + snd_pcm_resume( _soundDevice );
1.185 + }
1.186 +
1.187 + return TRUE;
1.188 +}
1.189 +
1.190 +
1.191 +gboolean audio_alsa_close( )
1.192 +{
1.193 + int err;
1.194 +
1.195 + return TRUE;
1.196 +}
1.197 +
1.198 +
1.199 +
1.200 +struct audio_driver audio_alsa_driver = {
1.201 + "alsa",
1.202 + audio_alsa_init,
1.203 + audio_alsa_set_format,
1.204 + audio_alsa_process_buffer,
1.205 + audio_alsa_close
1.206 +};
.