Old 05-10-2021, 05:23 PM   #1
daeavelwyn
Human being with feelings
 
daeavelwyn's Avatar
 
Join Date: Dec 2014
Posts: 600
Default [SOLVED] Get scale root note with right flat and/or sharp

Hi folks,

Any kind of solution to get the real scale's root with the right accidentals ?

Code:
reaper.MIDIEditor_GetSetting_int( getActiveMidiEditor, "scale_root" )
returns an int but I can't figure out if it's a sharp or a flat...

I already check those posts :

https://forums.cockos.com/showpost.p...1&postcount=47

https://forums.cockos.com/showpost.p...8&postcount=48

and well understood this specification :

http://midi.teragonaudio.com/tech/midifile/key.htm

But can't find a way to get this damned root note with the right accidental !

Last edited by daeavelwyn; 05-23-2021 at 03:02 PM. Reason: [SOLVED]
daeavelwyn is offline   Reply With Quote
Old 05-12-2021, 03:43 AM   #2
daeavelwyn
Human being with feelings
 
daeavelwyn's Avatar
 
Join Date: Dec 2014
Posts: 600
Default

Bump !

any workarounds or ideas would really be appreciate
daeavelwyn is offline   Reply With Quote
Old 05-12-2021, 04:44 AM   #3
bFooz
Human being with feelings
 
Join Date: Jul 2010
Location: Slovakia
Posts: 2,588
Default

The number returned indicates how much semitones higher from C the current root is. There is also
Code:
 retval, root, scale, name = reaper.MIDI_GetScale( take, root, scale, name )
If you do not use more than 6 accidentals you can figure it out easily by the circle of fifths. The only problem is 6b/6#. I use this method in one of my older workflows. But this only gets you the active key signature at the edit cursor position.

I use "Key sign. changes affect all tracks" OFF, the key signatures are stored within the items. Recently, I did searching by checking all items for the notation event described in the post you linked.
bFooz is offline   Reply With Quote
Old 05-12-2021, 04:46 AM   #4
bFooz
Human being with feelings
 
Join Date: Jul 2010
Location: Slovakia
Posts: 2,588
Default

As for getting key signature by searching notation events, there is -7 represented as (256-7) so you need to do some math.
bFooz is offline   Reply With Quote
Old 05-12-2021, 06:39 AM   #5
daeavelwyn
Human being with feelings
 
daeavelwyn's Avatar
 
Join Date: Dec 2014
Posts: 600
Default

Hi bFooz,

Quote:
If you do not use more than 6 accidentals you can figure it out easily by the circle of fifths. The only problem is 6b/6#. I use this method in one of my older workflows. But this only gets you the active key signature at the edit cursor position.
Nice idea !Thanks ! Perhaps have you already a snippet written I could use to avoid me writting everything from scratch?
daeavelwyn is offline   Reply With Quote
Old 05-12-2021, 09:43 AM   #6
bFooz
Human being with feelings
 
Join Date: Jul 2010
Location: Slovakia
Posts: 2,588
Default

Quote:
Originally Posted by daeavelwyn View Post
Nice idea !Thanks ! Perhaps have you already a snippet written I could use to avoid me writting everything from scratch?
I have not found it actually, must be really old and probably replaced with the other method.
bFooz is offline   Reply With Quote
Old 05-18-2021, 07:11 AM   #7
daeavelwyn
Human being with feelings
 
daeavelwyn's Avatar
 
Join Date: Dec 2014
Posts: 600
Default

Hi bFooz,

Ok, so as i'm dealing with chords, getting the scale is not easy, could you please show me how you get informations from rpp project ? A snippet would really help !

regards
daeavelwyn is offline   Reply With Quote
Old 05-18-2021, 08:56 AM   #8
bFooz
Human being with feelings
 
Join Date: Jul 2010
Location: Slovakia
Posts: 2,588
Default

Ok. Now, I use exclusively "Key signature changes affect all tracks" OFF. It means they are stored within items as midi events.

Here's how I retrieve a key signature event
Code:
function getKeySignAtPpq(ppq)
--find if we already have a key signature at ppq parameter, +-10 ticks
--return event id and event msg
      local _, notecnt, ccevtcnt, textsyxevtcnt = reaper.MIDI_CountEvts( take )
      local eventNum = 2*notecnt + ccevtcnt + textsyxevtcnt
      local returnId, returnMsg = -1, "" --event id and msg of existing key signature if found
      for e=0, eventNum-1 do 
            local retval, selected, muted, ppqpos, msg = reaper.MIDI_GetEvt( take, e,  0, 0, 0, 0 ) 
           
            --we are already after startMeas and we found nothing
            if ppqpos>startMeas+10 then break end 
            
            if math.abs(ppqpos-startMeas)<=10 then --10 ppq acceptance
                  --check if this message is a key signature
                  local byte1, byte2 = string.unpack("BB", msg)
                  --if we have a key signature, store message and break
                  if byte1==255 and byte2==89 then
                      returnId = e
                      returnMsg = msg
                      break
                  end
            end
      end
      
      return returnId, returnMsg 
end
Here is settings key signature:
Code:
function setKeySign(keySign, minor)
--sets exact number of flats or sharps
--parameter keySign: 5 for 5#, -4 for 4b
--parameter other than -7..+7 to remove key signature
--parameter minor indicates if the key signature will be major(false) or minor(true). If ommited then major.

      if keySign==nil then return end
      
      local minor = minor
      if minor==nil then minor = false end
      
      local continue = init()
      if not continue then return end 
      
      reaper.Undo_BeginBlock()
      reaper.PreventUIRefresh(1)
       
            --remove existing key signature
            removeKeySign() 
            
            if minor then minor = 1
                     else minor = 0 end
            
            --create key signature if a proper aprameter provided, otherwise just remove
            if keySign>=-7 and keySign<=7 then 
                  reaper.MIDI_InsertEvt( take, false, false, startMeas, string.pack("BBBBB",0xFF,0x59,0x02,keySign%256,minor) )
                  reaper.MIDI_Sort( take )
            end
            
            refreshFix()
      
      reaper.PreventUIRefresh(-1)      
      reaper.Undo_EndBlock("Script: Set key signature",-1)
      

end
And here is refresh fix when the key sig. is stored within items.
Code:
function refreshFix()
      --fix for refresh and for writing into all midi items (because does not always work when the cursor is at the start of emasure)
      reaper.MIDIEditor_OnCommand( editor, 40048 ) --move cursor right by grid 
      
      --turn on key snap and add to all items
      reaper.MIDIEditor_OnCommand( editor, 40757 ) --select next key signature
      reaper.MIDIEditor_OnCommand( editor, 40756 ) --select previous key signature
      
      reaper.MIDIEditor_OnCommand( editor, 40047 ) --move cursor left by grid 
end
And here is how you can calculate number of sharps/flats form the event
Code:
local keyId, keyMsg = getKeySignAtPpq(startMeas)
local byte = {}
byte[1], byte[2], byte[3], byte[4], byte[5] = string.unpack("BBBBB", keyMsg)
local accidNum = (( tonumber(byte[4],16)+128) % 256) - 128
I use other helper functions but this core should be sufficient.

And you just hardcode a table of this: https://external-content.duckduckgo....peg&f=1&nofb=1 (or code a formula)

Last edited by bFooz; 05-18-2021 at 09:02 AM.
bFooz is offline   Reply With Quote
Old 05-19-2021, 04:04 PM   #9
daeavelwyn
Human being with feelings
 
daeavelwyn's Avatar
 
Join Date: Dec 2014
Posts: 600
Default

Hi bFooz,

Woooow !! Thanks so much for all this material !! You save me an huge amount of time !
daeavelwyn is offline   Reply With Quote
Old 05-22-2021, 02:53 PM   #10
daeavelwyn
Human being with feelings
 
daeavelwyn's Avatar
 
Join Date: Dec 2014
Posts: 600
Default

Hi bFooz,

I took a moment to study and understand your code but still miss some points.

in
Code:
getKeySignAtPpq(startMeas)
I can't understand the lines :
Code:
 --check if this message is a key signature
                  local byte1, byte2 = string.unpack("BB", msg)
                  --if we have a key signature, store message and break
                  if byte1==255 and byte2==89 then
                      returnId = e
                      returnMsg = msg
                      break
                  end
What is "BB" ?, Where do you find information about the fact it's the midi key signature ?

While trying to use reaper.ShowConsoleMsg(), I just get a strange string
Code:
(ÿY)
I can't find the encoding (utf8? base64?hex?)

I've read this https://wiki.cockos.com/wiki/index.p...ions#MIDI_Item But found nothing about key signature probably because it's quite outdated.

Here is, for example, an extract of my rpp file I'm trying to understand :

Code:
 <ITEM
      POSITION 156.64551724138423
      SNAPOFFS 0
      LENGTH 9.6
      LOOP 0
      ALLTAKES 0
      FADEIN 1 0 0 1 0 0 0
      FADEOUT 1 0 0 1 0 0 0
      MUTE 0 0
      SEL 0
      IGUID {1BDDF6A6-5A7D-42C7-9BA4-B6F92666503F}
      IID 9
      NAME short-chord-grid
      VOLPAN 1 0 1 -1
      SOFFS 0 0
      PLAYRATE 1 1 0 -1 0 0.0025
      CHANMODE 0
      GUID {CA785A61-81CD-4CFF-89E7-295F91EADCEF}
      <SOURCE MIDI
        HASDATA 1 960 QN
        CCINTERP 32
        POOLEDEVTS {B5BD55CA-51FC-49FE-86C7-3DF88B72F882}
        <X 0 0 0 0 6 D♯
          /wZE4pmv
        >
        E 0 90 33 20 960
        E 0 90 37 3c 960
        E 0 90 3a 2f 960
        E 0 90 3f 46 960
        <X 0 0
          /w9UUkFDIHRleHQgROKZrw==
        >
        <X 2880 0 0 0 6 FM7
          /wZGTTc=
        >
        E 0 80 33 00
        E 0 80 37 00
        E 0 80 3a 00
        E 0 80 3f 00
        E 0 90 35 20
        E 0 90 39 3c
        E 0 90 3c 2f
        E 0 90 40 46
        <X 0 0
          /w9UUkFDIHRleHQgRk03
        >
        <X 1920 0 0 0 6 GM7
          /wZHTTc=
        >
        E 0 80 35 00
        E 0 80 39 00
        E 0 80 3c 00
        E 0 80 40 00
        E 0 90 37 2b
        E 0 90 3b 2f
        E 0 90 3e 32
        E 0 90 42 31
        <X 0 0
          /w9UUkFDIHRleHQgR003
        >
        E 2880 80 37 00
        E 0 80 3b 00
        E 0 80 3e 00
        E 0 80 42 00
        E 0 90 37 2b
        E 0 90 3b 2f
        E 0 90 3e 32
        E 0 90 42 31
        <X 1920 0 0 0 6 D7
          /wZENw==
        >
        E 0 80 37 00
        E 0 80 3b 00
        E 0 80 3e 00
        E 0 80 42 00
        E 0 90 32 27
        E 0 90 36 2c
        E 0 90 39 2c
        E 0 90 3c 40
        <X 0 0
          /w9UUkFDIHRleHQgRDc=
        >
        E 2880 80 32 00
        E 0 80 36 00
        E 0 80 39 00
        E 0 80 3c 00
        E 0 90 32 27
        E 0 90 36 2c
        E 0 90 39 2c
        E 0 90 3c 40
        <X 1920 0 0 0 6 Em7
          /wZFbTc=
        >
        E 0 80 32 00
        E 0 80 36 00
        E 0 80 39 00
        E 0 80 3c 00
        E 0 90 28 19
        E 0 90 34 13
        E 0 90 37 17
        E 0 90 3b 10
        E 0 90 3e 17
        <X 0 0
          /w9UUkFDIHRleHQgRW03
        >
        <X 1920 0 0 0 6 C♯m7
          /wZD4pmvbTc=
        >
        E 0 80 28 00
        E 0 80 34 00
        E 0 80 37 00
        E 0 80 3b 00
        E 0 80 3e 00
        E 0 90 25 19
        E 0 90 31 13
        E 0 90 34 17
        E 0 90 38 10
        E 0 90 3b 17
        <X 0 0
          /w9UUkFDIHRleHQgQ+KZr203
        >
        E 2880 80 25 00
        E 0 80 31 00
        E 0 80 34 00
        E 0 80 38 00
        E 0 80 3b 00
        E 0 b0 7b 00
        CCINTERP 32
        CHASE_CC_TAKEOFFS 1
        GUID {C2EABF2B-2B78-4F52-BA11-4421A7B95D42}
        IGNTEMPO 0 120 4 4
        SRCCOLOR 113
        VELLANE 166 35 0
        VELLANE 132 67 30
        VELLANE -1 67 0
        CFGEDITVIEW -667.201283 82.502948 59 16 0 -1 0 0 0 0.9
        KEYSNAP 0
        TRACKSEL -243
        EVTFILTER 0 -1 -1 -1 -1 0 0 0 0 -1 -1 -1 -1 0 -1 0 -1 -1
        CFGEDIT 1 1 0 1 3 0 1 0 1 1 1 1 201 132 1331 1113 0 0 1 4 0 0 1 0 0 0 1 0 1 64
      >
    >
daeavelwyn is offline   Reply With Quote
Old 05-23-2021, 01:44 AM   #11
bFooz
Human being with feelings
 
Join Date: Jul 2010
Location: Slovakia
Posts: 2,588
Default

Quote:
Originally Posted by daeavelwyn View Post
What is "BB" ?
The msg is packed (don't know much about that) and string.unpack() is a function build into lua to unpack that and make it readable/usable. "BB" means two bytes.
https://q-syshelp.qsc.com/Content/Co...lation.htm#3.2

Quote:
Where do you find information about the fact it's the midi key signature ?
byte1==255==0xFF
byte2==89 ==0x59

Open a midi item and run "Show raw MIDI data" action. You have to kind-of reverse-engineer what to look for. When you do not use "Key sig. affect all tracks" then they are stored within items. And you can recognize a key signature by "FF 59" as first two bytes.

Here is a raw data of an item with one key signature change of 3 sharps and nothing else. The second message is "All notes off" at the very end of the item.
Code:
    +0       0:   FF 59 02 03 00
 +9436    9436:   B0 7B 00
and this is how it looks in item state chunk:
Code:
        <X 0 0
          /1kCAwA=
        >
        E 9436 b0 7b 00
So I don't think you can obtain it easily from the state chunk.

I have loaded you item. The chord names you have there are not functional chords, they are just text. Written both as a standard midi text "FF 06" and as Reaper's track notation text "FF 0F". You can show both in piano roll CC lanes. But it's different than what I use in my code.

Code:
    +0       0:   FF 06 "D♯"
    +0       0:   90 33 20
    +0       0:   90 37 3C
    +0       0:   90 3A 2F
    +0       0:   90 3F 46
    +0       0:   FF 0F "TRAC text D♯"

Last edited by bFooz; 05-23-2021 at 01:52 AM.
bFooz is offline   Reply With Quote
Old 05-23-2021, 03:01 PM   #12
daeavelwyn
Human being with feelings
 
daeavelwyn's Avatar
 
Join Date: Dec 2014
Posts: 600
Default

Hi bFooz,

Thank you so much for your answer! I just realize I was facing a closed door you just gave me the keys ! I could'nt figure how to monitor raw midi data

Thank you very much for taking the time to detail all those stuff, I have now to investigate on my side to acheive my script.
daeavelwyn is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -7. The time now is 05:41 PM.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.