filename | src/drivers/audio_alsa.c |
changeset | 643:653b0a70f173 |
next | 669:ab344e42bca9 |
author | bhaal22 |
date | Tue Feb 26 01:10:48 2008 +0000 (16 years ago) |
permissions | -rwxr-xr-x |
last change | Commit initial ALSA audio driver Add init/shutdown stubs to audio driver structure |
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 };
.