Search
lxdream.org :: lxdream/src/aica/audio.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/aica/audio.c
changeset 111:230243c2b520
prev106:9048bac046c3
next242:04f5cdb68d8e
author nkeynes
date Thu Jun 15 10:25:45 2006 +0000 (17 years ago)
permissions -rw-r--r--
last change Add P4 I/O tracing
Add ability to set I/O trace by region address
view annotate diff log raw
     1 /**
     2  * $Id: audio.c,v 1.6 2006-03-16 12:41:59 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 1000
    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 }
.