📄 mixer.c
字号:
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 + -