LinkedList getVst2xPluginLocations(CharString currentDirectory) { LinkedList locations = newLinkedList(); CharString locationBuffer; const char* programFiles = (!isExecutable64Bit() && isHost64Bit()) ? kPlatformWindows32BitProgramFolder : kPlatformWindowsProgramFolder; linkedListAppend(locations, currentDirectory); locationBuffer = newCharString(); snprintf(locationBuffer->data, (size_t)(locationBuffer->length), "C:\\VstPlugins"); linkedListAppend(locations, locationBuffer); locationBuffer = newCharString(); snprintf(locationBuffer->data, (size_t)(locationBuffer->length), "%s\\VstPlugIns", programFiles); linkedListAppend(locations, locationBuffer); locationBuffer = newCharString(); snprintf(locationBuffer->data, (size_t)(locationBuffer->length), "%s\\Common Files\\VstPlugIns", programFiles); linkedListAppend(locations, locationBuffer); locationBuffer = newCharString(); snprintf(locationBuffer->data, (size_t)(locationBuffer->length), "%s\\Steinberg\\VstPlugIns", programFiles); linkedListAppend(locations, locationBuffer); return locations; }
int testAppend() { LinkedList list; linkedListInit(&list, INTEGER); linkedListAppend(&list, (mixed)1); _assert(linkedListIndexOf(&list, (mixed)1) == 0); linkedListAppend(&list, (mixed)2); _assert(linkedListIndexOf(&list, (mixed)2) == 1); return 0; }
LinkedList getVst2xPluginLocations(CharString currentDirectory) { LinkedList locations = newLinkedList(); CharString locationBuffer; linkedListAppend(locations, currentDirectory); locationBuffer = newCharString(); snprintf(locationBuffer->data, (size_t)(locationBuffer->capacity), "/Library/Audio/Plug-Ins/VST"); linkedListAppend(locations, locationBuffer); locationBuffer = newCharString(); snprintf(locationBuffer->data, (size_t)(locationBuffer->capacity), "%s/Library/Audio/Plug-Ins/VST", getenv("HOME")); linkedListAppend(locations, locationBuffer); return locations; }
static int _testAppendItemToNullList(void) { CharString c = newCharString(); // The test here is not to crash linkedListAppend(NULL, c); freeCharString(c); return 0; }
// Note that this method skips hidden files LinkedList listDirectory(const CharString directory) { LinkedList items = newLinkedList(); CharString filename; #if UNIX DIR* directoryPtr = opendir(directory->data); if(directoryPtr == NULL) { freeLinkedList(items); return 0; } struct dirent* entry; while((entry = readdir(directoryPtr)) != NULL) { if(entry->d_name[0] != '.') { filename = newCharStringWithCString(entry->d_name); linkedListAppend(items, filename); } } closedir(directoryPtr); #elif WINDOWS WIN32_FIND_DATAA findData; HANDLE findHandle; CharString searchString = newCharString(); snprintf(searchString->data, searchString->length, "%s\\*", directory->data); findHandle = FindFirstFileA((LPCSTR)(searchString->data), &findData); freeCharString(searchString); if(findHandle == INVALID_HANDLE_VALUE) { freeLinkedList(items); return 0; } do { if(findData.cFileName[0] != '.') { filename = newCharString(); strncpy(filename->data, findData.cFileName, filename->length); linkedListAppend(items, filename); } } while(FindNextFileA(findHandle, &findData) != 0); FindClose(findHandle); #else logUnsupportedFeature("List directory contents"); #endif return items; }
static int _testAppendNullItemToList(void) { LinkedList l = newLinkedList(); linkedListAppend(l, NULL); assertIsNull(l->item); assertIsNull(l->nextItem); assertIntEquals(linkedListLength(l), 0); freeLinkedList(l); return 0; }
static int _testLinkedListToArray(void) { LinkedList l = newLinkedList(); CharString* arr; CharString c; linkedListAppend(l, newCharStringWithCString("one")); linkedListAppend(l, newCharStringWithCString("two")); arr = (CharString*)linkedListToArray(l); assertNotNull(arr); c = (CharString)arr[0]; assertCharStringEquals(c, "one"); c = (CharString)arr[1]; assertCharStringEquals(c, "two"); assertIsNull(arr[2]); free(arr); freeLinkedListAndItems(l, (LinkedListFreeItemFunc)freeCharString); return 0; }
static int _testAppendItemToList(void) { LinkedList l = newLinkedList(); CharString c = newCharString(); charStringCopyCString(c, TEST_ITEM_STRING); linkedListAppend(l, c); assertNotNull(l->item); assertCharStringEquals(((CharString)l->item), TEST_ITEM_STRING); assertIsNull(l->nextItem); freeLinkedListAndItems(l, (LinkedListFreeItemFunc)freeCharString); return 0; }
static int _testNumItemsInList(void) { CharString c; int i; LinkedList l = newLinkedList(); for(i = 0; i < 100; i++) { c = newCharString(); charStringCopyCString(c, TEST_ITEM_STRING); linkedListAppend(l, c); } assertIntEquals(linkedListLength(l), 100); freeLinkedListAndItems(l, (LinkedListFreeItemFunc)freeCharString); return 0; }
static int _testAppendMultipleItemsToList(void) { LinkedListIterator i; LinkedList l = newLinkedList(); CharString c = newCharString(); CharString c2 = newCharString(); charStringCopyCString(c, TEST_ITEM_STRING); charStringCopyCString(c2, OTHER_TEST_ITEM_STRING); linkedListAppend(l, c); linkedListAppend(l, c2); assertNotNull(l->item); assertCharStringEquals(((CharString)l->item), TEST_ITEM_STRING); assertNotNull(l->nextItem); i = l->nextItem; assertNotNull(i->item); assertCharStringEquals(((CharString)i->item), OTHER_TEST_ITEM_STRING); assertIsNull(i->nextItem); assertIntEquals(linkedListLength(l), 2); freeLinkedListAndItems(l, (LinkedListFreeItemFunc)freeCharString); return 0; }
static int _testForeachOverUserData(void) { LinkedList l = newLinkedList(); CharString c = newCharString(); charStringCopyCString(c, TEST_ITEM_STRING); linkedListAppend(l, c); linkedListForeach(l, _linkedListUserDataCallback, c); assertIntEquals(_gNumForeachCallbacksMade, 1); assert(_gForeachCallbackOk); freeLinkedListAndItems(l, (LinkedListFreeItemFunc)freeCharString); return 0; }
LinkedList getVst2xPluginLocations(CharString currentDirectory) { LinkedList locations = newLinkedList(); CharString locationBuffer; char* vstPathEnv; linkedListAppend(locations, currentDirectory); locationBuffer = newCharString(); snprintf(locationBuffer->data, (size_t)(locationBuffer->capacity), "%s/.vst", getenv("HOME")); linkedListAppend(locations, locationBuffer); locationBuffer = newCharString(); vstPathEnv = getenv("VST_PATH"); if(vstPathEnv != NULL) { snprintf(locationBuffer->data, (size_t)(locationBuffer->capacity), "%s", vstPathEnv); linkedListAppend(locations, locationBuffer); } else { freeCharString(locationBuffer); } return locations; }
boolByte fillMidiEventsFromRange(MidiSequence self, const unsigned long startTimestamp, const unsigned long blocksize, LinkedList outMidiEvents) { MidiEvent midiEvent; LinkedListIterator iterator = self->_lastEvent; const unsigned long stopTimestamp = startTimestamp + blocksize; while (true) { if ((iterator == NULL) || (iterator->item == NULL)) { return false; } midiEvent = iterator->item; if (stopTimestamp < midiEvent->timestamp) { // We have not yet reached this event, stop iterating break; } else if (startTimestamp <= midiEvent->timestamp && stopTimestamp > midiEvent->timestamp) { midiEvent->deltaFrames = midiEvent->timestamp - startTimestamp; logDebug("Scheduling MIDI event 0x%x (%x, %x) in %ld frames", midiEvent->status, midiEvent->data1, midiEvent->data2, midiEvent->deltaFrames); linkedListAppend(outMidiEvents, midiEvent); self->_lastEvent = iterator->nextItem; self->numMidiEventsProcessed++; } else if (startTimestamp > midiEvent->timestamp) { logInternalError("Inconsistent MIDI sequence ordering"); } // Last item in the list if (iterator->nextItem == NULL) { if (startTimestamp <= midiEvent->timestamp && stopTimestamp > midiEvent->timestamp) { return false; } break; } iterator = iterator->nextItem; } return true; }
LinkedList charStringSplit(const CharString self, const char delimiter) { LinkedList result = NULL; char *delimiterPtr = NULL; char *selfIndex = self->data; CharString item = NULL; size_t charsToCopy = 0; boolByte done = false; if (delimiter == '\0') { logError("Cannot split string with NULL delimiter"); return NULL; } result = newLinkedList(); while (!done) { delimiterPtr = strchr(selfIndex, delimiter); if (delimiterPtr == NULL) { done = true; charsToCopy = self->data + strlen(self->data) - selfIndex; } else { charsToCopy = delimiterPtr - selfIndex; } if (charsToCopy > 0) { item = newCharStringWithCapacity(charsToCopy + 1); strncpy(item->data, selfIndex, charsToCopy); linkedListAppend(result, item); } selfIndex = delimiterPtr + 1; } return result; }
int mrsWatsonMain(ErrorReporter errorReporter, int argc, char** argv) { ReturnCodes result; // Input/Output sources, plugin chain, and other required objects SampleSource inputSource = NULL; SampleSource outputSource = NULL; AudioClock audioClock; PluginChain pluginChain; CharString pluginSearchRoot = newCharString(); boolByte shouldDisplayPluginInfo = false; MidiSequence midiSequence = NULL; MidiSource midiSource = NULL; unsigned long maxTimeInMs = 0; unsigned long maxTimeInFrames = 0; unsigned long tailTimeInMs = 0; unsigned long tailTimeInFrames = 0; unsigned long processingDelayInFrames; ProgramOptions programOptions; ProgramOption option; Plugin headPlugin; SampleBuffer inputSampleBuffer = NULL; SampleBuffer outputSampleBuffer = NULL; TaskTimer initTimer, totalTimer, inputTimer, outputTimer = NULL; LinkedList taskTimerList = NULL; CharString totalTimeString = NULL; boolByte finishedReading = false; SampleSource silentSampleInput; SampleSource silentSampleOutput; unsigned int i; initTimer = newTaskTimerWithCString(PROGRAM_NAME, "Initialization"); totalTimer = newTaskTimerWithCString(PROGRAM_NAME, "Total Time"); taskTimerStart(initTimer); taskTimerStart(totalTimer); initEventLogger(); initAudioSettings(); initAudioClock(); audioClock = getAudioClock(); initPluginChain(); pluginChain = getPluginChain(); programOptions = newMrsWatsonOptions(); inputSource = sampleSourceFactory(NULL); if(!programOptionsParseArgs(programOptions, argc, argv)) { printf("Run with '--help' to see possible options\n"); printf("Or run with '--help full' to see extended help for all options\n"); return RETURN_CODE_INVALID_ARGUMENT; } // These options conflict with standard processing (more or less), so check to see if the user wanted one // of these and then exit right away. if(argc == 1) { printf("%s needs at least a plugin, input source, and output source to run.\n\n", PROGRAM_NAME); printMrsWatsonQuickstart(argv[0]); return RETURN_CODE_NOT_RUN; } else if(programOptions->options[OPTION_HELP]->enabled) { printMrsWatsonQuickstart(argv[0]); if(charStringIsEmpty(programOptionsGetString(programOptions, OPTION_HELP))) { printf("All options, where <argument> is required and [argument] is optional:\n"); programOptionsPrintHelp(programOptions, false, DEFAULT_INDENT_SIZE); } else { if(charStringIsEqualToCString(programOptionsGetString(programOptions, OPTION_HELP), "full", true)) { programOptionsPrintHelp(programOptions, true, DEFAULT_INDENT_SIZE); } // Yeah this is a bit silly, but the performance obviously doesn't matter // here and I don't feel like cluttering up this already huge function // with more variables. else if(programOptionsFind(programOptions, programOptionsGetString(programOptions, OPTION_HELP))) { programOptionPrintHelp(programOptionsFind(programOptions, programOptionsGetString(programOptions, OPTION_HELP)), true, DEFAULT_INDENT_SIZE, 0); } else { printf("Invalid option '%s', try running --help full to see help for all options\n", programOptionsGetString(programOptions, OPTION_HELP)->data); } } return RETURN_CODE_NOT_RUN; } else if(programOptions->options[OPTION_VERSION]->enabled) { printVersion(); return RETURN_CODE_NOT_RUN; } else if(programOptions->options[OPTION_COLOR_TEST]->enabled) { printTestPattern(); return RETURN_CODE_NOT_RUN; } // See if we are to make an error report and make necessary changes to the // options for good diagnostics. Note that error reports cannot be generated // for any of the above options which return with RETURN_CODE_NOT_RUN. else if(programOptions->options[OPTION_ERROR_REPORT]->enabled) { errorReporterInitialize(errorReporter); programOptions->options[OPTION_VERBOSE]->enabled = true; programOptions->options[OPTION_LOG_FILE]->enabled = true; programOptions->options[OPTION_DISPLAY_INFO]->enabled = true; // Shell script with original command line arguments errorReporterCreateLauncher(errorReporter, argc, argv); // Rewrite some paths before any input or output sources have been opened. _remapFileToErrorReport(errorReporter, programOptions->options[OPTION_INPUT_SOURCE], true); _remapFileToErrorReport(errorReporter, programOptions->options[OPTION_OUTPUT_SOURCE], false); _remapFileToErrorReport(errorReporter, programOptions->options[OPTION_MIDI_SOURCE], true); _remapFileToErrorReport(errorReporter, programOptions->options[OPTION_LOG_FILE], false); } // Read in options from a configuration file, if given if(programOptions->options[OPTION_CONFIG_FILE]->enabled) { if(!programOptionsParseConfigFile(programOptions, programOptionsGetString(programOptions, OPTION_CONFIG_FILE))) { return RETURN_CODE_INVALID_ARGUMENT; } } // Parse these options first so that log messages displayed in the below // loop are properly displayed if(programOptions->options[OPTION_VERBOSE]->enabled) { setLogLevel(LOG_DEBUG); } else if(programOptions->options[OPTION_QUIET]->enabled) { setLogLevel(LOG_ERROR); } else if(programOptions->options[OPTION_LOG_LEVEL]->enabled) { setLogLevelFromString(programOptionsGetString(programOptions, OPTION_LOG_LEVEL)); } if(programOptions->options[OPTION_COLOR_LOGGING]->enabled) { // If --color was given but with no string argument, then force color. Otherwise // colors will be provided automatically anyways. if(charStringIsEmpty(programOptionsGetString(programOptions, OPTION_COLOR_LOGGING))) { programOptionsSetCString(programOptions, OPTION_COLOR_LOGGING, "force"); } setLoggingColorEnabledWithString(programOptionsGetString(programOptions, OPTION_COLOR_LOGGING)); } if(programOptions->options[OPTION_LOG_FILE]->enabled) { setLogFile(programOptionsGetString(programOptions, OPTION_LOG_FILE)); } // Parse other options and set up necessary objects for(i = 0; i < programOptions->numOptions; i++) { option = programOptions->options[i]; if(option->enabled) { switch(option->index) { case OPTION_BLOCKSIZE: setBlocksize((const unsigned long)programOptionsGetNumber(programOptions, OPTION_BLOCKSIZE)); break; case OPTION_CHANNELS: setNumChannels((const unsigned long)programOptionsGetNumber(programOptions, OPTION_CHANNELS)); break; case OPTION_DISPLAY_INFO: shouldDisplayPluginInfo = true; break; case OPTION_INPUT_SOURCE: freeSampleSource(inputSource); inputSource = sampleSourceFactory(programOptionsGetString(programOptions, OPTION_INPUT_SOURCE)); break; case OPTION_MAX_TIME: maxTimeInMs = (const unsigned long)programOptionsGetNumber(programOptions, OPTION_MAX_TIME); break; case OPTION_MIDI_SOURCE: midiSource = newMidiSource(guessMidiSourceType(programOptionsGetString( programOptions, OPTION_MIDI_SOURCE)), programOptionsGetString(programOptions, OPTION_MIDI_SOURCE)); break; case OPTION_OUTPUT_SOURCE: outputSource = sampleSourceFactory(programOptionsGetString(programOptions, OPTION_OUTPUT_SOURCE)); break; case OPTION_PLUGIN_ROOT: charStringCopy(pluginSearchRoot, programOptionsGetString(programOptions, OPTION_PLUGIN_ROOT)); break; case OPTION_SAMPLE_RATE: setSampleRate(programOptionsGetNumber(programOptions, OPTION_SAMPLE_RATE)); break; case OPTION_TAIL_TIME: tailTimeInMs = (long)programOptionsGetNumber(programOptions, OPTION_TAIL_TIME); break; case OPTION_TEMPO: setTempo(programOptionsGetNumber(programOptions, OPTION_TEMPO)); break; case OPTION_TIME_SIGNATURE: if(!setTimeSignatureFromString(programOptionsGetString(programOptions, OPTION_TIME_SIGNATURE))) { return RETURN_CODE_INVALID_ARGUMENT; } break; case OPTION_ZEBRA_SIZE: setLoggingZebraSize((int)programOptionsGetNumber(programOptions, OPTION_ZEBRA_SIZE)); break; default: // Ignore -- no special handling needs to be performed here break; } } } if(programOptions->options[OPTION_LIST_PLUGINS]->enabled) { listAvailablePlugins(pluginSearchRoot); return RETURN_CODE_NOT_RUN; } if(programOptions->options[OPTION_LIST_FILE_TYPES]->enabled) { sampleSourcePrintSupportedTypes(); return RETURN_CODE_NOT_RUN; } printWelcomeMessage(argc, argv); if((result = setupInputSource(inputSource)) != RETURN_CODE_SUCCESS) { logError("Input source could not be opened, exiting"); return result; } if((result = buildPluginChain(pluginChain, programOptionsGetString(programOptions, OPTION_PLUGIN), pluginSearchRoot)) != RETURN_CODE_SUCCESS) { logError("Plugin chain could not be constructed, exiting"); return result; } if(midiSource != NULL) { result = setupMidiSource(midiSource, &midiSequence); if(result != RETURN_CODE_SUCCESS) { logError("MIDI source could not be opened, exiting"); return result; } } // Copy plugins before they have been opened if(programOptions->options[OPTION_ERROR_REPORT]->enabled) { if(errorReporterShouldCopyPlugins()) { if(!errorReporterCopyPlugins(errorReporter, pluginChain)) { logWarn("Failed copying plugins to error report directory"); } } } // Initialize the plugin chain after the global sample rate has been set result = pluginChainInitialize(pluginChain); if(result != RETURN_CODE_SUCCESS) { logError("Could not initialize plugin chain"); return result; } // Display info for plugins in the chain before checking for valid input/output sources if(shouldDisplayPluginInfo) { pluginChainInspect(pluginChain); } // Execute any parameter changes if(programOptions->options[OPTION_PARAMETER]->enabled) { if(!pluginChainSetParameters(pluginChain, programOptionsGetList(programOptions, OPTION_PARAMETER))) { return RETURN_CODE_INVALID_ARGUMENT; } } // Setup output source here. Having an invalid output source should not cause the program // to exit if the user only wants to list plugins or query info about a chain. if((result = setupOutputSource(outputSource)) != RETURN_CODE_SUCCESS) { logError("Output source could not be opened, exiting"); return result; } // Verify input/output sources. This must be done after the plugin chain is initialized // otherwise the head plugin type is not known, which influences whether we must abort // processing. if(programOptions->options[OPTION_ERROR_REPORT]->enabled) { if(charStringIsEqualToCString(inputSource->sourceName, "-", false) || charStringIsEqualToCString(outputSource->sourceName, "-", false)) { printf("ERROR: Using stdin/stdout is incompatible with --error-report\n"); return RETURN_CODE_NOT_RUN; } if(midiSource != NULL && charStringIsEqualToCString(midiSource->sourceName, "-", false)) { printf("ERROR: MIDI source from stdin is incompatible with --error-report\n"); return RETURN_CODE_NOT_RUN; } } if(outputSource == NULL) { logInternalError("Default output sample source was null"); return RETURN_CODE_INTERNAL_ERROR; } if(inputSource == NULL || inputSource->sampleSourceType == SAMPLE_SOURCE_TYPE_SILENCE) { // If the first plugin in the chain is an instrument, use the silent source as our input and // make sure that there is a corresponding MIDI file headPlugin = pluginChain->plugins[0]; if(headPlugin->pluginType == PLUGIN_TYPE_INSTRUMENT) { if(midiSource == NULL) { // I guess some instruments (like white noise generators etc.) don't necessarily // need MIDI, actually this is most useful for our internal plugins and generators. // Anyways, this should only be a soft warning for those who know what they're doing. logWarn("Plugin chain contains an instrument, but no MIDI source was supplied"); if(maxTimeInMs == 0) { // However, if --max-time wasn't given, then there is effectively no input source // and thus processing would continue forever. That won't work. logError("No valid input source or maximum time, don't know when to stop processing"); return RETURN_CODE_MISSING_REQUIRED_OPTION; } else { // If maximum time was given and there is no other input source, then use silence inputSource = newSampleSourceSilence(); } } } else { logError("Plugin chain contains only effects, but no input source was supplied"); return RETURN_CODE_MISSING_REQUIRED_OPTION; } } inputSampleBuffer = newSampleBuffer(getNumChannels(), getBlocksize()); inputTimer = newTaskTimerWithCString(PROGRAM_NAME, "Input Source"); outputSampleBuffer = newSampleBuffer(getNumChannels(), getBlocksize()); outputTimer = newTaskTimerWithCString(PROGRAM_NAME, "Output Source"); // Initialization is finished, we should be able to free this memory now freeProgramOptions(programOptions); // If a maximum time was given, figure it out here if(maxTimeInMs > 0) { maxTimeInFrames = (unsigned long)(maxTimeInMs * getSampleRate()) / 1000l; } processingDelayInFrames = pluginChainGetProcessingDelay(pluginChain); // Get largest tail time requested by any plugin in the chain tailTimeInMs += pluginChainGetMaximumTailTimeInMs(pluginChain); tailTimeInFrames = (unsigned long)(tailTimeInMs * getSampleRate()) / 1000l + processingDelayInFrames; pluginChainPrepareForProcessing(pluginChain); // Update sample rate on the event logger setLoggingZebraSize((long)getSampleRate()); logInfo("Starting processing input source"); logDebug("Sample rate: %.0f", getSampleRate()); logDebug("Blocksize: %d", getBlocksize()); logDebug("Channels: %d", getNumChannels()); logDebug("Tempo: %.2f", getTempo()); logDebug("Processing delay frames: %lu", processingDelayInFrames); logDebug("Time signature: %d/%d", getTimeSignatureBeatsPerMeasure(), getTimeSignatureNoteValue()); taskTimerStop(initTimer); silentSampleInput = sampleSourceFactory(NULL); silentSampleOutput = sampleSourceFactory(NULL); // Main processing loop while(!finishedReading) { taskTimerStart(inputTimer); finishedReading = !readInput(inputSource, silentSampleInput, inputSampleBuffer, tailTimeInFrames); // TODO: For streaming MIDI, we would need to read in events from source here if(midiSequence != NULL) { LinkedList midiEventsForBlock = newLinkedList(); // MIDI source overrides the value set to finishedReading by the input source finishedReading = !fillMidiEventsFromRange(midiSequence, audioClock->currentFrame, getBlocksize(), midiEventsForBlock); linkedListForeach(midiEventsForBlock, _processMidiMetaEvent, &finishedReading); pluginChainProcessMidi(pluginChain, midiEventsForBlock); freeLinkedList(midiEventsForBlock); } taskTimerStop(inputTimer); if(maxTimeInFrames > 0 && audioClock->currentFrame >= maxTimeInFrames) { logInfo("Maximum time reached, stopping processing after this block"); finishedReading = true; } pluginChainProcessAudio(pluginChain, inputSampleBuffer, outputSampleBuffer); taskTimerStart(outputTimer); if(finishedReading) { outputSampleBuffer->blocksize = inputSampleBuffer->blocksize;//The input buffer size has been adjusted. logDebug("Using buffer size of %d for final block", outputSampleBuffer->blocksize); } writeOutput(outputSource, silentSampleOutput, outputSampleBuffer, processingDelayInFrames); taskTimerStop(outputTimer); advanceAudioClock(audioClock, outputSampleBuffer->blocksize); } // Close file handles for input/output sources silentSampleInput->closeSampleSource(silentSampleInput); silentSampleOutput->closeSampleSource(silentSampleOutput); inputSource->closeSampleSource(inputSource); outputSource->closeSampleSource(outputSource); // Print out statistics about each plugin's time usage // TODO: On windows, the total processing time is stored in clocks and not milliseconds // These values must be converted using the QueryPerformanceFrequency() function audioClockStop(audioClock); taskTimerStop(totalTimer); if(totalTimer->totalTaskTime > 0) { taskTimerList = newLinkedList(); linkedListAppend(taskTimerList, initTimer); linkedListAppend(taskTimerList, inputTimer); linkedListAppend(taskTimerList, outputTimer); for(i = 0; i < pluginChain->numPlugins; i++) { linkedListAppend(taskTimerList, pluginChain->audioTimers[i]); linkedListAppend(taskTimerList, pluginChain->midiTimers[i]); } totalTimeString = taskTimerHumanReadbleString(totalTimer); logInfo("Total processing time %s, approximate breakdown:", totalTimeString->data); linkedListForeach(taskTimerList, _printTaskTime, totalTimer); } else { // Woo-hoo! logInfo("Total processing time <1ms. Either something went wrong, or your computer is smokin' fast!"); } freeTaskTimer(initTimer); freeTaskTimer(inputTimer); freeTaskTimer(outputTimer); freeTaskTimer(totalTimer); freeLinkedList(taskTimerList); freeCharString(totalTimeString); if(midiSequence != NULL) { logInfo("Read %ld MIDI events from %s", midiSequence->numMidiEventsProcessed, midiSource->sourceName->data); } else { logInfo("Read %ld frames from %s", inputSource->numSamplesProcessed / getNumChannels(), inputSource->sourceName->data); } logInfo("Wrote %ld frames to %s", outputSource->numSamplesProcessed / getNumChannels(), outputSource->sourceName->data); // Shut down and free data (will also close open files, plugins, etc) logInfo("Shutting down"); freeSampleSource(inputSource); freeSampleSource(outputSource); freeSampleBuffer(inputSampleBuffer); freeSampleBuffer(outputSampleBuffer); pluginChainShutdown(pluginChain); freePluginChain(pluginChain); if(midiSource != NULL) { freeMidiSource(midiSource); } if(midiSequence != NULL) { freeMidiSequence(midiSequence); } freeAudioSettings(); logInfo("Goodbye!"); freeEventLogger(); freeAudioClock(getAudioClock()); if(errorReporter->started) { errorReporterClose(errorReporter); } freeErrorReporter(errorReporter); return RETURN_CODE_SUCCESS; }
static LinkedList _getTestSuites(void) { LinkedList internalTestSuites = newLinkedList(); linkedListAppend(internalTestSuites, addAudioClockTests()); linkedListAppend(internalTestSuites, addAudioSettingsTests()); linkedListAppend(internalTestSuites, addCharStringTests()); #if USE_NEW_FILE_API linkedListAppend(internalTestSuites, addFileTests()); #endif linkedListAppend(internalTestSuites, addFileUtilitiesTests()); linkedListAppend(internalTestSuites, addLinkedListTests()); linkedListAppend(internalTestSuites, addMidiSequenceTests()); linkedListAppend(internalTestSuites, addMidiSourceTests()); linkedListAppend(internalTestSuites, addPlatformUtilitiesTests()); linkedListAppend(internalTestSuites, addPluginTests()); linkedListAppend(internalTestSuites, addPluginChainTests()); linkedListAppend(internalTestSuites, addPluginPresetTests()); linkedListAppend(internalTestSuites, addProgramOptionTests()); linkedListAppend(internalTestSuites, addSampleBufferTests()); linkedListAppend(internalTestSuites, addSampleSourceTests()); linkedListAppend(internalTestSuites, addStringUtilitiesTests()); linkedListAppend(internalTestSuites, addTaskTimerTests()); linkedListAppend(internalTestSuites, addAnalysisClippingTests()); linkedListAppend(internalTestSuites, addAnalysisDistortionTests()); linkedListAppend(internalTestSuites, addAnalysisSilenceTests()); return internalTestSuites; }
void appendMidiEventToSequence(MidiSequence self, MidiEvent midiEvent) { if (self != NULL && midiEvent != NULL) { linkedListAppend(self->midiEvents, midiEvent); } }
static void _programOptionSetListItem(ProgramOption self, void* value) { if(self->type == kProgramOptionTypeList) { linkedListAppend(self->_data.list, value); } }
void addTestToTestSuite(TestSuite testSuite, TestCase testCase) { linkedListAppend(testSuite->testCases, testCase); }