コード例 #1
0
AlgorithmStatus OverlapAdd::process() {
  EXEC_DEBUG("process()");
  AlgorithmStatus status = acquireData();
  EXEC_DEBUG("data acquired");

  if (status != OK) {
    if (!shouldStop()) return status;

    int available = input("frame").available();
    if (available == 0) {
      return FINISHED;
    }
    // otherwise, there are still some frames
    return CONTINUE;
  }

  const vector<vector<Real> >& frames = _frames.tokens();
  vector<Real>& output = _output.tokens();

  assert(frames.size() == 1 && (int) output.size() == _hopSize);
  const vector<Real> & windowedFrame = frames[0];

  if (windowedFrame.empty()) throw EssentiaException("OverlapAdd: the input frame is empty");

  processFrame(_tmpFrame, windowedFrame, output, _frameHistory, _frameSize,
               _hopSize, _normalizationGain);

  EXEC_DEBUG("releasing");
  releaseData();
  EXEC_DEBUG("released");

  return OK;
}
コード例 #2
0
ファイル: silencerate.cpp プロジェクト: AnasGhrab/essentia
AlgorithmStatus SilenceRate::process() {
  EXEC_DEBUG("process()");

  AlgorithmStatus status = acquireData();

  if (status != OK) return status;

  const vector<Real>& frame = _frame.firstToken();

  if (frame.empty()) {
    throw EssentiaException("SilenceRate: a given input frame was empty, "
                            "cannot compute the power of an empty frame.");
  }

  Real power = instantPower(frame);

  for (int i=0; i<(int)_outputs.size(); i++) {
    Real& output = _outputs[i]->firstToken();
    output = power < _thresholds[i]? 1.0 : 0.0;
  }

  releaseData();

  return OK;
}
コード例 #3
0
AlgorithmStatus AccumulatorAlgorithm::process() {
  EXEC_DEBUG("process()");
  AlgorithmStatus status = acquireData();

  if (status == OK) {
    consume();
    releaseData();

    return OK;
  }

  // status != SYNC_OK: we couldn't acquire a sufficient number of tokens...

  // if we're not yet at the end of the stream, just return and wait for more
  if (!shouldStop()) return status; // most likely NO_INPUT


  // we are at the end of the stream, we need to work with what's available
  int available = _inputStream->available();
  EXEC_DEBUG("EOS; there are " << available << " available tokens left");

  if (available > 0) {
    _inputStream->setAcquireSize(available);
    _inputStream->setReleaseSize(available);

    status = acquireData();
    if (status != OK) {
      throw EssentiaException("Accumulator EOS internal scheduling error...");
    }

    // consume our very last tokens
    consume();
    releaseData();
  }

  // and now the big moment we've been waiting for all the time! All the tokens
  // from the input stream have been consumed, it is time to output our final result
  finalProduce();

  return FINISHED; // yes we produced something, and we're done!
}
コード例 #4
0
ファイル: framecutter.cpp プロジェクト: Mixgenius/essentia
AlgorithmStatus FrameCutter::process() {
  bool lastFrame = false;

  EXEC_DEBUG("process()");

  // if _streamIndex < _startIndex, we need to advance into the stream until we
  // arrive at _startIndex
  if (_streamIndex < _startIndex) {
    // to make sure we can skip that many, use frameSize (buffer has been resized
    // to be able to accomodate at least that many sample before starting processing)
    int skipSize = _frameSize;
    int howmuch = min(_startIndex - _streamIndex, skipSize);
    _audio.setAcquireSize(howmuch);
    _audio.setReleaseSize(howmuch);
    _frames.setAcquireSize(0);
    _frames.setReleaseSize(0);

    if (acquireData() != OK) return NO_INPUT;

    releaseData();
    _streamIndex += howmuch;

    return OK;
  }

  // need to know whether we have to zero-pad on the left: ie, _startIndex < 0
  int zeropadSize = 0;
  int acquireSize = _frameSize;
  int releaseSize = min(_hopSize, _frameSize); // in case hopsize > framesize
  int available = _audio.available();

  // we need this check anyway because we might be at the very end of the stream and try to acquire 0
  // for our last frame, which will unfortunately work, so just get rid of this case right now
  if (available == 0) return NO_INPUT;

  if (_startIndex < 0) {
    // left zero-padding and only acquire  as much as _frameSize + startIndex tokens and should release zero
    acquireSize = _frameSize + _startIndex;
    releaseSize = 0;
    zeropadSize = -_startIndex;
  }

  // if there are not enough tokens in the stream (howmuch < available):
  if (acquireSize >= available) { // has to be >= in case the size of the audio fits exactly with frameSize & hopSize
    if (!shouldStop()) return NO_INPUT; // not end of stream -> return and wait for more data to come

    acquireSize = available; // need to acquire what's left
    releaseSize = _startIndex >= 0 ? min(available, _hopSize) : 0; // cannot release more tokens than there are available
    if (_startFromZero) {
      if (_lastFrameToEndOfFile) {
        if (_startIndex >= _streamIndex+available) lastFrame = true;
      }
      else lastFrame = true;
    }
    else {
      if (_startIndex + _frameSize/2 >= _streamIndex + available) // center of frame >= end of stream
        lastFrame = true;
    }
  }

  _frames.setAcquireSize(1);
  _frames.setReleaseSize(1);
  _audio.setAcquireSize(acquireSize);
  _audio.setReleaseSize(releaseSize);

  /*
  EXEC_DEBUG("zeropadSize: " << zeropadSize
             << "\tacquireSize: " << acquireSize
             << "\treleaseSize: " << releaseSize
             << "\tavailable: " << available
             << "\tlast frame: " << lastFrame
             << "\tstartIndex: " << _startIndex
             << "\tstreamIndex: " << _streamIndex);
  */

  AlgorithmStatus status = acquireData();
  EXEC_DEBUG("data acquired (audio: " << acquireSize << " - frames: 1)");

  if (status != OK) {
    if (status == NO_INPUT) return NO_INPUT;
    if (status == NO_OUTPUT) return NO_OUTPUT;
    throw EssentiaException("FrameCutter: something weird happened.");
  }

  // some semantic description to not get mixed up between the 2 meanings
  // of a vector<Real> (which acts both as a stream of Real tokens at the
  // input and as a single vector<Real> token at the output)
  typedef vector<AudioSample> Frame;

  // get the audio input and copy it as a frame to the output
  const vector<AudioSample>& audio = _audio.tokens();
  Frame& frame = _frames.firstToken();


  frame.resize(_frameSize);

  // left zero-padding of the frame
  int idxInFrame = 0;
  for (; idxInFrame < zeropadSize; idxInFrame++) {
    frame[idxInFrame] = (Real)0.0;
  }

  fastcopy(frame.begin()+idxInFrame, audio.begin(), acquireSize);
  idxInFrame += acquireSize;

  // check if the idxInFrame is below the threshold (this would only happen
  // for the last frame in the stream) and if so, don't produce data
  if (idxInFrame < _validFrameThreshold) {
    E_INFO("FrameCutter: dropping incomplete frame");

    // release inputs (advance to next frame), but not the output frame (we didn't produce anything)
    _audio.release(_audio.releaseSize());
    return NO_INPUT;
  }

  // right zero-padding on the last frame
  for (; idxInFrame < _frameSize; idxInFrame++) {
    frame[idxInFrame] = (Real)0.0;
  }

  _startIndex += _hopSize;

  if (isSilent(frame)) {
    switch (_silentFrames) {
    case DROP:
      E_INFO("FrameCutter: dropping silent frame");

      // release inputs (advance to next frame), but not the output frame (we didn't produce anything)
      _audio.release(_audio.releaseSize());
      return OK;

    case ADD_NOISE: {
      vector<AudioSample> inputFrame(_frameSize, 0.0);
      fastcopy(&inputFrame[0]+zeropadSize, &frame[0], acquireSize);
      _noiseAdder->input("signal").set(inputFrame);
      _noiseAdder->output("signal").set(frame);
      _noiseAdder->compute();
      break;
    }

    // otherwise, don't do nothing...
    case KEEP:
    default:
      ;
    }
  }

  EXEC_DEBUG("produced frame; releasing");
  releaseData();
  _streamIndex += _audio.releaseSize();

  EXEC_DEBUG("released");

  if (lastFrame) return PASS;

  return OK;
}
コード例 #5
0
ファイル: audioonsetsmarker.cpp プロジェクト: MTG/essentia
AlgorithmStatus AudioOnsetsMarker::process() {
  EXEC_DEBUG("process()");
  AlgorithmStatus status = acquireData();
  EXEC_DEBUG("data acquired");

  if (status != OK) {
    if (!shouldStop()) return status;

    int available = input("signal").available();
    if (available == 0) return FINISHED;

    // otherwise, there's still some audio we can gobble up
    input("signal").setAcquireSize(available);
    input("signal").setReleaseSize(available);
    output("signal").setAcquireSize(available);
    output("signal").setReleaseSize(available);

    return CONTINUE;
  }

  const vector<Real>& input = _input.tokens();
  vector<Real>& output = _output.tokens();

  assert(output.size() == input.size());

  Real out = 0;
  for (int i=0; i<int(input.size()); i++) {
    if (_onsetIdx >= (int)_onsets.size()) {
      out = 0.5*input[i];
    }
    else {
      if (_processedSamples >= int(_onsets[_onsetIdx]) &&
          _processedSamples <= int(_onsets[_onsetIdx] + _burst.size())) {
        // check whether next onset is closer than noise.size():
        if (_onsetIdx < (int)_onsets.size()-1) {
          if (_processedSamples == int(_onsets[_onsetIdx+1])) {
            _burstIdx = 0;
            //cout << "onsetsmarker processing onset: " << _onsetIdx << "/" << _onsets.size() << " at " << _onsets[_onsetIdx]/_sampleRate  << " processedSamples: " << _processedSamples/_sampleRate << endl;
            _onsetIdx++;
            while (_onsetIdx < (int)_onsets.size() && _processedSamples > _onsets[_onsetIdx]) {
              _onsetIdx++;
            }
          }
        }
        out = 0.5*(input[i]+_burst[_burstIdx++]);
        if (_burstIdx >= (int)_burst.size()) {
          _burstIdx = 0;
          //cout << "onsetsmarker processing onset: " << _onsetIdx << "/" << _onsets.size() << " at " << _onsets[_onsetIdx]/_sampleRate  << " processedSamples: " << _processedSamples/_sampleRate << endl;
          _onsetIdx++;
          while (_onsetIdx < (int)_onsets.size() && _processedSamples > _onsets[_onsetIdx]) {
            _onsetIdx++;
          }
        }
      }
      else {
        out = 0.5*input[i];
      }
    }
    output[i] = out;
    _processedSamples++;
    //cout << "onsetIdx: " << _onsetIdx << " pos: " << _onsets[_onsetIdx] << "onsetsSize: " << _onsets.size() <<  " processedSamples: " << _processedSamples << endl;
  }

  EXEC_DEBUG("releasing");
  releaseData();
  EXEC_DEBUG("released");

  return OK;
}
コード例 #6
0
ファイル: resample.cpp プロジェクト: anthonycouret/essentia
AlgorithmStatus Resample::process() {
  EXEC_DEBUG("process()");

  EXEC_DEBUG("Trying to acquire data");
  AlgorithmStatus status = acquireData();

  if (status != OK) {
    // FIXME: are we sure this still works?
    // if status == NO_OUTPUT, we should temporarily stop the resampler,
    // return from this function so its dependencies can process the frames,
    // and reschedule the framecutter to run when all this is done.
    if (status == NO_OUTPUT) {
      EXEC_DEBUG("no more output available for resampling; mark it for rescheduling and return");
      //_reschedule = true;
      return NO_OUTPUT; // if the buffer is full, we need to have produced something!
    }

    // if shouldStop is true, that means there is no more audio, so we need
    // to take what's left to fill in the output, instead of waiting for more
    // data to come in (which would have done by returning from this function)
    if (!shouldStop()) return NO_INPUT;

    int available = input("signal").available();
    EXEC_DEBUG("There are " << available << " available tokens");
    if (available == 0) return NO_INPUT;

    input("signal").setAcquireSize(available);
    input("signal").setReleaseSize(available);
    output("signal").setAcquireSize((int)(_data.src_ratio * available + 100 + (int)_delay));
    _data.end_of_input = 1;

    return process();
  }

  EXEC_DEBUG("data acquired");

  const vector<AudioSample>& signal = _signal.tokens();
  vector<AudioSample>& resampled = _resampled.tokens();

  EXEC_DEBUG("signal size:" << signal.size());
  EXEC_DEBUG("resampled size:" << resampled.size());

  _data.data_in = const_cast<float*>(&(signal[0]));
  _data.input_frames = (long)signal.size();

  _data.data_out = &(resampled[0]);
  _data.output_frames = (long)resampled.size();


  if (_data.src_ratio == 1.0) {
    assert(_data.output_frames >= _data.input_frames);
    fastcopy(_data.data_out, _data.data_in, _data.input_frames);
    _data.input_frames_used = _data.input_frames;
    _data.output_frames_gen = _data.input_frames;
  }
  else {
    int error = src_process(_state, &_data);

    if (error) {
      throw EssentiaException("Resample: ", src_strerror(error));
    }

    if (_data.input_frames_used == 0) {
      throw EssentiaException("Resample: Internal consumption problem while resampling");
    }
  }

  EXEC_DEBUG("input frames:" << _data.input_frames_used);
  EXEC_DEBUG("produced:" << _data.output_frames_gen);

  _delay += (Real)_data.input_frames_used*_data.src_ratio - (Real)_data.output_frames_gen;

  assert((int)resampled.size() >= _data.output_frames_gen);
  assert((int)signal.size() >= _data.input_frames_used);

  _signal.setReleaseSize(_data.input_frames_used);
  _resampled.setReleaseSize(_data.output_frames_gen);

  releaseData();

  EXEC_DEBUG("released");

  return OK;
}
コード例 #7
0
ファイル: trimmer.cpp プロジェクト: Aldor007/essentia
AlgorithmStatus Trimmer::process() {
  EXEC_DEBUG("process()");

  if ((_consumed < _startIndex) && (_consumed + _preferredSize > _startIndex)) {
    _input.setAcquireSize(_startIndex - _consumed);
    _input.setReleaseSize(_startIndex - _consumed);
  }

  if (_consumed == _startIndex) {
    _input.setAcquireSize(_preferredSize);
    _input.setReleaseSize(_preferredSize);
  }

  AlgorithmStatus status = acquireData();

  if (status != OK) {
    // if status == NO_OUTPUT, we should temporarily stop the framecutter,
    // return from this function so its dependencies can process the frames,
    // and reschedule the framecutter to run when all this is done.
    if (status == NO_OUTPUT) {
      EXEC_DEBUG("no more output available for trimmer; mark it for rescheduling and return");
      //_reschedule = true;
      return NO_OUTPUT; // if the buffer is full, we need to have produced something!
    }

    // if shouldStop is true, that means there is no more audio, so we need
    // to take what's left to fill in the output buffer
    if (!shouldStop()) return NO_INPUT;

    int available = input("signal").available();
    EXEC_DEBUG("Frame could not be fully acquired. Next frame will be incomplete");
    EXEC_DEBUG("There are " << available << " available tokens");
    if (available == 0) {
      shouldStop(true);
      return NO_INPUT;
    }

    _input.setAcquireSize(available);
    _input.setReleaseSize(available);
    _output.setAcquireSize(available);
    _output.setReleaseSize(available);
    _preferredSize = available;
    return process();
  }

  EXEC_DEBUG("data acquired");


  // get the audio input and copy it to the output
  const vector<Real>& input = _input.tokens();
  vector<Real>& output = _output.tokens();


  if (_consumed >= _startIndex && _consumed < _endIndex) {
    assert(input.size() == output.size());
    int howMany = min((long long)input.size(), _endIndex - _consumed);
    fastcopy(output.begin(), input.begin(), howMany);

    _output.setReleaseSize(howMany);
  }
  else {
    _output.setReleaseSize(0);
  }

  EXEC_DEBUG("produced frame");

  _consumed += _input.releaseSize();

  // optimization: we should also tell the parent (most of the time an
  // audio loader) to also stop, to avoid decoding an entire mp3 when only
  // 10 seconds are needed
  if (_consumed >= _endIndex) {
    // FIXME: does still still work with the new composites?
    shouldStop(true);
    const_cast<SourceBase*>(_input.source())->parent()->shouldStop(true);
  }


  EXEC_DEBUG("releasing");
  releaseData();
  EXEC_DEBUG("released");

  return OK;
}
コード例 #8
0
ファイル: slicer.cpp プロジェクト: Aldor007/essentia
AlgorithmStatus Slicer::process() {
  EXEC_DEBUG("process()");

  // 10 first, consume and release tokens until we reach the start of the first slice
  // 20 produce the first slice, push it, and remove it from the list of slices to be processed
  // 30 goto 10

  // in case we already processed all slices, just gobble up data
  if (_sliceIdx == int(_slices.size())) {
    bool ok = _input.acquire(defaultPreferredSize);
    if (!ok) return NO_INPUT; // TODO: make a special case for end of stream?
    _input.release(defaultPreferredSize);
    return OK;
  }

  int startIndex = _slices[_sliceIdx].first;
  int endIndex = _slices[_sliceIdx].second;

  // arriving there, only consume the tokens left before we reach the beginning of the slice
  if ((_consumed < startIndex) && (_consumed + _input.acquireSize() > startIndex)) {
    _input.setAcquireSize(startIndex - _consumed);
    _input.setReleaseSize(startIndex - _consumed);
  }
  // we're at the beginning of a slice, grab it entirely at once
  if (_consumed == startIndex) {
    _input.setAcquireSize(endIndex - startIndex);
  }

  AlgorithmStatus status = acquireData();

  if (status != OK) {
    // FIXME: what does this return do here, without a comment explaining why we now skip everything after it???
    return status;

    // if shouldStop is true, that means there is no more audio, so we need to stop
    if (!shouldStop()) return status;

    EXEC_DEBUG("Slice could not be fully acquired. Creating a partial slice to "
               "the end of the token stream.");
    EXEC_DEBUG("There are " << _input.available() << " available tokens left.");

    // Since there is no more tokens to consume, the last slice will be
    // partial (not to the end of endIndex)
    if (_input.available() == 0) return NO_INPUT;

    _input.setAcquireSize(_input.available());
    _input.setReleaseSize(_input.available());
    status = acquireData();

    // If the last of the tokens could not be acquired, abort
    if (status != OK) return status;
  }

  int acquired = _input.acquireSize();

  EXEC_DEBUG("data acquired (in: " << acquired << ")");

  // are we dropping the tokens, or are we at the beginning of a slice, in which
  // case we need to copy it
  if (_consumed != startIndex) {
    // we're still dropping tokens to arrive to a slice
    _input.release(acquired);
    _consumed += acquired;

    return OK;
  }

  // we are copying a slice, get the audio input and copy it to the output
  const vector<Real>& input = _input.tokens();
  vector<Real>& output = _output.firstToken();

  assert((int)input.size() == _input.acquireSize());
  output.resize(input.size());

  fastcopy(output.begin(), input.begin(), (int)output.size());

  EXEC_DEBUG("produced frame");

  // set release size in function of next slice to get
  _sliceIdx++;

  int toRelease = acquired;

  // if next slice is very close, be careful not to release too many tokens
  if (_sliceIdx < (int)_slices.size()) {
    toRelease = min(toRelease, _slices[_sliceIdx].first - _consumed);
  }

  _input.setReleaseSize(toRelease);

  EXEC_DEBUG("releasing");
  releaseData();

  _consumed += _input.releaseSize();
  EXEC_DEBUG("released");

  // reset acquireSize to its default value
  _input.setAcquireSize(defaultPreferredSize);

  return OK;
}