music_modplug.c
author Ozkan Sezer <sezeroz@gmail.com>
Thu, 11 Oct 2018 11:50:10 +0300
branchSDL-1.2
changeset 902 6c862e733898
parent 561 87bdb4c81c0b
child 617 87116a42526e
permissions -rw-r--r--
remove smpeg support completely and backport libmpg123 support instead.
     1 #ifdef MODPLUG_MUSIC
     2 
     3 #include "music_modplug.h"
     4 
     5 static int current_output_channels=0;
     6 static int music_swap8=0;
     7 static int music_swap16=0;
     8 static ModPlug_Settings settings;
     9 
    10 int modplug_init(SDL_AudioSpec *spec)
    11 {
    12 	ModPlug_GetSettings(&settings);
    13 	settings.mFlags=MODPLUG_ENABLE_OVERSAMPLING;
    14 	current_output_channels=spec->channels;
    15 	settings.mChannels=spec->channels>1?2:1;
    16 	settings.mBits=spec->format&0xFF;
    17 
    18 	music_swap8 = 0;
    19 	music_swap16 = 0;
    20 
    21 	switch(spec->format)
    22 	{
    23 		case AUDIO_U8:
    24 		case AUDIO_S8: {
    25 			if ( spec->format == AUDIO_S8 ) {
    26 				music_swap8 = 1;
    27 			}
    28 			settings.mBits=8;
    29 		}
    30 		break;
    31 
    32 		case AUDIO_S16LSB:
    33 		case AUDIO_S16MSB: {
    34 			/* See if we need to correct MikMod mixing */
    35 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
    36 			if ( spec->format == AUDIO_S16MSB ) {
    37 #else
    38 			if ( spec->format == AUDIO_S16LSB ) {
    39 #endif
    40 				music_swap16 = 1;
    41 			}
    42 			settings.mBits=16;
    43 		}
    44 		break;
    45 
    46 		default: {
    47 			Mix_SetError("Unknown hardware audio format");
    48 			return -1;
    49 		}
    50 
    51 	}
    52 
    53 	settings.mFrequency=spec->freq; /*TODO: limit to 11025, 22050, or 44100 ? */
    54 	settings.mResamplingMode=MODPLUG_RESAMPLE_FIR;
    55 	settings.mReverbDepth=0;
    56 	settings.mReverbDelay=100;
    57 	settings.mBassAmount=0;
    58 	settings.mBassRange=50;
    59 	settings.mSurroundDepth=0;
    60 	settings.mSurroundDelay=10;
    61 	settings.mLoopCount=0;
    62 	ModPlug_SetSettings(&settings);
    63 	return 0;
    64 }
    65 
    66 /* Uninitialize the music players */
    67 void modplug_exit()
    68 {
    69 }
    70 
    71 /* Set the volume for a modplug stream */
    72 void modplug_setvolume(modplug_data *music, int volume)
    73 {
    74 	ModPlug_SetMasterVolume(music->file, volume*4);
    75 }
    76 
    77 /* Load a modplug stream from an SDL_RWops object */
    78 modplug_data *modplug_new_RW(SDL_RWops *rw, int freerw)
    79 {
    80 	modplug_data *music=NULL;
    81 	long offset,sz;
    82 	char *buf=NULL;
    83 
    84 	offset = SDL_RWtell(rw);
    85 	SDL_RWseek(rw, 0, RW_SEEK_END);
    86 	sz = SDL_RWtell(rw)-offset;
    87 	SDL_RWseek(rw, offset, RW_SEEK_SET);
    88 	buf=(char*)SDL_malloc(sz);
    89 	if(buf)
    90 	{
    91 		if(SDL_RWread(rw, buf, sz, 1)==1)
    92 		{
    93 			music=(modplug_data*)SDL_malloc(sizeof(modplug_data));
    94 			if (music)
    95 			{
    96 				music->playing=0;
    97 				music->file=ModPlug_Load(buf,sz);
    98 				if(!music->file)
    99 				{
   100 					SDL_free(music);
   101 					music=NULL;
   102 				}
   103 			}
   104 			else
   105 			{
   106 				SDL_OutOfMemory();
   107 			}
   108 		}
   109 		SDL_free(buf);
   110 	}
   111 	else
   112 	{
   113 		SDL_OutOfMemory();
   114 	}
   115 	if (freerw) {
   116 		SDL_RWclose(rw);
   117 	}
   118 	return music;
   119 }
   120 
   121 /* Start playback of a given modplug stream */
   122 void modplug_play(modplug_data *music)
   123 {
   124 	ModPlug_Seek(music->file,0);
   125 	music->playing=1;
   126 }
   127 
   128 /* Return non-zero if a stream is currently playing */
   129 int modplug_playing(modplug_data *music)
   130 {
   131 	return music && music->playing;
   132 }
   133 
   134 /* Play some of a stream previously started with modplug_play() */
   135 int modplug_playAudio(modplug_data *music, Uint8 *stream, int len)
   136 {
   137 	if (current_output_channels > 2) {
   138 		int small_len = 2 * len / current_output_channels;
   139 		int i;
   140 		Uint8 *src, *dst;
   141 
   142 		i=ModPlug_Read(music->file, stream, small_len);
   143 		if(i<small_len)
   144 		{
   145 			memset(stream+i,0,small_len-i);
   146 			music->playing=0;
   147 		}
   148 		/* and extend to len by copying channels */
   149 		src = stream + small_len;
   150 		dst = stream + len;
   151 
   152 		switch (settings.mBits) {
   153 			case 8:
   154 				for ( i=small_len/2; i; --i ) {
   155 					src -= 2;
   156 					dst -= current_output_channels;
   157 					dst[0] = src[0];
   158 					dst[1] = src[1];
   159 					dst[2] = src[0];
   160 					dst[3] = src[1];
   161 					if (current_output_channels == 6) {
   162 						dst[4] = src[0];
   163 						dst[5] = src[1];
   164 					}
   165 				}
   166 				break;
   167 			case 16:
   168 				for ( i=small_len/4; i; --i ) {
   169 					src -= 4;
   170 					dst -= 2 * current_output_channels;
   171 					dst[0] = src[0];
   172 					dst[1] = src[1];
   173 					dst[2] = src[2];
   174 					dst[3] = src[3];
   175 					dst[4] = src[0];
   176 					dst[5] = src[1];
   177 					dst[6] = src[2];
   178 					dst[7] = src[3];
   179 					if (current_output_channels == 6) {
   180 						dst[8] = src[0];
   181 						dst[9] = src[1];
   182 						dst[10] = src[2];
   183 						dst[11] = src[3];
   184 					}
   185 				}
   186 				break;
   187 		}
   188 	} else {
   189 		int i=ModPlug_Read(music->file, stream, len);
   190 		if(i<len)
   191 		{
   192 			memset(stream+i,0,len-i);
   193 			music->playing=0;
   194 		}
   195 	}
   196 	if ( music_swap8 ) {
   197 		Uint8 *dst;
   198 		int i;
   199 
   200 		dst = stream;
   201 		for ( i=len; i; --i ) {
   202 			*dst++ ^= 0x80;
   203 		}
   204 	} else
   205 	if ( music_swap16 ) {
   206 		Uint8 *dst, tmp;
   207 		int i;
   208 
   209 		dst = stream;
   210 		for ( i=(len/2); i; --i ) {
   211 			tmp = dst[0];
   212 			dst[0] = dst[1];
   213 			dst[1] = tmp;
   214 			dst += 2;
   215 		}
   216 	}
   217 	return 0;
   218 }
   219 
   220 /* Stop playback of a stream previously started with modplug_play() */
   221 void modplug_stop(modplug_data *music)
   222 {
   223 	music->playing=0;
   224 }
   225 
   226 /* Close the given modplug stream */
   227 void modplug_delete(modplug_data *music)
   228 {
   229 	ModPlug_Unload(music->file);
   230 	SDL_free(music);
   231 }
   232 
   233 /* Jump (seek) to a given position (time is in seconds) */
   234 void modplug_jump_to_time(modplug_data *music, double time)
   235 {
   236 	ModPlug_Seek(music->file,(int)(time*1000));
   237 }
   238 
   239 #endif