Advertisement
Craxic

Transistor Sound Ripper

Jan 6th, 2015
475
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 11.72 KB | None | 0 0
  1. #define SOUND_DIR "/home/matthew/.steam/steam/steamapps/common/Transistor/Content/Audio/AudenFMOD/Build/Desktop/"
  2.  
  3. #include "fmod_studio.hpp"
  4. #include "fmod.hpp"
  5. #include <stdio.h>
  6. #include <vector>
  7. #include <string>
  8. #include <string.h>
  9. #include <stdarg.h>
  10. #include <unistd.h>
  11. #include <algorithm>
  12. #include <iostream>
  13. #include <sstream>
  14.  
  15. class ParameterDetails {
  16. public:
  17.     std::string name;
  18. };
  19.  
  20. class SoundDetails {
  21. public:
  22.     int length_ms;
  23.     std::string name;
  24.     std::vector<ParameterDetails> parameters;
  25.     int user_property_count;
  26.     int bank_id;
  27.     int event_id;
  28.     FMOD::Studio::EventDescription * event;
  29.     FMOD::Sound * sound;
  30. };
  31.  
  32. class BankDetails {
  33. public:
  34.     std::string name;
  35.     std::string filename;
  36.     FMOD::Studio::Bank * bank;
  37. };
  38.  
  39. void ERRCHECK_fn(FMOD_RESULT result, const char *file, int line) {
  40.     if (result != 0) {
  41.         printf("[ERROR] Error at line %i in \"%s\". FMOD_RESULT: %i\n", line, file, result);
  42.     }
  43. }
  44. #define ERRCHECK(_result) ERRCHECK_fn(_result, __FILE__, __LINE__)
  45.  
  46. void RecurseSounds(FMOD::System * system, std::vector<SoundDetails> * soundDetails, std::vector<BankDetails> * bankDetails, int bank_id, FMOD::Sound * sound) {
  47.     SoundDetails soundDetail;
  48.     soundDetail.event = NULL;
  49.    
  50.     sound->getLength((unsigned int *)&(soundDetail.length_ms), FMOD_TIMEUNIT_MS);
  51.    
  52.     char name[8192];
  53.     memset(name, 0, sizeof(name));
  54.     ERRCHECK(sound->getName(name, sizeof(name)));
  55.     soundDetail.name = std::string(name);
  56.    
  57.     soundDetail.user_property_count = 0;
  58.     soundDetail.bank_id = bank_id;
  59.     soundDetail.event_id = 0;
  60.     soundDetail.sound = sound;
  61.     soundDetails->push_back(soundDetail);
  62.    
  63.     int numSubSounds = 0;
  64.     ERRCHECK(sound->getNumSubSounds(&numSubSounds));
  65.    
  66.     for (int i=0; i<numSubSounds; i++) {
  67.         FMOD::Sound * subSound;
  68.         ERRCHECK(sound->getSubSound(i, &subSound));
  69.         RecurseSounds(system, soundDetails, bankDetails, bank_id, subSound);
  70.     }
  71.    
  72. }
  73.  
  74. void LoadBank(FMOD::Studio::System * system, std::vector<SoundDetails> * soundDetails, std::vector<BankDetails> * bankDetails, const char * filename) {
  75.     printf("[LoadBank] Loading \"%s\".\n", filename);
  76.    
  77.     BankDetails bank;
  78.     bank.name = std::string(filename);
  79.     bank.filename = std::string(SOUND_DIR) + std::string(filename);
  80.     ERRCHECK(system->loadBankFile(bank.filename.c_str(), 0, &bank.bank));
  81.    
  82.     int event_count = -1;
  83.     ERRCHECK(bank.bank->getEventCount(&event_count));
  84.     printf("[LoadBank] Bank has %i events.\n", event_count);
  85.    
  86.     int bus_count = -1;
  87.     ERRCHECK(bank.bank->getBusCount(&bus_count));
  88.     printf("[LoadBank] Bank has %i busses.\n", bus_count);
  89.    
  90.     int string_count = -1;
  91.     ERRCHECK(bank.bank->getStringCount(&string_count));
  92.     printf("[LoadBank] Bank has %i strings.\n", string_count);
  93.    
  94.     int vca_count = -1;
  95.     ERRCHECK(bank.bank->getVCACount(&vca_count));
  96.     printf("[LoadBank] Bank has %i \"VCA\"s.\n", vca_count);
  97.    
  98.     bankDetails->push_back(bank);
  99.    
  100.     FMOD::Studio::EventDescription ** events = new FMOD::Studio::EventDescription*[event_count];
  101.     int event_list_count = -1;
  102.     ERRCHECK(bank.bank->getEventList(events, event_count, &event_list_count));
  103.     printf("[LoadBank] Reading %i event descriptors.\n", event_list_count);
  104.    
  105.     //std::vector<std::string> names;
  106.     for (int i=0; i<event_count; i++) {
  107.         SoundDetails sound;
  108.         sound.sound = NULL;
  109.         sound.event = events[i];
  110.        
  111.         char path[8192];
  112.         memset(path, 0, sizeof(path));
  113.         int out_len;
  114.         ERRCHECK(events[i]->getPath(path, sizeof(path), &out_len));
  115.         sound.name = std::string(path);
  116.         ERRCHECK(events[i]->getLength(&sound.length_ms));
  117.         ERRCHECK(events[i]->getUserPropertyCount(&sound.user_property_count));
  118.        
  119.         int param_count;
  120.         ERRCHECK(events[i]->getParameterCount(&param_count));
  121.        
  122.         for (int j=0; j<param_count; j++) {
  123.             FMOD_STUDIO_PARAMETER_DESCRIPTION param;
  124.             ERRCHECK(events[i]->getParameterByIndex(j, &param));
  125.            
  126.             ParameterDetails param_details;
  127.             param_details.name = std::string(param.name);
  128.             sound.parameters.push_back(param_details);
  129.         }
  130.        
  131.         sound.bank_id = bankDetails->size() - 1;
  132.         sound.event_id = i;
  133.         soundDetails->push_back(sound);
  134.     }
  135. }
  136.  
  137. void LoadVO(FMOD::System * system, std::vector<SoundDetails> * soundDetails, std::vector<BankDetails> * bankDetails, const char * filename) {
  138.     printf("[LoadVO] Loading \"%s\".\n", filename);
  139.  
  140.     BankDetails bank;
  141.     bank.name = std::string(filename);
  142.     bank.filename = std::string(SOUND_DIR) + std::string(filename);
  143.    
  144.     bankDetails->push_back(bank);
  145.    
  146.     FMOD::Sound * sound;
  147.     ERRCHECK(system->createSound(bank.filename.c_str(), 584, NULL, &sound));
  148.    
  149.     RecurseSounds(system, soundDetails, bankDetails, bankDetails->size() - 1, sound);
  150. }
  151.  
  152. bool SoundDetailsComparator(const SoundDetails & x, const SoundDetails & y) {
  153.     return x.name.compare(y.name) < 0;
  154. }
  155.  
  156. bool channelFinished = false;
  157.  
  158. FMOD_RESULT F_CALLBACK channelEndCallback(FMOD_CHANNELCONTROL *chanControl, FMOD_CHANNELCONTROL_TYPE controlType, FMOD_CHANNELCONTROL_CALLBACK_TYPE callbackType, void *commandData1, void *commandData2)
  159. {
  160.     if (callbackType == FMOD_CHANNELCONTROL_CALLBACK_END) {
  161.         channelFinished = true;
  162.     }
  163.  
  164.     return FMOD_OK;
  165. }
  166.  
  167. // Split from https://stackoverflow.com/questions/236129, thanks to Evan Teran.
  168. std::vector<std::string> &split(const std::string &s, char delim, std::vector<std::string> &elems) {
  169.     std::stringstream ss(s);
  170.     std::string item;
  171.     while (std::getline(ss, item, delim)) {
  172.         elems.push_back(item);
  173.     }
  174.     return elems;
  175. }
  176.  
  177. std::vector<std::string> split(const std::string &s, char delim) {
  178.     std::vector<std::string> elems;
  179.     split(s, delim, elems);
  180.     return elems;
  181. }
  182.  
  183. /* // This is gonna take way too long...
  184. //    output.getnumdrivers = GetNumDriversCB;
  185. FMOD_RESULT F_CALLBACK FMOD_OUTPUT_GETNUMDRIVERS_CALLBACK(FMOD_OUTPUT_STATE *output_state, int *numdrivers) {
  186.     *numdrivers = 1;
  187. }
  188. //    output.getdriverinfo = GetDriverInfoCB;
  189. FMOD_RESULT F_CALLBACK FMOD_OUTPUT_GETDRIVERINFO_CALLBACK(
  190.     FMOD_OUTPUT_STATE *output_state,
  191.     int id,
  192.     char *name,
  193.     int namelen,
  194.     FMOD_GUID *guid,
  195.     int *systemrate,
  196.     FMOD_SPEAKERMODE *speakermode,
  197.     int *speakermodechannels
  198. ) {
  199.     if (name != NULL)
  200.         name[0] = 0;
  201.     if (systemrate != NULL)
  202.         *systemrate = 0;
  203.     if (speakermode != NULL)
  204.         *speakermode = FMOD_SPEAKERMODE_STEREO;
  205.     if (speakermodechannels != NULL)
  206.         *speakermodechannels = 2;
  207. }
  208. //    output.init = InitCB;
  209. FMOD_RESULT F_CALLBACK FMOD_OUTPUT_INIT_CALLBACK(
  210.   FMOD_OUTPUT_STATE *output_state,
  211.   int selecteddriver,
  212.   FMOD_INITFLAGS flags,
  213.   int *outputrate,
  214.   FMOD_SPEAKERMODE *speakermode,
  215.   int *speakermodechannels,
  216.   FMOD_SOUND_FORMAT *outputformat,
  217.   int dspbufferlength,
  218.   int dspnumbuffers,
  219.   void *extradriverdata
  220. ) {
  221.    
  222. }
  223. //    output.start = StartCB;
  224. //    output.stop = StopCB;
  225. //    output.close = CloseCB;
  226. //    output.update = UpdateCB;
  227. //    output.gethandle = GetHandleCB;
  228. //    output.getposition = GetPositionCB;
  229. //    output.lock = LockCB;
  230. //    output.unlock = UnlockCB;
  231. */
  232.  
  233. int main(int argc, char ** argv)
  234. {
  235.     FMOD::Studio::System* system;
  236.     ERRCHECK(FMOD::Studio::System::create(&system));
  237.     FMOD::System* lowLevelSystem;
  238.     ERRCHECK(system->getLowLevelSystem(&lowLevelSystem));
  239.    
  240.     unsigned int handle;
  241.    
  242.     ERRCHECK(lowLevelSystem->setPluginPath("/home/matthew/Documents/FMOD/test"));
  243.     ERRCHECK(lowLevelSystem->loadPlugin("libFModPlugins.so", &handle, 0));
  244.    
  245.     /*
  246.     FMOD_OUTPUT_DESCRIPTION output;
  247.     output.name = "Raw Output";
  248.     output.version = 1;
  249.     output.polling = 0;
  250.     output.getnumdrivers = GetNumDriversCB;
  251.     output.getdriverinfo = GetDriverInfoCB;
  252.     output.init = InitCB;
  253.     output.start = StartCB;
  254.     output.stop = StopCB;
  255.     output.close = CloseCB;
  256.     output.update = UpdateCB;
  257.     output.gethandle = GetHandleCB;
  258.     output.getposition = GetPositionCB;
  259.     output.lock = LockCB;
  260.     output.unlock = UnlockCB;
  261.    
  262.    
  263.     unsigned int output_handle;
  264.     ERRCHECK(lowLevelSystem->registerOutput(&output, &output_handle));
  265.     ERRCHECK(lowLevelSystem->setOutputByPlugin(output_handle));
  266.     */
  267.    
  268. // UNCOMMENT THIS IF WANT TO SAVE TO WAV FILE. FMOD_OUTPUTTYPE_WAVWRITER_NRT is supposed to work but
  269. // doesn't. (NRT means not-real-time, so you wouldn't have to wait for the sound to play for it to save)
  270. //    ERRCHECK(lowLevelSystem->setOutput(FMOD_OUTPUTTYPE_WAVWRITER));
  271.     ERRCHECK(system->initialize(32, FMOD_STUDIO_INIT_NORMAL, FMOD_INIT_NORMAL, 0));
  272.    
  273.     std::vector<SoundDetails> soundDetails;
  274.     std::vector<BankDetails> bankDetails;
  275.    
  276.     LoadBank(system, &soundDetails, &bankDetails, "MasterBank.strings.bank");
  277.     LoadBank(system, &soundDetails, &bankDetails, "MasterBank.bank");
  278.     LoadBank(system, &soundDetails, &bankDetails, "AudenFMOD_Sounds.bank");
  279.     LoadBank(system, &soundDetails, &bankDetails, "AudenFMOD_OldSounds.bank");
  280.     LoadBank(system, &soundDetails, &bankDetails, "AudenFMOD_Music.bank");
  281.     LoadBank(system, &soundDetails, &bankDetails, "AudenFMOD_Ambience.bank");
  282.     LoadVO(lowLevelSystem, &soundDetails, &bankDetails, "VO.fsb");
  283.    
  284.     std::sort(soundDetails.begin(), soundDetails.end(), SoundDetailsComparator);
  285.    
  286.     for (int i=0; i<soundDetails.size(); i++) {
  287.         printf("[Event] %i: %-80s (from %-24s, length: %5i)\n", i, soundDetails[i].name.c_str(), bankDetails[soundDetails[i].bank_id].name.c_str(), soundDetails[i].length_ms);
  288.     }
  289.    
  290.     while (true) {
  291.         std::string sound_string;
  292.         std::cout << "[Main] Enter sound to play (nothing to quit, 0-5 to play 0-5 inclusive): ";
  293.         std::cin >> sound_string;
  294.        
  295.         std::vector<std::string> numbers = split(sound_string, '-');
  296.        
  297.         int start = 0;
  298.         int end = 0;
  299.        
  300.         if (numbers.size() == 1) {
  301.             start = end = atoi(numbers[0].c_str());
  302.         } else if (numbers.size() == 2) {
  303.             start = atoi(numbers[0].c_str());
  304.             end = atoi(numbers[1].c_str());
  305.         } else {
  306.             break;
  307.         }
  308.        
  309.         if (start < 0 || start >= soundDetails.size() || end < 0 || end >= soundDetails.size()) {
  310.             break;
  311.         }
  312.        
  313.         for (int sound_id = start; sound_id <= end; sound_id++) {
  314.             const SoundDetails & sound = soundDetails[sound_id];
  315.            
  316.             std::cout << "[Main] Playing " << sound_id << " (" << sound.name << ")..." << std::endl;
  317.            
  318.             if (sound.sound == NULL) {
  319.                 FMOD::Studio::EventInstance * instance;
  320.                 ERRCHECK(sound.event->createInstance(&instance));
  321.                 ERRCHECK(instance->start());
  322.            
  323.                 FMOD_STUDIO_PLAYBACK_STATE state;
  324.                 do {
  325.                     ERRCHECK(instance->getPlaybackState(&state));
  326.                     ERRCHECK(system->update());
  327.                     usleep(1000);
  328.                 } while (state != FMOD_STUDIO_PLAYBACK_STOPPED);
  329.             } else {
  330.                 FMOD::Channel * channel;
  331.                 ERRCHECK(lowLevelSystem->playSound(sound.sound, NULL, false, &channel));
  332.                 channel->setCallback(channelEndCallback);
  333.                 channelFinished = false;
  334.            
  335.                 while (!channelFinished) {
  336.                     ERRCHECK(system->update());
  337.                     usleep(1000);
  338.                 }
  339.             }
  340.         }
  341.     }
  342.    
  343.     ERRCHECK(system->release());
  344.    
  345.     return 0;
  346. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement