Search
lxdream.org :: lxdream :: r73:0bb57e51ac9e
lxdream 0.9.1
released Jun 29
Download Now
changeset73:0bb57e51ac9e
parent72:ceb5985fa8d8
child74:771ee2b1e4f8
authornkeynes
dateThu Jan 12 11:30:19 2006 +0000 (18 years ago)
Render multiple samples per shot, should be mildly faster
Move timer logic down into armcore
Minor tweaks
src/aica/aica.c
src/aica/armcore.c
src/aica/armcore.h
src/aica/audio.c
src/aica/audio.h
src/drivers/audio_esd.c
1.1 --- a/src/aica/aica.c Tue Jan 10 14:00:00 2006 +0000
1.2 +++ b/src/aica/aica.c Thu Jan 12 11:30:19 2006 +0000
1.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.13
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.49
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 else
1.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 +0000
2.2 +++ b/src/aica/armcore.c Thu Jan 12 11:30:19 2006 +0000
2.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.11
2.12 #define MODULE aica_module
2.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.18
2.19 #define STM_R15_OFFSET 12
2.20
2.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.24
2.25 +#define CYCLES_PER_SAMPLE ((ARM_BASE_RATE * 1000000) / AICA_SAMPLE_RATE)
2.26
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.32
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_MODE
2.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 +#endif
2.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_MODE
2.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 -#endif
2.84 }
2.85
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.93
2.94 void arm_save_state( FILE *f )
3.1 --- a/src/aica/armcore.h Tue Jan 10 14:00:00 2006 +0000
3.2 +++ b/src/aica/armcore.h Thu Jan 12 11:30:19 2006 +0000
3.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.13
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;
3.18
4.1 --- a/src/aica/audio.c Tue Jan 10 14:00:00 2006 +0000
4.2 +++ b/src/aica/audio.c Thu Jan 12 11:30:19 2006 +0000
4.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 sound
4.9 * buffer for output.
4.10 @@ -25,7 +25,7 @@
4.11 #include <string.h>
4.12
4.13 #define NUM_BUFFERS 3
4.14 -#define MS_PER_BUFFER 4000
4.15 +#define MS_PER_BUFFER 500
4.16
4.17 #define BUFFER_EMPTY 0
4.18 #define BUFFER_WRITING 1
4.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.40
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 + else
4.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 }
4.213
5.1 --- a/src/aica/audio.h Tue Jan 10 14:00:00 2006 +0000
5.2 +++ b/src/aica/audio.h Thu Jan 12 11:30:19 2006 +0000
5.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.22
5.23
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 buffers
5.35 */
5.36 -void audio_mix_sample( void );
5.37 +void audio_mix_samples( int num_samples );
5.38
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 +0000
6.2 +++ b/src/drivers/audio_esd.c Thu Jan 12 11:30:19 2006 +0000
6.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 driver
6.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.21
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" );
.