--- uae/src/audio.c 2018/04/24 16:43:19 1.1.1.3 +++ uae/src/audio.c 2018/04/24 16:48:32 1.1.1.6 @@ -79,7 +79,6 @@ typedef uae_u8 sample8_t; #define DO_CHANNEL(v, c) do { (v) &= audio_channel[c].adk_mask; data += v; } while (0); -/* Templates! I want templates! */ void sample16_handler (void) { BEGIN_BENCH @@ -109,6 +108,139 @@ void sample16_handler (void) check_sound_buffers (); } +void sample16i_rh_handler (void) +{ + unsigned long delta, ratio; + + BEGIN_BENCH + + uae_u32 data0 = audio_channel[0].current_sample; + uae_u32 data1 = audio_channel[1].current_sample; + uae_u32 data2 = audio_channel[2].current_sample; + uae_u32 data3 = audio_channel[3].current_sample; + uae_u32 data0p = audio_channel[0].last_sample; + uae_u32 data1p = audio_channel[1].last_sample; + uae_u32 data2p = audio_channel[2].last_sample; + uae_u32 data3p = audio_channel[3].last_sample; + DO_CHANNEL_1 (data0, 0); + DO_CHANNEL_1 (data1, 1); + DO_CHANNEL_1 (data2, 2); + DO_CHANNEL_1 (data3, 3); + DO_CHANNEL_1 (data0p, 0); + DO_CHANNEL_1 (data1p, 1); + DO_CHANNEL_1 (data2p, 2); + DO_CHANNEL_1 (data3p, 3); + + data0 &= audio_channel[0].adk_mask; + data0p &= audio_channel[0].adk_mask; + data1 &= audio_channel[1].adk_mask; + data1p &= audio_channel[1].adk_mask; + data2 &= audio_channel[2].adk_mask; + data2p &= audio_channel[2].adk_mask; + data3 &= audio_channel[3].adk_mask; + data3p &= audio_channel[3].adk_mask; + + /* linear interpolation and summing up... */ + delta = audio_channel[0].per; + ratio = ((audio_channel[0].evtime % delta) << 8) / delta; + data0 = (data0 * (256 - ratio) + data0p * ratio) >> 8; + delta = audio_channel[1].per; + ratio = ((audio_channel[1].evtime % delta) << 8) / delta; + data0 += (data1 * (256 - ratio) + data1p * ratio) >> 8; + delta = audio_channel[2].per; + ratio = ((audio_channel[2].evtime % delta) << 8) / delta; + data0 += (data2 * (256 - ratio) + data2p * ratio) >> 8; + delta = audio_channel[3].per; + ratio = ((audio_channel[3].evtime % delta) << 8) / delta; + data0 += (data3 * (256 - ratio) + data3p * ratio) >> 8; + + { + uae_u32 data = SBASEVAL16(2) + data0; + FINISH_DATA(16, 2); + PUT_SOUND_WORD (data); + } + END_BENCH + + check_sound_buffers (); +} + +void sample16i_crux_handler (void) +{ + unsigned long delta, ratio; + + BEGIN_BENCH + + uae_u32 data0 = audio_channel[0].current_sample; + uae_u32 data1 = audio_channel[1].current_sample; + uae_u32 data2 = audio_channel[2].current_sample; + uae_u32 data3 = audio_channel[3].current_sample; + uae_u32 data0p = audio_channel[0].last_sample; + uae_u32 data1p = audio_channel[1].last_sample; + uae_u32 data2p = audio_channel[2].last_sample; + uae_u32 data3p = audio_channel[3].last_sample; + DO_CHANNEL_1 (data0, 0); + DO_CHANNEL_1 (data1, 1); + DO_CHANNEL_1 (data2, 2); + DO_CHANNEL_1 (data3, 3); + DO_CHANNEL_1 (data0p, 0); + DO_CHANNEL_1 (data1p, 1); + DO_CHANNEL_1 (data2p, 2); + DO_CHANNEL_1 (data3p, 3); + + data0 &= audio_channel[0].adk_mask; + data0p &= audio_channel[0].adk_mask; + data1 &= audio_channel[1].adk_mask; + data1p &= audio_channel[1].adk_mask; + data2 &= audio_channel[2].adk_mask; + data2p &= audio_channel[2].adk_mask; + data3 &= audio_channel[3].adk_mask; + data3p &= audio_channel[3].adk_mask; + + { + struct audio_channel_data *cdp; + int ratio, ratio1; +#define INTERVAL (sample_evtime * 3) + cdp = audio_channel + 0; + ratio1 = cdp->per - cdp->evtime; + ratio = (ratio1 << 12) / INTERVAL; + if (cdp->evtime < sample_evtime || ratio1 >= INTERVAL) + ratio = 4096; + data0 = (data0 * ratio + data0p * (4096 - ratio)) >> 12; + + cdp = audio_channel + 1; + ratio1 = cdp->per - cdp->evtime; + ratio = (ratio1 << 12) / INTERVAL; + if (cdp->evtime < sample_evtime || ratio1 >= INTERVAL) + ratio = 4096; + data1 = (data1 * ratio + data1p * (4096 - ratio)) >> 12; + + cdp = audio_channel + 2; + ratio1 = cdp->per - cdp->evtime; + ratio = (ratio1 << 12) / INTERVAL; + if (cdp->evtime < sample_evtime || ratio1 >= INTERVAL) + ratio = 4096; + data2 = (data2 * ratio + data2p * (4096 - ratio)) >> 12; + + cdp = audio_channel + 3; + ratio1 = cdp->per - cdp->evtime; + ratio = (ratio1 << 12) / INTERVAL; + if (cdp->evtime < sample_evtime || ratio1 >= INTERVAL) + ratio = 4096; + data3 = (data3 * ratio + data3p * (4096 - ratio)) >> 12; + } + data1 += data2; + data0 += data3; + data0 += data1; + { + uae_u32 data = SBASEVAL16(2) + data0; + FINISH_DATA(16, 2); + PUT_SOUND_WORD (data); + } + END_BENCH + + check_sound_buffers (); +} + void sample8_handler (void) { BEGIN_BENCH @@ -176,6 +308,153 @@ void sample16s_handler (void) check_sound_buffers (); } +void sample16si_crux_handler (void) +{ + unsigned long delta, ratio; + + BEGIN_BENCH + + uae_u32 data0 = audio_channel[0].current_sample; + uae_u32 data1 = audio_channel[1].current_sample; + uae_u32 data2 = audio_channel[2].current_sample; + uae_u32 data3 = audio_channel[3].current_sample; + uae_u32 data0p = audio_channel[0].last_sample; + uae_u32 data1p = audio_channel[1].last_sample; + uae_u32 data2p = audio_channel[2].last_sample; + uae_u32 data3p = audio_channel[3].last_sample; + + DO_CHANNEL_1 (data0, 0); + DO_CHANNEL_1 (data1, 1); + DO_CHANNEL_1 (data2, 2); + DO_CHANNEL_1 (data3, 3); + DO_CHANNEL_1 (data0p, 0); + DO_CHANNEL_1 (data1p, 1); + DO_CHANNEL_1 (data2p, 2); + DO_CHANNEL_1 (data3p, 3); + + data0 &= audio_channel[0].adk_mask; + data0p &= audio_channel[0].adk_mask; + data1 &= audio_channel[1].adk_mask; + data1p &= audio_channel[1].adk_mask; + data2 &= audio_channel[2].adk_mask; + data2p &= audio_channel[2].adk_mask; + data3 &= audio_channel[3].adk_mask; + data3p &= audio_channel[3].adk_mask; + + { + struct audio_channel_data *cdp; + int ratio, ratio1; +#define INTERVAL (sample_evtime * 3) + cdp = audio_channel + 0; + ratio1 = cdp->per - cdp->evtime; + ratio = (ratio1 << 12) / INTERVAL; + if (cdp->evtime < sample_evtime || ratio1 >= INTERVAL) + ratio = 4096; + data0 = (data0 * ratio + data0p * (4096 - ratio)) >> 12; + + cdp = audio_channel + 1; + ratio1 = cdp->per - cdp->evtime; + ratio = (ratio1 << 12) / INTERVAL; + if (cdp->evtime < sample_evtime || ratio1 >= INTERVAL) + ratio = 4096; + data1 = (data1 * ratio + data1p * (4096 - ratio)) >> 12; + + cdp = audio_channel + 2; + ratio1 = cdp->per - cdp->evtime; + ratio = (ratio1 << 12) / INTERVAL; + if (cdp->evtime < sample_evtime || ratio1 >= INTERVAL) + ratio = 4096; + data2 = (data2 * ratio + data2p * (4096 - ratio)) >> 12; + + cdp = audio_channel + 3; + ratio1 = cdp->per - cdp->evtime; + ratio = (ratio1 << 12) / INTERVAL; + if (cdp->evtime < sample_evtime || ratio1 >= INTERVAL) + ratio = 4096; + data3 = (data3 * ratio + data3p * (4096 - ratio)) >> 12; + } + data1 += data2; + data0 += data3; + { + uae_u32 data = SBASEVAL16 (1) + data0; + FINISH_DATA (16, 1); + PUT_SOUND_WORD_RIGHT (data); + } + + { + uae_u32 data = SBASEVAL16 (1) + data1; + FINISH_DATA (16, 1); + PUT_SOUND_WORD_LEFT (data); + } + + END_BENCH + + check_sound_buffers (); +} + +void sample16si_rh_handler (void) +{ + unsigned long delta, ratio; + + BEGIN_BENCH + + uae_u32 data0 = audio_channel[0].current_sample; + uae_u32 data1 = audio_channel[1].current_sample; + uae_u32 data2 = audio_channel[2].current_sample; + uae_u32 data3 = audio_channel[3].current_sample; + uae_u32 data0p = audio_channel[0].last_sample; + uae_u32 data1p = audio_channel[1].last_sample; + uae_u32 data2p = audio_channel[2].last_sample; + uae_u32 data3p = audio_channel[3].last_sample; + + DO_CHANNEL_1 (data0, 0); + DO_CHANNEL_1 (data1, 1); + DO_CHANNEL_1 (data2, 2); + DO_CHANNEL_1 (data3, 3); + DO_CHANNEL_1 (data0p, 0); + DO_CHANNEL_1 (data1p, 1); + DO_CHANNEL_1 (data2p, 2); + DO_CHANNEL_1 (data3p, 3); + + data0 &= audio_channel[0].adk_mask; + data0p &= audio_channel[0].adk_mask; + data1 &= audio_channel[1].adk_mask; + data1p &= audio_channel[1].adk_mask; + data2 &= audio_channel[2].adk_mask; + data2p &= audio_channel[2].adk_mask; + data3 &= audio_channel[3].adk_mask; + data3p &= audio_channel[3].adk_mask; + + /* linear interpolation and summing up... */ + delta = audio_channel[0].per; + ratio = ((audio_channel[0].evtime % delta) << 8) / delta; + data0 = (data0 * (256 - ratio) + data0p * ratio) >> 8; + delta = audio_channel[1].per; + ratio = ((audio_channel[1].evtime % delta) << 8) / delta; + data1 = (data1 * (256 - ratio) + data1p * ratio) >> 8; + delta = audio_channel[2].per; + ratio = ((audio_channel[2].evtime % delta) << 8) / delta; + data1 += (data2 * (256 - ratio) + data2p * ratio) >> 8; + delta = audio_channel[3].per; + ratio = ((audio_channel[3].evtime % delta) << 8) / delta; + data0 += (data3 * (256 - ratio) + data3p * ratio) >> 8; + { + uae_u32 data = SBASEVAL16 (1) + data0; + FINISH_DATA (16, 1); + PUT_SOUND_WORD_RIGHT (data); + } + + { + uae_u32 data = SBASEVAL16 (1) + data1; + FINISH_DATA (16, 1); + PUT_SOUND_WORD_LEFT (data); + } + + END_BENCH + + check_sound_buffers (); +} + void sample8s_handler (void) { BEGIN_BENCH @@ -220,6 +499,14 @@ void sample16s_handler (void) { sample16_handler(); } +void sample16si_crux_handler (void) +{ + sample16i_crux_handler(); +} +void sample16si_rh_handler (void) +{ + sample16i_rh_handler(); +} #endif static uae_u8 int2ulaw (int ch) @@ -301,6 +588,7 @@ static void audio_handler (int nr) cdp->evtime = cdp->per; cdp->dat = cdp->nextdat; + cdp->last_sample = cdp->current_sample; cdp->current_sample = (sample8_t)(cdp->dat >> 8); cdp->state = 2; @@ -318,6 +606,7 @@ static void audio_handler (int nr) if (currprefs.produce_sound == 0) cdp->per = 65535; + cdp->last_sample = cdp->current_sample; cdp->current_sample = (sample8_t)(cdp->dat & 0xFF); cdp->evtime = cdp->per; @@ -353,6 +642,7 @@ static void audio_handler (int nr) if ((INTREQR() & (0x80 << nr)) && !cdp->dmaen) { cdp->state = 0; + cdp->last_sample = 0; cdp->current_sample = 0; break; } else { @@ -367,6 +657,7 @@ static void audio_handler (int nr) cdp->intreq2 = 0; cdp->dat = cdp->nextdat; + cdp->last_sample = cdp->current_sample; cdp->current_sample = (sample8_t)(cdp->dat >> 8); if (cdp->dmaen && napnav) @@ -423,47 +714,59 @@ void audio_reset (void) next_sample_evtime = sample_evtime; } -static __inline__ int sound_prefs_changed (void) +STATIC_INLINE int sound_prefs_changed (void) { return (changed_prefs.produce_sound != currprefs.produce_sound || changed_prefs.stereo != currprefs.stereo + || changed_prefs.sound_freq != currprefs.sound_freq || changed_prefs.sound_bits != currprefs.sound_bits); } void check_prefs_changed_audio (void) { - if (! sound_available || ! sound_prefs_changed ()) - return; - - close_sound (); - - currprefs.produce_sound = changed_prefs.produce_sound; - currprefs.stereo = changed_prefs.stereo; - currprefs.sound_bits = changed_prefs.sound_bits; + if (sound_available && sound_prefs_changed ()) { + close_sound (); - if (currprefs.produce_sound < 2) - return; - - if (init_sound ()) { - last_cycles = cycles - 1; - next_sample_evtime = sample_evtime; - return; - } - if (! sound_available) { - fprintf (stderr, "Sound is not supported.\n"); - } else { - fprintf (stderr, "Sorry, can't initialize sound.\n"); - currprefs.produce_sound = 0; - /* So we don't do this every frame */ - changed_prefs.produce_sound = 0; + currprefs.produce_sound = changed_prefs.produce_sound; + currprefs.stereo = changed_prefs.stereo; + currprefs.sound_bits = changed_prefs.sound_bits; + currprefs.sound_freq = changed_prefs.sound_freq; + + if (currprefs.produce_sound >= 2) { + if (init_sound ()) { + last_cycles = cycles - 1; + next_sample_evtime = sample_evtime; + } else + if (! sound_available) { + fprintf (stderr, "Sound is not supported.\n"); + } else { + fprintf (stderr, "Sorry, can't initialize sound.\n"); + currprefs.produce_sound = 0; + /* So we don't do this every frame */ + changed_prefs.produce_sound = 0; + } + } } + /* Select the right interpolation method. */ + if (sample_handler == sample16_handler + || sample_handler == sample16i_crux_handler + || sample_handler == sample16i_rh_handler) + sample_handler = (currprefs.sound_interpol == 0 ? sample16_handler + : currprefs.sound_interpol == 1 ? sample16i_rh_handler + : sample16i_crux_handler); + else if (sample_handler == sample16s_handler + || sample_handler == sample16si_crux_handler + || sample_handler == sample16si_rh_handler) + sample_handler = (currprefs.sound_interpol == 0 ? sample16s_handler + : currprefs.sound_interpol == 1 ? sample16si_rh_handler + : sample16si_crux_handler); } void update_audio (void) { unsigned long int n_cycles; - if (currprefs.produce_sound == 0) + if (currprefs.produce_sound < 2) return; n_cycles = cycles - last_cycles;