filename | src/drivers/audio_alsa.c |
changeset | 1073:92dfe34665ed |
prev | 1024:c67f2d61ab97 |
author | nkeynes |
date | Tue Feb 28 18:22:52 2012 +1000 (12 years ago) |
permissions | -rwxr-xr-x |
last change | Add a GL-only video driver for android usage (since the Java code is responsible for creating the context) |
view | annotate | diff | log | raw |
1 /**
2 * $Id$
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 static struct lxdream_config_group alsa_config = {
35 "alsa", NULL, NULL, NULL,
36 {{"device", N_("Audio output device"), CONFIG_TYPE_FILE, "default"},
37 {NULL, CONFIG_TYPE_NONE}} };
40 static 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.params[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.params[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 static 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 static gboolean audio_alsa_shutdown( )
179 {
180 return TRUE;
181 }
185 static struct audio_driver audio_alsa_driver = {
186 "alsa",
187 N_("Linux ALSA system driver"),
188 40,
189 DEFAULT_SAMPLE_RATE,
190 DEFAULT_SAMPLE_FORMAT,
191 audio_alsa_init,
192 NULL,
193 audio_alsa_process_buffer,
194 NULL,
195 audio_alsa_shutdown
196 };
198 static gboolean audio_alsa_static_init( void )
199 {
200 lxdream_register_config_group( "alsa", &alsa_config );
201 audio_register_driver( &audio_alsa_driver );
202 return TRUE;
203 }
205 DEFINE_PLUGIN( PLUGIN_AUDIO_DRIVER, "alsa", audio_alsa_static_init );
.