revision 73:0bb57e51ac9e
summary |
tree |
shortlog |
changelog |
graph |
changeset |
raw | bz2 | zip | gz changeset | 73:0bb57e51ac9e |
parent | 72:ceb5985fa8d8 |
child | 74:771ee2b1e4f8 |
author | nkeynes |
date | Thu Jan 12 11:30:19 2006 +0000 (17 years ago) |
Render multiple samples per shot, should be mildly faster
Move timer logic down into armcore
Minor tweaks
Move timer logic down into armcore
Minor tweaks
1.1 --- a/src/aica/aica.c Tue Jan 10 14:00:00 2006 +00001.2 +++ b/src/aica/aica.c Thu Jan 12 11:30:19 2006 +00001.3 @@ -1,5 +1,5 @@1.4 /**1.5 - * $Id: aica.c,v 1.11 2006-01-10 13:56:54 nkeynes Exp $1.6 + * $Id: aica.c,v 1.12 2006-01-12 11:30:19 nkeynes Exp $1.7 *1.8 * This is the core sound system (ie the bit which does the actual work)1.9 *1.10 @@ -39,8 +39,6 @@1.11 int aica_load_state( FILE *f );1.12 uint32_t aica_run_slice( uint32_t );1.14 -#define IS_TIMER_ENABLED() (MMIO_READ( AICA2, AICA_TCR ) & 0x40)1.15 -1.16 struct dreamcast_module aica_module = { "AICA", aica_init, aica_reset,1.17 aica_start, aica_run_slice, aica_stop,1.18 aica_save_state, aica_load_state };1.19 @@ -82,23 +80,16 @@1.20 int reset = MMIO_READ( AICA2, AICA_RESET );1.21 if( (reset & 1) == 0 ) { /* Running */1.22 int num_samples = (nanosecs_done + nanosecs) / AICA_SAMPLE_RATE - samples_done;1.23 - int i;1.24 - for( i=0; i<num_samples; i++ ) {1.25 - nanosecs = arm_run_slice( AICA_SAMPLE_PERIOD );1.26 - audio_mix_sample();1.27 - if( IS_TIMER_ENABLED() ) {1.28 - uint8_t val = MMIO_READ( AICA2, AICA_TIMER );1.29 - val++;1.30 - if( val == 0 )1.31 - aica_event( AICA_EVENT_TIMER );1.32 - MMIO_WRITE( AICA2, AICA_TIMER, val );1.33 - }1.34 - if( !dreamcast_is_running() )1.35 - break;1.36 - }1.37 + num_samples = arm_run_slice( num_samples );1.38 + audio_mix_samples( num_samples );1.39 +1.40 samples_done += num_samples;1.41 nanosecs_done += nanosecs;1.42 }1.43 + if( nanosecs_done > 1000000000 ) {1.44 + samples_done -= AICA_SAMPLE_RATE;1.45 + nanosecs_done -= 1000000000;1.46 + }1.47 return nanosecs;1.48 }1.50 @@ -256,9 +247,9 @@1.51 case 0x00: /* Config + high address bits*/1.52 channel->start = (channel->start & 0xFFFF) | ((val&0x1F) << 16);1.53 if( val & 0x200 )1.54 - channel->loop_count = -1;1.55 + channel->loop = TRUE;1.56 else1.57 - channel->loop_count = 0;1.58 + channel->loop = FALSE;1.59 switch( (val >> 7) & 0x03 ) {1.60 case 0:1.61 channel->sample_format = AUDIO_FMT_16BIT;1.62 @@ -289,8 +280,8 @@1.63 case 0x08: /* Loop start */1.64 channel->loop_start = val;1.65 break;1.66 - case 0x0C: /* Loop end */1.67 - channel->loop_end = channel->end = val;1.68 + case 0x0C: /* End */1.69 + channel->end = val;1.70 break;1.71 case 0x10: /* Envelope register 1 */1.72 break;
2.1 --- a/src/aica/armcore.c Tue Jan 10 14:00:00 2006 +00002.2 +++ b/src/aica/armcore.c Thu Jan 12 11:30:19 2006 +00002.3 @@ -1,5 +1,5 @@2.4 /**2.5 - * $Id: armcore.c,v 1.16 2006-01-10 13:56:54 nkeynes Exp $2.6 + * $Id: armcore.c,v 1.17 2006-01-12 11:30:19 nkeynes Exp $2.7 *2.8 * ARM7TDMI CPU emulation core.2.9 *2.10 @@ -18,8 +18,9 @@2.12 #define MODULE aica_module2.13 #include "dream.h"2.14 +#include "mem.h"2.15 #include "aica/armcore.h"2.16 -#include "mem.h"2.17 +#include "aica/aica.h"2.19 #define STM_R15_OFFSET 122.21 @@ -46,6 +47,7 @@2.22 uint32_t arm_cpu_freq = ARM_BASE_RATE;2.23 uint32_t arm_cpu_period = 1000 / ARM_BASE_RATE;2.25 +#define CYCLES_PER_SAMPLE ((ARM_BASE_RATE * 1000000) / AICA_SAMPLE_RATE)2.27 static struct breakpoint_struct arm_breakpoints[MAX_BREAKPOINTS];2.28 static int arm_breakpoint_count = 0;2.29 @@ -85,35 +87,40 @@2.30 return 0;2.31 }2.33 -uint32_t arm_run_slice( uint32_t nanosecs )2.34 +#define IS_TIMER_ENABLED() (MMIO_READ( AICA2, AICA_TCR ) & 0x40)2.35 +2.36 +uint32_t arm_run_slice( uint32_t num_samples )2.37 {2.38 - int i;2.39 - uint32_t target = armr.icount + nanosecs / arm_cpu_period;2.40 - uint32_t start = armr.icount;2.41 - while( armr.icount < target ) {2.42 - armr.icount++;2.43 - if( !arm_execute_instruction() )2.44 + int i,j,k;2.45 + for( i=0; i<num_samples; i++ ) {2.46 + for( j=0; j < CYCLES_PER_SAMPLE; j++ ) {2.47 + armr.icount++;2.48 + if( !arm_execute_instruction() )2.49 + return i;2.50 +#ifdef ENABLE_DEBUG_MODE2.51 + for( k=0; k<arm_breakpoint_count; k++ ) {2.52 + if( arm_breakpoints[k].address == armr.r[15] ) {2.53 + dreamcast_stop();2.54 + if( arm_breakpoints[k].type == BREAK_ONESHOT )2.55 + arm_clear_breakpoint( armr.r[15], BREAK_ONESHOT );2.56 + return i;2.57 + }2.58 + }2.59 +#endif2.60 + }2.61 +2.62 + if( IS_TIMER_ENABLED() ) {2.63 + uint8_t val = MMIO_READ( AICA2, AICA_TIMER );2.64 + val++;2.65 + if( val == 0 )2.66 + aica_event( AICA_EVENT_TIMER );2.67 + MMIO_WRITE( AICA2, AICA_TIMER, val );2.68 + }2.69 + if( !dreamcast_is_running() )2.70 break;2.71 -#ifdef ENABLE_DEBUG_MODE2.72 - for( i=0; i<arm_breakpoint_count; i++ ) {2.73 - if( arm_breakpoints[i].address == armr.r[15] ) {2.74 - break;2.75 - }2.76 - }2.77 - if( i != arm_breakpoint_count ) {2.78 - dreamcast_stop();2.79 - if( arm_breakpoints[i].type == BREAK_ONESHOT )2.80 - arm_clear_breakpoint( armr.r[15], BREAK_ONESHOT );2.81 - break;2.82 - }2.83 -#endif2.84 }2.86 - if( target != armr.icount ) {2.87 - /* Halted - compute time actually executed */2.88 - nanosecs = (armr.icount - start) * arm_cpu_period;2.89 - }2.90 - return nanosecs;2.91 + return i;2.92 }2.94 void arm_save_state( FILE *f )
3.1 --- a/src/aica/armcore.h Tue Jan 10 14:00:00 2006 +00003.2 +++ b/src/aica/armcore.h Thu Jan 12 11:30:19 2006 +00003.3 @@ -1,5 +1,5 @@3.4 /**3.5 - * $Id: armcore.h,v 1.12 2006-01-10 13:56:54 nkeynes Exp $3.6 + * $Id: armcore.h,v 1.13 2006-01-12 11:30:19 nkeynes Exp $3.7 *3.8 * Interface definitions for the ARM CPU emulation core proper.3.9 *3.10 @@ -23,7 +23,7 @@3.11 #include <stdint.h>3.12 #include <stdio.h>3.14 -#define ARM_BASE_RATE 25 /* MHZ */3.15 +#define ARM_BASE_RATE 2 /* MHZ */3.16 extern uint32_t arm_cpu_freq;3.17 extern uint32_t arm_cpu_period;
4.1 --- a/src/aica/audio.c Tue Jan 10 14:00:00 2006 +00004.2 +++ b/src/aica/audio.c Thu Jan 12 11:30:19 2006 +00004.3 @@ -1,5 +1,5 @@4.4 /**4.5 - * $Id: audio.c,v 1.1 2006-01-10 13:56:54 nkeynes Exp $4.6 + * $Id: audio.c,v 1.2 2006-01-12 11:30:19 nkeynes Exp $4.7 *4.8 * Audio mixer core. Combines all the active streams into a single sound4.9 * buffer for output.4.10 @@ -25,7 +25,7 @@4.11 #include <string.h>4.13 #define NUM_BUFFERS 34.14 -#define MS_PER_BUFFER 40004.15 +#define MS_PER_BUFFER 5004.17 #define BUFFER_EMPTY 04.18 #define BUFFER_WRITING 14.19 @@ -71,7 +71,7 @@4.20 if( audio.output_buffers[i] != NULL )4.21 free(audio.output_buffers[i]);4.22 audio.output_buffers[i] = g_malloc0( sizeof(struct audio_buffer) + samples_per_buffer * bytes_per_sample );4.23 - audio.output_buffers[i]->length = samples_per_buffer;4.24 + audio.output_buffers[i]->length = samples_per_buffer * bytes_per_sample;4.25 audio.output_buffers[i]->posn = 0;4.26 audio.output_buffers[i]->status = BUFFER_EMPTY;4.27 }4.28 @@ -175,10 +175,12 @@4.29 /**4.30 * Mix a single output sample.4.31 */4.32 -void audio_mix_sample( )4.33 +void audio_mix_samples( int num_samples )4.34 {4.35 int i, j;4.36 - int32_t result_left = 0, result_right = 0;4.37 + int32_t result_buf[num_samples][2];4.38 +4.39 + memset( &result_buf, 0, sizeof(result_buf) );4.41 for( i=0; i < 64; i++ ) {4.42 audio_channel_t channel = &audio.channels[i];4.43 @@ -186,74 +188,113 @@4.44 int32_t sample;4.45 switch( channel->sample_format ) {4.46 case AUDIO_FMT_16BIT:4.47 - sample = *(int16_t *)(arm_mem + channel->posn + channel->start);4.48 + for( j=0; j<num_samples; j++ ) {4.49 + sample = *(int16_t *)(arm_mem + channel->posn + channel->start);4.50 + result_buf[j][0] += sample * channel->vol_left;4.51 + result_buf[j][1] += sample * channel->vol_right;4.52 +4.53 + channel->posn_left += channel->sample_rate;4.54 + while( channel->posn_left > audio.output_rate ) {4.55 + channel->posn_left -= audio.output_rate;4.56 + channel->posn++;4.57 +4.58 + if( channel->posn == channel->end ) {4.59 + if( channel->loop )4.60 + channel->posn = channel->loop_start;4.61 + else {4.62 + audio_stop_channel(i);4.63 + j = num_samples;4.64 + break;4.65 + }4.66 + }4.67 + }4.68 + }4.69 break;4.70 case AUDIO_FMT_8BIT:4.71 - sample = (*(int8_t *)(arm_mem + channel->posn + channel->start)) << 8;4.72 - break;4.73 - case AUDIO_FMT_16BIT|AUDIO_FMT_UNSIGNED:4.74 - sample = (int8_t)((*(uint16_t *)(arm_mem + channel->posn + channel->start)) - 0x8000);4.75 - break;4.76 - case AUDIO_FMT_8BIT|AUDIO_FMT_UNSIGNED:4.77 - sample = (int8_t)((*(uint8_t *)(arm_mem + channel->posn + channel->start)) - 0x80);4.78 + for( j=0; j<num_samples; j++ ) {4.79 + sample = (*(int8_t *)(arm_mem + channel->posn + channel->start)) << 8;4.80 + result_buf[j][0] += sample * channel->vol_left;4.81 + result_buf[j][1] += sample * channel->vol_right;4.82 +4.83 + channel->posn_left += channel->sample_rate;4.84 + while( channel->posn_left > audio.output_rate ) {4.85 + channel->posn_left -= audio.output_rate;4.86 + channel->posn++;4.87 +4.88 + if( channel->posn == channel->end ) {4.89 + if( channel->loop )4.90 + channel->posn = channel->loop_start;4.91 + else {4.92 + audio_stop_channel(i);4.93 + j = num_samples;4.94 + break;4.95 + }4.96 + }4.97 + }4.98 + }4.99 break;4.100 case AUDIO_FMT_ADPCM:4.101 - sample = (int16_t)channel->adpcm_predict;4.102 + for( j=0; j<num_samples; j++ ) {4.103 + sample = (int16_t)channel->adpcm_predict;4.104 + result_buf[j][0] += sample * channel->vol_left;4.105 + result_buf[j][1] += sample * channel->vol_right;4.106 + channel->posn_left += channel->sample_rate;4.107 + while( channel->posn_left > audio.output_rate ) {4.108 + channel->posn_left -= audio.output_rate;4.109 + if( channel->adpcm_nibble == 0 ) {4.110 + uint8_t data = *(uint8_t *)(arm_mem + channel->posn + channel->start);4.111 + adpcm_yamaha_decode_nibble( channel, (data >> 4) & 0x0F );4.112 + channel->adpcm_nibble = 1;4.113 + } else {4.114 + channel->posn++;4.115 + if( channel->posn == channel->end ) {4.116 + if( channel->loop )4.117 + channel->posn = channel->loop_start;4.118 + else4.119 + audio_stop_channel(i);4.120 + break;4.121 + }4.122 + uint8_t data = *(uint8_t *)(arm_mem + channel->posn + channel->start);4.123 + adpcm_yamaha_decode_nibble( channel, data & 0x0F );4.124 + channel->adpcm_nibble = 0;4.125 + }4.126 + }4.127 + }4.128 + break;4.129 default:4.130 - sample = 0; /* Unsupported */4.131 - }4.132 - result_left += sample * channel->vol_left;4.133 - result_right += sample * channel->vol_right;4.134 -4.135 - channel->posn_left += channel->sample_rate;4.136 - while( channel->posn_left > audio.output_rate ) {4.137 - channel->posn_left -= audio.output_rate;4.138 - if( channel->sample_format == AUDIO_FMT_ADPCM &&4.139 - channel->adpcm_nibble == 0 ) {4.140 - uint8_t data = *(uint8_t *)(arm_mem + channel->posn + channel->start);4.141 - adpcm_yamaha_decode_nibble( channel, (data >> 4) & 0x0F );4.142 - channel->adpcm_nibble = 1;4.143 - continue;4.144 - }4.145 -4.146 - channel->posn++;4.147 -4.148 - if( channel->loop_count != 0 &&4.149 - channel->posn >= channel->loop_end ) {4.150 - channel->posn = channel->loop_start;4.151 - if( channel->loop_count != -1 )4.152 - channel->loop_count --;4.153 - } else if( channel->posn >= channel->end ) {4.154 - audio_stop_channel( i );4.155 - break;4.156 - }4.157 -4.158 - if( channel->sample_format == AUDIO_FMT_ADPCM ) {4.159 - uint8_t data = *(uint8_t *)(arm_mem + channel->posn + channel->start);4.160 - adpcm_yamaha_decode_nibble( channel, data & 0x0F );4.161 - channel->adpcm_nibble = 0;4.162 - }4.163 + break;4.164 }4.165 }4.166 }4.167 -4.168 +4.169 /* Down-render to the final output format */4.170 - audio_buffer_t buf =4.171 - audio.output_buffers[audio.write_buffer];4.172 +4.173 if( audio.output_format & AUDIO_FMT_16BIT ) {4.174 - uint16_t *data = (uint16_t *)&buf->data[buf->posn*audio.output_sample_size];4.175 - *data++ = (int16_t)(result_left >> 8);4.176 - *data++ = (int16_t)(result_right >> 8);4.177 + audio_buffer_t buf = audio.output_buffers[audio.write_buffer];4.178 + uint16_t *data = (uint16_t *)&buf->data[buf->posn];4.179 + for( j=0; j < num_samples; j++ ) {4.180 + *data++ = (int16_t)(result_buf[j][0] >> 8);4.181 + *data++ = (int16_t)(result_buf[j][1] >> 8);4.182 + buf->posn += 4;4.183 + if( buf->posn == buf->length ) {4.184 + audio_next_write_buffer();4.185 + buf = audio.output_buffers[audio.write_buffer];4.186 + data = (uint16_t *)&buf->data[0];4.187 + }4.188 + }4.189 } else {4.190 - audio_buffer_t buf =4.191 - audio.output_buffers[audio.write_buffer];4.192 - uint8_t *data = (uint8_t *)&buf->data[buf->posn*audio.output_sample_size];4.193 - *data++ = (int8_t)(result_left >> 22);4.194 - *data++ = (int8_t)(result_right >>22);4.195 - }4.196 - buf->posn++;4.197 - if( buf->posn == buf->length ) {4.198 - audio_next_write_buffer();4.199 + audio_buffer_t buf = audio.output_buffers[audio.write_buffer];4.200 + uint8_t *data = (uint8_t *)&buf->data[buf->posn];4.201 + for( j=0; j < num_samples; j++ ) {4.202 + *data++ = (uint8_t)(result_buf[j][0] >> 16);4.203 + *data++ = (uint8_t)(result_buf[j][1] >> 16);4.204 + buf->posn += 2;4.205 + if( buf->posn == buf->length ) {4.206 + audio_next_write_buffer();4.207 + buf = audio.output_buffers[audio.write_buffer];4.208 + data = (uint8_t *)&buf->data[0];4.209 + }4.210 + }4.211 }4.212 }
5.1 --- a/src/aica/audio.h Tue Jan 10 14:00:00 2006 +00005.2 +++ b/src/aica/audio.h Thu Jan 12 11:30:19 2006 +00005.3 @@ -1,5 +1,5 @@5.4 /**5.5 - * $Id: audio.h,v 1.1 2006-01-10 13:56:54 nkeynes Exp $5.6 + * $Id: audio.h,v 1.2 2006-01-12 11:30:19 nkeynes Exp $5.7 *5.8 * Audio engine, ie the part that does the actual work.5.9 *5.10 @@ -40,9 +40,8 @@5.11 uint32_t posn_left;5.12 uint32_t start;5.13 uint32_t end;5.14 + gboolean loop;5.15 uint32_t loop_start;5.16 - uint32_t loop_end;5.17 - int loop_count; /* 0 = no loop, -1 = loop forever */5.18 int vol_left; /* 0..255 */5.19 int vol_right; /* 0..255 */5.20 uint32_t sample_rate;5.21 @@ -56,8 +55,8 @@5.24 typedef struct audio_buffer {5.25 - uint32_t length; /* Samples */5.26 - uint32_t posn; /* Samples */5.27 + uint32_t length; /* Bytes */5.28 + uint32_t posn; /* Bytes */5.29 int status;5.30 char data[0];5.31 } *audio_buffer_t;5.32 @@ -96,7 +95,7 @@5.33 /**5.34 * Mix a single output sample and append it to the output buffers5.35 */5.36 -void audio_mix_sample( void );5.37 +void audio_mix_samples( int num_samples );5.39 /**5.40 * Retrieve the channel information for the channel, numbered 0..63.
6.1 --- a/src/drivers/audio_esd.c Tue Jan 10 14:00:00 2006 +00006.2 +++ b/src/drivers/audio_esd.c Thu Jan 12 11:30:19 2006 +00006.3 @@ -1,5 +1,5 @@6.4 /**6.5 - * $Id: audio_esd.c,v 1.1 2006-01-10 13:56:54 nkeynes Exp $6.6 + * $Id: audio_esd.c,v 1.2 2006-01-12 11:30:19 nkeynes Exp $6.7 *6.8 * The esd (esound) audio driver6.9 *6.10 @@ -31,11 +31,9 @@6.11 esd_sample_size = 1;6.12 if( format & AUDIO_FMT_16BIT ) {6.13 esd_format |= ESD_BITS16;6.14 - esd_sample_size = 1;6.15 } else esd_format |= ESD_BITS8;6.16 if( format & AUDIO_FMT_STEREO ) {6.17 esd_format |= ESD_STEREO;6.18 - esd_sample_size = esd_sample_size << 1 ;6.19 }6.20 else esd_format |= ESD_MONO;6.22 @@ -46,7 +44,7 @@6.23 gboolean esd_audio_process_buffer( audio_buffer_t buffer )6.24 {6.25 if( esd_handle != -1 ) {6.26 - write( esd_handle, buffer->data, buffer->length * esd_sample_size );6.27 + write( esd_handle, buffer->data, buffer->length );6.28 DEBUG("Wrote buffer" );6.29 } else {6.30 ERROR( "ESD not initialized" );
.