Smoosic icon indicating copy to clipboard operation
Smoosic copied to clipboard

return notes position

Open marilenadaquino opened this issue 3 years ago • 3 comments
trafficstars

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!

marilenadaquino avatar Aug 25 '22 08:08 marilenadaquino

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.

  • If you mean position in the SVG, each note, measure, and modifier will have an 'svg' structure that is filled in at run time. The structures vary, but they all contain a logicalBox which is the bounding box of the element.
  • if you mean the position in time, you can add up all the tickCount of all the measure and note that came before. There are 4096 ticks to a beat.
  • if you mean position in terms of how to reference the note in a selection, it would be the staff-measure-voice-note position, just like an array. A selection has an optional pitch array if it is a chord, with each entry being the index of the pitch.

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

AaronDavidNewman avatar Aug 25 '22 21:08 AaronDavidNewman

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:

  • is there a (smoosic-native) way to toggle only sharp #?
  • is there a (smoosic-native) way I can store this information in my object above (e.g. 7: "b#")?

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!

marilenadaquino avatar Aug 26 '22 07:08 marilenadaquino

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='#';

AaronDavidNewman avatar Aug 26 '22 19:08 AaronDavidNewman