AaronDavidNewman / Smoosic

A music notation editor written in javascript
Other
95 stars 14 forks source link

return notes position #75

Open marilenadaquino opened 1 year ago

marilenadaquino commented 1 year ago

I was trying your nice demo https://codepen.io/aarondavidnewman/pen/WNoRqgg and I'd like to reuse the library to create a simple melodic search.

I have a question. When my user submits, how can I get the final list of keys and their position in the score? Thanks in advance, it would save me some time!

AaronDavidNewman commented 1 year ago

Hi Marilena, I can think of three different things 'position' might mean :) And I think you mean position of note and not key signature. I'll try to answer for each.

I hope it helps. I'm honored that you're using my thing in your work.

marilenadaquino commented 1 year ago

Hi Aaron, thanks for your reply, and apologies for not being clear. I need to create a simple melodic search, with only two requirements: two measures, and the possibility to add only accidentals to make the pitch sharp. I'm building on the demo on top, using smoosic as a library (btw, I'm no music expert, in case you wonder).

When the user submits the form, I need to collect an object that includes (a) the sequence of pitches and (b) the sharp accidentals only (if any). I managed to get the the sequence of pitches (see screenshot) I need to perform the search on the dataset (this was my original question, I hoped there was an out-of-the-box method to get it), and it is automatically updated if the user moves left/right.

Screenshot 2022-08-26 at 09 01 14

I'm using toggleEnharmonic to allow the user adding an accidental when pressing shift. I'd have two more questions here:

Below my tentative code so far.

      const editorKeys = [];
      'abcdefg'.split('').forEach((key) => {
        editorKeys.push({
          event: 'keydown',
          key,
          action: 'setPitch'
        });
      });

      const trackerKeys = [{
        event: "keydown",
        key: "ArrowRight",
        action: "moveSelectionRight"
      }, {
        event: "keydown",
        key: "ArrowLeft",
        action: "moveSelectionLeft"
      }];

      Smo.SuiApplication.configure({
        mode: 'library',
        scoreDomContainer: 'outer-container',
        keys: { trackerKeys, editorKeys },
        initialScore: Smo.basicJson,
      }).then((application) => {
        const view = application.view;
        view.addMeasure(true);

        var last = 7;
        var pos = 0;
        var final = new Object();

        window.addEventListener('keydown', (evKey) => {
          const trackerAction = trackerKeys.find((ev) => ev.key === evKey.key);
          if (trackerAction) {
            view[trackerAction.action](evKey);
            // if moves left / right update the index of final
            if (trackerAction.key == 'ArrowLeft') {
              if (pos == 0) {pos = 0} else {pos = pos - 1;}
            }
            if (trackerAction.key == 'ArrowRight') {
              if (pos == last) {pos = last} else {pos = pos + 1;}
            }
            return false;
          }

          // if enters a key
          const editorAction = editorKeys.find((ev) => ev.key === evKey.key);
          if (editorAction) {
            view[editorAction.action](evKey.key);
            final[pos] = evKey.key;
            if (pos == last) {pos = last} else {pos = pos + 1;};
            console.log("editorAction", editorAction.action,pos, final);
            return false;
          } else {

            // change accidental
            if (evKey.shiftKey) {
                console.log('shift!', evKey);
                view['toggleEnharmonic'](evKey.key);
                console.log("view['toggleEnharmonic'](evKey.key)",view['toggleEnharmonic'](evKey.key));
            }

          }
        });

        // Get mouse move event to highlight mouseover.  We pass the client coordinates
        // into tracker (via view).  The tracker maps client space to SVG space
        document.getElementById('container1').addEventListener('mousemove', (ev) => {
          view.intersectingArtifact({
            x: ev.clientX,
            y: ev.clientY
          });
        });

      });

Thank you for your help!

AaronDavidNewman commented 1 year ago

I admit I have no idea why you are doing this :) but, if you want to force a sharp you could just go:

view.tracker.selections[0].note.pitches[0].accidental='#';

Or toggle the sharp, read the value first and set 'n' for natural and '#' for sharp, etc..

Edit: to access the score directly: view.score.staves[0].measures[1].voices[0].notes[3].pitches[0].accidental='#';