added the readme
This commit is contained in:
@@ -0,0 +1,373 @@
|
||||
/*==============================================================================
|
||||
API Recording Example
|
||||
Copyright (c), Firelight Technologies Pty, Ltd 2012-2026.
|
||||
|
||||
This example shows recording and playback functionality, allowing the user to
|
||||
trigger some sounds and then play back what they have recorded. The provided
|
||||
functionality is intended to assist in debugging.
|
||||
|
||||
For information on using FMOD example code in your own programs, visit
|
||||
https://www.fmod.com/legal
|
||||
==============================================================================*/
|
||||
#include "fmod_studio.hpp"
|
||||
#include "fmod.hpp"
|
||||
#include "common.h"
|
||||
|
||||
const int SCREEN_WIDTH = NUM_COLUMNS;
|
||||
const int SCREEN_HEIGHT = 10;
|
||||
|
||||
int currentScreenPosition = -1;
|
||||
char screenBuffer[(SCREEN_WIDTH + 1) * SCREEN_HEIGHT + 1] = {0};
|
||||
|
||||
void initializeScreenBuffer();
|
||||
void updateScreenPosition(const FMOD_VECTOR& worldPosition);
|
||||
|
||||
static const char* RECORD_FILENAME = "playback.cmd.txt";
|
||||
|
||||
enum State
|
||||
{
|
||||
State_Selection,
|
||||
State_Record,
|
||||
State_Playback,
|
||||
State_Quit
|
||||
};
|
||||
|
||||
State executeSelection(FMOD::Studio::System* system);
|
||||
State executeRecord(FMOD::Studio::System* system);
|
||||
State executePlayback(FMOD::Studio::System* system);
|
||||
|
||||
int FMOD_Main()
|
||||
{
|
||||
void *extraDriverData = 0;
|
||||
Common_Init(&extraDriverData);
|
||||
|
||||
FMOD::Studio::System* system = NULL;
|
||||
ERRCHECK( FMOD::Studio::System::create(&system) );
|
||||
|
||||
// The example Studio project is authored for 5.1 sound, so set up the system output mode to match
|
||||
FMOD::System* coreSystem = NULL;
|
||||
ERRCHECK( system->getCoreSystem(&coreSystem) );
|
||||
ERRCHECK( coreSystem->setSoftwareFormat(0, FMOD_SPEAKERMODE_5POINT1, 0) );
|
||||
|
||||
ERRCHECK( system->initialize(1024, FMOD_STUDIO_INIT_NORMAL, FMOD_INIT_NORMAL, extraDriverData) );
|
||||
|
||||
State state = State_Selection;
|
||||
while (state != State_Quit)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case State_Selection:
|
||||
state = executeSelection(system);
|
||||
break;
|
||||
case State_Record:
|
||||
state = executeRecord(system);
|
||||
break;
|
||||
case State_Playback:
|
||||
state = executePlayback(system);
|
||||
break;
|
||||
case State_Quit:
|
||||
break;
|
||||
};
|
||||
};
|
||||
|
||||
ERRCHECK( system->release() );
|
||||
|
||||
Common_Close();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Show the main selection menu
|
||||
State executeSelection(FMOD::Studio::System* system)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
Common_Update();
|
||||
|
||||
if (Common_BtnPress(BTN_ACTION1))
|
||||
{
|
||||
return State_Record;
|
||||
}
|
||||
if (Common_BtnPress(BTN_ACTION2))
|
||||
{
|
||||
return State_Playback;
|
||||
}
|
||||
if (Common_BtnPress(BTN_QUIT))
|
||||
{
|
||||
return State_Quit;
|
||||
}
|
||||
|
||||
ERRCHECK( system->update() );
|
||||
|
||||
Common_Draw("==================================================");
|
||||
Common_Draw("Recording and playback example.");
|
||||
Common_Draw("Copyright (c) Firelight Technologies 2012-2026.");
|
||||
Common_Draw("==================================================");
|
||||
Common_Draw("");
|
||||
Common_Draw("Waiting to start recording");
|
||||
Common_Draw("");
|
||||
Common_Draw("Press %s to start recording", Common_BtnStr(BTN_ACTION1));
|
||||
Common_Draw("Press %s to play back recording", Common_BtnStr(BTN_ACTION2));
|
||||
Common_Draw("Press %s to quit", Common_BtnStr(BTN_QUIT));
|
||||
Common_Draw("");
|
||||
Common_Sleep(50);
|
||||
}
|
||||
}
|
||||
|
||||
// Start recording, load banks and then let the user trigger some sounds
|
||||
State executeRecord(FMOD::Studio::System* system)
|
||||
{
|
||||
FMOD::Studio::Bank* masterBank = NULL;
|
||||
ERRCHECK( system->loadBankFile(Common_MediaPath("Master.bank"), FMOD_STUDIO_LOAD_BANK_NONBLOCKING, &masterBank) );
|
||||
|
||||
FMOD::Studio::Bank* stringsBank = NULL;
|
||||
ERRCHECK( system->loadBankFile(Common_MediaPath("Master.strings.bank"), FMOD_STUDIO_LOAD_BANK_NONBLOCKING, &stringsBank) );
|
||||
|
||||
FMOD::Studio::Bank* vehiclesBank = NULL;
|
||||
ERRCHECK( system->loadBankFile(Common_MediaPath("Vehicles.bank"), FMOD_STUDIO_LOAD_BANK_NONBLOCKING, &vehiclesBank) );
|
||||
|
||||
FMOD::Studio::Bank* sfxBank = NULL;
|
||||
ERRCHECK( system->loadBankFile(Common_MediaPath("SFX.bank"), FMOD_STUDIO_LOAD_BANK_NONBLOCKING, &sfxBank) );
|
||||
|
||||
// Wait for banks to load
|
||||
ERRCHECK( system->flushCommands() );
|
||||
|
||||
// Start recording commands - it will also record which banks we have already loaded by now
|
||||
ERRCHECK( system->startCommandCapture(Common_WritePath(RECORD_FILENAME), FMOD_STUDIO_COMMANDCAPTURE_NORMAL) );
|
||||
|
||||
FMOD_GUID explosionID = {0};
|
||||
ERRCHECK( system->lookupID("event:/Weapons/Explosion", &explosionID) );
|
||||
|
||||
FMOD::Studio::EventDescription* engineDescription = NULL;
|
||||
ERRCHECK( system->getEvent("event:/Vehicles/Ride-on Mower", &engineDescription) );
|
||||
|
||||
FMOD::Studio::EventInstance* engineInstance = NULL;
|
||||
ERRCHECK( engineDescription->createInstance(&engineInstance) );
|
||||
|
||||
ERRCHECK( engineInstance->setParameterByName("RPM", 650.0f) );
|
||||
ERRCHECK( engineInstance->start() );
|
||||
|
||||
// Position the listener at the origin
|
||||
FMOD_3D_ATTRIBUTES attributes = { { 0 } };
|
||||
attributes.forward.z = 1.0f;
|
||||
attributes.up.y = 1.0f;
|
||||
ERRCHECK( system->setListenerAttributes(0, &attributes) );
|
||||
|
||||
// Position the event 2 units in front of the listener
|
||||
attributes.position.z = 2.0f;
|
||||
ERRCHECK( engineInstance->set3DAttributes(&attributes) );
|
||||
|
||||
initializeScreenBuffer();
|
||||
|
||||
bool wantQuit = false;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
Common_Update();
|
||||
|
||||
if (Common_BtnPress(BTN_MORE))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (Common_BtnPress(BTN_QUIT))
|
||||
{
|
||||
wantQuit = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (Common_BtnPress(BTN_ACTION1))
|
||||
{
|
||||
// One-shot event
|
||||
FMOD::Studio::EventDescription* eventDescription = NULL;
|
||||
ERRCHECK( system->getEventByID(&explosionID, &eventDescription) );
|
||||
|
||||
FMOD::Studio::EventInstance* eventInstance = NULL;
|
||||
ERRCHECK( eventDescription->createInstance(&eventInstance) );
|
||||
for (int i=0; i<10; ++i)
|
||||
{
|
||||
ERRCHECK( eventInstance->setVolume(i / 10.0f) );
|
||||
}
|
||||
|
||||
ERRCHECK( eventInstance->start() );
|
||||
|
||||
// Release will clean up the instance when it completes
|
||||
ERRCHECK( eventInstance->release() );
|
||||
}
|
||||
|
||||
if (Common_BtnPress(BTN_LEFT))
|
||||
{
|
||||
attributes.position.x -= 1.0f;
|
||||
ERRCHECK( engineInstance->set3DAttributes(&attributes) );
|
||||
}
|
||||
|
||||
if (Common_BtnPress(BTN_RIGHT))
|
||||
{
|
||||
attributes.position.x += 1.0f;
|
||||
ERRCHECK( engineInstance->set3DAttributes(&attributes) );
|
||||
}
|
||||
|
||||
if (Common_BtnPress(BTN_UP))
|
||||
{
|
||||
attributes.position.z += 1.0f;
|
||||
ERRCHECK( engineInstance->set3DAttributes(&attributes) );
|
||||
}
|
||||
|
||||
if (Common_BtnPress(BTN_DOWN))
|
||||
{
|
||||
attributes.position.z -= 1.0f;
|
||||
ERRCHECK( engineInstance->set3DAttributes(&attributes) );
|
||||
}
|
||||
|
||||
if (Common_BtnPress(BTN_MORE))
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (Common_BtnPress(BTN_QUIT))
|
||||
{
|
||||
wantQuit = true;
|
||||
break;
|
||||
}
|
||||
|
||||
ERRCHECK(system->update());
|
||||
|
||||
updateScreenPosition(attributes.position);
|
||||
Common_Draw("==================================================");
|
||||
Common_Draw("Recording and playback example.");
|
||||
Common_Draw("Copyright (c) Firelight Technologies 2012-2026.");
|
||||
Common_Draw("==================================================");
|
||||
Common_Draw("");
|
||||
Common_Draw("Recording!");
|
||||
Common_Draw("");
|
||||
Common_Draw(screenBuffer);
|
||||
Common_Draw("");
|
||||
Common_Draw("Press %s to finish recording", Common_BtnStr(BTN_MORE));
|
||||
Common_Draw("Press %s to play a one-shot", Common_BtnStr(BTN_ACTION1));
|
||||
Common_Draw("Use the arrow keys (%s, %s, %s, %s) to control the engine position",
|
||||
Common_BtnStr(BTN_LEFT), Common_BtnStr(BTN_RIGHT), Common_BtnStr(BTN_UP), Common_BtnStr(BTN_DOWN));
|
||||
Common_Draw("Press %s to quit", Common_BtnStr(BTN_QUIT));
|
||||
|
||||
Common_Sleep(50);
|
||||
}
|
||||
|
||||
// Unload all the banks
|
||||
ERRCHECK( masterBank->unload() );
|
||||
ERRCHECK( stringsBank->unload() );
|
||||
ERRCHECK( vehiclesBank->unload() );
|
||||
ERRCHECK( sfxBank->unload() );
|
||||
|
||||
// Finish recording
|
||||
ERRCHECK( system->flushCommands() );
|
||||
ERRCHECK( system->stopCommandCapture() );
|
||||
|
||||
return (wantQuit ? State_Quit : State_Selection);
|
||||
}
|
||||
|
||||
// Play back a previously recorded file
|
||||
State executePlayback(FMOD::Studio::System* system)
|
||||
{
|
||||
FMOD::Studio::CommandReplay* replay;
|
||||
ERRCHECK( system->loadCommandReplay(Common_WritePath(RECORD_FILENAME), FMOD_STUDIO_COMMANDREPLAY_NORMAL, &replay));
|
||||
int commandCount;
|
||||
ERRCHECK(replay->getCommandCount(&commandCount));
|
||||
float totalTime;
|
||||
ERRCHECK(replay->getLength(&totalTime));
|
||||
ERRCHECK(replay->start());
|
||||
ERRCHECK(system->update());
|
||||
|
||||
for (;;)
|
||||
{
|
||||
Common_Update();
|
||||
|
||||
if (Common_BtnPress(BTN_QUIT))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (Common_BtnPress(BTN_MORE))
|
||||
{
|
||||
bool paused;
|
||||
ERRCHECK(replay->getPaused(&paused));
|
||||
ERRCHECK(replay->setPaused(!paused));
|
||||
}
|
||||
|
||||
FMOD_STUDIO_PLAYBACK_STATE state;
|
||||
ERRCHECK(replay->getPlaybackState(&state));
|
||||
if (state == FMOD_STUDIO_PLAYBACK_STOPPED)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
int currentIndex;
|
||||
float currentTime;
|
||||
ERRCHECK(replay->getCurrentCommand(¤tIndex, ¤tTime));
|
||||
|
||||
ERRCHECK(system->update());
|
||||
|
||||
Common_Draw("==================================================");
|
||||
Common_Draw("Recording and playback example.");
|
||||
Common_Draw("Copyright (c) Firelight Technologies 2012-2026.");
|
||||
Common_Draw("==================================================");
|
||||
Common_Draw("");
|
||||
Common_Draw("Playing back commands:");
|
||||
Common_Draw("Command = %d / %d\n", currentIndex, commandCount);
|
||||
Common_Draw("Time = %.3f / %.3f\n", currentTime, totalTime);
|
||||
Common_Draw("");
|
||||
Common_Draw("Press %s to pause/unpause recording", Common_BtnStr(BTN_MORE));
|
||||
Common_Draw("Press %s to quit", Common_BtnStr(BTN_QUIT));
|
||||
|
||||
Common_Sleep(50);
|
||||
}
|
||||
|
||||
|
||||
ERRCHECK( replay->release() );
|
||||
ERRCHECK( system->unloadAll() );
|
||||
return State_Selection;
|
||||
}
|
||||
|
||||
void initializeScreenBuffer()
|
||||
{
|
||||
memset(screenBuffer, ' ', sizeof(screenBuffer));
|
||||
|
||||
int idx = SCREEN_WIDTH;
|
||||
for (int i = 0; i < SCREEN_HEIGHT; ++i)
|
||||
{
|
||||
screenBuffer[idx] = '\n';
|
||||
idx += SCREEN_WIDTH + 1;
|
||||
}
|
||||
|
||||
screenBuffer[(SCREEN_WIDTH + 1) * SCREEN_HEIGHT] = '\0';
|
||||
}
|
||||
|
||||
int getCharacterIndex(const FMOD_VECTOR& position)
|
||||
{
|
||||
int row = static_cast<int>(-position.z + (SCREEN_HEIGHT / 2));
|
||||
int col = static_cast<int>(position.x + (SCREEN_WIDTH / 2));
|
||||
|
||||
if (0 < row && row < SCREEN_HEIGHT && 0 < col && col < SCREEN_WIDTH)
|
||||
{
|
||||
return (row * (SCREEN_WIDTH + 1)) + col;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void updateScreenPosition(const FMOD_VECTOR& eventPosition)
|
||||
{
|
||||
if (currentScreenPosition != -1)
|
||||
{
|
||||
screenBuffer[currentScreenPosition] = ' ';
|
||||
currentScreenPosition = -1;
|
||||
}
|
||||
|
||||
FMOD_VECTOR origin = {0};
|
||||
int idx = getCharacterIndex(origin);
|
||||
screenBuffer[idx] = '^';
|
||||
|
||||
idx = getCharacterIndex(eventPosition);
|
||||
if (idx != -1)
|
||||
{
|
||||
screenBuffer[idx] = 'o';
|
||||
currentScreenPosition = idx;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user