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