Ejemplo n.º 1
0
 public void testStretch2() {
   double[] signal = FFTTest.getSampleSignal(16000);
   int samplingRate = 8000;
   double rateFactor = 0.5;
   NaiveVocoder nv =
       new NaiveVocoder(new BufferedDoubleDataSource(signal), samplingRate, rateFactor);
   double[] result = nv.getAllData();
   double meanSignalEnergy = MathUtils.mean(MathUtils.multiply(signal, signal));
   double meanResultEnergy = MathUtils.mean(MathUtils.multiply(result, result));
   double percentDifference =
       Math.abs(meanSignalEnergy - meanResultEnergy) / meanSignalEnergy * 100;
   assertTrue(
       "Stretching changed signal energy by  " + percentDifference + "%", percentDifference < 6);
 }
  // st: Sinusoidal tracks
  // absMaxDesired: Desired absolute maximum of the output
  public double[] synthesize(SinusoidalTracks st, boolean isSilentSynthesis) {
    int n; // discrete time index
    int i, j;
    int nStart, nEnd, pStart, pEnd;
    float t; // continuous time
    float t2; // continuous time squared
    float t3; // continuous time cubed

    float tFinal = st.getOriginalDuration();
    int nFinal = (int) (Math.floor(tFinal * st.fs + 0.5));
    double[] y = new double[nFinal + 1];
    Arrays.fill(y, 0.0);
    float currentAmp;
    float currentTheta;
    double alpha, beta;
    int M;
    float
        T; // Number of samples between consecutive frames (equals to pitch period in pitch
           // synchronous analysis/synthesis)
    float T2; // T squared
    float T3; // T cubed
    double oneOverTwoPi = 1.0 / MathUtils.TWOPI;
    double term1, term2;

    float currentTime; // For debugging purposes

    for (i = 0; i < st.totalTracks; i++) {
      for (j = 0; j < st.tracks[i].totalSins - 1; j++) {
        if (st.tracks[i].states[j] != SinusoidalTrack.TURNED_OFF) {
          pStart = (int) Math.floor(st.tracks[i].times[j] * st.fs + 0.5);
          pEnd = (int) Math.floor(st.tracks[i].times[j + 1] * st.fs + 0.5);

          nStart = Math.max(0, pStart);
          nEnd = Math.max(0, pEnd);
          nStart = Math.min(y.length - 1, nStart);
          nEnd = Math.min(y.length - 1, nEnd);

          // currentTime = 0.5f*(nEnd+nStart)/st.fs;
          // System.out.println("currentTime=" + String.valueOf(currentTime));

          for (n = nStart; n < nEnd; n++) {
            if (false) // Direct synthesis
            {
              currentAmp = st.tracks[i].amps[j];
              currentTheta = (n - nStart) * st.tracks[i].freqs[j] + st.tracks[i].phases[j];
              y[n] += currentAmp * Math.cos(currentTheta);
            } else // Synthesis with interpolation
            {
              // Amplitude interpolation
              currentAmp =
                  st.tracks[i].amps[j]
                      + (st.tracks[i].amps[j + 1] - st.tracks[i].amps[j])
                          * ((float) n - pStart)
                          / (pEnd - pStart + 1);

              T = (pEnd - pStart);

              if (n == nStart
                  && st.tracks[i].states[j] == SinusoidalTrack.TURNED_ON) // Turning on a track
              {
                // Quatieri
                currentTheta = st.tracks[i].phases[j + 1] - T * st.tracks[i].freqs[j + 1];
                currentAmp = 0.0f;
              } else if (n == nStart
                  && st.tracks[i].states[j] == SinusoidalTrack.TURNED_OFF
                  && j > 0) // Turning off a track
              {
                // Quatieri
                currentTheta = st.tracks[i].phases[j - 1] + T * st.tracks[i].freqs[j - 1];
                currentAmp = 0.0f;
              } else // Cubic phase interpolation
              {
                // Quatieri
                M =
                    (int)
                        (Math.floor(
                            oneOverTwoPi
                                    * ((st.tracks[i].phases[j]
                                            + T * st.tracks[i].freqs[j]
                                            - st.tracks[i].phases[j + 1])
                                        + (st.tracks[i].freqs[j + 1] - st.tracks[i].freqs[j])
                                            * 0.5
                                            * T)
                                + 0.5));
                term1 =
                    st.tracks[i].phases[j + 1]
                        - st.tracks[i].phases[j]
                        - T * st.tracks[i].freqs[j]
                        + M * MathUtils.TWOPI;
                term2 = st.tracks[i].freqs[j + 1] - st.tracks[i].freqs[j];

                T2 = T * T;
                T3 = T * T2;
                alpha = 3.0 * term1 / T2 - term2 / T;
                beta = -2 * term1 / T3 + term2 / T2;

                t = ((float) n - nStart);
                t2 = t * t;
                t3 = t * t2;

                // Quatieri
                currentTheta =
                    (float)
                        (st.tracks[i].phases[j]
                            + st.tracks[i].freqs[j] * t
                            + alpha * t2
                            + beta * t3);
              }

              // Synthesis
              y[n] += currentAmp * Math.cos(currentTheta);
            }

            // System.out.println(String.valueOf(currentTheta));
          }
        }
      }

      if (!isSilentSynthesis)
        System.out.println(
            "Synthesized track " + String.valueOf(i + 1) + " of " + String.valueOf(st.totalTracks));
    }

    y = MathUtils.multiply(y, st.absMaxOriginal / MathUtils.getAbsMax(y));

    return y;
  }