Search
lxdream.org :: lxdream/src/aica/audio.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/aica/audio.c
changeset 697:479b8c213f61
prev657:c4143facbfcb
next700:4650d0c7f6f9
author nkeynes
date Sun Jun 22 04:01:27 2008 +0000 (12 years ago)
permissions -rw-r--r--
last change Commit work-in-progress CoreAudio driver
(along with various changes to the audio subsystem)
file annotate diff log raw
1.1 --- a/src/aica/audio.c Wed Apr 16 10:12:12 2008 +0000
1.2 +++ b/src/aica/audio.c Sun Jun 22 04:01:27 2008 +0000
1.3 @@ -24,21 +24,31 @@
1.4 #include <assert.h>
1.5 #include <string.h>
1.6
1.7 -audio_driver_t audio_driver_list[] = {
1.8 +
1.9 +extern struct audio_driver audio_null_driver;
1.10 +extern struct audio_driver audio_osx_driver;
1.11 +extern struct audio_driver audio_pulse_driver;
1.12 +extern struct audio_driver audio_esd_driver;
1.13 +extern struct audio_driver audio_alsa_driver;
1.14 +
1.15 +audio_driver_t audio_driver_list[] = {
1.16 +#ifdef HAVE_CORE_AUDIO
1.17 + &audio_osx_driver,
1.18 +#endif
1.19 #ifdef HAVE_PULSE
1.20 - &audio_pulse_driver,
1.21 + &audio_pulse_driver,
1.22 #endif
1.23 #ifdef HAVE_ESOUND
1.24 - &audio_esd_driver,
1.25 + &audio_esd_driver,
1.26 #endif
1.27 #ifdef HAVE_ALSA
1.28 - &audio_alsa_driver,
1.29 + &audio_alsa_driver,
1.30 #endif
1.31 - &audio_null_driver,
1.32 - NULL };
1.33 + &audio_null_driver,
1.34 + NULL };
1.35
1.36 #define NUM_BUFFERS 3
1.37 -#define MS_PER_BUFFER 100
1.38 +#define MS_PER_BUFFER 1000
1.39
1.40 #define BUFFER_EMPTY 0
1.41 #define BUFFER_WRITING 1
1.42 @@ -78,57 +88,79 @@
1.43 {
1.44 int i;
1.45 if( name == NULL ) {
1.46 - return audio_driver_list[0];
1.47 + return audio_driver_list[0];
1.48 }
1.49 for( i=0; audio_driver_list[i] != NULL; i++ ) {
1.50 - if( strcasecmp( audio_driver_list[i]->name, name ) == 0 ) {
1.51 - return audio_driver_list[i];
1.52 - }
1.53 + if( strcasecmp( audio_driver_list[i]->name, name ) == 0 ) {
1.54 + return audio_driver_list[i];
1.55 + }
1.56 }
1.57
1.58 return NULL;
1.59 }
1.60
1.61 +audio_driver_t audio_init_driver( const char *preferred_driver )
1.62 +{
1.63 + audio_driver_t audio_driver = get_audio_driver_by_name(preferred_driver);
1.64 + if( audio_driver == NULL ) {
1.65 + ERROR( "Audio driver '%s' not found, aborting.", preferred_driver );
1.66 + exit(2);
1.67 + } else if( audio_set_driver( audio_driver ) == FALSE ) {
1.68 + ERROR( "Failed to initialize audio driver '%s', using null driver",
1.69 + audio_driver->name );
1.70 + audio_set_driver( &audio_null_driver );
1.71 + }
1.72 +}
1.73 +
1.74 /**
1.75 * Set the output driver, sample rate and format. Also initializes the
1.76 * output buffers, flushing any current data and reallocating as
1.77 * necessary.
1.78 */
1.79 -gboolean audio_set_driver( audio_driver_t driver,
1.80 - uint32_t samplerate, int format )
1.81 +gboolean audio_set_driver( audio_driver_t driver )
1.82 {
1.83 uint32_t bytes_per_sample = 1;
1.84 uint32_t samples_per_buffer;
1.85 int i;
1.86
1.87 if( audio_driver == NULL || driver != NULL ) {
1.88 - if( driver == NULL )
1.89 - driver = &audio_null_driver;
1.90 - if( driver != audio_driver ) {
1.91 - if( !driver->set_output_format( samplerate, format ) )
1.92 - return FALSE;
1.93 - audio_driver = driver;
1.94 - }
1.95 + if( driver == NULL )
1.96 + driver = &audio_null_driver;
1.97 + if( driver != audio_driver ) {
1.98 + if( !driver->init() )
1.99 + return FALSE;
1.100 + audio_driver = driver;
1.101 + }
1.102 }
1.103
1.104 - if( format & AUDIO_FMT_16BIT )
1.105 - bytes_per_sample = 2;
1.106 - if( format & AUDIO_FMT_STEREO )
1.107 - bytes_per_sample <<= 1;
1.108 - if( samplerate == audio.output_rate &&
1.109 - bytes_per_sample == audio.output_sample_size )
1.110 - return TRUE;
1.111 - samples_per_buffer = (samplerate * MS_PER_BUFFER / 1000);
1.112 + switch( driver->sample_format & AUDIO_FMT_SAMPLE_MASK ) {
1.113 + case AUDIO_FMT_8BIT:
1.114 + bytes_per_sample = 1;
1.115 + break;
1.116 + case AUDIO_FMT_16BIT:
1.117 + bytes_per_sample = 2;
1.118 + break;
1.119 + case AUDIO_FMT_FLOAT:
1.120 + bytes_per_sample = 4;
1.121 + break;
1.122 + }
1.123 +
1.124 + if( driver->sample_format & AUDIO_FMT_STEREO )
1.125 + bytes_per_sample <<= 1;
1.126 + if( driver->sample_rate == audio.output_rate &&
1.127 + bytes_per_sample == audio.output_sample_size )
1.128 + return TRUE;
1.129 + samples_per_buffer = (driver->sample_rate * MS_PER_BUFFER / 1000);
1.130 for( i=0; i<NUM_BUFFERS; i++ ) {
1.131 - if( audio.output_buffers[i] != NULL )
1.132 - free(audio.output_buffers[i]);
1.133 - audio.output_buffers[i] = g_malloc0( sizeof(struct audio_buffer) + samples_per_buffer * bytes_per_sample );
1.134 - audio.output_buffers[i]->length = samples_per_buffer * bytes_per_sample;
1.135 - audio.output_buffers[i]->posn = 0;
1.136 - audio.output_buffers[i]->status = BUFFER_EMPTY;
1.137 + if( audio.output_buffers[i] != NULL )
1.138 + free(audio.output_buffers[i]);
1.139 + audio.output_buffers[i] = g_malloc0( sizeof(struct audio_buffer) + samples_per_buffer * bytes_per_sample );
1.140 + audio.output_buffers[i]->length = samples_per_buffer * bytes_per_sample;
1.141 + audio.output_buffers[i]->posn = 0;
1.142 + audio.output_buffers[i]->status = BUFFER_EMPTY;
1.143 }
1.144 - audio.output_format = format;
1.145 - audio.output_rate = samplerate;
1.146 + audio.output_format = driver->sample_format;
1.147 + audio.output_rate = driver->sample_rate;
1.148 audio.output_sample_size = bytes_per_sample;
1.149 audio.write_buffer = 0;
1.150 audio.read_buffer = 0;
1.151 @@ -147,16 +179,17 @@
1.152 audio_buffer_t current = audio.output_buffers[audio.write_buffer];
1.153 current->status = BUFFER_FULL;
1.154 if( audio.read_buffer == audio.write_buffer &&
1.155 - audio_driver->process_buffer( current ) ) {
1.156 - audio_next_read_buffer();
1.157 + audio_driver->process_buffer( current ) ) {
1.158 + audio_next_read_buffer();
1.159 }
1.160 - audio.write_buffer = NEXT_BUFFER();
1.161 - result = audio.output_buffers[audio.write_buffer];
1.162 + int next_buffer = NEXT_BUFFER();
1.163 + result = audio.output_buffers[next_buffer];
1.164 if( result->status == BUFFER_FULL )
1.165 - return NULL;
1.166 + return NULL;
1.167 else {
1.168 - result->status = BUFFER_WRITING;
1.169 - return result;
1.170 + audio.write_buffer = next_buffer;
1.171 + result->status = BUFFER_WRITING;
1.172 + return result;
1.173 }
1.174 }
1.175
1.176 @@ -167,17 +200,24 @@
1.177 audio_buffer_t audio_next_read_buffer( )
1.178 {
1.179 audio_buffer_t current = audio.output_buffers[audio.read_buffer];
1.180 - assert( current->status == BUFFER_FULL );
1.181 - current->status = BUFFER_EMPTY;
1.182 - current->posn = 0;
1.183 - audio.read_buffer++;
1.184 - if( audio.read_buffer == NUM_BUFFERS )
1.185 - audio.read_buffer = 0;
1.186 -
1.187 - current = audio.output_buffers[audio.read_buffer];
1.188 - if( current->status == BUFFER_FULL )
1.189 - return current;
1.190 - else return NULL;
1.191 + if( current->status == BUFFER_FULL ) {
1.192 + // Current read buffer has data, which we've just emptied
1.193 + current->status = BUFFER_EMPTY;
1.194 + current->posn = 0;
1.195 + audio.read_buffer++;
1.196 + if( audio.read_buffer == NUM_BUFFERS )
1.197 + audio.read_buffer = 0;
1.198 +
1.199 + current = audio.output_buffers[audio.read_buffer];
1.200 + if( current->status == BUFFER_FULL ) {
1.201 + current->posn = 0;
1.202 + return current;
1.203 + }
1.204 + else return NULL;
1.205 + } else {
1.206 + return NULL;
1.207 + }
1.208 +
1.209 }
1.210
1.211 /*************************** ADPCM ***********************************/
1.212 @@ -232,124 +272,158 @@
1.213 memset( &result_buf, 0, sizeof(result_buf) );
1.214
1.215 for( i=0; i < AUDIO_CHANNEL_COUNT; i++ ) {
1.216 - audio_channel_t channel = &audio.channels[i];
1.217 - if( channel->active ) {
1.218 - int32_t sample;
1.219 - int vol_left = (channel->vol * (32 - channel->pan)) >> 5;
1.220 - int vol_right = (channel->vol * (channel->pan + 1)) >> 5;
1.221 - switch( channel->sample_format ) {
1.222 - case AUDIO_FMT_16BIT:
1.223 - for( j=0; j<num_samples; j++ ) {
1.224 - sample = ((int16_t *)(arm_mem + channel->start))[channel->posn];
1.225 - result_buf[j][0] += sample * vol_left;
1.226 - result_buf[j][1] += sample * vol_right;
1.227 -
1.228 - channel->posn_left += channel->sample_rate;
1.229 - while( channel->posn_left > audio.output_rate ) {
1.230 - channel->posn_left -= audio.output_rate;
1.231 - channel->posn++;
1.232 -
1.233 - if( channel->posn == channel->end ) {
1.234 - if( channel->loop ) {
1.235 - channel->posn = channel->loop_start;
1.236 - channel->loop = LOOP_LOOPED;
1.237 - } else {
1.238 - audio_stop_channel(i);
1.239 - j = num_samples;
1.240 - break;
1.241 - }
1.242 - }
1.243 - }
1.244 - }
1.245 - break;
1.246 - case AUDIO_FMT_8BIT:
1.247 - for( j=0; j<num_samples; j++ ) {
1.248 - sample = ((int8_t *)(arm_mem + channel->start))[channel->posn] << 8;
1.249 - result_buf[j][0] += sample * vol_left;
1.250 - result_buf[j][1] += sample * vol_right;
1.251 -
1.252 - channel->posn_left += channel->sample_rate;
1.253 - while( channel->posn_left > audio.output_rate ) {
1.254 - channel->posn_left -= audio.output_rate;
1.255 - channel->posn++;
1.256 -
1.257 - if( channel->posn == channel->end ) {
1.258 - if( channel->loop ) {
1.259 - channel->posn = channel->loop_start;
1.260 - channel->loop = LOOP_LOOPED;
1.261 - } else {
1.262 - audio_stop_channel(i);
1.263 - j = num_samples;
1.264 - break;
1.265 - }
1.266 - }
1.267 - }
1.268 - }
1.269 - break;
1.270 - case AUDIO_FMT_ADPCM:
1.271 - for( j=0; j<num_samples; j++ ) {
1.272 - sample = (int16_t)channel->adpcm_predict;
1.273 - result_buf[j][0] += sample * vol_left;
1.274 - result_buf[j][1] += sample * vol_right;
1.275 - channel->posn_left += channel->sample_rate;
1.276 - while( channel->posn_left > audio.output_rate ) {
1.277 - channel->posn_left -= audio.output_rate;
1.278 - channel->posn++;
1.279 - if( channel->posn == channel->end ) {
1.280 - if( channel->loop ) {
1.281 - channel->posn = channel->loop_start;
1.282 - channel->loop = LOOP_LOOPED;
1.283 - channel->adpcm_predict = 0;
1.284 - channel->adpcm_step = 0;
1.285 - } else {
1.286 - audio_stop_channel(i);
1.287 - j = num_samples;
1.288 - break;
1.289 - }
1.290 - }
1.291 - uint8_t data = ((uint8_t *)(arm_mem + channel->start))[channel->posn>>1];
1.292 - if( channel->posn&1 ) {
1.293 - adpcm_yamaha_decode_nibble( channel, (data >> 4) & 0x0F );
1.294 - } else {
1.295 - adpcm_yamaha_decode_nibble( channel, data & 0x0F );
1.296 - }
1.297 - }
1.298 - }
1.299 - break;
1.300 - default:
1.301 - break;
1.302 - }
1.303 - }
1.304 + audio_channel_t channel = &audio.channels[i];
1.305 + if( channel->active ) {
1.306 + int32_t sample;
1.307 + int vol_left = (channel->vol * (32 - channel->pan)) >> 5;
1.308 + int vol_right = (channel->vol * (channel->pan + 1)) >> 5;
1.309 + switch( channel->sample_format ) {
1.310 + case AUDIO_FMT_16BIT:
1.311 + for( j=0; j<num_samples; j++ ) {
1.312 + sample = ((int16_t *)(arm_mem + channel->start))[channel->posn];
1.313 + result_buf[j][0] += sample * vol_left;
1.314 + result_buf[j][1] += sample * vol_right;
1.315 +
1.316 + channel->posn_left += channel->sample_rate;
1.317 + while( channel->posn_left > audio.output_rate ) {
1.318 + channel->posn_left -= audio.output_rate;
1.319 + channel->posn++;
1.320 +
1.321 + if( channel->posn == channel->end ) {
1.322 + if( channel->loop ) {
1.323 + channel->posn = channel->loop_start;
1.324 + channel->loop = LOOP_LOOPED;
1.325 + } else {
1.326 + audio_stop_channel(i);
1.327 + j = num_samples;
1.328 + break;
1.329 + }
1.330 + }
1.331 + }
1.332 + }
1.333 + break;
1.334 + case AUDIO_FMT_8BIT:
1.335 + for( j=0; j<num_samples; j++ ) {
1.336 + sample = ((int8_t *)(arm_mem + channel->start))[channel->posn] << 8;
1.337 + result_buf[j][0] += sample * vol_left;
1.338 + result_buf[j][1] += sample * vol_right;
1.339 +
1.340 + channel->posn_left += channel->sample_rate;
1.341 + while( channel->posn_left > audio.output_rate ) {
1.342 + channel->posn_left -= audio.output_rate;
1.343 + channel->posn++;
1.344 +
1.345 + if( channel->posn == channel->end ) {
1.346 + if( channel->loop ) {
1.347 + channel->posn = channel->loop_start;
1.348 + channel->loop = LOOP_LOOPED;
1.349 + } else {
1.350 + audio_stop_channel(i);
1.351 + j = num_samples;
1.352 + break;
1.353 + }
1.354 + }
1.355 + }
1.356 + }
1.357 + break;
1.358 + case AUDIO_FMT_ADPCM:
1.359 + for( j=0; j<num_samples; j++ ) {
1.360 + sample = (int16_t)channel->adpcm_predict;
1.361 + result_buf[j][0] += sample * vol_left;
1.362 + result_buf[j][1] += sample * vol_right;
1.363 + channel->posn_left += channel->sample_rate;
1.364 + while( channel->posn_left > audio.output_rate ) {
1.365 + channel->posn_left -= audio.output_rate;
1.366 + channel->posn++;
1.367 + if( channel->posn == channel->end ) {
1.368 + if( channel->loop ) {
1.369 + channel->posn = channel->loop_start;
1.370 + channel->loop = LOOP_LOOPED;
1.371 + channel->adpcm_predict = 0;
1.372 + channel->adpcm_step = 0;
1.373 + } else {
1.374 + audio_stop_channel(i);
1.375 + j = num_samples;
1.376 + break;
1.377 + }
1.378 + }
1.379 + uint8_t data = ((uint8_t *)(arm_mem + channel->start))[channel->posn>>1];
1.380 + if( channel->posn&1 ) {
1.381 + adpcm_yamaha_decode_nibble( channel, (data >> 4) & 0x0F );
1.382 + } else {
1.383 + adpcm_yamaha_decode_nibble( channel, data & 0x0F );
1.384 + }
1.385 + }
1.386 + }
1.387 + break;
1.388 + default:
1.389 + break;
1.390 + }
1.391 + }
1.392 }
1.393
1.394 /* Down-render to the final output format */
1.395 + audio_buffer_t buf = audio.output_buffers[audio.write_buffer];
1.396 + if( buf->status == BUFFER_FULL ) {
1.397 + buf = audio_next_write_buffer();
1.398 + if( buf == NULL ) { // no available space
1.399 + return;
1.400 + }
1.401 + }
1.402
1.403 - if( audio.output_format & AUDIO_FMT_16BIT ) {
1.404 - audio_buffer_t buf = audio.output_buffers[audio.write_buffer];
1.405 - uint16_t *data = (uint16_t *)&buf->data[buf->posn];
1.406 - for( j=0; j < num_samples; j++ ) {
1.407 - *data++ = (int16_t)(result_buf[j][0] >> 6);
1.408 - *data++ = (int16_t)(result_buf[j][1] >> 6);
1.409 - buf->posn += 4;
1.410 - if( buf->posn == buf->length ) {
1.411 - audio_next_write_buffer();
1.412 - buf = audio.output_buffers[audio.write_buffer];
1.413 - data = (uint16_t *)&buf->data[0];
1.414 - }
1.415 - }
1.416 - } else {
1.417 - audio_buffer_t buf = audio.output_buffers[audio.write_buffer];
1.418 - uint8_t *data = (uint8_t *)&buf->data[buf->posn];
1.419 - for( j=0; j < num_samples; j++ ) {
1.420 - *data++ = (uint8_t)(result_buf[j][0] >> 16);
1.421 - *data++ = (uint8_t)(result_buf[j][1] >> 16);
1.422 - buf->posn += 2;
1.423 - if( buf->posn == buf->length ) {
1.424 - audio_next_write_buffer();
1.425 - buf = audio.output_buffers[audio.write_buffer];
1.426 - data = (uint8_t *)&buf->data[0];
1.427 - }
1.428 - }
1.429 + switch( audio.output_format & AUDIO_FMT_SAMPLE_MASK ) {
1.430 + case AUDIO_FMT_FLOAT: {
1.431 + float scale = 1.0/SHRT_MAX;
1.432 + float *data = (float *)&buf->data[buf->posn];
1.433 + for( j=0; j<num_samples; j++ ) {
1.434 + *data++ = scale * (result_buf[j][0] >> 6);
1.435 + *data++ = scale * (result_buf[j][1] >> 6);
1.436 + buf->posn += 8;
1.437 + if( buf->posn == buf->length ) {
1.438 + buf = audio_next_write_buffer();
1.439 + if( buf == NULL ) {
1.440 + break;
1.441 + }
1.442 + data = (float *)&buf->data[0];
1.443 + }
1.444 + }
1.445 + break;
1.446 + }
1.447 + case AUDIO_FMT_16BIT: {
1.448 + int16_t *data = (int16_t *)&buf->data[buf->posn];
1.449 + for( j=0; j < num_samples; j++ ) {
1.450 + *data++ = (int16_t)(result_buf[j][0] >> 6);
1.451 + *data++ = (int16_t)(result_buf[j][1] >> 6);
1.452 + buf->posn += 4;
1.453 + if( buf->posn == buf->length ) {
1.454 + buf = audio_next_write_buffer();
1.455 + if( buf == NULL ) {
1.456 + // All buffers are full
1.457 + break;
1.458 + }
1.459 + data = (int16_t *)&buf->data[0];
1.460 + }
1.461 + }
1.462 + break;
1.463 + }
1.464 + case AUDIO_FMT_8BIT: {
1.465 + int8_t *data = (uint8_t *)&buf->data[buf->posn];
1.466 + for( j=0; j < num_samples; j++ ) {
1.467 + *data++ = (int8_t)(result_buf[j][0] >> 16);
1.468 + *data++ = (int8_t)(result_buf[j][1] >> 16);
1.469 + buf->posn += 2;
1.470 + if( buf->posn == buf->length ) {
1.471 + buf = audio_next_write_buffer();
1.472 + if( buf == NULL ) {
1.473 + // All buffers are full
1.474 + break;
1.475 + }
1.476 + buf = audio.output_buffers[audio.write_buffer];
1.477 + data = (uint8_t *)&buf->data[0];
1.478 + }
1.479 + }
1.480 + break;
1.481 + }
1.482 }
1.483 }
1.484
.