var BitcrushAudioProcessor::getState() { DynamicObject* properties = new DynamicObject; properties->setProperty("bitcrush", bitcrush->getValue()); properties->setProperty("downsample", downsample->getValue()); properties->setProperty("wet", wet->getValue()); return var(properties); }
var FilterAudioProcessor::getState() { DynamicObject* properties = new DynamicObject; properties->setProperty("frequency", frequency->getValue()); properties->setProperty("resonance", resonance->getValue()); properties->setProperty("filterType", filterType); return var(&properties); }
var VolumeAudioProcessor::getState() { DynamicObject* properties = new DynamicObject; properties->setProperty("volumeL", volumeL->getValue()); properties->setProperty("volumeR", volumeR->getValue()); properties->setProperty("stereoCoupling", stereoCoupling->getBoolValue()); return var(&properties); }
void IniFile::load() { const GenericScopedLock<CriticalSection> scopedlock(lock); StringArray lines; file.readLines(lines); lines.removeEmptyStrings(); lines.trim(); clear(); String section("__empty"); for (int i = 0; i < lines.size(); i++) { if (lines[i].startsWithChar(';')) { continue; } if (lines[i].startsWithChar('[') && lines[i].endsWithChar(']')) { section = lines[i].substring(1, lines[i].length() - 1); continue; } if (!lines[i].containsChar('=')) { continue; } String key = lines[i].upToFirstOccurrenceOf("=", false, false).trim(); String value = lines[i].fromFirstOccurrenceOf("=", false, false).trim(); DynamicObject *sectionObject; if (data.contains(section)) { sectionObject = data[section].getDynamicObject(); } else { sectionObject = new DynamicObject(); data.set(section, var(sectionObject)); } sectionObject->setProperty(key, var(value)); } }
const var EnviJSONRPC::toArray (const StringPairArray &stringPairArray) { var ret = empty(false); DynamicObject *dso = ret.getDynamicObject(); for (int i=0; i<stringPairArray.size(); i++) { dso->setProperty (stringPairArray.getAllKeys() [i], stringPairArray.getAllValues() [i]); } return (ret); }
//============================================================================== void MidiSelectProcessor::getStateInformation (MemoryBlock &destData) { // Use json for better forward-compatibility (not just splat) DynamicObject *data = new DynamicObject; data->setProperty("lowerNote", lowerNote); data->setProperty("upperNote", upperNote); String json = JSON::toString(var(data), true); MemoryOutputStream stream(destData, false); stream.write(json.toUTF8(), json.length()); }
void IniFile::set(const String& section, const String& key, const String& value) { const GenericScopedLock<CriticalSection> scopedlock(lock); String realSection(section); if (realSection.isEmpty()) { realSection = "__empty"; } DynamicObject *sectionObject; if (data.contains(realSection)) { sectionObject = data[realSection].getDynamicObject(); } else { sectionObject = new DynamicObject(); data.set(section, var(sectionObject)); } sectionObject->setProperty(key, var(value)); }
static var parseModuleDesc (const StringArray& lines) { DynamicObject* o = new DynamicObject(); var result (o); for (int i = 0; i < lines.size(); ++i) { String line = trimCommentCharsFromStartOfLine (lines[i]); int colon = line.indexOfChar (':'); if (colon >= 0) { String key = line.substring (0, colon).trim(); String value = line.substring (colon + 1).trim(); o->setProperty (key, value); } } return result; }
const var EnviData::toVAR(const EnviData &enviData) { String ret; DynamicObject *ds = new DynamicObject(); ds->setProperty ("name", enviData.name); ds->setProperty ("type", enviData.type); ds->setProperty ("instance", enviData.instance); var values; for (int i=0; i<enviData.getNumValues(); i++) { DynamicObject *value = new DynamicObject(); value->setProperty ("name", enviData[i].name); value->setProperty ("value", enviData[i].value.toString()); value->setProperty ("unit", enviData[i].unit); value->setProperty ("error", enviData[i].error); value->setProperty ("timestamp", enviData[i].timestamp.toMilliseconds()); values.append (value); } ds->setProperty ("values", values); return (var(ds)); }
var ApplicationSettingsFile::toJSON() { DynamicObject *root = new DynamicObject(); root->setProperty("PlayType", (int)playType); root->setProperty("UseGlobalHooks", useGlobalHooks); Array<var> keyPressObjects; for (int i = 0; i < stopAllSoundsKeys.size(); ++i) { const KeyPress &keyPress = stopAllSoundsKeys.getUnchecked(i); DynamicObject *keyPressObject = new DynamicObject(); keyPressObject->setProperty("KeyCode", keyPress.getKeyCode()); keyPressObject->setProperty("ModifierFlags", keyPress.getModifiers().getRawFlags()); keyPressObject->setProperty("TextCharacter", (int)keyPress.getTextCharacter()); keyPressObjects.add(var(keyPressObject)); } root->setProperty("StopAllSoundKeyPresses", keyPressObjects); return var(root); }
void PMixDocument::createNodeFromXml (XmlElement& xml, const String& newSourceCode) { PluginDescription pd; forEachXmlChildElement (xml, e) { if (pd.loadFromXml (*e)) break; } String errorMessage; AudioPluginInstance* instance = audioEngine.createPluginInstance(pd, errorMessage); jassert(instance != nullptr); if (pd.pluginFormatName == "FAUST") { FaustAudioPluginInstance* faustProc = dynamic_cast<FaustAudioPluginInstance*>(instance); faustProc->initialize(getLibraryPath(), drawPath); if (newSourceCode.length()) faustProc->setSourceCode(newSourceCode, true); // TODO: this is a bit wrong! faustProc->prepareToPlay(44100., 8192); // xml.setAttribute("numInputs", faustProc->getNumInputChannels()); // xml.setAttribute("numOutputs", faustProc->getNumOutputChannels()); ??? } AudioProcessorGraph::Node::Ptr node (audioEngine.getGraph().addNode (instance, xml.getIntAttribute ("uid"))); if (!newSourceCode.length()) { if (const XmlElement* const state = xml.getChildByName ("STATE")) { MemoryBlock m; m.fromBase64Encoding (state->getAllSubText()); node->getProcessor()->setStateInformation (m.getData(), (int) m.getSize()); } } node->properties.set ("x", xml.getDoubleAttribute ("x")); node->properties.set ("y", xml.getDoubleAttribute ("y")); node->properties.set ("uiLastX", xml.getIntAttribute ("uiLastX")); node->properties.set ("uiLastY", xml.getIntAttribute ("uiLastY")); node->properties.set ("uiStatus", xml.getIntAttribute ("uiStatus")); // presets etc for faust & plugin nodes if(!InternalPluginFormat::isInternalFormat(pd.name)) { node->properties.set ("colour", xml.getStringAttribute ("colour")); node->properties.set ("iposx", xml.getDoubleAttribute ("iposx")); node->properties.set ("iposy", xml.getDoubleAttribute ("iposy")); if (const XmlElement* const params = xml.getChildByName ("PARAMS")) { var vparams = JSON::parse(params->getAllSubText()); node->properties.set ("params", vparams); } Array<var> presetsArr; forEachXmlChildElement (xml, e) { if (e->hasTagName ("PRESET")) { DynamicObject* obj = new DynamicObject(); obj->setProperty("name", e->getStringAttribute("name")); obj->setProperty("x", e->getDoubleAttribute("x")); obj->setProperty("y", e->getDoubleAttribute("y")); obj->setProperty("radius", e->getDoubleAttribute("radius")); obj->setProperty("hidden", e->getBoolAttribute("hidden")); // obj->setProperty("distance", e->getDoubleAttribute("distance")); obj->setProperty("coeff", e->getDoubleAttribute("coeff")); var vparams = JSON::parse(e->getAllSubText()); obj->setProperty("state", vparams); obj->setProperty("uid", e->getIntAttribute("uid")); var preset = var(obj); presetsArr.add(preset); } } node->properties.set("presets", presetsArr); }
var PanAudioProcessor::getState() { DynamicObject* properties = new DynamicObject; properties->setProperty("panning", panning->getValue()); return var(&properties); }
bool handlePluginRequest(const PluginRequestParameters ¶ms, OutputStream &ostream, ThreadSafePlugin *plugin = nullptr) { if (!plugin) { // It's very possible that all of this was a premature optimization. // For VSTs at least, code loading and caching is handled by ModuleHandle::findOrCreateModule, // and each instantiation only requires a couple of disc hits for working directory setting. // On the other hand, we want to make sure that each audio request has a "fresh" instance. // The easiest way to do this is by bypassing the instance pool and instantiating on demand. #if PLUGIN_POOL_SIZE // Recurse with a plugin from the pool, locking on it. // Keep trying with a delay until a timeout occurs. const int TIMEOUT = 5000, WAIT = 200; int64 startTime = Time::currentTimeMillis(); while (Time::currentTimeMillis() < startTime + TIMEOUT) { int i = 0; while ((plugin = pluginPool[i++])) { const ScopedTryLock pluginTryLock(plugin->crit); if (pluginTryLock.isLocked()) { DBG << "Handling with plugin " << i << endl; return handlePluginRequest(params, ostream, plugin); } } DBG << "Trying again in " << WAIT << endl; Thread::sleep(WAIT); } // If we were unable to obtain a lock, return failure. DBG << "Timeout" << endl; return false; #else ThreadSafePlugin temporaryPlugin(createSynthInstance()); return handlePluginRequest(params, ostream, &temporaryPlugin); #endif } else { // Re-acquire or acquire the lock. const ScopedLock pluginLock(plugin->crit); AudioPluginInstance *instance = plugin->instance; // unmanaged, for simplicity // Attempt to reset the plugin in all ways possible. instance->reset(); // Setting default parameters here causes miniTERA to become unresponsive to parameter settings. // It's possible that it's effectively pressing some interface buttons that change the editor mode entirely. // It's not necessary anyways if the plugin instance has been freshly created (see above). // pluginParametersOldNewFallback(instance, nullptr, &pluginDefaults); // note that the defaults may be empty instance->setCurrentProgram(0); // Load preset if specified, before listing or modifying parameters! if (params.presetNumber >= 0 && params.presetNumber < instance->getNumPrograms()) { DBG << "Setting program/preset: " << params.presetNumber << endl; instance->setCurrentProgram(params.presetNumber); } int currentProgram = instance->getCurrentProgram(); DBG << "Current program/preset: " << currentProgram << " - " << instance->getProgramName(currentProgram) << endl; // Set parameters, starting with named, then indexed pluginParametersSet(instance, params.parameters); pluginParametersSetIndexed(instance, params.indexedParameters); // If parameters requested, output them and return if (params.listParameters) { DBG << "Rendering parameter list: # parameters " << instance->getNumPrograms() << endl; // Output each parameter setting in two places: // an indexed array and a dictionary by name // All DynamicObjects created will be freed when their var's leave scope. DynamicObject *outer = new DynamicObject(); DynamicObject *innerParams = new DynamicObject(); var indexedParamVar; { for (int i = 0, n = instance->getNumParameters(); i < n; ++i) { String name = instance->getParameterName(i); float val = instance->getParameter(i); innerParams->setProperty(name, val); DynamicObject *indexedInnerObj = new DynamicObject(); indexedInnerObj->setProperty("index", i); indexedInnerObj->setProperty("name", name); indexedInnerObj->setProperty("value", val); indexedParamVar.append(var(indexedInnerObj)); // frees indexedInnerObj when this scope ends } } outer->setProperty(Identifier("parameters"), var(innerParams)); outer->setProperty(Identifier("indexedParameters"), indexedParamVar); // List presets/programs. var progVar; { for (int i = 0, n = instance->getNumPrograms(); i < n; ++i) { progVar.append(var(instance->getProgramName(i))); } } outer->setProperty(Identifier("presets"), progVar); var outerVar(outer); JSON::writeToStream(ostream, outerVar); // DBG << JSON::toString(outerVar, true /* allOnOneLine */) << endl; return true; } // Now attempt to render audio. AudioFormatManager formatManager; formatManager.registerBasicFormats(); OptionalScopedPointer<AudioFormat> outputFormat(formatManager.findFormatForFileExtension(params.getFormatName()), false); if (!outputFormat) return false; instance->setNonRealtime(true); instance->prepareToPlay(params.sampleRate, params.blockSize); instance->setNonRealtime(true); // The writer takes ownership of the output stream; the writer will delete it when the writer leaves scope. // Therefore, we pass a special pointer class that does not allow the writer to delete it. OutputStream *ostreamNonDeleting = new NonDeletingOutputStream(&ostream); ScopedPointer<AudioFormatWriter> writer(outputFormat->createWriterFor(ostreamNonDeleting, params.sampleRate, params.nChannels, params.bitDepth, StringPairArray(), 0)); // Create a MIDI buffer MidiBuffer midiBuffer; midiBuffer.addEvent(MidiMessage::noteOn(params.midiChannel, (uint8)params.midiPitch, (uint8)params.midiVelocity), 0 /* time */); midiBuffer.addEvent(MidiMessage::allNotesOff(params.midiChannel), params.noteSeconds * params.sampleRate); AudioSampleBuffer buffer(params.nChannels, params.blockSize); int numBuffers = (int)(params.renderSeconds * params.sampleRate / params.blockSize); for (int i = 0; i < numBuffers; ++i) { // DBG << "Processing block " << i << "..." << flush; instance->processBlock(buffer, midiBuffer); // DBG << " left RMS level " << buffer.getRMSLevel(0, 0, params.blockSize) << endl; writer->writeFromAudioSampleBuffer(buffer, 0 /* offset into buffer */, params.blockSize); } instance->reset(); return true; } }