shithub: candycrisis

Download patch

ref: 1de494ed50a7b368dafbcdf1b77f3c1e87332f85
parent: 7d5a28fd902385d1517de4ae47f73a8150dd02e3
author: Iliyas Jorio <iliyas@jor.io>
date: Thu Jul 30 17:58:13 EDT 2020

Implement mod playback speed multiplier

--- a/src/music.cpp
+++ b/src/music.cpp
@@ -38,7 +38,7 @@
 {
     if (s_musicChannel && !s_musicFast)
     {
-        printf("Implement Me! FastMusic (1.3x playback speed)\n");
+        s_musicChannel->SetPlaybackSpeed(1.3);
         s_musicFast = true;
     }
 }
@@ -47,7 +47,7 @@
 {
     if (s_musicChannel && s_musicFast)
     {
-        printf("Implement Me! SlowMusic\n");
+        s_musicChannel->SetPlaybackSpeed(1.0);
         s_musicFast = false;
     }
 }
--- a/src/support/ModStream.cpp
+++ b/src/support/ModStream.cpp
@@ -10,6 +10,7 @@
         , replayBuffer(2048*8)
         , rbOffset(0)
         , rbLength(0)
+        , playbackSpeedMult(1.0)
 {
     ibxm::data d;
     d.buffer = moduleFile.data();
@@ -26,6 +27,11 @@
     printf("Rewind not supported\n");
 }
 
+void ModStream::SetPlaybackSpeed(double f)
+{
+    playbackSpeedMult = f;
+}
+
 void ModStream::FillBuffer(int16_t *output, int length)
 {
     length /= 2;
@@ -34,7 +40,7 @@
         // refill replay buffer if exhausted
         if (rbLength == 0) {
             rbOffset = 0;
-            rbLength = ibxm::replay_get_audio(replay, replayBuffer.data(), 0);
+            rbLength = ibxm::replay_get_audio(replay, replayBuffer.data(), 0, (int)(playbackSpeedMult * 100.0));
         }
 
         // number of stereo samples to copy from replay buffer to output buffer
--- a/src/support/ModStream.h
+++ b/src/support/ModStream.h
@@ -16,6 +16,7 @@
     std::vector<int> replayBuffer;
     int rbOffset;
     int rbLength;
+    double playbackSpeedMult;
 
     void Rewind2();
     void FillBuffer(int16_t* buffer, int length);
@@ -22,5 +23,6 @@
 
 public:
     ModStream(std::vector<char>&& rawModule);
+    void SetPlaybackSpeed(double f);
 };
 }
\ No newline at end of file
--- a/src/support/ibxm.c
+++ b/src/support/ibxm.c
@@ -1854,21 +1854,21 @@
     return replay;
 }
 
-static int calculate_tick_len( int tempo, int sample_rate ) {
-    return ( sample_rate * 5 ) / ( tempo * 2 );
+static int calculate_tick_len( int tempo, int sample_rate, int speed_percent ) {
+    return 100 * ( sample_rate * 5 ) / ( tempo * 2 ) / speed_percent;
 }
 
 /* Returns the length of the output buffer required by replay_get_audio(). */
-int calculate_mix_buf_len( int sample_rate ) {
-    return ( calculate_tick_len( 32, sample_rate ) + 65 ) * 4;
+int calculate_mix_buf_len( int sample_rate, int speed_percent ) {
+    return ( calculate_tick_len( 32, sample_rate, speed_percent ) + 65 ) * 4;
 }
 
 /* Returns the song duration in samples at the current sampling rate. */
-int replay_calculate_duration( struct replay *replay ) {
+int replay_calculate_duration( struct replay *replay, int speed_multiplier_percent ) {
     int count = 0, duration = 0;
     replay_set_sequence_pos( replay, 0 );
     while( count < 1 ) {
-        duration += calculate_tick_len( replay->tempo, replay->sample_rate );
+        duration += calculate_tick_len( replay->tempo, replay->sample_rate, speed_multiplier_percent );
         count = replay_tick( replay );
     }
     replay_set_sequence_pos( replay, 0 );
@@ -1877,6 +1877,7 @@
 
 /* Seek to approximately the specified sample position.
    The actual sample position reached is returned. */
+/*
 int replay_seek( struct replay *replay, int sample_pos ) {
     int idx, tick_len, current_pos = 0;
     replay_set_sequence_pos( replay, 0 );
@@ -1892,6 +1893,7 @@
     }
     return current_pos;
 }
+ */
 
 static void replay_volume_ramp( struct replay *replay, int *mix_buf, int tick_len ) {
     int idx, a1, a2, ramp_rate = 256 * 2048 / replay->sample_rate;
@@ -1914,9 +1916,9 @@
 
 /* Generates audio and returns the number of stereo samples written into mix_buf.
    Individual channels may be excluded using the mute bitmask. */
-int replay_get_audio( struct replay *replay, int *mix_buf, int mute ) {
+int replay_get_audio( struct replay *replay, int *mix_buf, int mute, int speed_multiplier ) {
     struct channel *channel;
-    int idx, num_channels, tick_len = calculate_tick_len( replay->tempo, replay->sample_rate );
+    int idx, num_channels, tick_len = calculate_tick_len( replay->tempo, replay->sample_rate, speed_multiplier );
     /* Clear output buffer. */
     memset( mix_buf, 0, ( tick_len + 65 ) * 4 * sizeof( int ) );
     /* Resample. */
--- a/src/support/ibxm.h
+++ b/src/support/ibxm.h
@@ -54,19 +54,19 @@
 /* Deallocate the specified replay. */
 void dispose_replay(struct replay *replay);
 /* Returns the song duration in samples at the current sampling rate. */
-int replay_calculate_duration(struct replay *replay);
+int replay_calculate_duration(struct replay *replay, int speed_multiplier_percent);
 /* Seek to approximately the specified sample position.
    The actual sample position reached is returned. */
-int replay_seek(struct replay *replay, int sample_pos);
+//int replay_seek(struct replay *replay, int sample_pos);
 /* Set the pattern in the sequence to play. The tempo is reset to the default. */
 void replay_set_sequence_pos(struct replay *replay, int pos);
 /* Generates audio and returns the number of stereo samples written into mix_buf.
    Individual channels may be excluded using the mute bitmask. */
-int replay_get_audio(struct replay *replay, int *mix_buf, int mute);
+int replay_get_audio(struct replay *replay, int *mix_buf, int mute, int speed_multiplier_percent);
 /* Returns the currently playing pattern in the sequence.*/
 int replay_get_sequence_pos(struct replay *replay);
 /* Returns the currently playing row in the pattern. */
 int replay_get_row(struct replay *replay);
 /* Returns the length of the output buffer required by replay_get_audio(). */
-int calculate_mix_buf_len(int sample_rate);
+int calculate_mix_buf_len(int sample_rate, int speed_multiplier_percent);