예제 #1
0
파일: MessageLine.cpp 프로젝트: LuaAV/LuaAV
void MessageLine::processMessage(int inletIndex, PdMessage *message) {
  switch (inletIndex) {
    case 0: {
      switch (message->getNumElements()) {
        case 1: {
          if (message->getElement(0)->getType() == FLOAT) {
            // jump to the given value
            PdMessage *outgoingMessage = getNextOutgoingMessage(0);
            outgoingMessage->setTimestamp(message->getTimestamp());
            
            currentValue = message->getElement(0)->getFloat();
            // TODO(mhroth): cancel any callbacks
            
            outgoingMessage->getElement(0)->setFloat(currentValue);
            sendMessage(0, outgoingMessage);
          }
          break;
        }
        case 2: {
          if (message->getElement(0)->getType() == FLOAT &&
              message->getElement(1)->getType() == FLOAT) {
            // set value and target
            targetValue = message->getElement(0)->getFloat();
            float duration = message->getElement(1)->getFloat();
            slope = (targetValue - currentValue) / duration;
            
            // send the current message
            PdMessage *outgoingMessage = getNextOutgoingMessage(0);
            outgoingMessage->setTimestamp(message->getTimestamp());
            outgoingMessage->getElement(0)->setFloat(currentValue);
            sendMessage(0, outgoingMessage);
            
            // schedule the next message
            pendingMessage = getNextOutgoingMessage(0);
            pendingMessage->setTimestamp(message->getTimestamp() + grainRate);
            pendingMessage->getElement(0)->setFloat(currentValue + slope);
            graph->scheduleMessage(this, 0, pendingMessage);
          }
          break;
        }
        default: {
          break;
        }
      }
      break;
    }
    case 1: {
      // not sure what to do in this case
      break;
    }
  }
}
예제 #2
0
void MessageSwap::processMessage(int inletIndex, PdMessage *message) {
  switch (inletIndex) {
    case 0: {
      MessageElement *messageElement = message->getElement(0);
      switch (messageElement->getType()) {
        case FLOAT: {
          left = messageElement->getFloat();

          PdMessage *outgoingMessageRight = getNextOutgoingMessage(0);
          outgoingMessageRight->getElement(0)->setFloat(left);
          outgoingMessageRight->setTimestamp(message->getTimestamp());
          sendMessage(1, outgoingMessageRight); // send a message from outlet 1

          PdMessage *outgoingMessageLeft = getNextOutgoingMessage(1);
          outgoingMessageLeft->getElement(0)->setFloat(right);
          outgoingMessageLeft->setTimestamp(message->getTimestamp());
          sendMessage(0, outgoingMessageLeft); // send a message from outlet 0
          break;
        }
        case BANG: {
          PdMessage *outgoingMessageRight = getNextOutgoingMessage(0);
          outgoingMessageRight->getElement(0)->setFloat(left);
          outgoingMessageRight->setTimestamp(message->getTimestamp());
          sendMessage(0, outgoingMessageRight); // send a message from outlet 1

          PdMessage *outgoingMessageLeft = getNextOutgoingMessage(1);
          outgoingMessageLeft->getElement(0)->setFloat(right);
          outgoingMessageLeft->setTimestamp(message->getTimestamp());
          sendMessage(1, outgoingMessageLeft); // send a message from outlet 0
          break;
        }
        default: {
          break;
        }
      }
      break;
    }
    case 1: {
      MessageElement *messageElement = message->getElement(0);
      if (messageElement->getType() == FLOAT) {
        right = messageElement->getFloat();
      }
      break;
    }
    default: {
      break;
    }
  }
}
예제 #3
0
파일: DspEnvelope.cpp 프로젝트: LuaAV/LuaAV
// windowSize and windowInterval are constrained to be multiples of the block size
void DspEnvelope::processDspWithIndex(int fromIndex, int toIndex) {
  // copy the input into the signal buffer
  memcpy(signalBuffer + numSamplesReceived, dspBufferAtInlet0, numBytesInBlock);
  numSamplesReceived += blockSizeInt;
  numSamplesReceivedSinceLastInterval += blockSizeInt;
  if (numSamplesReceived >= windowSize) {
    numSamplesReceived = 0;
  }
  if (numSamplesReceivedSinceLastInterval == windowInterval) {
    numSamplesReceivedSinceLastInterval -= windowInterval;
    // apply hanning window to signal and calculate Root Mean Square
    float rms = 0.0f;
    if (ArrayArithmetic::hasAccelerate) {
      #if __APPLE__
      vDSP_vsq(signalBuffer, 1, rmsBuffer, 1, windowSize); // signalBuffer^2 
      vDSP_vmul(rmsBuffer, 1, hanningCoefficients, 1, rmsBuffer, 1, windowSize); // * hanning window
      vDSP_sve(rmsBuffer, 1, &rms, windowSize); // sum the result
      #endif
    } else {
      for (int i = 0; i < windowSize; i++) {
        rms += signalBuffer[i] * signalBuffer[i] * hanningCoefficients[i];
      }
    }
    // finish RMS calculation. sqrt is removed as it can be combined with the log operation.
    // result is normalised such that 1 RMS == 100 dB
    rms = 10.0f * log10f(rms) + 100.0f;

    PdMessage *outgoingMessage = getNextOutgoingMessage(0);
    // graph will schedule this at the beginning of the next block because the timestamp will be
    // behind the block start timestamp
    outgoingMessage->setTimestamp(0.0);
    outgoingMessage->setFloat(0, (rms < 0.0f) ? 0.0f : rms);
    graph->scheduleMessage(this, 0, outgoingMessage);
  }
}
예제 #4
0
void MessageDbToPow::processMessage(int inletIndex, PdMessage *message) {
  if (message->getElement(0)->getType() == FLOAT) {
    if (message->getElement(0)->getFloat() <= 0) {
      PdMessage *outgoingMessage = getNextOutgoingMessage(0);
      outgoingMessage->getElement(0)->setFloat(0);
      outgoingMessage->setTimestamp(message->getTimestamp());
      sendMessage(0, outgoingMessage);
    }
    else if (message->getElement(0)->getFloat() > 0) {
      PdMessage *outgoingMessage = getNextOutgoingMessage(0);
      outgoingMessage->getElement(0)->setFloat(powf(0.00001f * powf(10.0f,(message->getElement(0)->getFloat())/20.0f),2.0f));
      outgoingMessage->setTimestamp(message->getTimestamp());
      sendMessage(0, outgoingMessage); // send a message from outlet 0
    }
  }
}
예제 #5
0
void MessageGreaterThanOrEqualTo::processMessage(int inletIndex, PdMessage *message) {
  switch (inletIndex) {
    case 0: {
      switch (message->getType(0)) {
        case FLOAT: {
          lastOutput = (message->getFloat(0) >= constant) ? 1.0f : 0.0f;
          // allow fallthrough
        }
        case BANG: {
          PdMessage *outgoingMessage = getNextOutgoingMessage(0);
          outgoingMessage->setFloat(0, lastOutput);
          outgoingMessage->setTimestamp(message->getTimestamp());
          sendMessage(0, outgoingMessage);
          break;
        }
        default: {
          break;
        }
      }
      break;
    }
    case 1: {
      if (message->isFloat(0)) {
        constant = message->getFloat(0);
      }
      break;
    }
    default: {
      break;
    }
  }
}
예제 #6
0
void MessageSelect::processMessage(int inletIndex, PdMessage *message) {
  switch (inletIndex) {
    case 0: {
      MessageElement *messageElement = message->getElement(0);
      for (int i = 0; i < messageElementList->getNumElements(); i++) {
        MessageElement *selector = (MessageElement *) messageElementList->get(i);
        if (messageElement->equals(selector)) {
          PdMessage *outgoingMessage = getNextOutgoingMessage(i);
          outgoingMessage->setBlockIndex(message->getBlockIndex());
          return;
        }
      }

      setNextOutgoingMessage(messageElementList->getNumElements(), message);
      break;
    }
    case 1: {
      // TODO(mhroth): be able to set the selctor
      break;
    }
    default: {
      break;
    }
  }
}
예제 #7
0
void MessageMaximum::processMessage(int inletIndex, PdMessage *message) {
  switch (inletIndex) {
    case 0: {
      switch (message->getType(0)) {
        case FLOAT: {
          lastOutput = fmaxf(message->getFloat(0), constant);
          // allow fallthrough
        }
        case BANG: {
          PdMessage *outgoingMessage = getNextOutgoingMessage(0);
          outgoingMessage->setFloat(0, lastOutput);
          outgoingMessage->setTimestamp(message->getTimestamp());
          sendMessage(0, outgoingMessage);
          break;
        }
        default: {
          break;
        }
      }
      break;
    }
    case 1: {
      if (message->isFloat(0)) {
        constant = message->getFloat(0);
      }
      break;
    }
    default: {
      break;
    }
  }
}
예제 #8
0
void MessageListPrepend::processMessage(int inletIndex, PdMessage *message) {
  switch (inletIndex) {
    case 0: {
      PdMessage *outgoingMessage = getNextOutgoingMessage(0);
      outgoingMessage->setTimestamp(message->getTimestamp());
      outgoingMessage->clear();
      int numElements = message->getNumElements();
      for (int i = 0; i < numElements; i++) {
        outgoingMessage->addElement(prependMessage->getElement(i));
      }
      numElements = prependMessage->getNumElements();
      for (int i = 0; i < numElements; i++) {
        outgoingMessage->addElement(message->getElement(i));
      }
      sendMessage(0, outgoingMessage);
      break;
    }
    case 1: {
      // NOTE(mhroth): would be faster to copy in place rather than destroying and creating memory
      // can change if it becomes a problem
      delete prependMessage;
      prependMessage = message->copy();
      break;
    }
    default: {
      break;
    }
  }
}
예제 #9
0
void MessageLine::processMessage(int inletIndex, PdMessage *message) {
  switch (inletIndex) {
    case 0: {
      MessageElement *messageElement = message->getElement(0);
      switch (messageElement->getType()) {
        case FLOAT: {
          MessageElement *messageElement1 = message->getElement(1);
          if (messageElement1 != NULL && messageElement1->getType() == FLOAT) {
            // start a new line
            processDspToIndex(message->getBlockIndex());
            float delayInMs = StaticUtils::millisecondsToSamples(
                messageElement1->getFloat(), sampleRate);
            samplesToTarget = lrintf(delayInMs);
            target = messageElement->getFloat();
            slope = (target - lastValue) / delayInMs;
          } else {
            // set the current value
            processDspToIndex(message->getBlockIndex());
            target = messageElement->getFloat();
            lastValue = target;
            slope = 0.0f;
            samplesToTarget = -1;
          }
          PdMessage *outgoingMessage = getNextOutgoingMessage(0);
          outgoingMessage->getElement(0)->setFloat(lastValue);
          outgoingMessage->setBlockIndex(message->getBlockIndex());
          break;
        }
        case SYMBOL: {
          MessageElement *messageElement = message->getElement(0);
          if (strcmp(messageElement->getSymbol(), "stop") == 0) {
            processDspToIndex(message->getBlockIndex());
            samplesToTarget = -1;
          } else if (strcmp(messageElement->getSymbol(), "set") == 0) {
            MessageElement *messageElement1 = message->getElement(0);
            if (messageElement1 != NULL && messageElement1->getType() == FLOAT) {
              processDspToIndex(message->getBlockIndex());
              target = messageElement1->getFloat();
              lastValue = target;
              samplesToTarget = -1;
            }
          }
          break;
        }
        default: {
          break;
        }
      }
      break;
    }
    case 1: {
      // not sure what to do in this case
      break;
    }
    default: {
      break;
    }
  }
}
예제 #10
0
void MessageCosine::processMessage(int inletIndex, PdMessage *message) {
  if (message->isFloat(0)) {
    PdMessage *outgoingMessage = getNextOutgoingMessage(0);
    outgoingMessage->getElement(0)->setFloat(cosf(message->getFloat(0)));
    outgoingMessage->setTimestamp(message->getTimestamp());
    sendMessage(0, outgoingMessage); // send a message from outlet 0
  }
}
예제 #11
0
inline void MessageAbsoluteValue::processMessage(int inletIndex, PdMessage *message) {
  if (inletIndex == 0) {
    MessageElement *messageElement = message->getElement(0);
    if (messageElement != NULL && messageElement->getType() == FLOAT) {
      PdMessage *outgoingMessage = getNextOutgoingMessage(0);
      outgoingMessage->setBlockIndex(message->getBlockIndex());
      outgoingMessage->getElement(0)->setFloat(fabsf(messageElement->getFloat()));
    }
  }
}
void MessageUnaryOperationObject::processMessage(int inletIndex, PdMessage *message) {
  if (inletIndex == 0) {
    // TODO(mhroth): do we need to be able to handle a list of numbers?
    MessageElement *messageElement = message->getElement(0);
    if (messageElement->getType() == FLOAT) {
      PdMessage *outgoingMessage = getNextOutgoingMessage(0);
      outgoingMessage->setBlockIndex(message->getBlockIndex());
      outgoingMessage->getElement(0)->setFloat(performUnaryOperation(messageElement->getFloat()));
    }
  }
}
예제 #13
0
void MessageArcTangent::processMessage(int inletIndex, PdMessage *message) {
  if (inletIndex == 0) {
    MessageElement *messageElement = message->getElement(0);
    if (messageElement->getType() == FLOAT) {
      PdMessage *outgoingMessage = getNextOutgoingMessage(0);
      outgoingMessage->getElement(0)->setFloat(atanf(messageElement->getFloat()));
      outgoingMessage->setTimestamp(message->getTimestamp());
      sendMessage(0, outgoingMessage); // send a message from outlet 0
    }
  }
}
예제 #14
0
void MessageListLength::processMessage(int inletIndex, PdMessage *message) {
  PdMessage *outgoingMessage = getNextOutgoingMessage(0);
  outgoingMessage->setTimestamp(message->getTimestamp());
  if (message->isBang(0)) {
    // bangs are not considered to add length to lists
    outgoingMessage->getElement(0)->setFloat(0.0f);
  } else {
    outgoingMessage->getElement(0)->setFloat((float) message->getNumElements());
  }
  sendMessage(0, outgoingMessage);
}
예제 #15
0
void MessageListSplit::processMessage(int inletIndex, PdMessage *message) {
  switch (inletIndex) {
    case 0: {
      int numElements = message->getNumElements();
      if (numElements <= splitIndex) {
        // if there aren't enough elements to split on, forward the message on the third outlet
        sendMessage(2, message);
      } else {
        PdMessage *outgoingMessage0 = getNextOutgoingMessage(0);
        outgoingMessage0->setTimestamp(message->getTimestamp());
        outgoingMessage0->clear();
        for (int i = 0; i < splitIndex; i++) {
          outgoingMessage0->addElement(message->getElement(i));
        }
        
        PdMessage *outgoingMessage1 = getNextOutgoingMessage(1);
        outgoingMessage1->setTimestamp(message->getTimestamp());
        outgoingMessage1->clear();
        for (int i = splitIndex; i < numElements; i++) {
          outgoingMessage1->addElement(message->getElement(i));
        }
        
        sendMessage(1, outgoingMessage1);
        sendMessage(0, outgoingMessage0);
      }
      break;
    }
    case 1: {
      if (message->isFloat(0)) {
        // split index may not be negative
        splitIndex = (message->getFloat(0) < 0.0f) ? 0 : (int) message->getFloat(0);
      }
      break;
    }
    default: {
      break;
    }
  }
}
예제 #16
0
PdMessage *MessageMessageBox::getNextResolvedMessage(int objMessageIndex,
    PdMessage *templateMessage, PdMessage *incomingMessage) {
  
  PdMessage *outgoingMessage = getNextOutgoingMessage(objMessageIndex);
  outgoingMessage->setTimestamp(incomingMessage->getTimestamp());
  for (int i = 0; i < templateMessage->getNumElements(); i++) {
    if (templateMessage->isSymbol(i)) {
      PdMessage::resolveElement(templateMessage->getSymbol(i), incomingMessage,
          outgoingMessage->getElement(i));
    }
  }
  
  return outgoingMessage;
}
예제 #17
0
void MessageLine::processDspToIndex(int newBlockIndex) {
  int processLength = newBlockIndex - blockIndexOfLastMessage;
  if (samplesToTarget >= 0 && processLength > 0) {
    if (samplesToTarget < processLength) {
      lastValue += slope;
      PdMessage *outgoingMessage = getNextOutgoingMessage(0);
      outgoingMessage->getElement(0)->setFloat(lastValue);
      outgoingMessage->setBlockIndex(samplesToTarget);
      samplesToTarget = samplesToTarget - processLength + grainRateInSamples;
    } else {
      samplesToTarget -= processLength;
    }
    blockIndexOfLastMessage = newBlockIndex;
  }
}
예제 #18
0
void DspSnapshot::processMessage(int inletIndex, PdMessage *message) {
  switch (message->getType(0)) {
    case SYMBOL: {
      graph->printErr("snapshot~ does not support the \"set\" message.\n");
      break;
    }
    case BANG: {
      PdMessage *outgoingMessage = getNextOutgoingMessage(0);
      outgoingMessage->setTimestamp(message->getTimestamp());
      float blockIndex = message->getBlockIndex(graph->getBlockStartTimestamp(), graph->getSampleRate());
      outgoingMessage->setFloat(0, localDspBufferAtInlet[0][(int) blockIndex]);
      sendMessage(0, outgoingMessage);
      break;
    }
    default: {
      break;
    }
  }
}
예제 #19
0
inline void MessageFloat::processMessage(int inletIndex, PdMessage *message) {
  if (inletIndex == 0) {
    MessageElement *messageElement = message->getElement(0);
    switch (messageElement->getType()) {
      case FLOAT: {
        constant = messageElement->getFloat();
        // allow fallthrough
      }
      case BANG: {
        PdMessage *outgoingMessage = getNextOutgoingMessage(0);
        outgoingMessage->getElement(0)->setFloat(constant);
        outgoingMessage->setBlockIndex(message->getBlockIndex());
        break;
      }
      default: {
        break;
      }
    }
  }
}
예제 #20
0
void MessageTimer::processMessage(int inletIndex, PdMessage *message) {
  switch (inletIndex) {
    case 0: {
      MessageElement *messageElement = message->getElement(0);
      if (messageElement->getType() == BANG) {
        processDspToIndex(message->getBlockIndex());
        elapsedSamples = 0.0f;
      }
      break;
    }
    case 1: {
      // return the elapsed number milliseconds
      processDspToIndex(message->getBlockIndex());
      PdMessage *outgoingMessage = getNextOutgoingMessage(0);
      outgoingMessage->getElement(0)->setFloat(1000.0f * elapsedSamples / sampleRate);
      outgoingMessage->setBlockIndexAsFloat(message->getBlockIndexAsFloat());
      break;
    }
    default: {
      break;
    }
  }
}
예제 #21
0
inline void MessagePack::processMessage(int inletIndex, PdMessage *message) {
  MessageElement *messageElement = message->getElement(0);
  MessageElement *outgoingMessageElement = (MessageElement *) messageElementList->get(inletIndex);
  switch (outgoingMessageElement->getType()) {
    case FLOAT: {
      outgoingMessageElement->setFloat(messageElement->getFloat());
      break;
    }
    case SYMBOL: {
      outgoingMessageElement->setSymbol(messageElement->getSymbol());
      break;
    }
    default: {
      break;
    }
  }
  if (inletIndex == 0) {
    PdMessage *outgoingMessage = getNextOutgoingMessage(0);
    outgoingMessage->setBlockIndex(message->getBlockIndex());
    for (int i = 0; i < messageElementList->getNumElements(); i++) {
      messageElement = (MessageElement *) messageElementList->get(i);
      switch (messageElement->getType()) {
        case FLOAT: {
          outgoingMessage->getElement(i)->setFloat(messageElement->getFloat());
          break;
        }
        case SYMBOL: {
          outgoingMessage->getElement(i)->setSymbol(messageElement->getSymbol());
          break;
        }
        default: {
          break;
        }
      }
    }
  }
}
예제 #22
0
void MessageSubtract::processMessage(int inletIndex, PdMessage *message) {
  switch (inletIndex) {
    case 0: {
      MessageElement *messageElement = message->getElement(0);
      if (messageElement->getType() == FLOAT) {
        PdMessage *outgoingMessage = getNextOutgoingMessage(0);
        outgoingMessage->getElement(0)->setFloat(messageElement->getFloat() - constant);
        outgoingMessage->setTimestamp(message->getTimestamp());
        sendMessage(0, outgoingMessage); // send a message from outlet 0
      }
      break;
    }
    case 1: {
      MessageElement *messageElement = message->getElement(0);
      if (messageElement->getType() == FLOAT) {
        constant = messageElement->getFloat();
      }
      break;
    }
    default: {
      break;
    }
  }
}
예제 #23
0
void MessageSoundfiler::processMessage(int inletIndex, PdMessage *message) {
    if (message->isSymbol(0) && strcmp(message->getSymbol(0), "read") == 0) {
        int currentElementIndex = 1;
        bool shouldResizeTable = false;

        while (currentElementIndex < message->getNumElements()) {
            MessageElement *messageElement = message->getElement(currentElementIndex++);
            if (messageElement->getType() == SYMBOL) {
                // only the -resize flag is supported for now
                if (strcmp(messageElement->getSymbol(), "-resize") == 0) {
                    shouldResizeTable = true;
                } else {
                    // all of the flags should have been seen now and now we expect the last two parameters,
                    // which are file location and destination table name
                    MessageElement *tableNameElement = message->getElement(currentElementIndex++);
                    if (messageElement != NULL && messageElement->getType() == SYMBOL &&
                            tableNameElement != NULL && tableNameElement->getType() == SYMBOL) {
                        MessageTable *table = graph->getTable(tableNameElement->getSymbol());
                        if (table != NULL) {
                            // use libsndfile to load and read the file (also converting the samples to [-1,1] float)
                            SF_INFO sfInfo;
                            char *fullPath = graph->resolveFullPath(messageElement->getSymbol());
                            SNDFILE *sndFile = sf_open(fullPath, SFM_READ, &sfInfo);

                            if (sndFile == NULL) {
                                graph->printErr("soundfiler can't open %s.", fullPath);
                                free(fullPath);
                                return; // there was an error reading the file. Move on with life.
                            }
                            free(fullPath);

                            // It is assumed that the channels are interleaved.
                            int samplesPerChannel = sfInfo.frames;
                            int bufferLength = samplesPerChannel * sfInfo.channels;
                            // create a buffer in memory for the file data
                            float *buffer = (float *) malloc(bufferLength * sizeof(float));
                            sf_read_float(sndFile, buffer, bufferLength); // read the whole file into memory
                            sf_close(sndFile); // release the handle to the file

                            if (sfInfo.channels > 0) { // sanity check
                                // get the table's buffer. Resize the buffer if necessary.
                                int tableLength = samplesPerChannel;
                                float *tableBuffer = shouldResizeTable ? table->resizeBuffer(samplesPerChannel) :
                                                     table->getBuffer(&tableLength);
                                if (tableLength > samplesPerChannel) {
                                    // avoid trying to read more into the table buffer than is available
                                    tableLength = samplesPerChannel;
                                }

                                // extract the first channel
                                for (int i = 0, j = 0; i < bufferLength; i+=sfInfo.channels, j++) {
                                    tableBuffer[j] = buffer[i];
                                }

                                // extract the second channel (if it exists and if there is a table to write it to)
                                if (sfInfo.channels > 1 &&
                                        (tableNameElement = message->getElement(currentElementIndex++)) != NULL &&
                                        tableNameElement->getType() == SYMBOL &&
                                        (table = graph->getTable(tableNameElement->getSymbol())) != NULL) {
                                    tableLength = samplesPerChannel;
                                    tableBuffer = shouldResizeTable ? table->resizeBuffer(samplesPerChannel) :
                                                  table->getBuffer(&tableLength);
                                    if (tableLength > samplesPerChannel) {
                                        // avoid trying to read more into the table buffer than is available
                                        tableLength = samplesPerChannel;
                                    }
                                    for (int i = 1, j = 0; i < bufferLength; i+=sfInfo.channels, j++) {
                                        tableBuffer[j] = buffer[i];
                                    }
                                }
                            }
                            free(buffer);

                            // send message with sample length when all tables have been filled
                            PdMessage *outgoingMessage = getNextOutgoingMessage(0);
                            outgoingMessage->setFloat(0, (float) samplesPerChannel);
                            outgoingMessage->setTimestamp(message->getTimestamp());
                            sendMessage(0, outgoingMessage);
                        }
                    }
                }
            }
        }
    } else if (message->isSymbol(0) && strcmp(message->getSymbol(0), "write") == 0) {
        // TODO(mhroth): not supported yet
        graph->printErr("The \"write\" command to soundfiler is not supported.");
    }
}