summary refs log blame commit diff stats
path: root/src/muxer.cpp
blob: e6c9a0980f2a47c8f0732c0ac09e7b02d2554971 (plain) (tree)
1
2
3
4

                        
                    



















                                                                                                        
                                                                                                                              
                                            
                                                                                                                                       









                                                           
                                         
                     









                                                                    
                                                                     
                     

















                                                                    
                                                  

                                                                        












                                                                            










                                                                              




                                                                       


                                               

                                           



















                                                                        

                      









                                                                         

                                                 

     
                              










































                                                   
#include "muxer.h"
#include <iostream>
#include <fmod_errors.h>
#include "runtime.h"

void ERRCHECK_fn(FMOD_RESULT result, const char* file, int line) {
  if (result != FMOD_OK) {
    std::cout << file << "(" << line << "): FMOD error " << result << " - " << FMOD_ErrorString(result);
    abort();
  }
}

#define ERRCHECK(_result) ERRCHECK_fn(_result, __FILE__, __LINE__)

Muxer::Muxer() {
  FMOD::Studio::System* system_holder = nullptr;
  ERRCHECK(FMOD::Studio::System::create(&system_holder));
  system_.reset(system_holder);

  FMOD::System* coreSystem = nullptr;
  ERRCHECK(system_->getCoreSystem(&coreSystem));
  ERRCHECK(coreSystem->setSoftwareFormat(0, FMOD_SPEAKERMODE_5POINT1, 0));
  ERRCHECK(system_->initialize(1024, FMOD_STUDIO_INIT_NORMAL, FMOD_INIT_NORMAL, nullptr));

  FMOD::Studio::Bank* masterBank = nullptr;
  ERRCHECK(system_->loadBankFile(Runtime::getResourcePath("Master.bank").c_str(), FMOD_STUDIO_LOAD_BANK_NORMAL, &masterBank));

  FMOD::Studio::Bank* stringsBank = nullptr;
  ERRCHECK(system_->loadBankFile(Runtime::getResourcePath("Master.strings.bank").c_str(), FMOD_STUDIO_LOAD_BANK_NORMAL, &stringsBank));
}

void Muxer::setPlayerLoc(int x, int y) {
  FMOD_3D_ATTRIBUTES attributes = {{0}};
  attributes.forward.z = 1.0f;
  attributes.up.y = 1.0f;
  attributes.position.x = x;
  attributes.position.y = y;
  ERRCHECK(system_->setListenerAttributes(0, &attributes));
}

void Muxer::playSound(std::string name) {
  if (muted_) return;

  std::string eventPath = std::string("event:/") + name;

  FMOD::Studio::EventDescription* eventDescription = nullptr;
  ERRCHECK(system_->getEvent(eventPath.c_str(), &eventDescription));

  FMOD::Studio::EventInstance* eventInstance = nullptr;
  ERRCHECK(eventDescription->createInstance(&eventInstance));
  ERRCHECK(eventInstance->start());
  ERRCHECK(eventInstance->release());
}

void Muxer::playSoundAtPosition(std::string name, float x, float y) {
  if (muted_) return;

  std::string eventPath = std::string("event:/") + name;

  FMOD::Studio::EventDescription* eventDescription = nullptr;
  ERRCHECK(system_->getEvent(eventPath.c_str(), &eventDescription));

  FMOD::Studio::EventInstance* eventInstance = nullptr;
  ERRCHECK(eventDescription->createInstance(&eventInstance));

  FMOD_3D_ATTRIBUTES attributes = {{0}};
  attributes.forward.z = 1.0f;
  attributes.up.y = 1.0f;
  attributes.position.x = x;
  attributes.position.y = y;
  ERRCHECK(eventInstance->set3DAttributes(&attributes));
  ERRCHECK(eventInstance->start());
  ERRCHECK(eventInstance->release());
}

void Muxer::setMusicLevel(int level) {
  if (transition_state_ == TransitionState::Pre) {
    if (level >= 3) {
      ERRCHECK(exploration_event_->stop(FMOD_STUDIO_STOP_ALLOWFADEOUT));
      ERRCHECK(exploration_event_->release());

      if (muted_) {
        FMOD::Studio::EventDescription* eventDescription = nullptr;
        ERRCHECK(system_->getEvent("event:/the_world", &eventDescription));
        ERRCHECK(eventDescription->createInstance(&the_world_event_));
        ERRCHECK(the_world_event_->start());
        ERRCHECK(the_world_event_->setVolume(0));
        transition_state_ = TransitionState::Post;
      } else {
        FMOD::Studio::EventDescription* eventDescription = nullptr;
        ERRCHECK(system_->getEvent("event:/transition", &eventDescription));
        ERRCHECK(eventDescription->createInstance(&transition_event_));
        ERRCHECK(transition_event_->start());
        transition_state_ = TransitionState::Transition;
      }
    } else {
      ERRCHECK(exploration_event_->setParameterByName("level", level));
    }
  } else if (transition_state_ == TransitionState::Post) {
    if (level <= 3) {
      ERRCHECK(the_world_event_->setParameterByName("level_full", 0));
    } else {
      ERRCHECK(the_world_event_->setParameterByName("level_full", level - 3));
    }
  }
}

void Muxer::startMusic() {
  FMOD::Studio::EventDescription* exploration_desc = nullptr;
  ERRCHECK(system_->getEvent("event:/exploration", &exploration_desc));
  ERRCHECK(exploration_desc->createInstance(&exploration_event_));
  ERRCHECK(exploration_event_->start());

  if (muted_) {
    ERRCHECK(exploration_event_->setVolume(0));
  }

  transition_state_ = TransitionState::Pre;
}

void Muxer::stopMusic() {
  switch (transition_state_) {
    case TransitionState::Pre: {
      ERRCHECK(exploration_event_->stop(FMOD_STUDIO_STOP_ALLOWFADEOUT));
      break;
    }
    case TransitionState::Transition: {
      ERRCHECK(transition_event_->stop(FMOD_STUDIO_STOP_ALLOWFADEOUT));
      break;
    }
    case TransitionState::Post: {
      ERRCHECK(the_world_event_->stop(FMOD_STUDIO_STOP_ALLOWFADEOUT));
      break;
    }
    case TransitionState::Stopped: {
      // Do nothing.
      break;
    }
  }

  transition_state_ = TransitionState::Stopped;
}

void Muxer::update() {
  if (transition_state_ == TransitionState::Transition) {
    FMOD_STUDIO_PLAYBACK_STATE playbackState;
    ERRCHECK(transition_event_->getPlaybackState(&playbackState));
    if (playbackState == FMOD_STUDIO_PLAYBACK_STOPPED) {
      transition_state_ = TransitionState::Post;
      transition_event_->release();

      FMOD::Studio::EventDescription* eventDescription = nullptr;
      ERRCHECK(system_->getEvent("event:/the_world", &eventDescription));
      ERRCHECK(eventDescription->createInstance(&the_world_event_));
      ERRCHECK(the_world_event_->start());
      if (muted_) {
        ERRCHECK(the_world_event_->setVolume(0));
      }
    }
  }

  ERRCHECK(system_->update());
}

void Muxer::toggleMute() {
  muted_ = !muted_;

  if (muted_) {
    switch (transition_state_) {
      case TransitionState::Pre: {
        ERRCHECK(exploration_event_->setVolume(0));
        break;
      }
      case TransitionState::Transition: {
        ERRCHECK(transition_event_->setVolume(0));
        break;
      }
      case TransitionState::Post: {
        ERRCHECK(the_world_event_->setVolume(0));
        break;
      }
      case TransitionState::Stopped: {
        // Do nothing.
        break;
      }
    }
  } else {
    switch (transition_state_) {
      case TransitionState::Pre: {
        ERRCHECK(exploration_event_->setVolume(1));
        break;
      }
      case TransitionState::Transition: {
        ERRCHECK(transition_event_->setVolume(1));
        break;
      }
      case TransitionState::Post: {
        ERRCHECK(the_world_event_->setVolume(1));
        break;
      }
      case TransitionState::Stopped: {
        // Do nothing.
        break;
      }
    }
  }
}