Search
lxdream.org :: lxdream/src/aica/audio.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/aica/audio.c
changeset 242:04f5cdb68d8e
prev111:230243c2b520
next431:248dd77a9e44
author nkeynes
date Wed Jan 03 09:00:17 2007 +0000 (17 years ago)
permissions -rw-r--r--
last change Adjust timers when they're read rather than waiting until the next time
slice. Also temporarily cut the CPU time by 4.
Initialize the FRQCR register to 0x0E0A for convenience
view annotate diff log raw
     1 /**
     2  * $Id: audio.c,v 1.7 2006-12-15 10:19:49 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 50
    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[64];
    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  * Set the output driver, sample rate and format. Also initializes the 
    52  * output buffers, flushing any current data and reallocating as 
    53  * necessary.
    54  */
    55 gboolean audio_set_driver( audio_driver_t driver, 
    56 			   uint32_t samplerate, int format )
    57 {
    58     uint32_t bytes_per_sample = 1;
    59     uint32_t samples_per_buffer;
    60     int i;
    62     if( audio_driver == NULL || driver != NULL ) {
    63 	if( driver == NULL  )
    64 	    driver = &audio_null_driver;
    65 	if( driver != audio_driver ) {	
    66 	    if( !driver->set_output_format( samplerate, format ) )
    67 		return FALSE;
    68 	    audio_driver = driver;
    69 	}
    70     }
    72     if( format & AUDIO_FMT_16BIT )
    73 	bytes_per_sample = 2;
    74     if( format & AUDIO_FMT_STEREO )
    75 	bytes_per_sample <<= 1;
    76     if( samplerate == audio.output_rate &&
    77 	bytes_per_sample == audio.output_sample_size )
    78 	return;
    79     samples_per_buffer = (samplerate * MS_PER_BUFFER / 1000);
    80     for( i=0; i<NUM_BUFFERS; i++ ) {
    81 	if( audio.output_buffers[i] != NULL )
    82 	    free(audio.output_buffers[i]);
    83 	audio.output_buffers[i] = g_malloc0( sizeof(struct audio_buffer) + samples_per_buffer * bytes_per_sample );
    84 	audio.output_buffers[i]->length = samples_per_buffer * bytes_per_sample;
    85 	audio.output_buffers[i]->posn = 0;
    86 	audio.output_buffers[i]->status = BUFFER_EMPTY;
    87     }
    88     audio.output_format = format;
    89     audio.output_rate = samplerate;
    90     audio.output_sample_size = bytes_per_sample;
    91     audio.write_buffer = 0;
    92     audio.read_buffer = 0;
    94     return TRUE;
    95 }
    97 /**
    98  * Mark the current write buffer as full and prepare the next buffer for
    99  * writing. Returns the next buffer to write to.
   100  * If all buffers are full, returns NULL.
   101  */
   102 audio_buffer_t audio_next_write_buffer( )
   103 {
   104     audio_buffer_t result = NULL;
   105     audio_buffer_t current = audio.output_buffers[audio.write_buffer];
   106     current->status = BUFFER_FULL;
   107     if( audio.read_buffer == audio.write_buffer &&
   108 	audio_driver->process_buffer( current ) ) {
   109 	audio_next_read_buffer();
   110     }
   111     audio.write_buffer = NEXT_BUFFER();
   112     result = audio.output_buffers[audio.write_buffer];
   113     if( result->status == BUFFER_FULL )
   114 	return NULL;
   115     else {
   116 	result->status = BUFFER_WRITING;
   117 	return result;
   118     }
   119 }
   121 /**
   122  * Mark the current read buffer as empty and return the next buffer for
   123  * reading. If there is no next buffer yet, returns NULL.
   124  */
   125 audio_buffer_t audio_next_read_buffer( )
   126 {
   127     audio_buffer_t current = audio.output_buffers[audio.read_buffer];
   128     assert( current->status == BUFFER_FULL );
   129     current->status = BUFFER_EMPTY;
   130     current->posn = 0;
   131     audio.read_buffer++;
   132     if( audio.read_buffer == NUM_BUFFERS )
   133 	audio.read_buffer = 0;
   135     current = audio.output_buffers[audio.read_buffer];
   136     if( current->status == BUFFER_FULL )
   137 	return current;
   138     else return NULL;
   139 }
   141 /*************************** ADPCM ***********************************/
   143 /**
   144  * The following section borrows heavily from ffmpeg, which is
   145  * copyright (c) 2001-2003 by the fine folks at the ffmpeg project,
   146  * distributed under the GPL version 2 or later.
   147  */
   149 #define CLAMP_TO_SHORT(value) \
   150 if (value > 32767) \
   151     value = 32767; \
   152 else if (value < -32768) \
   153     value = -32768; \
   155 static const int yamaha_indexscale[] = {
   156     230, 230, 230, 230, 307, 409, 512, 614,
   157     230, 230, 230, 230, 307, 409, 512, 614
   158 };
   160 static const int yamaha_difflookup[] = {
   161     1, 3, 5, 7, 9, 11, 13, 15,
   162     -1, -3, -5, -7, -9, -11, -13, -15
   163 };
   165 static inline short adpcm_yamaha_decode_nibble( audio_channel_t c, 
   166 						unsigned char nibble )
   167 {
   168     if( c->adpcm_step == 0 ) {
   169         c->adpcm_predict = 0;
   170         c->adpcm_step = 127;
   171     }
   173     c->adpcm_predict += (c->adpcm_step * yamaha_difflookup[nibble]) >> 3;
   174     CLAMP_TO_SHORT(c->adpcm_predict);
   175     c->adpcm_step = (c->adpcm_step * yamaha_indexscale[nibble]) >> 8;
   176     c->adpcm_step = CLAMP(c->adpcm_step, 127, 24567);
   177     return c->adpcm_predict;
   178 }
   180 /*************************** Sample mixer *****************************/
   182 /**
   183  * Mix a single output sample.
   184  */
   185 void audio_mix_samples( int num_samples )
   186 {
   187     int i, j;
   188     int32_t result_buf[num_samples][2];
   190     memset( &result_buf, 0, sizeof(result_buf) );
   192     for( i=0; i < 64; i++ ) {
   193 	audio_channel_t channel = &audio.channels[i];
   194 	if( channel->active ) {
   195 	    int32_t sample;
   196 	    int vol_left = (channel->vol * (32 - channel->pan)) >> 5;
   197 	    int vol_right = (channel->vol * (channel->pan + 1)) >> 5;
   198 	    switch( channel->sample_format ) {
   199 	    case AUDIO_FMT_16BIT:
   200 		for( j=0; j<num_samples; j++ ) {
   201 		    sample = *(int16_t *)(arm_mem + channel->posn + channel->start);
   202 		    result_buf[j][0] += sample * vol_left;
   203 		    result_buf[j][1] += sample * vol_right;
   205 		    channel->posn_left += channel->sample_rate;
   206 		    while( channel->posn_left > audio.output_rate ) {
   207 			channel->posn_left -= audio.output_rate;
   208 			channel->posn++;
   210 			if( channel->posn == channel->end ) {
   211 			    if( channel->loop )
   212 				channel->posn = channel->loop_start;
   213 			    else {
   214 				audio_stop_channel(i);
   215 				j = num_samples;
   216 				break;
   217 			    }
   218 			}
   219 		    }
   220 		}
   221 		break;
   222 	    case AUDIO_FMT_8BIT:
   223 		for( j=0; j<num_samples; j++ ) {
   224 		    sample = (*(int8_t *)(arm_mem + channel->posn + channel->start)) << 8;
   225 		    result_buf[j][0] += sample * vol_left;
   226 		    result_buf[j][1] += sample * vol_right;
   228 		    channel->posn_left += channel->sample_rate;
   229 		    while( channel->posn_left > audio.output_rate ) {
   230 			channel->posn_left -= audio.output_rate;
   231 			channel->posn++;
   233 			if( channel->posn == channel->end ) {
   234 			    if( channel->loop )
   235 				channel->posn = channel->loop_start;
   236 			    else {
   237 				audio_stop_channel(i);
   238 				j = num_samples;
   239 				break;
   240 			    }
   241 			}
   242 		    }
   243 		}
   244 		break;
   245 	    case AUDIO_FMT_ADPCM:
   246 		for( j=0; j<num_samples; j++ ) {
   247 		    sample = (int16_t)channel->adpcm_predict;
   248 		    result_buf[j][0] += sample * vol_left;
   249 		    result_buf[j][1] += sample * vol_right;
   250 		    channel->posn_left += channel->sample_rate;
   251 		    while( channel->posn_left > audio.output_rate ) {
   252 			channel->posn_left -= audio.output_rate;
   253 			if( channel->adpcm_nibble == 0 ) {
   254 			    uint8_t data = *(uint8_t *)(arm_mem + channel->posn + channel->start);
   255 			    adpcm_yamaha_decode_nibble( channel, (data >> 4) & 0x0F );
   256 			    channel->adpcm_nibble = 1;
   257 			} else {
   258 			    channel->posn++;
   259 			    if( channel->posn == channel->end ) {
   260 				if( channel->loop )
   261 				    channel->posn = channel->loop_start;
   262 				else
   263 				    audio_stop_channel(i);
   264 				break;
   265 			    }
   266 			    uint8_t data = *(uint8_t *)(arm_mem + channel->posn + channel->start);
   267 			    adpcm_yamaha_decode_nibble( channel, data & 0x0F );
   268 			    channel->adpcm_nibble = 0;
   269 			}
   270 		    }
   271 		}
   272 		break;
   273 	    default:
   274 		break;
   275 	    }
   276 	}
   277     }
   279     /* Down-render to the final output format */
   281     if( audio.output_format & AUDIO_FMT_16BIT ) {
   282 	audio_buffer_t buf = audio.output_buffers[audio.write_buffer];
   283 	uint16_t *data = (uint16_t *)&buf->data[buf->posn];
   284 	for( j=0; j < num_samples; j++ ) {
   285 	    *data++ = (int16_t)(result_buf[j][0] >> 6);
   286 	    *data++ = (int16_t)(result_buf[j][1] >> 6);	
   287 	    buf->posn += 4;
   288 	    if( buf->posn == buf->length ) {
   289 		audio_next_write_buffer();
   290 		buf = audio.output_buffers[audio.write_buffer];
   291 		data = (uint16_t *)&buf->data[0];
   292 	    }
   293 	}
   294     } else {
   295 	audio_buffer_t buf = audio.output_buffers[audio.write_buffer];
   296 	uint8_t *data = (uint8_t *)&buf->data[buf->posn];
   297 	for( j=0; j < num_samples; j++ ) {
   298 	    *data++ = (uint8_t)(result_buf[j][0] >> 16);
   299 	    *data++ = (uint8_t)(result_buf[j][1] >> 16);	
   300 	    buf->posn += 2;
   301 	    if( buf->posn == buf->length ) {
   302 		audio_next_write_buffer();
   303 		buf = audio.output_buffers[audio.write_buffer];
   304 		data = (uint8_t *)&buf->data[0];
   305 	    }
   306 	}
   307     }
   308 }
   310 /********************** Internal AICA calls ***************************/
   312 audio_channel_t audio_get_channel( int channel ) 
   313 {
   314     return &audio.channels[channel];
   315 }
   317 void audio_stop_channel( int channel ) 
   318 {
   319     audio.channels[channel].active = FALSE;
   320 }
   323 void audio_start_channel( int channel )
   324 {
   325     audio.channels[channel].posn = 0;
   326     audio.channels[channel].posn_left = 0;
   327     audio.channels[channel].adpcm_nibble = 0;
   328     audio.channels[channel].adpcm_step = 0;
   329     audio.channels[channel].adpcm_predict = 0;
   330     audio.channels[channel].active = TRUE;
   331 }
.