#include "LoggerFactory.hpp" #include "Feedlet.hpp" #include "TimerEvent.hpp" #include "ValueEvent.hpp" #include "PortLibrary.hpp" #include#include #ifndef M_PI #define M_PI 3.1415926 #endif /* --------------------- INSTRUMENTATION START ------------------------- */ ILogger* logger; IFeedlet* signalFeedlet; IFeedlet* activityFeedlet; IFeedlet* midiFeedlet; TimerEvent* activityTimer; ValueEvent* signalET; ValueEvent* loudnessET; PortLibrary *portLibrary; EventType *midiEventET; void instrumentationInit(char* fileNameOrPortNumber, int durationSeconds) { portLibrary = new PortLibrary(); // Create a logger int portNumber = atoi(fileNameOrPortNumber); const int numEventTypeSpaces = 1; EventTypeSpaceVersion* eventTypeSpaces[numEventTypeSpaces]; eventTypeSpaces[0] = EventTypeSpaceVersion::newInstance(portLibrary, "com.ibm.tuningfork.music", 1); if (portNumber > 0) { logger = LoggerFactory::makeServerLogger(portLibrary, portNumber, eventTypeSpaces, numEventTypeSpaces); } else { if (strcmp(fileNameOrPortNumber, "none") == 0) { logger = LoggerFactory::makeNullLogger(portLibrary); } else { logger = LoggerFactory::makeFileLogger(portLibrary, fileNameOrPortNumber, eventTypeSpaces, numEventTypeSpaces); } if (logger == NULL) { fprintf(stderr, "Could not open file %s for writing.\n", fileNameOrPortNumber); exit(-1); } } // Add some properties char valueBuffer[20]; sprintf(valueBuffer, "%d sec", durationSeconds); logger->addProperty("Program Run Length", valueBuffer); // Add some event types - two for each type of threads activityTimer = logger->makeTimerEvent("Activity"); signalET = logger->makeValueEvent("Signal Value"); loudnessET = logger->makeValueEvent("Loudness"); EventAttribute* eventAttrs[4]; eventAttrs[0] = EventAttribute::newInstance(portLibrary, "channel", "channel", logger->getInt(portLibrary)); eventAttrs[1] = EventAttribute::newInstance(portLibrary, "status", "status", logger->getInt(portLibrary)); eventAttrs[2] = EventAttribute::newInstance(portLibrary, "data1", "data1", logger->getInt(portLibrary)); eventAttrs[3] = EventAttribute::newInstance(portLibrary, "data2", "data2", logger->getInt(portLibrary)); midiEventET = EventType::newInstance(portLibrary, logger, "MIDI Events", "MIDI Events", 4, eventAttrs); logger->addEventType(midiEventET); midiFeedlet = logger->makeFeedlet(); midiFeedlet->setName("midi"); signalFeedlet = logger->makeFeedlet(); signalFeedlet->setName("signal feedlet"); activityFeedlet = logger->makeFeedlet(); activityFeedlet->setName("activity"); } void setSignal(double amplitude, double loudness) { signalET->addValue(amplitude); // ---------------- INSTRUMENTATION ------------------- loudnessET->addValue(loudness); // ---------------- INSTRUMENTATION ------------------- // Do some work related to setting signal - we simulate by sleeping briefly portLibrary->sleep(1); } void runOneInterval(int timeMs) { activityTimer->start(); // ---------------------- INSTRUMENTATION ------------------- portLibrary->sleep(timeMs); activityTimer->stop(); // --------------------- INSTRUMENTATION ------------------- } int runMidi(void* durSec) { int durationSec = (int) durSec; midiFeedlet->bindToCurrentThread(); // --------------------- INSTRUMENTATION ------------------- // Now make some MIDI events int channel = 0; int status = 0x90; // on int data1 = 0x30; // pitch int data2 = 64; // velocity U_64 start = portLibrary->nanoTimeCoarse(); while (true) { double timeSec = (portLibrary->nanoTimeCoarse() - start) / 1e9; I_32 ivals[4]; ivals[0] = channel; ivals[1] = status; ivals[2] = data1; ivals[3] = data2; midiFeedlet->addEvent(midiEventET, 4, ivals, 0, NULL, 0, NULL, 0, NULL); if (status == 0x90) { status = 0x80; } else { status = 0x90; if (++data1 > 0x60) { data1 = 0x30; } } if (timeSec > durationSec) { break; } portLibrary->sleep(100); } } int runSignal(void *durSec) { int durationSec = (int) durSec; signalFeedlet->bindToCurrentThread(); // --------------------- INSTRUMENTATION ------------------- // Now make some events double pitchFrequency = 5; double loudnessFrequency = 0.5; U_64 start = portLibrary->nanoTimeCoarse(); while (true) { double timeSec = (portLibrary->nanoTimeCoarse() - start) / 1e9; double pitchPosition = timeSec * pitchFrequency * 2 * M_PI; double loudnessPosition = timeSec * loudnessFrequency * 2 * M_PI; double loudness = 1 + 0.5 * sin(loudnessPosition); double amplitude = sin(pitchPosition) * loudness; setSignal(amplitude, loudness); if (timeSec > durationSec) { break; } } return 0; } int runIntervals(void* durSec) { int durationSec = (int) durSec; activityFeedlet->bindToCurrentThread(); // --------------------- INSTRUMENTATION ------------------- double onMaxLenMs = 200; // activity's length is from a uniform distribution from 0 to onMaxLen double offMaxLenMs = 500; // time until next activity is from a uniform distribution from 0 to onMaxLen U_64 start = portLibrary->nanoTimeCoarse(); while (true) { double r1 = rand() / ((double) RAND_MAX); double r2 = rand() / ((double) RAND_MAX); int onLenMs = (int) (onMaxLenMs * r1); int offLenMs = (int) (offMaxLenMs * r2); runOneInterval(onLenMs); portLibrary->sleep(offLenMs); double timeSec = (portLibrary->nanoTimeCoarse() - start) / 1e9; if (timeSec > durationSec) { break; } } return 0; } int main(int argc, char **args) { /* ------- INSTRUMENTATION MODIFICATION START --------- */ if (argc != 3) { fprintf(stderr, "Usage: Client "); return -1; } char* duration = args[1]; int durationSeconds = atoi(duration); if (durationSeconds == 0) { durationSeconds = 60; // Default is 60 seconds fprintf(stderr, "Could not parse duration argument. Using %d seconds.", durationSeconds); } char* fileNameOrPortNumber = args[2]; // INSRUMENTATION instrumentationInit(fileNameOrPortNumber, durationSeconds); // INSRUMENTATION /* ------- INSTRUMENTATION MODIFICATION END --------- */ // Run 2 threads that make events for some time fprintf(stderr, "Running 2 threads for %d seconds.\n", durationSeconds); portLibrary->runOnNewThread(runSignal, (void*) durationSeconds); portLibrary->runOnNewThread(runIntervals, (void*) durationSeconds); portLibrary->runOnNewThread(runMidi, (void*) durationSeconds); // This is only an approximation - not synchronized with event-generating threads portLibrary->sleep(durationSeconds * 1000); logger->flush(); /* INSTRUMENTATION */ // Flush buffered data fprintf(stderr, "Done."); } }