filename | src/drivers/audio_alsa.c |
changeset | 880:214979b3bc80 |
prev | 806:6ef1ce4a9dbc |
next | 1021:848db285a184 |
author | nkeynes |
date | Thu Jan 15 04:15:11 2009 +0000 (15 years ago) |
permissions | -rwxr-xr-x |
last change | Add support for the Intel ICC compiler (C only, icc doesn't support Obj-C) - Rename Obj-C source to .m - Separate paths.c into paths_unix.c and paths_osx.m - Add configuration detection of ICC, along with specific opt flags |
file | annotate | diff | log | raw |
bhaal22@643 | 1 | /** |
bhaal22@643 | 2 | * $Id: audio_esd.c 602 2008-01-15 20:50:23Z nkeynes $ |
bhaal22@643 | 3 | * |
bhaal22@643 | 4 | * The asla audio driver |
bhaal22@643 | 5 | * |
bhaal22@643 | 6 | * Copyright (c) 2008 Jonathan Muller |
bhaal22@643 | 7 | * |
bhaal22@643 | 8 | * This program is free software; you can redistribute it and/or modify |
bhaal22@643 | 9 | * it under the terms of the GNU General Public License as published by |
bhaal22@643 | 10 | * the Free Software Foundation; either version 2 of the License, or |
bhaal22@643 | 11 | * (at your option) any later version. |
bhaal22@643 | 12 | * |
bhaal22@643 | 13 | * This program is distributed in the hope that it will be useful, |
bhaal22@643 | 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
bhaal22@643 | 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
bhaal22@643 | 16 | * GNU General Public License for more details. |
bhaal22@643 | 17 | */ |
bhaal22@643 | 18 | #include <stdio.h> |
bhaal22@643 | 19 | #include <unistd.h> |
bhaal22@643 | 20 | |
bhaal22@643 | 21 | /* Use the newer ALSA API */ |
bhaal22@643 | 22 | #define ALSA_PCM_NEW_HW_PARAMS_API |
bhaal22@643 | 23 | |
bhaal22@643 | 24 | #include <alsa/asoundlib.h> |
bhaal22@643 | 25 | #include "config.h" |
bhaal22@643 | 26 | #include "aica/audio.h" |
bhaal22@643 | 27 | #include "dream.h" |
bhaal22@643 | 28 | |
bhaal22@643 | 29 | |
bhaal22@643 | 30 | static snd_pcm_t *_soundDevice = NULL; |
bhaal22@643 | 31 | static int frame_bytes; |
bhaal22@643 | 32 | |
bhaal22@643 | 33 | |
bhaal22@643 | 34 | struct lxdream_config_entry alsa_config[] = { |
nkeynes@736 | 35 | {"device", N_("Audio output device"), CONFIG_TYPE_FILE, "default"}, |
nkeynes@736 | 36 | {NULL, CONFIG_TYPE_NONE} |
bhaal22@643 | 37 | }; |
bhaal22@643 | 38 | |
bhaal22@643 | 39 | |
bhaal22@643 | 40 | gboolean audio_alsa_init( ) |
bhaal22@643 | 41 | { |
bhaal22@643 | 42 | int err; |
bhaal22@643 | 43 | snd_pcm_hw_params_t *hw_params; |
bhaal22@643 | 44 | snd_pcm_sw_params_t *sw_params; |
bhaal22@643 | 45 | snd_pcm_uframes_t frames; |
bhaal22@643 | 46 | snd_pcm_uframes_t bufferSize; |
nkeynes@806 | 47 | unsigned int rate = DEFAULT_SAMPLE_RATE; |
nkeynes@697 | 48 | int format = DEFAULT_SAMPLE_FORMAT; |
bhaal22@643 | 49 | int dir; |
bhaal22@643 | 50 | |
bhaal22@643 | 51 | |
bhaal22@643 | 52 | // Open the device we were told to open. |
bhaal22@643 | 53 | err = snd_pcm_open( &_soundDevice, alsa_config[0].value, |
nkeynes@736 | 54 | SND_PCM_STREAM_PLAYBACK, 0 ); |
bhaal22@643 | 55 | |
bhaal22@643 | 56 | // Check for error on open. |
bhaal22@643 | 57 | if ( err < 0 ) { |
bhaal22@643 | 58 | ERROR( "Init: cannot open audio device %s (%s)\n", |
nkeynes@736 | 59 | alsa_config[0].value, snd_strerror( err ) ); |
bhaal22@643 | 60 | return FALSE; |
bhaal22@643 | 61 | } else { |
bhaal22@643 | 62 | DEBUG( "Audio device opened successfully." ); |
bhaal22@643 | 63 | } |
bhaal22@643 | 64 | |
bhaal22@643 | 65 | frame_bytes = ( 2 * ( snd_pcm_format_width( SND_PCM_FORMAT_S16_LE ) / 8 ) ); |
bhaal22@643 | 66 | |
bhaal22@643 | 67 | |
bhaal22@643 | 68 | //snd_pcm_hw_params_alloca (&hw_params); |
bhaal22@643 | 69 | // Allocate the hardware parameter structure. |
bhaal22@643 | 70 | if ( ( err = snd_pcm_hw_params_malloc( &hw_params ) ) < 0 ) { |
bhaal22@643 | 71 | ERROR( "Init: cannot allocate hardware parameter structure (%s)\n", |
nkeynes@736 | 72 | snd_strerror( err ) ); |
bhaal22@643 | 73 | return FALSE; |
bhaal22@643 | 74 | } |
bhaal22@643 | 75 | |
bhaal22@643 | 76 | if ( ( err = snd_pcm_hw_params_any( _soundDevice, hw_params ) ) < 0 ) { |
bhaal22@643 | 77 | ERROR( "Init: cannot allocate hardware parameter structure (%s)\n", |
nkeynes@736 | 78 | snd_strerror( err ) ); |
bhaal22@643 | 79 | return FALSE; |
bhaal22@643 | 80 | } |
bhaal22@643 | 81 | // Set access to RW interleaved. |
bhaal22@643 | 82 | if ( ( err = snd_pcm_hw_params_set_access( _soundDevice, hw_params, |
nkeynes@736 | 83 | SND_PCM_ACCESS_RW_INTERLEAVED ) ) |
nkeynes@736 | 84 | < 0 ) { |
bhaal22@643 | 85 | ERROR( " Init: cannot set access type (%s)\n", snd_strerror( err ) ); |
bhaal22@643 | 86 | return FALSE; |
bhaal22@643 | 87 | } |
bhaal22@643 | 88 | |
bhaal22@643 | 89 | if ( ( err = snd_pcm_hw_params_set_format( _soundDevice, hw_params, |
nkeynes@736 | 90 | SND_PCM_FORMAT_S16_LE ) ) < |
nkeynes@736 | 91 | 0 ) { |
bhaal22@643 | 92 | ERROR( "Init: cannot set sample format (%s)\n", snd_strerror( err ) ); |
bhaal22@643 | 93 | return FALSE; |
bhaal22@643 | 94 | } |
bhaal22@643 | 95 | |
bhaal22@643 | 96 | err = snd_pcm_hw_params_set_rate_near( _soundDevice, hw_params, &rate, 0 ); |
bhaal22@643 | 97 | if ( err < 0 ) { |
bhaal22@643 | 98 | ERROR( "Init: Resampling setup failed for playback: %s\n", |
nkeynes@736 | 99 | snd_strerror( err ) ); |
bhaal22@643 | 100 | return err; |
bhaal22@643 | 101 | } |
bhaal22@643 | 102 | // Set channels to stereo (2). |
bhaal22@643 | 103 | err = snd_pcm_hw_params_set_channels( _soundDevice, hw_params, 2 ); |
bhaal22@643 | 104 | if ( err < 0 ) { |
bhaal22@643 | 105 | ERROR( "Init: cannot set channel count (%s)\n", snd_strerror( err ) ); |
bhaal22@643 | 106 | return FALSE; |
bhaal22@643 | 107 | } |
bhaal22@643 | 108 | |
bhaal22@643 | 109 | // frames = 4410; |
bhaal22@643 | 110 | // snd_pcm_hw_params_set_period_size_near( _soundDevice, hw_params, &frames, |
bhaal22@643 | 111 | // &dir ); |
bhaal22@643 | 112 | |
bhaal22@643 | 113 | // Apply the hardware parameters that we've set. |
bhaal22@643 | 114 | err = snd_pcm_hw_params( _soundDevice, hw_params ); |
bhaal22@643 | 115 | if ( err < 0 ) { |
bhaal22@643 | 116 | DEBUG( "Init: cannot set parameters (%s)\n", snd_strerror( err ) ); |
bhaal22@643 | 117 | return FALSE; |
bhaal22@643 | 118 | } else { |
bhaal22@643 | 119 | DEBUG( "Audio device parameters have been set successfully." ); |
bhaal22@643 | 120 | } |
bhaal22@643 | 121 | |
bhaal22@643 | 122 | snd_pcm_hw_params_get_period_size( hw_params, &frames, &dir ); |
bhaal22@643 | 123 | DEBUG( "period size = %d\n", frames ); |
bhaal22@643 | 124 | |
bhaal22@643 | 125 | // Get the buffer size. |
bhaal22@643 | 126 | snd_pcm_hw_params_get_buffer_size( hw_params, &bufferSize ); |
bhaal22@643 | 127 | DEBUG("Buffer Size = %d\n", bufferSize); |
bhaal22@643 | 128 | |
bhaal22@643 | 129 | // If we were going to do more with our sound device we would want to store |
bhaal22@643 | 130 | // the buffer size so we know how much data we will need to fill it with. |
bhaal22@643 | 131 | |
bhaal22@643 | 132 | //cout << "Init: Buffer size = " << bufferSize << " frames." << endl; |
bhaal22@643 | 133 | |
bhaal22@643 | 134 | // Display the bit size of samples. |
bhaal22@643 | 135 | //cout << "Init: Significant bits for linear samples = " << snd_pcm_hw_params_get_sbits(hw_params) << endl; |
bhaal22@643 | 136 | |
bhaal22@643 | 137 | // Free the hardware parameters now that we're done with them. |
bhaal22@643 | 138 | snd_pcm_hw_params_free( hw_params ); |
bhaal22@643 | 139 | |
bhaal22@643 | 140 | // Set the start threshold to reduce inter-buffer gaps |
bhaal22@643 | 141 | snd_pcm_sw_params_alloca( &sw_params ); |
bhaal22@643 | 142 | snd_pcm_sw_params_current( _soundDevice, sw_params ); |
nkeynes@880 | 143 | snd_pcm_sw_params_set_start_threshold( _soundDevice, sw_params, bufferSize ); |
bhaal22@643 | 144 | err = snd_pcm_sw_params( _soundDevice, sw_params ); |
bhaal22@643 | 145 | if( err < 0 ) { |
nkeynes@736 | 146 | ERROR("Unable to set sw params for alsa driver: %s\n", snd_strerror(err)); |
nkeynes@736 | 147 | return FALSE; |
bhaal22@643 | 148 | } |
bhaal22@643 | 149 | |
bhaal22@643 | 150 | err = snd_pcm_prepare( _soundDevice ); |
bhaal22@643 | 151 | if ( err < 0 ) { |
bhaal22@643 | 152 | ERROR( "Init: cannot prepare audio interface for use (%s)\n", |
nkeynes@736 | 153 | snd_strerror( err ) ); |
bhaal22@643 | 154 | return FALSE; |
bhaal22@643 | 155 | } |
bhaal22@643 | 156 | return TRUE; |
bhaal22@643 | 157 | } |
bhaal22@643 | 158 | |
bhaal22@643 | 159 | gboolean audio_alsa_process_buffer( audio_buffer_t buffer ) |
bhaal22@643 | 160 | { |
bhaal22@643 | 161 | int err; |
bhaal22@643 | 162 | int length; |
bhaal22@643 | 163 | |
bhaal22@643 | 164 | |
bhaal22@643 | 165 | length = buffer->length / frame_bytes; |
bhaal22@643 | 166 | |
bhaal22@643 | 167 | err = snd_pcm_writei( _soundDevice, buffer->data, length ); |
bhaal22@643 | 168 | if( err == -EPIPE ) { |
nkeynes@736 | 169 | snd_pcm_prepare( _soundDevice ); |
bhaal22@643 | 170 | } else if( err == -ESTRPIPE ) { |
nkeynes@736 | 171 | snd_pcm_resume( _soundDevice ); |
bhaal22@643 | 172 | } |
bhaal22@643 | 173 | |
bhaal22@643 | 174 | return TRUE; |
bhaal22@643 | 175 | } |
bhaal22@643 | 176 | |
bhaal22@643 | 177 | |
nkeynes@697 | 178 | gboolean audio_alsa_shutdown( ) |
bhaal22@643 | 179 | { |
bhaal22@643 | 180 | return TRUE; |
bhaal22@643 | 181 | } |
bhaal22@643 | 182 | |
bhaal22@643 | 183 | |
bhaal22@643 | 184 | |
bhaal22@643 | 185 | struct audio_driver audio_alsa_driver = { |
nkeynes@736 | 186 | "alsa", |
nkeynes@736 | 187 | N_("Linux ALSA system driver"), |
nkeynes@736 | 188 | DEFAULT_SAMPLE_RATE, |
nkeynes@736 | 189 | DEFAULT_SAMPLE_FORMAT, |
nkeynes@736 | 190 | audio_alsa_init, |
nkeynes@736 | 191 | NULL, |
nkeynes@736 | 192 | audio_alsa_process_buffer, |
nkeynes@736 | 193 | NULL, |
nkeynes@736 | 194 | audio_alsa_shutdown |
bhaal22@643 | 195 | }; |
.