void set_paused(FMOD_CHANNEL **channel, int paused) { FMOD_RESULT result; unsigned int blocksize; result = FMOD_System_GetDSPBufferSize(gSystem, &blocksize, 0); ERRCHECK(result); if (!paused) { unsigned int pausestart_hi = 0, pausestart_lo = 0; FMOD_System_GetDSPClock(gSystem, &pausestart_hi, &pausestart_lo); FMOD_64BIT_ADD(pausestart_hi, pausestart_lo, 0, blocksize * 2); /* Into the future by 2 mixer blocks. */ printf("\npause BOTH at %d \n", pausestart_lo); /* Make them both pause at exactly the same tick. Mute them both to avoid a click as well. */ FMOD_Channel_SetMute(channel[0], TRUE); FMOD_Channel_SetDelay(channel[0], FMOD_DELAYTYPE_DSPCLOCK_PAUSE, pausestart_hi, pausestart_lo); FMOD_Channel_SetMute(channel[1], TRUE); FMOD_Channel_SetDelay(channel[1], FMOD_DELAYTYPE_DSPCLOCK_PAUSE, pausestart_hi, pausestart_lo); } else { unsigned int syshi, syslo; int count; FMOD_System_GetDSPClock(gSystem, &syshi, &syslo); printf("\nunpause BOTH at %d\n", syslo); for (count = 0; count < 2; count++) { unsigned int starttime_hi, starttime_lo; unsigned int pausetime_hi = 0, pausetime_lo = 0; unsigned int hi = syshi, lo = syslo; FMOD_Channel_GetDelay(channel[count], FMOD_DELAYTYPE_DSPCLOCK_PAUSE, &pausetime_hi, &pausetime_lo); FMOD_Channel_GetDelay(channel[count], FMOD_DELAYTYPE_DSPCLOCK_START, &starttime_hi, &starttime_lo); FMOD_64BIT_ADD(hi, lo, 0, blocksize * 2); /* Push operation into the future by 2 mixer blocks so it doesnt conflict with mixer. */ if (starttime_lo > pausetime_lo) /* Was already playing, unpause immediately. */ { FMOD_64BIT_ADD(hi, lo, starttime_hi, starttime_lo); /* Push forward the delayed start by the gap between starting and pausing */ FMOD_64BIT_SUB(hi, lo, pausetime_hi, pausetime_lo); /* Push forward the delayed start by the gap between starting and pausing */ } printf("restart %d at %d\n", count, lo); FMOD_Channel_SetDelay(channel[count], FMOD_DELAYTYPE_DSPCLOCK_PAUSE, 0, 0); FMOD_Channel_SetDelay(channel[count], FMOD_DELAYTYPE_DSPCLOCK_START, hi, lo); FMOD_Channel_SetMute(channel[count], FALSE); FMOD_Channel_SetPaused(channel[count], FALSE); } } }
FMOD_CHANNEL *queue_next_sound(int outputrate, FMOD_CHANNEL *playingchannel, int newindex, int slot) { FMOD_RESULT result; FMOD_CHANNEL *newchannel; FMOD_SOUND *newsound; #ifdef USE_STREAMS /* Create a new stream */ FMOD_CREATESOUNDEXINFO info; memset(&info, 0, sizeof(FMOD_CREATESOUNDEXINFO)); info.cbsize = sizeof(FMOD_CREATESOUNDEXINFO); info.suggestedsoundtype = FMOD_SOUND_TYPE_OGGVORBIS; result = FMOD_System_CreateStream(gSystem, soundname[newindex], FMOD_IGNORETAGS | FMOD_LOWMEM, &info, &sound[slot]); ERRCHECK(result); newsound = sound[slot]; #else /* Use an existing sound that was passed into us */ newsound = sound[newindex]; #endif result = FMOD_System_PlaySound(gSystem, FMOD_CHANNEL_FREE, newsound, 1, &newchannel); ERRCHECK(result); result = FMOD_Channel_SetSpeakerMix(newchannel, 1,1,1,1,1,1,1,1); ERRCHECK(result); if (playingchannel) { unsigned int hi = 0, lo = 0, sound_length; float sound_frequency; FMOD_SOUND *playingsound; /* Get the start time of the playing channel. */ result = FMOD_Channel_GetDelay(playingchannel, FMOD_DELAYTYPE_DSPCLOCK_START, &hi, &lo); ERRCHECK(result); printf("playing sound started at %d\n", lo); /* Grab the length of the playing sound, and its frequency, so we can caluate where to place the new sound on the time line. */ result = FMOD_Channel_GetCurrentSound(playingchannel, &playingsound); ERRCHECK(result); result = FMOD_Sound_GetLength(playingsound, &sound_length, FMOD_TIMEUNIT_PCM); ERRCHECK(result); result = FMOD_Channel_GetFrequency(playingchannel, &sound_frequency); ERRCHECK(result); /* Now calculate the length of the sound in 'output samples'. Ie if a 44khz sound is 22050 samples long, and the output rate is 48khz, then we want to delay by 24000 output samples. */ sound_length *= outputrate; sound_length /= (int)sound_frequency; FMOD_64BIT_ADD(hi, lo, 0, sound_length); /* Add output rate adjusted sound length, to the clock value of the sound that is currently playing */ result = FMOD_Channel_SetDelay(newchannel, FMOD_DELAYTYPE_DSPCLOCK_START, hi, lo); /* Set the delay of the new sound to the end of the old sound */ ERRCHECK(result); } { unsigned int hi = 0, lo = 0; float val, variation; /* Randomize pitch/volume to make it sound more realistic / random. */ FMOD_Channel_GetFrequency(newchannel, &val); variation = (((float)(rand()%10000) / 5000.0f) - 1.0f); /* -1.0 to +1.0 */ val *= (1.0f + (variation * 0.02f)); /* @22khz, range fluctuates from 21509 to 22491 */ FMOD_Channel_SetFrequency(newchannel, val); FMOD_Channel_GetVolume(newchannel, &val); variation = ((float)(rand()%10000) / 10000.0f); /* 0.0 to 1.0 */ val *= (1.0f - (variation * 0.2f)); /* 0.8 to 1.0 */ FMOD_Channel_SetVolume(newchannel, val); FMOD_Channel_GetDelay(newchannel, FMOD_DELAYTYPE_DSPCLOCK_START, &hi, &lo); printf("new sound to start at %d (slot %d)\n", lo, slot); } result = FMOD_Channel_SetPaused(newchannel, FALSE); ERRCHECK(result); return newchannel; }
FMOD_RESULT bmx_FMOD_Channel_SetDelay(MAX_FMOD_CHANNEL *channel, FMOD_DELAYTYPE delayType, unsigned int delayHi, unsigned int delayLo) { return FMOD_Channel_SetDelay(channel->channel, delayType, delayHi, delayLo); }