Exemplo n.º 1
0
  private float getBestPitch(float[] audioFloatBuffer) {
    if (PITCHDETECTOR.equals("YIN")) {
      float yin_pitch = yin.getPitch(audioFloatBuffer);
      // Pitch pitchYIN=
      // Pitch.getInstance(PitchUnit.HERTZ,(double)yin_pitch);
      // int midiKeyYIN = (int)pitchYIN.getPitch(PitchUnit.MIDI_KEY);
      // float yin_prob = yin.getProbability();
      yin_cnt++;
      pitch_probability = yin.getProbability();
      return yin_pitch;
    } else if (PITCHDETECTOR.equals("MPM")) {
      float mpm_pitch = mpm.getPitch(audioFloatBuffer);
      // Pitch pitchMPM=
      // Pitch.getInstance(PitchUnit.HERTZ,(double)mpm_pitch);
      // int midiKeyMPM = (int)pitchMPM.getPitch(PitchUnit.MIDI_KEY);
      // float mcleod_prob = mpm.getProbability();
      pitch_probability = mpm.getProbability();
      mpm_cnt++;
      return mpm_pitch;
    } else {
      System.err.println("SHIT: PITCHDETECTOR: " + PITCHDETECTOR);
      System.exit(-1);
      return -1;
    }

    // TODO "2 Ohren " ????? erstmal beide evaluieren

    // if(midiKeyYIN==midiKeyMPM) { // --> wird am HŠufigsten eintreten !
    // yin_cnt++;
    // pitch_probability=yin_prob;
    // return yin_pitch;
    // }
    // else {
    // if(midiKeyYIN==lastDetectedMidiKey) {//dann nehme YIN pitch
    // yin_cnt++;
    // pitch_probability=yin_prob;
    // return yin_pitch;
    // }
    // else {
    // mpm_cnt++;
    // pitch_probability=mcleod_prob;
    // return mpm_pitch;
    // }
    // }
  }
Exemplo n.º 2
0
  /**
   * <b>This is the most important function of the collector pipeline</b> First we detect the pitch
   * of the audioFloatBuffer using YIN or MPM.<br>
   * Then the collector process starts, checking onsets and offsets based on midiKeys and dB,
   * collects<br>
   * and convert these pich vectors to abc-notes based on the bpm, samplerate buffersize and
   * bufferoverlap.<br>
   */
  private void detectPitchAndCollect(float[] audioFloatBuffer, double level) {
    int midiKey;
    String note;

    // TODO
    pitchInHertz = getBestPitch(audioFloatBuffer);

    // ---------- ENTSCHEIDUNG ----------
    // pitchInHertz=mpm_pitch;
    pitch = Pitch.getInstance(PitchUnit.HERTZ, (double) pitchInHertz);
    midiKey =
        (int)
            pitch.getPitch(
                PitchUnit.MIDI_KEY); // PitchConverter.hertzToMidiKey((double)pitchInHertz);

    if (model.plottingSelected()) {
      plotterYIN.setData(yin.getCurrentBuffer());
      plotterYIN.setInfoString("CURRENT PITCH: " + pitchInHertz + "Hz PROB: " + pitch_probability);

      plotterMPM.setData(mpm.getCurrentBuffer());
      plotterMPM.setInfoString("CURRENT PITCH: " + pitchInHertz + "Hz PROB: " + pitch_probability);

      plotterBUFFER.setData(audioFloatBuffer);
      plotterBUFFER.setInfoString("level: " + level);
    }

    // nach dem pitch erkannt wurde muss ggf. entsprechend dem Instrument
    // transponiert werden
    if (model.getTransposeRecIndex() == 1) {
      // Bb Clarinet: 2 halftonesteps up
      pitch.convertPitch(2);
      pitchInHertz = (float) pitch.getPitch(PitchUnit.HERTZ);
      midiKey = PitchConverter.hertzToMidiKey((double) pitchInHertz);
    }

    String[] arr = pitch.getBaseNote(pitchInHertz).split(" ");
    String note2 = arr[0];
    int oktave = Integer.parseInt(arr[1]);
    //
    note = pitch.noteName();
    String str = "";

    // formatted Info output to GUI
    str =
        pitchInHertz == -1
            ? "NO PITCH DETECTED"
            : note
                + " at "
                + String.format("%.5g%n", pitchInHertz)
                + "Hz - IDEAL: "
                + String.format("%.5g%n", pitch.getIdealFreq(note2, oktave))
                + "Hz - PROB: "
                + String.format("%.5g%n", pitch_probability)
                + "%";

    model.firePropertyChange(ControllerEngine.INFO_LABEL_PROPERTY, "", str);

    countMSprocessing += (audioFloatBuffer.length - overlap) / audioSampleRate * 1000.0f;

    float duration = (bufferSize - overlap) / audioSampleRate * 1000.0f;
    // finally:
    //		collect(audioFloatBuffer, midiKey, duration, level, note);

    // ------------------------- begin collector process -------------------------
    // ----- sammel ALLE erkannten Noten fuer statistiken -----
    if (midiKeySammlerInsgesamt.get(midiKey) != null) {
      midiKeySammlerInsgesamt.put(midiKey, midiKeySammlerInsgesamt.get(midiKey) + duration);
    } else {
      midiKeySammlerInsgesamt.put(midiKey, duration);
    }

    // TODO level neuer Ansatz ? zusaetzliche offset/Onset bedingung
    //		levels.add(level);
    //
    //		boolean minima=true;
    //		Vector<double[]>extremwerte = jAMUtils.detectExtremum(levels, delta, minima);
    //
    //		//sysout
    //		if(!model.isEvaluating() && extremwerte.size()==1) {  //kann so immer nur 1 finden
    ////			jAMUtils.printArray(levels);
    //			String str="";
    //			for (int i = 0; i < extremwerte.size(); i++) {
    //				str+= "(" + extremwerte.get(i)[0] + ","+extremwerte.get(i)[1] + "),";
    //			}
    //			System.out.println("============> EXTREM!!!: " + str + " at levels: " + levels);
    //			System.out.println("midiKey: " + midiKey);
    //
    //			levels.clear(); //wenn ein minima entdeckt: offset und dann leeren ?
    //		}
    /**
     * * wenn eine note zb 200ms lang, dann -> 16tel aber die 50 ms muessen beim NŠchsten Mal
     * ignoriert werden wenn dies pausen entspricht !!! sonst kann sein dass zB z(3) gemalt wird
     * obwohl z(2) !!!
     *
     * <p>if(msToIgnore>0 && !ONSET) { //MINIMUM_DURATION dur+=duration; if(dur<msToIgnore) return;
     * else { System.out.println( "============================================>>>>>> IGNORED: " +
     * dur + "ms OF DATA - msToIgnore: " + msToIgnore); dur=0; msToIgnore=0; } }
     */
    boolean silence = jAMUtils.isSilence(audioFloatBuffer, MINIMUM_LEVEL);
    // 1. OFFSET basierend auf neuer note!
    if ((ONSET && midiKey > 0 && !silence /* level > MINIMUM_LEVEL*/)
        && (midiKey != lastTakenMidiKey)) { // es kommt ne andere /Note/
      // System.out.println("POSSIBLE NEW NOTE: "+ midiKey);

      if (newNoteCount == 0) // die erste "andere" Note
      newNoteCount++;
      else if (midiKey == lastDetectedMidiKey) newNoteCount++;

      if (newNoteCount
          > (int)
              (MINIMUM_DURATION
                  / duration)) { // 60/25.01 --> 2 also mind.  3  nehmen! wie  sonst auch
        ONSET =
            false; // dann macht er jetzt unten ne Entscheidung und beim next Mal fŠngt er an die
                   // neue note zu collecten
        NEW_NOTE_ONSET = true; // TODO sinn?

        newNoteCount = 0;

        // sysout
        if (!model.isEvaluating() && jAM.SYSOUT)
          System.out.println(
              timestamp()
                  + " ================================================== OFFSET NEWNOTE: "
                  + midiKey
                  + " could be possible new note");
      }

      // 2. ONSET
    } else if (!ONSET && midiKey > 0 && !silence /*&& level > MINIMUM_LEVEL*/) {
      newNoteCount = 0;

      // gibts diese note schon? und kam sie beim letzten Mal?
      if (midiKeySammler.get(midiKey) != null && midiKey == lastDetectedMidiKey) {
        midiKeySammler.put(midiKey, midiKeySammler.get(midiKey) + duration);
        if (midiKeySammler.get(midiKey) > MINIMUM_DURATION) {
          //
          // sysout
          if (!model.isEvaluating() && jAM.SYSOUT)
            System.out.println(
                timestamp()
                    + " ================================================== ONSET - Entscheidung basiert auf: "
                    + midiKeySammler);

          ONSET = true;

          // wir kšnnen davon ausgehen dass "note" die lastTakenNote
          // wird, da sie alle Bedingungen fuer ein note-OFFSET erfŸllt
          // Problem: es kann sein dass zb 3 buffer A1 kommen, das is
          // ne new note bedingung
          // der naechst kommt dann hier rein und is aber diesmal A3
          // also lastTakenNote="A3" anstatt A1 ???
          lastTakenMidiKey = midiKey;

          midiKeySammler.clear();
        }
      } else {
        midiKeySammler.put(midiKey, duration);
      }

      // 3. OFFSET basierend auf Pause
    } else if (silence
        || midiKey
            == 0 /*|| level < MINIMUM_LEVEL*/) { // sonst ist alles ne Pause: kein pitch und auch
                                                 // level < MIN_LEVEL
      /**
       * gibts diese Pause schon? und kam sie beim letzten Mal? ob sie beim letzten Mal kam is
       * unwichtig es mŸssen die Pausen gezŠhlt werden! BSP: 60,60,60,0,0,0,0,55,0,0,0, --> die 55
       * MUSS mitgezaehlt werden ! ??? stimmt das?
       */
      if (midiKeySammler.get(0) != null && lastDetectedMidiKey == 0) {
        midiKeySammler.put(0, midiKeySammler.get(0) + duration);

        if (midiKeySammler.get(0) > MINIMUM_DURATION) {
          if (ONSET) {
            if (!model.isEvaluating() && jAM.SYSOUT)
              System.out.println(
                  timestamp()
                      + " ================================================== OFFSET - Entscheidung basiert auf: "
                      + midiKeySammler);

            ONSET = false; // jetzt ist wieder vorbei
            NEW_NOTE_ONSET = false;
          }
          midiKeySammler.clear();
        }
      } else {
        midiKeySammler.put(0, duration);
      }
    }

    // ----- wenn nun ONSET==true anfangen zu sammeln bis ONSET==false!
    if (ONSET) {
      if (midiKeysRests.size() > 0
          && !NEW_NOTE_ONSET) { // hier sind nun pausen in der off Phase gezaehlt worden
        detectRest(duration);
      } else { // sonst: sammle noten
        // hier midiKey und level speichern:
        midiKeysAndLevels.add(new Float[] {(float) midiKey, (float) level});
      }
    } else { // wenn ein OFFSET und noten sind vorhanden: entscheidung!
      if (midiKeysAndLevels.size() > 0) {
        detectNote(duration);
      } else
        // sonst sammple pausen
        midiKeysRests.add(midiKey);
    }

    lastDetectedMidiKey = midiKey;

    // TODO fft
    //		fft(audioFloatBuffer);

    // TODO sysout
    if (!model.isEvaluating() && jAM.SYSOUT) {
      if (pitchInHertz == -1)
        System.out.println(
            timestamp()
                + "\t"
                + "--> Rest: "
                + note
                + (note.length() == 2 ? "\t" : "")
                + "\t\t midiKey: "
                + midiKey
                + "\t RMS: "
                + String.format("%.2f", level)
                + "  Zustand: "
                + (ONSET ? "ONSET " : "OFFSET ")
                + (silence ? "SILENCE" : "NO SILENCE"));
      else
        System.out.println(
            timestamp()
                + "\t"
                + "--> Note: "
                + note
                + (note.length() == 2 ? "\t" : "")
                + "\t midiKey: "
                + midiKey
                + "\t RMS: "
                + String.format("%.2f", level)
                + "  Zustand: "
                + (ONSET ? "ONSET " : "OFFSET ")
                + (silence ? "SILENCE" : "NO SILENCE"));
    }
  }