/* Halt playing of a particular channel */
int Mix_HaltChannel(int which)
{
	int i;

	if ( which == -1 ) {
		for ( i=0; i<num_channels; ++i ) {
			Mix_HaltChannel(i);
		}
	} else if ( which < num_channels ) {
		SDL_LockAudio();
		if (mix_channel[which].playing) {
			if (mix_channel[which].is_music)
				Mix_HaltMusicCh(mix_channel[which].music);
			else _Mix_channel_done_playing(which);
			mix_channel[which].playing = 0;
			mix_channel[which].looping = 0;
		}
		mix_channel[which].expire = 0;
		if(mix_channel[which].fading != MIX_NO_FADING) /* Restore volume */
			mix_channel[which].volume = mix_channel[which].fade_volume_reset;
		mix_channel[which].fading = MIX_NO_FADING;
		SDL_UnlockAudio();
	}
	return(0);
}
int _Mix_SetupChunk(int which, Mix_Chunk* chunk, int loops, int ticks, int fade_in, int loop_start)
{
	int loop_start_bytes;

	/* Lock the mixer while modifying the playing channels */
	SDL_LockAudio();
	{
		/* If which is -1, play on the first free channel */
		if ( which == -1 ) {
			which = get_available_channel();
			if ( which == -1 ) {
				Mix_SetError("No free channels available");
				which = -1;
			}
		}

        loop_start_bytes = milliseconds_to_bytes(loop_start);
        if (((Uint32) loop_start_bytes) >= chunk->alen) {
            loop_start_bytes = 0;
        }

		/* Queue up the audio data for this channel */
		if ( which >= 0 && which < num_channels ) {
			Uint32 sdl_ticks = SDL_GetTicks();
			if (Mix_Playing(which))
				_Mix_channel_done_playing(which);
			if (mix_channel[which].is_music) {
				mix_channel[which].music = NULL;
				mix_channel[which].sound = (Mix_Sound *) malloc(sizeof(Mix_Sound));
				mix_channel[which].is_music = SDL_FALSE;
			}
			mix_channel[which].sound->samples = chunk->abuf + loop_start_bytes;
			mix_channel[which].playing = chunk->alen - loop_start_bytes;
			mix_channel[which].looping = loops;
			mix_channel[which].loop_start = loop_start_bytes;
			mix_channel[which].sound->chunk = chunk;
			mix_channel[which].paused = 0;
			mix_channel[which].expire = (ticks>0) ? (sdl_ticks + ticks) : 0;
			if (fade_in){
				mix_channel[which].fading = MIX_FADING_IN;
				mix_channel[which].sound->fade_volume = mix_channel[which].volume;
				mix_channel[which].fade_volume_reset = mix_channel[which].volume;
				mix_channel[which].volume = 0;
				mix_channel[which].sound->fade_length = (Uint32)fade_in;
				mix_channel[which].sound->start_time = mix_channel[which].sound->ticks_fade = sdl_ticks;
			} else {
				mix_channel[which].fading = MIX_NO_FADING;
				mix_channel[which].sound->start_time = sdl_ticks;
			}
		}
	}
	SDL_UnlockAudio();
	return(which);
}
Example #3
0
/* Fade in a sound on a channel, over ms milliseconds */
int Mix_FadeInChannelTimed(int which, Mix_Chunk *chunk, int loops, int ms, int ticks)
{
	int i;

	/* Don't play null pointers :-) */
	if ( chunk == NULL ) {
		return(-1);
	}
	if ( !checkchunkintegral(chunk)) {
		Mix_SetError("Tried to play a chunk with a bad frame");
		return(-1);
	}

	/* Lock the mixer while modifying the playing channels */
	SDL_LockAudio();
	{
		/* If which is -1, play on the first free channel */
		if ( which == -1 ) {
			for ( i=reserved_channels; i<num_channels; ++i ) {
				if ( mix_channel[i].playing <= 0 )
					break;
			}
			if ( i == num_channels ) {
				which = -1;
			} else {
				which = i;
			}
		}

		/* Queue up the audio data for this channel */
		if ( which >= 0 && which < num_channels ) {
			Uint32 sdl_ticks = SDL_GetTicks();
			if (Mix_Playing(which))
				_Mix_channel_done_playing(which);
			mix_channel[which].samples = chunk->abuf;
			mix_channel[which].playing = chunk->alen;
			mix_channel[which].looping = loops;
			mix_channel[which].chunk = chunk;
			mix_channel[which].paused = 0;
			mix_channel[which].fading = MIX_FADING_IN;
			mix_channel[which].fade_volume = mix_channel[which].volume;
			mix_channel[which].fade_volume_reset = mix_channel[which].volume;
			mix_channel[which].volume = 0;
			mix_channel[which].fade_length = (Uint32)ms;
			mix_channel[which].start_time = mix_channel[which].ticks_fade = sdl_ticks;
			mix_channel[which].expire = (ticks > 0) ? (sdl_ticks+ticks) : 0;
		}
	}
	SDL_UnlockAudio();

	/* Return the channel on which the sound is being played */
	return(which);
}
Example #4
0
/* Halt playing of a particular channel */
int Mix_HaltChannel(int which)
{
	int i;

	if ( which == -1 ) {
		for ( i=0; i<num_channels; ++i ) {
			Mix_HaltChannel(i);
		}
	} else {
		SDL_LockAudio();
		if (mix_channel[which].playing) {
			_Mix_channel_done_playing(which);
		mix_channel[which].playing = 0;
		}
		mix_channel[which].expire = 0;
		if(mix_channel[which].fading != MIX_NO_FADING) /* Restore volume */
			mix_channel[which].volume = mix_channel[which].fade_volume;
		mix_channel[which].fading = MIX_NO_FADING;
		SDL_UnlockAudio();
	}
	return(0);
}
_Mix_Channel *_StartMusic(int which, int is_fading, Mix_Music* music)
{
	_Mix_Channel* channel = NULL;
	/* Lock the mixer while modifying the playing channels */
	SDL_LockAudio();
	{
		if ( which == MUSIC_COMPAT_MAGIC_CHANNEL ) {
			channel = &mix_music_compat_channel;
		} else if ( which >= 0 && which < num_channels ) {
			channel = &mix_channel[which];
		}
		/* Queue up the audio data for this channel */
		if ( channel != NULL ) {
			if (Mix_Playing(which))
				_Mix_channel_done_playing(which);
			if (!channel->is_music) {
				free(channel->sound);
				channel->sound = NULL;
				channel->is_music = SDL_TRUE;
			}
			channel->music = music;
			channel->playing = 1;
			channel->looping = -1;
			channel->paused = 0;
			if (is_fading){
				channel->fading = MIX_FADING_IN;
				channel->fade_volume_reset = channel->volume;
				channel->volume = 0;
			} else {
				channel->fading = MIX_NO_FADING;
			}
		}
	}
	SDL_UnlockAudio();
	return channel;
}
Example #6
0
/* Mixing function */
static void mix_channels(void *udata, Uint8 *stream, int len)
{
	Uint8 *mix_input;
	int i, mixable, volume = SDL_MIX_MAXVOLUME;
	Uint32 sdl_ticks;

#if SDL_VERSION_ATLEAST(1, 3, 0)
	/* Need to initialize the stream in SDL 1.3+ */
	memset(stream, mixer.silence, len);
#endif

	/* Mix the music (must be done before the channels are added) */
	if ( music_active || (mix_music != music_mixer) ) {
		mix_music(music_data, stream, len);
	}

	/* Mix any playing channels... */
	sdl_ticks = SDL_GetTicks();
	for ( i=0; i<num_channels; ++i ) {
		if( ! mix_channel[i].paused ) {
			if ( mix_channel[i].expire > 0 && mix_channel[i].expire < sdl_ticks ) {
				/* Expiration delay for that channel is reached */
				mix_channel[i].playing = 0;
				mix_channel[i].looping = 0;
				mix_channel[i].fading = MIX_NO_FADING;
				mix_channel[i].expire = 0;
				_Mix_channel_done_playing(i);
			} else if ( mix_channel[i].fading != MIX_NO_FADING ) {
				Uint32 ticks = sdl_ticks - mix_channel[i].ticks_fade;
				if( ticks > mix_channel[i].fade_length ) {
				    Mix_Volume(i, mix_channel[i].fade_volume_reset); /* Restore the volume */
					if( mix_channel[i].fading == MIX_FADING_OUT ) {
						mix_channel[i].playing = 0;
						mix_channel[i].looping = 0;
						mix_channel[i].expire = 0;
						_Mix_channel_done_playing(i);
					}
					mix_channel[i].fading = MIX_NO_FADING;
				} else {
					if( mix_channel[i].fading == MIX_FADING_OUT ) {
						Mix_Volume(i, (mix_channel[i].fade_volume * (mix_channel[i].fade_length-ticks))
								   / mix_channel[i].fade_length );
					} else {
						Mix_Volume(i, (mix_channel[i].fade_volume * ticks) / mix_channel[i].fade_length );
					}
				}
			}
			if ( mix_channel[i].playing > 0 ) {
				int index = 0;
				int remaining = len;
				while (mix_channel[i].playing > 0 && index < len) {
					remaining = len - index;
					volume = (mix_channel[i].volume*mix_channel[i].chunk->volume) / MIX_MAX_VOLUME;
					mixable = mix_channel[i].playing;
					if ( mixable > remaining ) {
						mixable = remaining;
					}

					mix_input = Mix_DoEffects(i, mix_channel[i].samples, mixable);
					SDL_MixAudio(stream+index,mix_input,mixable,volume);
					if (mix_input != mix_channel[i].samples)
						SDL_free(mix_input);

					mix_channel[i].samples += mixable;
					mix_channel[i].playing -= mixable;
					index += mixable;

					/* rcg06072001 Alert app if channel is done playing. */
					if (!mix_channel[i].playing && !mix_channel[i].looping) {
						_Mix_channel_done_playing(i);
					}
				}

				/* If looping the sample and we are at its end, make sure
				   we will still return a full buffer */
				while ( mix_channel[i].looping && index < len ) {
					int alen = mix_channel[i].chunk->alen;
					remaining = len - index;
					if (remaining > alen) {
						remaining = alen;
					}

					mix_input = Mix_DoEffects(i, mix_channel[i].chunk->abuf, remaining);
					SDL_MixAudio(stream+index, mix_input, remaining, volume);
					if (mix_input != mix_channel[i].chunk->abuf)
						SDL_free(mix_input);

					--mix_channel[i].looping;
					mix_channel[i].samples = mix_channel[i].chunk->abuf + remaining;
					mix_channel[i].playing = mix_channel[i].chunk->alen - remaining;
					index += remaining;
				}
				if ( ! mix_channel[i].playing && mix_channel[i].looping ) {
					--mix_channel[i].looping;
					mix_channel[i].samples = mix_channel[i].chunk->abuf;
					mix_channel[i].playing = mix_channel[i].chunk->alen;
				}
			}
		}
	}

	/* rcg06122001 run posteffects... */
	Mix_DoEffects(MIX_CHANNEL_POST, stream, len);

	if ( mix_postmix ) {
		mix_postmix(mix_postmix_data, stream, len);
	}
}
static void do_mix_channel(void* udata, Uint8 *stream, int len, _Mix_Channel* channel, Mix_Sound *sound, int i, Uint32 sdl_ticks)
{
	Uint8 *mix_input;

	if ( channel->expire > 0 && channel->expire < sdl_ticks ) {
		/* Expiration delay for that channel is reached */
		channel->playing = 0;
		channel->looping = 0;
		channel->fading = MIX_NO_FADING;
		channel->expire = 0;
		_Mix_channel_done_playing(i);
	} else if ( channel->fading != MIX_NO_FADING ) {
		Uint32 ticks = sdl_ticks - sound->ticks_fade;
		if( ticks > sound->fade_length ) {
		    Mix_Volume(i, channel->fade_volume_reset); /* Restore the volume */
			if( channel->fading == MIX_FADING_OUT ) {
				channel->playing = 0;
				channel->looping = 0;
				channel->expire = 0;
				_Mix_channel_done_playing(i);
			}
			channel->fading = MIX_NO_FADING;
		} else {
			if( channel->fading == MIX_FADING_OUT ) {
				Mix_Volume(i, (sound->fade_volume * (sound->fade_length-ticks))
						   / sound->fade_length );
			} else {
				Mix_Volume(i, (sound->fade_volume * ticks) / sound->fade_length );
			}
		}
	}
	if ( channel->playing > 0 ) {
		int index = 0;
		int remaining = len;
		int volume, mixable;
		while (channel->playing > 0 && index < len) {
			volume = (channel->volume * sound->chunk->volume) / MIX_MAX_VOLUME;
			mixable = channel->playing;

			remaining = len - index;
			if ( mixable > remaining ) {
				mixable = remaining;
			}

			mix_input = Mix_DoEffects(i, sound->samples, mixable);
			SDL_MixAudio(stream+index,mix_input,mixable,volume);
			if (mix_input != sound->samples)
				free(mix_input);

			sound->samples += mixable;
			channel->playing -= mixable;
			index += mixable;

			/* rcg06072001 Alert app if channel is done playing. */
			if (!channel->playing && !channel->looping) {
				_Mix_channel_done_playing(i);
			}
		}

		/* If looping the sample and we are at its end, make sure
		   we will still return a full buffer */
		while ( channel->looping && index < len ) {
			int alen = sound->chunk->alen - channel->loop_start;
			remaining = len - index;
			if (remaining > alen) {
				remaining = alen;
			}

			mix_input = Mix_DoEffects(i, sound->chunk->abuf + channel->loop_start, remaining);
			SDL_MixAudio(stream+index, mix_input, remaining, volume);
			if (mix_input != sound->chunk->abuf + channel->loop_start)
				SDL_free(mix_input);

			if (channel->looping > 0) {
				--channel->looping;
			}
			sound->samples = sound->chunk->abuf + channel->loop_start + remaining;
			channel->playing = sound->chunk->alen - channel->loop_start - remaining;
			index += remaining;
		}
		if ( ! channel->playing && channel->looping ) {
			if (channel->looping > 0) {
				--channel->looping;
			}
			sound->samples = sound->chunk->abuf + channel->loop_start;
			channel->playing = sound->chunk->alen - channel->loop_start;
		}
	}
}