(Courtesy of Jerome Zago on the SDL mailing list...)
authorRyan C. Gordon <icculus@icculus.org>
Sun, 09 Nov 2003 20:11:30 +0000
changeset 2375fb7a859f158
parent 236 66bbfd8bb710
child 238 2eae977be9d0
(Courtesy of Jerome Zago on the SDL mailing list...)


+++++ Synopsis:
Mix_FadeInMusic(Music, 0, chunksize) following Mix_VolumeMusic(0) doesn't take
into account the latter for low values of "chunksize" when "Music" is a mod.

+++++ How to reproduce the problem:
#####
$ cat testmusic.c
#include <SDL/SDL.h>
#include <SDL/SDL_mixer.h>
#include <stdlib.h>

int main (int argc, char **argv)
{
if (argc != 4) {
fprintf(stderr, "Usage: %s <music file> <chunksize> <ms>\n", argv[0]);
return 1;
}

if (SDL_Init(SDL_INIT_AUDIO) >= 0) {
if (Mix_OpenAudio(44100, AUDIO_S16, 1, atoi(argv[2])) >= 0) {
Mix_Music* Music = Mix_LoadMUS(argv[1]);
if (Music) {
Mix_VolumeMusic(0);
Mix_FadeInMusic(Music, 0, atoi(argv[3]));
printf("Now playing\n");
SDL_Delay(2000);
Mix_FreeMusic(Music);
}
}
}
SDL_Quit();
return 0;
};

$ cc -g -O2 -Wall -I/usr/include/SDL -D_REENTRANT -L/usr/lib -lSDL \
-lpthread -lSDL_mixer testmusic.c -o testmusic

$ ./testmusic /usr/local/share/heroes/mod/heroes01.xm 512 10
Now playing
[ I hear the music => BAD ]

$ ./testmusic /usr/local/share/heroes/mod/heroes01.xm 512 11
Now playing
[ I don't hear the music => GOOD ]

$ ./testmusic /usr/local/share/heroes/mod/heroes01.xm 1024 22
Now playing
[ I hear the music => BAD ]

$ ./testmusic /usr/local/share/heroes/mod/heroes01.xm 1024 23
Now playing
[ I don't hear the music => GOOD ]

$ ./testmusic /usr/local/share/heroes/mod/heroes01.xm 2048 45
Now playing
[ I hear the music => BAD ]

$ ./testmusic /usr/local/share/heroes/mod/heroes01.xm 2048 46
Now playing
[ I don't hear the music => GOOD ]
#####

+++++ Comments
heroes01.xm comes from
http://prdownloads.sourceforge.net/heroes/heroes-sound-tracks-1.0.tar.bz2.
All the other modules I've tested show the same behaviour.

+++++ Analysis (using SDL_mixer source code):
It appears that the lowest value of chunksize for which the volume is taken
into account is equal to ms_per_step = (int) (((float)mixer->samples *
1000.0) / mixer->freq) [file music.c, function open_music()].
This also means that music->fade_steps [function Mix_FadeInMusicPos()] = 0
when and only when the volume isn't taken into account.
In this case, note that music_internal_volume() is never called from
music_mixer(), since (music_playing->fade_step++ < music_playing->fade_steps)
is never verified. This might explain the bug.

+++++ Testing environment:
- Mandrake Linux 9.1 i386
- SDL_mixer 1.2.4 (Mandrake package), 1.2.5 or CVS (both built from scratch)
- Athlon XP 1500+
- SB Live!

More details upon request. Thanks for your time.


--------

This is related to my previous message:
[SDL] Strange behaviour of Mix_FadeInMusic (1.2.5) on mods
http://www.libsdl.org/pipermail/sdl/2003-November/057749.html

+++++ Analysis (continued):
It appears that calling mikmod's Player_SetVolume() does nothing when called
before Player_Start() since pf [global variable initialized in mplayer.c] is
NULL then. This API seems a bit strange to me but well...
music.c
     1.1 --- a/music.c	Mon Oct 06 15:41:04 2003 +0000
     1.2 +++ b/music.c	Sun Nov 09 20:11:30 2003 +0000
     1.3 @@ -135,6 +135,7 @@
     1.4  static int ms_per_step;
     1.5  
     1.6  /* Local low-level functions prototypes */
     1.7 +static void music_internal_initialize_volume(void);
     1.8  static void music_internal_volume(int volume);
     1.9  static int  music_internal_play(Mix_Music *music, double position);
    1.10  static int  music_internal_position(double position);
    1.11 @@ -620,10 +621,8 @@
    1.12  	music_playing = music;
    1.13  
    1.14  	/* Set the initial volume */
    1.15 -	if ( music->fading == MIX_FADING_IN ) {
    1.16 -		music_internal_volume(0);
    1.17 -	} else {
    1.18 -		music_internal_volume(music_volume);
    1.19 +	if ( music->type != MUS_MOD ) {
    1.20 +		music_internal_initialize_volume();
    1.21  	}
    1.22  
    1.23  	/* Set up for playback */
    1.24 @@ -641,6 +640,8 @@
    1.25  #ifdef MOD_MUSIC
    1.26  	    case MUS_MOD:
    1.27  		Player_Start(music->data.module);
    1.28 +		/* Player_SetVolume() does nothing before Player_Start() */
    1.29 +		music_internal_initialize_volume();
    1.30  		break;
    1.31  #endif
    1.32  #ifdef MID_MUSIC
    1.33 @@ -788,6 +789,16 @@
    1.34  	return(retval);
    1.35  }
    1.36  
    1.37 +/* Set the music's initial volume */
    1.38 +static void music_internal_initialize_volume(void)
    1.39 +{
    1.40 +	if ( music_playing->fading == MIX_FADING_IN ) {
    1.41 +		music_internal_volume(0);
    1.42 +	} else {
    1.43 +		music_internal_volume(music_volume);
    1.44 +	}
    1.45 +}
    1.46 +
    1.47  /* Set the music volume */
    1.48  static void music_internal_volume(int volume)
    1.49  {