// Check that the value doesn't change until the time is advanced.
  public void testGetValue() {
    SynthesisTime time = new SynthesisTime();
    time.setSampleRate(44100.0);

    MockCachedFrequencyProvider mock = new MockCachedFrequencyProvider();

    assertEquals(0, mock.getLogFrequency(time), TOLERANCE);
    assertEquals(0, mock.getLogFrequency(time), TOLERANCE);
    assertEquals(0, mock.getLogFrequency(time), TOLERANCE);

    time.advance();

    assertEquals(1, mock.getLogFrequency(time), TOLERANCE);
    assertEquals(1, mock.getLogFrequency(time), TOLERANCE);

    time.advance();

    assertEquals(2, mock.getLogFrequency(time), TOLERANCE);
    assertEquals(2, mock.getLogFrequency(time), TOLERANCE);
    assertEquals(2, mock.getLogFrequency(time), TOLERANCE);
    assertEquals(2, mock.getLogFrequency(time), TOLERANCE);
  }
  /** Gets one value from the synthesizer. */
  public synchronized double computeValue(SynthesisTime time) {
    // How many samples have passed?
    double deltaTime = time.getAbsoluteTime() - previousTime_;
    previousTime_ = time.getAbsoluteTime();

    // First, skip over however many samples we've passed in the buffer.
    int bufferSamples = (int) (deltaTime * sampleRateInHz_ + 0.5);
    // If everything in the buffer would be skipped, don't do extra work.
    if (bufferSamples > buffer_.length) {
      bufferSamples = buffer_.length;
    }
    // Clear all of the ones we've passed.
    for (int i = 0; i < bufferSamples; ++i) {
      buffer_[bufferIndex_++] = 0.0;
      if (bufferIndex_ >= buffer_.length) {
        bufferIndex_ = 0;
      }
    }
    double output = buffer_[bufferIndex_];

    // If the instrument has been retriggered, find the right sample.
    if (pressed_) {
      pressed_ = false;
      int key = Note.getKeyforLog12TET(frequency_.getLogFrequency(time));
      int velocity = 255;
      initSample(key, velocity);
    } else {
      if (currentSample_ != null) {
        // Advance by deltaTime in the current sample.
        currentSampleIndex_ += deltaTime * currentSample_.getSample().getRate();
        if (currentSample_.getSampleMode() == SampleMode.NO_LOOP) {
          if (currentSampleIndex_ > currentSample_.getEnd()) {
            // We're off the end of the sample.
            currentSample_ = null;
          }
        } else {
          if (currentSampleIndex_ >= currentSample_.getEndLoop()) {
            double distanceFromLoopStart = currentSampleIndex_ - currentSample_.getStartLoop();
            double loopLength = currentSample_.getEndLoop() - currentSample_.getStartLoop();
            currentSampleIndex_ =
                currentSample_.getStartLoop() + (distanceFromLoopStart % loopLength);
          }
        }
      }
    }

    // Okay, now get the new data from the current sample.
    if (currentSample_ != null) {
      int firstSample = (int) currentSampleIndex_;
      double weight = 1.0 - (currentSampleIndex_ - firstSample);
      if (weight == 1.0) {
        output += currentSample_.getSample().getSample(firstSample);
      } else {
        output +=
            weight * currentSample_.getSample().getSample(firstSample)
                + (1.0 - weight) * currentSample_.getSample().getSample(firstSample + 1);
      }
    }

    return output;
  }