/* 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); }
/* 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); }
/* 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; }
/* 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; } } }