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