void Java_org_fmod_realtimestitching_Example_cUpdate(JNIEnv *env, jobject thiz) { FMOD_RESULT result = FMOD_OK; /* Replace the subsound that just finished with a new subsound, to create endless seamless stitching! Note that this polls the currently playing subsound using the FMOD_TIMEUNIT_BUFFERED flag. Remember streams are decoded / buffered ahead in advance! Don't use the 'audible time' which is FMOD_TIMEUNIT_SENTENCE_SUBSOUND by itself. When streaming, sound is processed ahead of time, and things like stream buffer / sentence manipulation (as done below) is required to be in 'buffered time', or else there will be synchronization problems and you might end up releasing a sub-sound that is still playing! */ result = FMOD_Channel_GetPosition(gChannel, &gCurrentSubSoundID, (FMOD_TIMEUNIT)(FMOD_TIMEUNIT_SENTENCE_SUBSOUND | FMOD_TIMEUNIT_BUFFERED)); CHECK_RESULT(result); if (gCurrentSubSoundID != gSubSoundID) { /* Release the sound that isn't playing any more. */ result = FMOD_Sound_Release(gSubSound[gSubSoundID]); CHECK_RESULT(result); /* Replace it with a new sound in our list. */ result = FMOD_System_CreateStream(gSystem, gSoundName[gSentenceID], FMOD_DEFAULT, 0, &gSubSound[gSubSoundID]); CHECK_RESULT(result); result = FMOD_Sound_SetSubSound(gSound, gSubSoundID, gSubSound[gSubSoundID]); CHECK_RESULT(result); sprintf(s, "Replacing subsound %d / 2 with sound %d / %d\n", gSubSoundID, gSentenceID, NUMSOUNDS); __android_log_write(ANDROID_LOG_INFO, "fmod_realtimestitching", s); gSentenceID++; if (gSentenceID >= NUMSOUNDS) { gSentenceID = 0; } gSubSoundID = gCurrentSubSoundID; } result = FMOD_System_Update(gSystem); CHECK_RESULT(result); }
void Java_org_fmod_realtimestitching_Example_cBegin(JNIEnv *env, jobject thiz) { FMOD_RESULT result = FMOD_OK; FMOD_CREATESOUNDEXINFO exinfo; result = FMOD_System_Create(&gSystem); CHECK_RESULT(result); result = FMOD_System_Init(gSystem, 1, FMOD_INIT_NORMAL, 0); CHECK_RESULT(result); /* Set up the FMOD_CREATESOUNDEXINFO structure for the user stream with room for 2 subsounds. (our subsound double buffer) */ memset(&exinfo, 0, sizeof(FMOD_CREATESOUNDEXINFO)); exinfo.cbsize = sizeof(FMOD_CREATESOUNDEXINFO); exinfo.defaultfrequency = 44100; exinfo.numsubsounds = 2; exinfo.numchannels = 1; exinfo.format = FMOD_SOUND_FORMAT_PCM16; /* Create the 'parent' stream that contains the substreams. Set it to loop so that it loops between subsound 0 and 1. */ result = FMOD_System_CreateStream(gSystem, 0, FMOD_LOOP_NORMAL | FMOD_OPENUSER, &exinfo, &gSound); CHECK_RESULT(result); /* Add 2 of our streams as children of the parent. They should be the same format (ie mono/stereo and bitdepth) as the parent sound. When subsound 0 has finished and it is playing subsound 1, we will swap subsound 0 with a new sound, and the same for when subsound 1 has finished, causing a continual double buffered flip, which means continuous sound. */ result = FMOD_System_CreateStream(gSystem, gSoundName[0], FMOD_DEFAULT, 0, &gSubSound[0]); CHECK_RESULT(result); result = FMOD_System_CreateStream(gSystem, gSoundName[1], FMOD_DEFAULT, 0, &gSubSound[1]); CHECK_RESULT(result); result = FMOD_Sound_SetSubSound(gSound, 0, gSubSound[0]); CHECK_RESULT(result); result = FMOD_Sound_SetSubSound(gSound, 1, gSubSound[1]); CHECK_RESULT(result); /* Set up the gapless sentence to contain these first 2 streams. */ { int soundlist[2] = { 0, 1 }; result = FMOD_Sound_SetSubSoundSentence(gSound, soundlist, 2); CHECK_RESULT(result); } gSubSoundID = 0; gSentenceID = 2; /* The next sound to be appended to the stream. */ sprintf(s, "Inserted subsound %d / 2 with sound %d / %d\n", 0, 0, NUMSOUNDS); __android_log_write(ANDROID_LOG_INFO, "fmod_realtimestitching", s); sprintf(s, "Inserted subsound %d / 2 with sound %d / %d\n", 1, 1, NUMSOUNDS); __android_log_write(ANDROID_LOG_INFO, "fmod_realtimestitching", s); /* Play the sound. */ result = FMOD_System_PlaySound(gSystem, FMOD_CHANNEL_FREE, gSound, 0, &gChannel); CHECK_RESULT(result); }
int main(int argc, char *argv[]) { FMOD_SYSTEM *system; FMOD_SOUND *sound; FMOD_SOUND *subsound[2]; FMOD_CREATESOUNDEXINFO exinfo; FMOD_CHANNEL *channel = 0; FMOD_RESULT result; int key; unsigned int subsoundid, sentenceid; unsigned int version; const char *soundname[NUMSOUNDS] = { "../media/e.ogg", /* Ma- */ "../media/d.ogg", /* ry */ "../media/c.ogg", /* had */ "../media/d.ogg", /* a */ "../media/e.ogg", /* lit- */ "../media/e.ogg", /* tle */ "../media/e.ogg", /* lamb, */ "../media/e.ogg", /* ..... */ "../media/d.ogg", /* lit- */ "../media/d.ogg", /* tle */ "../media/d.ogg", /* lamb, */ "../media/d.ogg", /* ..... */ "../media/e.ogg", /* lit- */ "../media/e.ogg", /* tle */ "../media/e.ogg", /* lamb, */ "../media/e.ogg", /* ..... */ "../media/e.ogg", /* Ma- */ "../media/d.ogg", /* ry */ "../media/c.ogg", /* had */ "../media/d.ogg", /* a */ "../media/e.ogg", /* lit- */ "../media/e.ogg", /* tle */ "../media/e.ogg", /* lamb, */ "../media/e.ogg", /* its */ "../media/d.ogg", /* fleece */ "../media/d.ogg", /* was */ "../media/e.ogg", /* white */ "../media/d.ogg", /* as */ "../media/c.ogg", /* snow. */ "../media/c.ogg", /* ..... */ "../media/c.ogg", /* ..... */ "../media/c.ogg", /* ..... */ }; /* Create a System object and initialize. */ result = FMOD_System_Create(&system); ERRCHECK(result); result = FMOD_System_GetVersion(system, &version); ERRCHECK(result); if (version < FMOD_VERSION) { printf("Error! You are using an old version of FMOD %08x. This program requires %08x\n", version, FMOD_VERSION); return 0; } result = FMOD_System_Init(system, 1, FMOD_INIT_NORMAL, NULL); ERRCHECK(result); /* Set up the FMOD_CREATESOUNDEXINFO structure for the user stream with room for 2 subsounds. (our subsound double buffer) */ memset(&exinfo, 0, sizeof(FMOD_CREATESOUNDEXINFO)); exinfo.cbsize = sizeof(FMOD_CREATESOUNDEXINFO); exinfo.defaultfrequency = 44100; exinfo.numsubsounds = 2; exinfo.numchannels = 1; exinfo.format = FMOD_SOUND_FORMAT_PCM16; /* Create the 'parent' stream that contains the substreams. Set it to loop so that it loops between subsound 0 and 1. */ result = FMOD_System_CreateStream(system, 0, FMOD_LOOP_NORMAL | FMOD_OPENUSER, &exinfo, &sound); ERRCHECK(result); /* Add 2 of our streams as children of the parent. They should be the same format (ie mono/stereo and bitdepth) as the parent sound. When subsound 0 has finished and it is playing subsound 1, we will swap subsound 0 with a new sound, and the same for when subsound 1 has finished, causing a continual double buffered flip, which means continuous sound. */ result = FMOD_System_CreateStream(system, soundname[0], FMOD_DEFAULT, 0, &subsound[0]); ERRCHECK(result); result = FMOD_System_CreateStream(system, soundname[1], FMOD_DEFAULT, 0, &subsound[1]); ERRCHECK(result); result = FMOD_Sound_SetSubSound(sound, 0, subsound[0]); ERRCHECK(result); result = FMOD_Sound_SetSubSound(sound, 1, subsound[1]); ERRCHECK(result); /* Set up the gapless sentence to contain these first 2 streams. */ { int soundlist[2] = { 0, 1 }; result = FMOD_Sound_SetSubSoundSentence(sound, soundlist, 2); ERRCHECK(result); } subsoundid = 0; sentenceid = 2; /* The next sound to be appeneded to the stream. */ printf("=============================================================================\n"); printf("Real-time stitching example. Copyright (c) Firelight Technologies 2004-2014.\n"); printf("=============================================================================\n"); printf("\n"); printf("Press space to pause, Esc to quit\n"); printf("\n"); printf("Inserted subsound %d / 2 with sound %d / %d\n", 0, 0, NUMSOUNDS); printf("Inserted subsound %d / 2 with sound %d / %d\n", 1, 1, NUMSOUNDS); /* Play the sound. */ result = FMOD_System_PlaySound(system, FMOD_CHANNEL_FREE, sound, FALSE, &channel); ERRCHECK(result); /* Main loop. */ do { unsigned int currentsubsoundid; if (_kbhit()) { key = _getch(); switch (key) { case ' ' : { int paused; FMOD_Channel_GetPaused(channel, &paused); FMOD_Channel_SetPaused(channel, !paused); break; } } } FMOD_System_Update(system); /* Replace the subsound that just finished with a new subsound, to create endless seamless stitching! Note that this polls the currently playing subsound using the FMOD_TIMEUNIT_BUFFERED flag. Remember streams are decoded / buffered ahead in advance! Don't use the 'audible time' which is FMOD_TIMEUNIT_SENTENCE_SUBSOUND by itself. When streaming, sound is processed ahead of time, and things like stream buffer / sentence manipulation (as done below) is required to be in 'buffered time', or else there will be synchronization problems and you might end up releasing a sub-sound that is still playing! */ result = FMOD_Channel_GetPosition(channel, ¤tsubsoundid, (FMOD_TIMEUNIT)(FMOD_TIMEUNIT_SENTENCE_SUBSOUND | FMOD_TIMEUNIT_BUFFERED)); ERRCHECK(result); if (currentsubsoundid != subsoundid) { /* Release the sound that isn't playing any more. */ result = FMOD_Sound_Release(subsound[subsoundid]); ERRCHECK(result); /* Replace it with a new sound in our list. */ result = FMOD_System_CreateStream(system, soundname[sentenceid], FMOD_DEFAULT, 0, &subsound[subsoundid]); ERRCHECK(result); result = FMOD_Sound_SetSubSound(sound, subsoundid, subsound[subsoundid]); ERRCHECK(result); printf("Replacing subsound %d / 2 with sound %d / %d\n", subsoundid, sentenceid, NUMSOUNDS); sentenceid++; if (sentenceid >= NUMSOUNDS) { sentenceid = 0; } subsoundid = currentsubsoundid; } Sleep(50); } while (key != 27); printf("\n"); /* Shut down */ result = FMOD_Sound_Release(sound); /* Freeing a parent subsound also frees its children. */ ERRCHECK(result); result = FMOD_System_Close(system); ERRCHECK(result); result = FMOD_System_Release(system); ERRCHECK(result); return 0; }