⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mixer.c

📁 SDL_mixer 是一个基于 SDL 的混音器
💻 C
📖 第 1 页 / 共 2 页
字号:
	int frame_width = 1;	if ((mixer.format & 0xFF) == 16) frame_width = 2;	frame_width *= mixer.channels;	while (chunk->alen % frame_width) chunk->alen--;	return chunk->alen;}/* Play an audio chunk on a specific channel.   If the specified channel is -1, play on the first free channel.   'ticks' is the number of milliseconds at most to play the sample, or -1   if there is no limit.   Returns which channel was used to play the sound.*/int Mix_PlayChannelTimed(int which, Mix_Chunk *chunk, int loops, int ticks){	int i;	/* Don't play null pointers :-) */	if ( chunk == NULL ) {		Mix_SetError("Tried to play a NULL chunk");		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 ) {				Mix_SetError("No free channels available");				which = -1;			} else {				which = i;			}		}		/* Queue up the audio data for this channel */		if ( which >= 0 ) {			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_NO_FADING;			mix_channel[which].start_time = 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);}/* Change the expiration delay for a channel */int Mix_ExpireChannel(int which, int ticks){	int status = 0;	if ( which == -1 ) {		int i;		for ( i=0; i < num_channels; ++ i ) {			status += Mix_ExpireChannel(i, ticks);		}	} else if ( which < num_channels ) {		SDL_LockAudio();		mix_channel[which].expire = (ticks>0) ? (SDL_GetTicks() + ticks) : 0;		SDL_UnlockAudio();		++ status;	}	return(status);}/* 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 ) {			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].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);}/* Set volume of a particular channel */int Mix_Volume(int which, int volume){	int i;	int prev_volume;	if ( which == -1 ) {		prev_volume = 0;		for ( i=0; i<num_channels; ++i ) {			prev_volume += Mix_Volume(i, volume);		}		prev_volume /= num_channels;	} else {		prev_volume = mix_channel[which].volume;		if ( volume >= 0 ) {			if ( volume > SDL_MIX_MAXVOLUME ) {				volume = SDL_MIX_MAXVOLUME;			}			mix_channel[which].volume = volume;		}	}	return(prev_volume);}/* Set volume of a particular chunk */int Mix_VolumeChunk(Mix_Chunk *chunk, int volume){	int prev_volume;	prev_volume = chunk->volume;	if ( volume >= 0 ) {		if ( volume > MIX_MAX_VOLUME ) {			volume = MIX_MAX_VOLUME;		}		chunk->volume = volume;	}	return(prev_volume);}/* 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);}/* Halt playing of a particular group of channels */int Mix_HaltGroup(int tag){	int i;	for ( i=0; i<num_channels; ++i ) {		if( mix_channel[i].tag == tag ) {			Mix_HaltChannel(i);		}	}	return(0);}/* Fade out a channel and then stop it automatically */int Mix_FadeOutChannel(int which, int ms){	int status;	status = 0;	if ( audio_opened ) {		if ( which == -1 ) {			int i;			for ( i=0; i<num_channels; ++i ) {				status += Mix_FadeOutChannel(i, ms);			}		} else {			SDL_LockAudio();			if ( mix_channel[which].playing && 			    (mix_channel[which].volume > 0) &&			    (mix_channel[which].fading != MIX_FADING_OUT) ) {				mix_channel[which].fading = MIX_FADING_OUT;				mix_channel[which].fade_volume = mix_channel[which].volume;				mix_channel[which].fade_length = ms;				mix_channel[which].ticks_fade = SDL_GetTicks();				++status;			}			SDL_UnlockAudio();		}	}	return(status);}/* Halt playing of a particular group of channels */int Mix_FadeOutGroup(int tag, int ms){	int i;	int status = 0;	for ( i=0; i<num_channels; ++i ) {		if( mix_channel[i].tag == tag ) {			status += Mix_FadeOutChannel(i,ms);		}	}	return(status);}Mix_Fading Mix_FadingChannel(int which){	return mix_channel[which].fading;}/* Check the status of a specific channel.   If the specified mix_channel is -1, check all mix channels.*/int Mix_Playing(int which){	int status;	status = 0;	if ( which == -1 ) {		int i;		for ( i=0; i<num_channels; ++i ) {			if ((mix_channel[i].playing > 0) ||				(mix_channel[i].looping > 0))			{				++status;			}		}	} else {		if ((mix_channel[which].playing > 0) ||			(mix_channel[which].looping > 0))		{			++status;		}	}	return(status);}/* rcg06072001 Get the chunk associated with a channel. */Mix_Chunk *Mix_GetChunk(int channel){	Mix_Chunk *retval = NULL;	if ((channel >= 0) && (channel < num_channels)) {		retval = mix_channel[channel].chunk;	}	return(retval);}/* Close the mixer, halting all playing audio */void Mix_CloseAudio(void){	int i;	if ( audio_opened ) {		if ( audio_opened == 1 ) {			for (i = 0; i < num_channels; i++) {				Mix_UnregisterAllEffects(i);			}			Mix_UnregisterAllEffects(MIX_CHANNEL_POST);			close_music();			Mix_HaltChannel(-1);			SDL_CloseAudio();			free(mix_channel);			mix_channel = NULL;		}		--audio_opened;	}}/* Pause a particular channel (or all) */void Mix_Pause(int which){	Uint32 sdl_ticks = SDL_GetTicks();	if ( which == -1 ) {		int i;		for ( i=0; i<num_channels; ++i ) {			if ( mix_channel[i].playing > 0 ) {				mix_channel[i].paused = sdl_ticks;			}		}	} else {		if ( mix_channel[which].playing > 0 ) {			mix_channel[which].paused = sdl_ticks;		}	}}/* Resume a paused channel */void Mix_Resume(int which){	Uint32 sdl_ticks = SDL_GetTicks();	SDL_LockAudio();	if ( which == -1 ) {		int i;		for ( i=0; i<num_channels; ++i ) {			if ( mix_channel[i].playing > 0 ) {				if(mix_channel[i].expire > 0)					mix_channel[i].expire += sdl_ticks - mix_channel[i].paused;				mix_channel[i].paused = 0;			}		}	} else {		if ( mix_channel[which].playing > 0 ) {			if(mix_channel[which].expire > 0)				mix_channel[which].expire += sdl_ticks - mix_channel[which].paused;			mix_channel[which].paused = 0;		}	}	SDL_UnlockAudio();}int Mix_Paused(int which){	if ( which > num_channels )		return(0);	if ( which < 0 ) {		int status = 0;		int i;		for( i=0; i < num_channels; ++i ) {			if ( mix_channel[i].paused ) {				++ status;			}		}		return(status);	} else {		return(mix_channel[which].paused != 0);	}}/* Change the group of a channel */int Mix_GroupChannel(int which, int tag){	if ( which < 0 || which > num_channels )		return(0);	SDL_LockAudio();	mix_channel[which].tag = tag;	SDL_UnlockAudio();	return(1);}/* Assign several consecutive channels to a group */int Mix_GroupChannels(int from, int to, int tag){	int status = 0;	for( ; from <= to; ++ from ) {		status += Mix_GroupChannel(from, tag);	}	return(status);}/* Finds the first available channel in a group of channels */int Mix_GroupAvailable(int tag){	int i;	for( i=0; i < num_channels; i ++ ) {		if ( ((tag == -1) || (tag == mix_channel[i].tag)) &&		                    (mix_channel[i].playing <= 0) )			return i;	}	return(-1);}int Mix_GroupCount(int tag){	int count = 0;	int i;	for( i=0; i < num_channels; i ++ ) {		if ( mix_channel[i].tag==tag || tag==-1 )			++ count;	}	return(count);}/* Finds the "oldest" sample playing in a group of channels */int Mix_GroupOldest(int tag){	int chan = -1;	Uint32 mintime = SDL_GetTicks();	int i;	for( i=0; i < num_channels; i ++ ) {		if ( (mix_channel[i].tag==tag || tag==-1) && mix_channel[i].playing > 0			 && mix_channel[i].start_time <= mintime ) {			mintime = mix_channel[i].start_time;			chan = i;		}	}	return(chan);}/* Finds the "most recent" (i.e. last) sample playing in a group of channels */int Mix_GroupNewer(int tag){	int chan = -1;	Uint32 maxtime = 0;	int i;	for( i=0; i < num_channels; i ++ ) {		if ( (mix_channel[i].tag==tag || tag==-1) && mix_channel[i].playing > 0			 && mix_channel[i].start_time >= maxtime ) {			maxtime = mix_channel[i].start_time;			chan = i;		}	}	return(chan);}/* * rcg06122001 The special effects exportable API. *  Please see effect_*.c for internally-implemented effects, such *  as Mix_SetPanning(). *//* MAKE SURE you hold the audio lock (SDL_LockAudio()) before calling this! */static int _Mix_register_effect(effect_info **e, Mix_EffectFunc_t f,				Mix_EffectDone_t d, void *arg){	effect_info *new_e = malloc(sizeof (effect_info));	if (!e) {		Mix_SetError("Internal error");		return(0);	}	if (f == NULL) {		Mix_SetError("NULL effect callback");		return(0);	}	if (new_e == NULL) {		Mix_SetError("Out of memory");		return(0);	}	new_e->callback = f;	new_e->done_callback = d;	new_e->udata = arg;	new_e->next = NULL;	/* add new effect to end of linked list... */	if (*e == NULL) {		*e = new_e;	} else {		effect_info *cur = *e;		while (1) {			if (cur->next == NULL) {				cur->next = new_e;				break;			}			cur = cur->next;		}	}	return(1);}/* MAKE SURE you hold the audio lock (SDL_LockAudio()) before calling this! */static int _Mix_remove_effect(int channel, effect_info **e, Mix_EffectFunc_t f){	effect_info *cur;	effect_info *prev = NULL;	effect_info *next = NULL;	if (!e) {		Mix_SetError("Internal error");		return(0);	}	for (cur = *e; cur != NULL; cur = cur->next) {		if (cur->callback == f) {			next = cur->next;			if (cur->done_callback != NULL) {				cur->done_callback(channel, cur->udata);			}			free(cur);			if (prev == NULL) {   /* removing first item of list? */				*e = next;			} else {				prev->next = next;			}			return(1);		}		prev = cur;	}	Mix_SetError("No such effect registered");	return(0);}/* MAKE SURE you hold the audio lock (SDL_LockAudio()) before calling this! */static int _Mix_remove_all_effects(int channel, effect_info **e){	effect_info *cur;	effect_info *next;	if (!e) {		Mix_SetError("Internal error");		return(0);	}	for (cur = *e; cur != NULL; cur = next) {		next = cur->next;		if (cur->done_callback != NULL) {			cur->done_callback(channel, cur->udata);		}		free(cur);	}	*e = NULL;	return(1);}int Mix_RegisterEffect(int channel, Mix_EffectFunc_t f,			Mix_EffectDone_t d, void *arg){	effect_info **e = NULL;	int retval;	if (channel == MIX_CHANNEL_POST) {		e = &posteffects;	} else {		if ((channel < 0) || (channel >= num_channels)) {			Mix_SetError("Invalid channel number");			return(0);		}		e = &mix_channel[channel].effects;	}	SDL_LockAudio();	retval = _Mix_register_effect(e, f, d, arg);	SDL_UnlockAudio();	return(retval);}int Mix_UnregisterEffect(int channel, Mix_EffectFunc_t f){	effect_info **e = NULL;	int retval;	if (channel == MIX_CHANNEL_POST) {		e = &posteffects;	} else {		if ((channel < 0) || (channel >= num_channels)) {			Mix_SetError("Invalid channel number");			return(0);		}		e = &mix_channel[channel].effects;	}	SDL_LockAudio();	retval = _Mix_remove_effect(channel, e, f);	SDL_UnlockAudio();	return(retval);}int Mix_UnregisterAllEffects(int channel){	effect_info **e = NULL;	int retval;	if (channel == MIX_CHANNEL_POST) {		e = &posteffects;	} else {		if ((channel < 0) || (channel >= num_channels)) {			Mix_SetError("Invalid channel number");			return(0);		}		e = &mix_channel[channel].effects;	}	SDL_LockAudio();	retval = _Mix_remove_all_effects(channel, e);	SDL_UnlockAudio();	return(retval);}/* end of mixer.c ... */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -