1919#define CLIP8 (v ) \
2020(v) = (((v) <= -128) ? -128 : (((v) >= 127) ? 127 : (v)))
2121
22+ #define MIX_BUFFER_SIZE SOUND_BUFFER_SIZE
2223static struct {
23- int32_t wave [SOUND_BUFFER_SIZE ];
24- int32_t Echo [24000 ];
25- int32_t MixBuffer [SOUND_BUFFER_SIZE ];
26- int32_t EchoBuffer [SOUND_BUFFER_SIZE ];
24+ int32_t wave [MIX_BUFFER_SIZE / 2 ];
25+ int32_t Echo [16000 ]; // (512 * 0xF * so.playback_rate) / 32040 * 2
26+ int32_t MixBuffer [MIX_BUFFER_SIZE ];
27+ int32_t EchoBuffer [MIX_BUFFER_SIZE ];
2728 int32_t FilterTaps [8 ];
28- uint8_t FilterTapDefinitionBitfield ;
29+ uint32_t FilterTapDefinitionBitfield ;
2930 /* In the above, bit I is set if FilterTaps[I] is non-zero. */
3031 uint32_t Z ;
3132 int32_t Loop [16 ];
@@ -95,6 +96,11 @@ static const uint32_t IncreaseRate [32] =
9596
9697#define SustainRate DecreaseRateExp
9798
99+ static const int32_t EnvSteps [10 ] =
100+ {
101+ 0 , 64 , 619 , 619 , 128 , 1 , 64 , 55 , 64 , 619
102+ };
103+
98104#define FIXED_POINT 0x10000UL
99105#define FIXED_POINT_REMAINDER 0xffffUL
100106#define FIXED_POINT_SHIFT 16
@@ -231,8 +237,12 @@ void S9xSetEchoFeedback(int32_t feedback)
231237
232238void S9xSetEchoDelay (int32_t delay )
233239{
234- SoundData .echo_buffer_size = (512 * delay * so .playback_rate ) / 32040 ;
240+ SoundData .echo_buffer_size = (512 * ( delay & 0xF ) * so .playback_rate ) / 32040 ;
235241 SoundData .echo_buffer_size <<= 1 ;
242+ // This can happen if so.playback_rate frequency is higher than 32040. This check replaces a possible crash with at worse bogus echo...
243+ // You have to enlarge Echo to accommodate higher playback rate
244+ if (SoundData .echo_buffer_size > sizeof (Echo ) / sizeof (Echo [0 ]))
245+ SoundData .echo_buffer_size = sizeof (Echo ) / sizeof (Echo [0 ]);
236246 if (SoundData .echo_buffer_size )
237247 SoundData .echo_ptr %= SoundData .echo_buffer_size ;
238248 else
@@ -755,72 +765,78 @@ stereo_exit:;
755765
756766void S9xMixSamples (int16_t * buffer , int32_t sample_count )
757767{
758- int32_t J ;
759- int32_t I ;
768+ for (int32_t remaining = sample_count ; remaining > 0 ; remaining -= sample_count )
769+ {
770+ sample_count = MIN (sizeof (MixBuffer ) / sizeof (MixBuffer [0 ]), remaining );
760771
761- if (SoundData .echo_enable )
762- memset (EchoBuffer , 0 , sample_count * sizeof (EchoBuffer [0 ]));
763- memset (MixBuffer , 0 , sample_count * sizeof (MixBuffer [0 ]));
764- MixStereo (sample_count );
772+ int32_t J ;
773+ int32_t I ;
765774
766- /* Mix and convert waveforms */
767- if (SoundData .echo_enable && SoundData .echo_buffer_size )
768- {
769- /* 16-bit stereo sound with echo enabled ... */
770- if (FilterTapDefinitionBitfield == 0 )
775+ if (SoundData .echo_enable && SoundData .echo_buffer_size )
776+ memset (EchoBuffer , 0 , sample_count * sizeof (EchoBuffer [0 ]));
777+ memset (MixBuffer , 0 , sample_count * sizeof (MixBuffer [0 ]));
778+ MixStereo (sample_count );
779+
780+ /* Mix and convert waveforms */
781+ if (SoundData .echo_enable && SoundData .echo_buffer_size )
771782 {
772- /* ... but no filter defined . */
773- for ( J = 0 ; J < sample_count ; J ++ )
783+ /* 16-bit stereo sound with echo enabled .. . */
784+ if ( FilterTapDefinitionBitfield == 0 )
774785 {
775- int32_t E = Echo [SoundData .echo_ptr ];
776- Echo [SoundData .echo_ptr ++ ] = (E * SoundData .echo_feedback ) / 128 + EchoBuffer [J ];
786+ /* ... but no filter defined. */
787+ for (J = 0 ; J < sample_count ; J ++ )
788+ {
789+ int32_t E = Echo [SoundData .echo_ptr ];
790+ Echo [SoundData .echo_ptr ++ ] = (E * SoundData .echo_feedback ) / 128 + EchoBuffer [J ];
777791
778- if (SoundData .echo_ptr >= SoundData .echo_buffer_size )
779- SoundData .echo_ptr = 0 ;
792+ if (SoundData .echo_ptr >= SoundData .echo_buffer_size )
793+ SoundData .echo_ptr = 0 ;
780794
781- I = (MixBuffer [J ] * SoundData .master_volume [J & 1 ] + E * SoundData .echo_volume [J & 1 ]) / VOL_DIV16 ;
782- CLIP16 (I );
783- buffer [J ] = I ;
795+ I = (MixBuffer [J ] * SoundData .master_volume [J & 1 ] + E * SoundData .echo_volume [J & 1 ]) / VOL_DIV16 ;
796+ CLIP16 (I );
797+ buffer [J ] = I ;
798+ }
799+ }
800+ else
801+ {
802+ /* ... with filter defined. */
803+ for (J = 0 ; J < sample_count ; J ++ )
804+ {
805+ int32_t E ;
806+ Loop [(Z - 0 ) & 15 ] = Echo [SoundData .echo_ptr ];
807+ E = Loop [(Z - 0 ) & 15 ] * FilterTaps [0 ];
808+ if (FilterTapDefinitionBitfield & 0x02 ) E += Loop [(Z - 2 ) & 15 ] * FilterTaps [1 ];
809+ if (FilterTapDefinitionBitfield & 0x04 ) E += Loop [(Z - 4 ) & 15 ] * FilterTaps [2 ];
810+ if (FilterTapDefinitionBitfield & 0x08 ) E += Loop [(Z - 6 ) & 15 ] * FilterTaps [3 ];
811+ if (FilterTapDefinitionBitfield & 0x10 ) E += Loop [(Z - 8 ) & 15 ] * FilterTaps [4 ];
812+ if (FilterTapDefinitionBitfield & 0x20 ) E += Loop [(Z - 10 ) & 15 ] * FilterTaps [5 ];
813+ if (FilterTapDefinitionBitfield & 0x40 ) E += Loop [(Z - 12 ) & 15 ] * FilterTaps [6 ];
814+ if (FilterTapDefinitionBitfield & 0x80 ) E += Loop [(Z - 14 ) & 15 ] * FilterTaps [7 ];
815+ E /= 128 ;
816+ Z ++ ;
817+
818+ Echo [SoundData .echo_ptr ++ ] = (E * SoundData .echo_feedback ) / 128 + EchoBuffer [J ];
819+
820+ if (SoundData .echo_ptr >= SoundData .echo_buffer_size )
821+ SoundData .echo_ptr = 0 ;
822+
823+ I = (MixBuffer [J ] * SoundData .master_volume [J & 1 ] + E * SoundData .echo_volume [J & 1 ]) / VOL_DIV16 ;
824+ CLIP16 (I );
825+ buffer [J ] = I ;
826+ }
784827 }
785828 }
786829 else
787830 {
788- /* ... with filter defined. */
831+ /* 16-bit mono or stereo sound, no echo */
789832 for (J = 0 ; J < sample_count ; J ++ )
790833 {
791- int32_t E ;
792- Loop [(Z - 0 ) & 15 ] = Echo [SoundData .echo_ptr ];
793- E = Loop [(Z - 0 ) & 15 ] * FilterTaps [0 ];
794- if (FilterTapDefinitionBitfield & 0x02 ) E += Loop [(Z - 2 ) & 15 ] * FilterTaps [1 ];
795- if (FilterTapDefinitionBitfield & 0x04 ) E += Loop [(Z - 4 ) & 15 ] * FilterTaps [2 ];
796- if (FilterTapDefinitionBitfield & 0x08 ) E += Loop [(Z - 6 ) & 15 ] * FilterTaps [3 ];
797- if (FilterTapDefinitionBitfield & 0x10 ) E += Loop [(Z - 8 ) & 15 ] * FilterTaps [4 ];
798- if (FilterTapDefinitionBitfield & 0x20 ) E += Loop [(Z - 10 ) & 15 ] * FilterTaps [5 ];
799- if (FilterTapDefinitionBitfield & 0x40 ) E += Loop [(Z - 12 ) & 15 ] * FilterTaps [6 ];
800- if (FilterTapDefinitionBitfield & 0x80 ) E += Loop [(Z - 14 ) & 15 ] * FilterTaps [7 ];
801- E /= 128 ;
802- Z ++ ;
803-
804- Echo [SoundData .echo_ptr ++ ] = (E * SoundData .echo_feedback ) / 128 + EchoBuffer [J ];
805-
806- if (SoundData .echo_ptr >= SoundData .echo_buffer_size )
807- SoundData .echo_ptr = 0 ;
808-
809- I = (MixBuffer [J ] * SoundData .master_volume [J & 1 ] + E * SoundData .echo_volume [J & 1 ]) / VOL_DIV16 ;
834+ I = (MixBuffer [J ] * SoundData .master_volume [J & 1 ]) / VOL_DIV16 ;
810835 CLIP16 (I );
811836 buffer [J ] = I ;
812837 }
813838 }
814- }
815- else
816- {
817- /* 16-bit mono or stereo sound, no echo */
818- for (J = 0 ; J < sample_count ; J ++ )
819- {
820- I = (MixBuffer [J ] * SoundData .master_volume [J & 1 ]) / VOL_DIV16 ;
821- CLIP16 (I );
822- buffer [J ] = I ;
823- }
839+ buffer += sample_count ;
824840 }
825841}
826842
@@ -912,7 +928,6 @@ void S9xSetPlaybackRate(uint32_t playback_rate)
912928
913929 if (playback_rate )
914930 {
915- int32_t steps [] = {0 , 64 , 619 , 619 , 128 , 1 , 64 , 55 , 64 , 619 };
916931 int32_t i , u ;
917932
918933 /* notaz: calculate a value (let's call it freqbase) to simplify channel freq calculations later. */
@@ -921,7 +936,7 @@ void S9xSetPlaybackRate(uint32_t playback_rate)
921936
922937 for (u = 0 ; u < 10 ; u ++ )
923938 {
924- int64_t fp1000su = ((int64_t ) FIXED_POINT * 1000 * steps [u ]);
939+ int64_t fp1000su = ((int64_t ) FIXED_POINT * 1000 * EnvSteps [u ]);
925940
926941 for (i = 0 ; i < 16 ; i ++ )
927942 AttackERate [i ][u ] = (uint32_t ) (fp1000su / (AttackRate [i ] * playback_rate ));
0 commit comments