Search
lxdream.org :: lxdream/src/aica/audio.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/aica/audio.c
changeset 465:3bd7be575792
prev463:0655796f9bb5
next531:f0fee3ba71d1
author nkeynes
date Wed Nov 07 11:45:53 2007 +0000 (16 years ago)
permissions -rw-r--r--
last change Add crash handler to get a backtrace via gdb
view annotate diff log raw
     1 /**
     2  * $Id: audio.c,v 1.11 2007-10-27 05:47:21 nkeynes Exp $
     3  * 
     4  * Audio mixer core. Combines all the active streams into a single sound
     5  * buffer for output. 
     6  *
     7  * Copyright (c) 2005 Nathan Keynes.
     8  *
     9  * This program is free software; you can redistribute it and/or modify
    10  * it under the terms of the GNU General Public License as published by
    11  * the Free Software Foundation; either version 2 of the License, or
    12  * (at your option) any later version.
    13  *
    14  * This program is distributed in the hope that it will be useful,
    15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    17  * GNU General Public License for more details.
    18  */
    20 #include "aica/aica.h"
    21 #include "aica/audio.h"
    22 #include "glib/gmem.h"
    23 #include "dream.h"
    24 #include <assert.h>
    25 #include <string.h>
    27 #define NUM_BUFFERS 3
    28 #define MS_PER_BUFFER 100
    30 #define BUFFER_EMPTY   0
    31 #define BUFFER_WRITING 1
    32 #define BUFFER_FULL    2
    34 struct audio_state {
    35     audio_buffer_t output_buffers[NUM_BUFFERS];
    36     int write_buffer;
    37     int read_buffer;
    38     uint32_t output_format;
    39     uint32_t output_rate;
    40     uint32_t output_sample_size;
    41     struct audio_channel channels[AUDIO_CHANNEL_COUNT];
    42 } audio;
    44 audio_driver_t audio_driver = NULL;
    46 #define NEXT_BUFFER() ((audio.write_buffer == NUM_BUFFERS-1) ? 0 : audio.write_buffer+1)
    48 extern char *arm_mem;
    50 /**
    51  * Preserve audio channel state only - don't bother saving the buffers
    52  */
    53 void audio_save_state( FILE *f )
    54 {
    55     fwrite( &audio.channels[0], sizeof(struct audio_channel), AUDIO_CHANNEL_COUNT, f );
    56 }
    58 int audio_load_state( FILE *f )
    59 {
    60     int read = fread( &audio.channels[0], sizeof(struct audio_channel), AUDIO_CHANNEL_COUNT, f );
    61     return (read == AUDIO_CHANNEL_COUNT ? 0 : -1 );
    62 }
    64 /**
    65  * Set the output driver, sample rate and format. Also initializes the 
    66  * output buffers, flushing any current data and reallocating as 
    67  * necessary.
    68  */
    69 gboolean audio_set_driver( audio_driver_t driver, 
    70 			   uint32_t samplerate, int format )
    71 {
    72     uint32_t bytes_per_sample = 1;
    73     uint32_t samples_per_buffer;
    74     int i;
    76     if( audio_driver == NULL || driver != NULL ) {
    77 	if( driver == NULL  )
    78 	    driver = &audio_null_driver;
    79 	if( driver != audio_driver ) {	
    80 	    if( !driver->set_output_format( samplerate, format ) )
    81 		return FALSE;
    82 	    audio_driver = driver;
    83 	}
    84     }
    86     if( format & AUDIO_FMT_16BIT )
    87 	bytes_per_sample = 2;
    88     if( format & AUDIO_FMT_STEREO )
    89 	bytes_per_sample <<= 1;
    90     if( samplerate == audio.output_rate &&
    91 	bytes_per_sample == audio.output_sample_size )
    92 	return TRUE;
    93     samples_per_buffer = (samplerate * MS_PER_BUFFER / 1000);
    94     for( i=0; i<NUM_BUFFERS; i++ ) {
    95 	if( audio.output_buffers[i] != NULL )
    96 	    free(audio.output_buffers[i]);
    97 	audio.output_buffers[i] = g_malloc0( sizeof(struct audio_buffer) + samples_per_buffer * bytes_per_sample );
    98 	audio.output_buffers[i]->length = samples_per_buffer * bytes_per_sample;
    99 	audio.output_buffers[i]->posn = 0;
   100 	audio.output_buffers[i]->status = BUFFER_EMPTY;
   101     }
   102     audio.output_format = format;
   103     audio.output_rate = samplerate;
   104     audio.output_sample_size = bytes_per_sample;
   105     audio.write_buffer = 0;
   106     audio.read_buffer = 0;
   108     return TRUE;
   109 }
   111 /**
   112  * Mark the current write buffer as full and prepare the next buffer for
   113  * writing. Returns the next buffer to write to.
   114  * If all buffers are full, returns NULL.
   115  */
   116 audio_buffer_t audio_next_write_buffer( )
   117 {
   118     audio_buffer_t result = NULL;
   119     audio_buffer_t current = audio.output_buffers[audio.write_buffer];
   120     current->status = BUFFER_FULL;
   121     if( audio.read_buffer == audio.write_buffer &&
   122 	audio_driver->process_buffer( current ) ) {
   123 	audio_next_read_buffer();
   124     }
   125     audio.write_buffer = NEXT_BUFFER();
   126     result = audio.output_buffers[audio.write_buffer];
   127     if( result->status == BUFFER_FULL )
   128 	return NULL;
   129     else {
   130 	result->status = BUFFER_WRITING;
   131 	return result;
   132     }
   133 }
   135 /**
   136  * Mark the current read buffer as empty and return the next buffer for
   137  * reading. If there is no next buffer yet, returns NULL.
   138  */
   139 audio_buffer_t audio_next_read_buffer( )
   140 {
   141     audio_buffer_t current = audio.output_buffers[audio.read_buffer];
   142     assert( current->status == BUFFER_FULL );
   143     current->status = BUFFER_EMPTY;
   144     current->posn = 0;
   145     audio.read_buffer++;
   146     if( audio.read_buffer == NUM_BUFFERS )
   147 	audio.read_buffer = 0;
   149     current = audio.output_buffers[audio.read_buffer];
   150     if( current->status == BUFFER_FULL )
   151 	return current;
   152     else return NULL;
   153 }
   155 /*************************** ADPCM ***********************************/
   157 /**
   158  * The following section borrows heavily from ffmpeg, which is
   159  * copyright (c) 2001-2003 by the fine folks at the ffmpeg project,
   160  * distributed under the GPL version 2 or later.
   161  */
   163 #define CLAMP_TO_SHORT(value) \
   164 if (value > 32767) \
   165     value = 32767; \
   166 else if (value < -32768) \
   167     value = -32768; \
   169 static const int yamaha_indexscale[] = {
   170     230, 230, 230, 230, 307, 409, 512, 614,
   171     230, 230, 230, 230, 307, 409, 512, 614
   172 };
   174 static const int yamaha_difflookup[] = {
   175     1, 3, 5, 7, 9, 11, 13, 15,
   176     -1, -3, -5, -7, -9, -11, -13, -15
   177 };
   179 static inline short adpcm_yamaha_decode_nibble( audio_channel_t c, 
   180 						unsigned char nibble )
   181 {
   182     if( c->adpcm_step == 0 ) {
   183         c->adpcm_predict = 0;
   184         c->adpcm_step = 127;
   185     }
   187     c->adpcm_predict += (c->adpcm_step * yamaha_difflookup[nibble]) >> 3;
   188     CLAMP_TO_SHORT(c->adpcm_predict);
   189     c->adpcm_step = (c->adpcm_step * yamaha_indexscale[nibble]) >> 8;
   190     c->adpcm_step = CLAMP(c->adpcm_step, 127, 24567);
   191     return c->adpcm_predict;
   192 }
   194 /*************************** Sample mixer *****************************/
   196 /**
   197  * Mix a single output sample.
   198  */
   199 void audio_mix_samples( int num_samples )
   200 {
   201     int i, j;
   202     int32_t result_buf[num_samples][2];
   204     memset( &result_buf, 0, sizeof(result_buf) );
   206     for( i=0; i < AUDIO_CHANNEL_COUNT; i++ ) {
   207 	audio_channel_t channel = &audio.channels[i];
   208 	if( channel->active ) {
   209 	    int32_t sample;
   210 	    int vol_left = (channel->vol * (32 - channel->pan)) >> 5;
   211 	    int vol_right = (channel->vol * (channel->pan + 1)) >> 5;
   212 	    switch( channel->sample_format ) {
   213 	    case AUDIO_FMT_16BIT:
   214 		for( j=0; j<num_samples; j++ ) {
   215 		    sample = ((int16_t *)(arm_mem + channel->start))[channel->posn];
   216 		    result_buf[j][0] += sample * vol_left;
   217 		    result_buf[j][1] += sample * vol_right;
   219 		    channel->posn_left += channel->sample_rate;
   220 		    while( channel->posn_left > audio.output_rate ) {
   221 			channel->posn_left -= audio.output_rate;
   222 			channel->posn++;
   224 			if( channel->posn == channel->end ) {
   225 			    if( channel->loop ) {
   226 				channel->posn = channel->loop_start;
   227 				channel->loop = LOOP_LOOPED;
   228 			    } else {
   229 				audio_stop_channel(i);
   230 				j = num_samples;
   231 				break;
   232 			    }
   233 			}
   234 		    }
   235 		}
   236 		break;
   237 	    case AUDIO_FMT_8BIT:
   238 		for( j=0; j<num_samples; j++ ) {
   239 		    sample = ((int8_t *)(arm_mem + channel->start))[channel->posn] << 8;
   240 		    result_buf[j][0] += sample * vol_left;
   241 		    result_buf[j][1] += sample * vol_right;
   243 		    channel->posn_left += channel->sample_rate;
   244 		    while( channel->posn_left > audio.output_rate ) {
   245 			channel->posn_left -= audio.output_rate;
   246 			channel->posn++;
   248 			if( channel->posn == channel->end ) {
   249 			    if( channel->loop ) {
   250 				channel->posn = channel->loop_start;
   251 				channel->loop = LOOP_LOOPED;
   252 			    } else {
   253 				audio_stop_channel(i);
   254 				j = num_samples;
   255 				break;
   256 			    }
   257 			}
   258 		    }
   259 		}
   260 		break;
   261 	    case AUDIO_FMT_ADPCM:
   262 		for( j=0; j<num_samples; j++ ) {
   263 		    sample = (int16_t)channel->adpcm_predict;
   264 		    result_buf[j][0] += sample * vol_left;
   265 		    result_buf[j][1] += sample * vol_right;
   266 		    channel->posn_left += channel->sample_rate;
   267 		    while( channel->posn_left > audio.output_rate ) {
   268 			channel->posn_left -= audio.output_rate;
   269 			channel->posn++;
   270 			if( channel->posn == channel->end ) {
   271 			    if( channel->loop ) {
   272 				channel->posn = channel->loop_start;
   273 				channel->loop = LOOP_LOOPED;
   274 				channel->adpcm_predict = 0;
   275 				channel->adpcm_step = 0;
   276 			    } else {
   277 				audio_stop_channel(i);
   278 				j = num_samples;
   279 				break;
   280 			    }
   281 			}
   282 			uint8_t data = ((uint8_t *)(arm_mem + channel->start))[channel->posn>>1];
   283 			if( channel->posn&1 ) {
   284 			    adpcm_yamaha_decode_nibble( channel, (data >> 4) & 0x0F );
   285 			} else {
   286 			    adpcm_yamaha_decode_nibble( channel, data & 0x0F );
   287 			}
   288 		    }
   289 		}
   290 		break;
   291 	    default:
   292 		break;
   293 	    }
   294 	}
   295     }
   297     /* Down-render to the final output format */
   299     if( audio.output_format & AUDIO_FMT_16BIT ) {
   300 	audio_buffer_t buf = audio.output_buffers[audio.write_buffer];
   301 	uint16_t *data = (uint16_t *)&buf->data[buf->posn];
   302 	for( j=0; j < num_samples; j++ ) {
   303 	    *data++ = (int16_t)(result_buf[j][0] >> 6);
   304 	    *data++ = (int16_t)(result_buf[j][1] >> 6);	
   305 	    buf->posn += 4;
   306 	    if( buf->posn == buf->length ) {
   307 		audio_next_write_buffer();
   308 		buf = audio.output_buffers[audio.write_buffer];
   309 		data = (uint16_t *)&buf->data[0];
   310 	    }
   311 	}
   312     } else {
   313 	audio_buffer_t buf = audio.output_buffers[audio.write_buffer];
   314 	uint8_t *data = (uint8_t *)&buf->data[buf->posn];
   315 	for( j=0; j < num_samples; j++ ) {
   316 	    *data++ = (uint8_t)(result_buf[j][0] >> 16);
   317 	    *data++ = (uint8_t)(result_buf[j][1] >> 16);	
   318 	    buf->posn += 2;
   319 	    if( buf->posn == buf->length ) {
   320 		audio_next_write_buffer();
   321 		buf = audio.output_buffers[audio.write_buffer];
   322 		data = (uint8_t *)&buf->data[0];
   323 	    }
   324 	}
   325     }
   326 }
   328 /********************** Internal AICA calls ***************************/
   330 audio_channel_t audio_get_channel( int channel ) 
   331 {
   332     return &audio.channels[channel];
   333 }
   335 void audio_start_stop_channel( int channel, gboolean start )
   336 {
   337     if( audio.channels[channel].active ) {
   338 	if( !start ) {
   339 	    audio_stop_channel(channel);
   340 	}
   341     } else if( start ) {
   342 	audio_start_channel(channel);
   343     }
   344 }
   346 void audio_stop_channel( int channel ) 
   347 {
   348     audio.channels[channel].active = FALSE;
   349 }
   352 void audio_start_channel( int channel )
   353 {
   354     audio.channels[channel].posn = 0;
   355     audio.channels[channel].posn_left = 0;
   356     audio.channels[channel].active = TRUE;
   357     if( audio.channels[channel].sample_format == AUDIO_FMT_ADPCM ) {
   358 	audio.channels[channel].adpcm_step = 0;
   359 	audio.channels[channel].adpcm_predict = 0;
   360 	uint8_t data = ((uint8_t *)(arm_mem + audio.channels[channel].start))[0];
   361 	adpcm_yamaha_decode_nibble( &audio.channels[channel], data & 0x0F );
   362     }
   363 }
.