Jump to content


Photo

Build a perfect Virtual Piano using buttons only

viewbuilder virtual piano perfect virtual piano virtual piano buttons

  • Please log in to reply
29 replies to this topic

#1 Raul (ulneiz)

Raul (ulneiz)

    Guruh Member

  • Normal Members
  • PipPipPipPipPipPipPipPipPipPipPipPip
  • 965 posts
  • Gender:Male
  • Location:Spain

Posted 06 June 2017 - 18:39

There is a surprisingly simple and repetitive way to build a perfect virtual piano just by using buttons with Viewbuilder. I share it because I have not seen any tool that uses this method.

 

Main elements:

  1. button (id, height, width, color, bitmap or text, pressed & released or notifier, tooltip... )
  2. row
  3. row with negative spacing
  4. space with width
    vb:row { --row(0)
      margin = 5, -- general margin for all piano.
      spacing = -2, -- space between octaves ( 12 keys ! space ! 12 keys... )
      
      --- --- OCTAVE 0 (0-11)
      vb:row { spacing = -131, --row(1)
        vb:row { spacing = -3, --row(2)
          vb:button { id = "KEY_0",  height = 66, width = 23, color = { 255,255,255 } },
          vb:button { id = "KEY_2",  height = 66, width = 23, color = { 255,255,255 } },
          vb:button { id = "KEY_4",  height = 66, width = 23, color = { 255,255,255 } },
          vb:button { id = "KEY_5",  height = 66, width = 23, color = { 255,255,255 } },
          vb:button { id = "KEY_7",  height = 66, width = 23, color = { 255,255,255 } },
          vb:button { id = "KEY_9",  height = 66, width = 23, color = { 255,255,255 } },
          vb:button { id = "KEY_11", height = 66, width = 23, color = { 255,255,255 } },
        },
        vb:row { --row(3)
          vb:button { id = "KEY_1",  height = 40, width = 15, color = { 001,000,000 } },
          vb:space { width = 8 }, --vb:row { width = 8 },
          vb:button { id = "KEY_3",  height = 40, width = 15, color = { 001,000,000 } },
          vb:space { width = 22 },
          vb:button { id = "KEY_6",  height = 40, width = 15, color = { 001,000,000 } },
          vb:space { width = 7 },
          vb:button { id = "KEY_8",  height = 40, width = 15, color = { 001,000,000 } },
          vb:space { width = 7 },
          vb:button { id = "KEY_10", height = 40, width = 15, color = { 001,000,000 } },
        }
      },
      --- --- OCTAVE 1 (12-23)
      vb:row { spacing = -131, --row(1)
        vb:row { spacing = -3, --row(2)
          vb:button { id = "KEY_12", height = 66, width = 23, color = { 255,255,255 } },
          vb:button { id = "KEY_14", height = 66, width = 23, color = { 255,255,255 } },
          vb:button { id = "KEY_16", height = 66, width = 23, color = { 255,255,255 } },
          vb:button { id = "KEY_17", height = 66, width = 23, color = { 255,255,255 } },
          vb:button { id = "KEY_19", height = 66, width = 23, color = { 255,255,255 } },
          vb:button { id = "KEY_21", height = 66, width = 23, color = { 255,255,255 } },
          vb:button { id = "KEY_23", height = 66, width = 23, color = { 255,255,255 } },
        },
        vb:row { --row(3)
          vb:button { id = "KEY_13", height = 40, width = 15, color = { 001,000,000 } },
          vb:space { width = 8 },
          vb:button { id = "KEY_15", height = 40, width = 15, color = { 001,000,000 } },
          vb:space { width = 22 },
          vb:button { id = "KEY_18", height = 40, width = 15, color = { 001,000,000 } },
          vb:space { width = 7 },
          vb:button { id = "KEY_20", height = 40, width = 15, color = { 001,000,000 } },
          vb:space { width = 7 },
          vb:button { id = "KEY_22", height = 40, width = 15, color = { 001,000,000 } },
        }
      },
      --- --- OCTAVE 2 (24-35)
      vb:row { spacing = -131,
        vb:row { spacing = -3,
          vb:button { id = "KEY_24", height = 66, width = 23, color = { 255,255,255 } },
          vb:button { id = "KEY_26", height = 66, width = 23, color = { 255,255,255 } },
          vb:button { id = "KEY_28", height = 66, width = 23, color = { 255,255,255 } },
          vb:button { id = "KEY_29", height = 66, width = 23, color = { 255,255,255 } },
          vb:button { id = "KEY_31", height = 66, width = 23, color = { 255,255,255 } },
          vb:button { id = "KEY_33", height = 66, width = 23, color = { 255,255,255 } },
          vb:button { id = "KEY_35", height = 66, width = 23, color = { 255,255,255 } },
        },
        vb:row {
          vb:button { id = "KEY_25", height = 40, width = 15, color = { 001,000,000 } },
          vb:space { width = 8 },
          vb:button { id = "KEY_27", height = 40, width = 15, color = { 001,000,000 } },
          vb:space { width = 22 },
          vb:button { id = "KEY_30", height = 40, width = 15, color = { 001,000,000 } },
          vb:space { width = 7 },
          vb:button { id = "KEY_32", height = 40, width = 15, color = { 001,000,000 } },
          vb:space { width = 7 },
          vb:button { id = "KEY_34", height = 40, width = 15, color = { 001,000,000 } },
        }
      },
      --- --- OCTAVE 3 (36-47)
      vb:row { spacing = -131,
        vb:row { spacing = -3,
          vb:button { id = "KEY_36", height = 66, width = 23, color = { 255,255,255 } },
          vb:button { id = "KEY_38", height = 66, width = 23, color = { 255,255,255 } },
          vb:button { id = "KEY_40", height = 66, width = 23, color = { 255,255,255 } },
          vb:button { id = "KEY_41", height = 66, width = 23, color = { 255,255,255 } },
          vb:button { id = "KEY_43", height = 66, width = 23, color = { 255,255,255 } },
          vb:button { id = "KEY_45", height = 66, width = 23, color = { 255,255,255 } },
          vb:button { id = "KEY_47", height = 66, width = 23, color = { 255,255,255 } },
        },
        vb:row {
          vb:button { id = "KEY_37", height = 40, width = 15, color = { 001,000,000 } },
          vb:space { width = 8 },
          vb:button { id = "KEY_39", height = 40, width = 15, color = { 001,000,000 } },
          vb:space { width = 22 },
          vb:button { id = "KEY_42", height = 40, width = 15, color = { 001,000,000 } },
          vb:space { width = 7 },
          vb:button { id = "KEY_44", height = 40, width = 15, color = { 001,000,000 } },
          vb:space { width = 7 },
          vb:button { id = "KEY_46", height = 40, width = 15, color = { 001,000,000 } },
        }
      },
      --- --- OCTAVE 4 (48-59)
      vb:row { spacing = -131,
        vb:row { spacing = -3,
          vb:button { id = "KEY_48", height = 66, width = 23, color = { 255,255,255 } },
          vb:button { id = "KEY_50", height = 66, width = 23, color = { 255,255,255 } },
          vb:button { id = "KEY_52", height = 66, width = 23, color = { 255,255,255 } },
          vb:button { id = "KEY_53", height = 66, width = 23, color = { 255,255,255 } },
          vb:button { id = "KEY_55", height = 66, width = 23, color = { 255,255,255 } },
          vb:button { id = "KEY_57", height = 66, width = 23, color = { 255,255,255 } },
          vb:button { id = "KEY_59", height = 66, width = 23, color = { 255,255,255 } },
        },
        vb:row {
          vb:button { id = "KEY_49", height = 40, width = 15, color = { 001,000,000 } },
          vb:space { width = 8 },
          vb:button { id = "KEY_51", height = 40, width = 15, color = { 001,000,000 } },
          vb:space { width = 22 },
          vb:button { id = "KEY_54", height = 40, width = 15, color = { 001,000,000 } },
          vb:space { width = 7 },
          vb:button { id = "KEY_56", height = 40, width = 15, color = { 001,000,000 } },
          vb:space { width = 7 },
          vb:button { id = "KEY_58", height = 40, width = 15, color = { 001,000,000 } },
        }
      },
    }

The basic steps to create a octave:

  1. Create a general row(1) for each octave. Then insert two rows, row (2) and row (3).
  2. Group the 7 white buttons in row(2) (the buttons must be sorted in scale: C-, D-, E-, F-, G-, A-, B-. color = { 255,255,255 } for pure white.
  3. Group the 5 black buttons in other row(3) (the buttons must be sorted in scale: C#, D#, F#, G#, A# ) . color = { 0,0,0 } according with your theme of Renoise or color = { 1,0,0 } for pure black.
  4. Without using spacing, the white and black buttons are placed on the same line. Use negative spacing to overlap the row (3) above the row (2), for example: vb:row { spacing = -131,  . Then, all black overlap with white.
  5. Finally, inside the row(3), uses rows with a given width to separate the black buttons correctly, for example: vb:space { width = 7 }

Repeat steps to create up to 10 octaves. You can group all octaves in another row and use a concrete spacing among them.

 

The crude result (with 5 octaves. The black keys use color = { 0,0,0 } to respect the theme):

virtual_piano_ulneiz.gif
 
With the properties of each button (pressed, released, notifier), key_handler, midi and mouse is possible to control this virtual piano and build very interesting tools, with a more pro look.
 
Notes 1:
  1. It is possible to modify the size of the buttons and accompanying the spacing.
  2. Is possible to modify the colors of the buttons grouped in octaves or groups of octaves.
  3. You can add the right and left scroll buttons to display only the desired octaves (a tool that takes up little space, using only the negative or positive spacing.
  4. Use "spacing" inside the "row" (horizontal scroll) and "spacing" inside the "column" (vertical scroll).
  5. You can build a virtual piano vertically, using "column" and "spacing", with the same results...

Notes 2:

  1. Another trick is to call the id of each button as well: id = "KEY_0", id = "KEY_1"id = "KEY_2"... id = "KEY_10", id = "KEY_11", id = "KEY_12"... In this way, we can call a group of buttons as well:
function change_color_octave_0()
  for k = 0, 11 do
    vb.views["KEY_"..k..""].color = {x70,x00,x00} --red
  end
end

function change_color_octave_1()
  for k = 12, 23 do
    vb.views["KEY_"..k..""].color = {x00,x70,x00} --green
  end
end 

Using this trick you can modify properties of each button in a group. For example, offer the user 2 or 3 different virtual piano sizes, adding an id to each row to resize it as needed. In my GT16-Colors tool, I was able to add a button that returns the last note pressed, to remember it. Pressing this button points the corresponding key back on the piano. With a little creativity, you can build wonderful things...

 

Enjoy and build your tools!!!

 


Edited by Raul (ulneiz), 07 June 2017 - 10:32.

  • danoise, Ledger, Conner_Bw and 1 other like this

:excl: Development of my tool: GT16-Colors

 

:excl: My API wishlist R3.1 (updated 24 July 2017):

Spoiler

 

:excl: My Renoise 3.1 wishlist (updated 18 July 2017):

Spoiler

#2 Raul (ulneiz)

Raul (ulneiz)

    Guruh Member

  • Normal Members
  • PipPipPipPipPipPipPipPipPipPipPipPip
  • 965 posts
  • Gender:Male
  • Location:Spain

Posted 06 June 2017 - 18:49

Applying this method in my tool:

 

wmp_ulneiz.png

 

Beautiful!  :wub:


  • Ledger, sokoban and encryptedmind like this

:excl: Development of my tool: GT16-Colors

 

:excl: My API wishlist R3.1 (updated 24 July 2017):

Spoiler

 

:excl: My Renoise 3.1 wishlist (updated 18 July 2017):

Spoiler

#3 Ledger

Ledger

    Guruh Motha Fakka Knows More About Renoise Than Taktik

  • Normal Members
  • PipPipPipPipPipPipPipPipPipPipPipPipPipPip
  • 3372 posts
  • Gender:Male

Posted 06 June 2017 - 23:11

Great work Raul!

 

thanks for sharing


--> Lua For Beginners <--
--> Lua for newbies <--

My Scripts On Forum

Top Tip!

 

cpu : Xeon 1231 v3, os : Win 7 64bit, audio: Audient iD4
posts as 4tune @ KvR and some other music related sites


#4 Raul (ulneiz)

Raul (ulneiz)

    Guruh Member

  • Normal Members
  • PipPipPipPipPipPipPipPipPipPipPipPip
  • 965 posts
  • Gender:Male
  • Location:Spain

Posted 06 June 2017 - 23:26

Great work Raul!

 

thanks for sharing

 

Thanks Ledger! I forgot to comment on another detail. The code can be optimized by saving many lines because the key buttons use equal values (same with, height, color, etc.). Actually, only 2 types of buttons are defined, with id, notifier, pressed, released, tooltip, bitmap, text differents. We can get great tools this way.


:excl: Development of my tool: GT16-Colors

 

:excl: My API wishlist R3.1 (updated 24 July 2017):

Spoiler

 

:excl: My Renoise 3.1 wishlist (updated 18 July 2017):

Spoiler

#5 Raul (ulneiz)

Raul (ulneiz)

    Guruh Member

  • Normal Members
  • PipPipPipPipPipPipPipPipPipPipPipPip
  • 965 posts
  • Gender:Male
  • Location:Spain

Posted 06 June 2017 - 23:46

By the way, the button overlay allows you to create another class of interesting utilities to improve the appearance. One option is to create 2 buttons, the first a little larger than the second, and overlap the second button above the first in a centered manner. When you press the second button, you can color the first color so that a color selection frame appears. I have not yet built it, but I'm sure it's possible, and it's very easy. This would allow you to use buttons with text and forget the checkboxes. When I have time, I will share an example here.


:excl: Development of my tool: GT16-Colors

 

:excl: My API wishlist R3.1 (updated 24 July 2017):

Spoiler

 

:excl: My Renoise 3.1 wishlist (updated 18 July 2017):

Spoiler

#6 joule

joule

    Guruh Motha Fakka is Levitating and Knows Everything About Renoise Member

  • Normal Members
  • PipPipPipPipPipPipPipPipPipPipPipPipPip
  • 1467 posts
  • Gender:Not Telling
  • Location:Sweden
  • Interests:music, philosophy, engineering

Posted 07 June 2017 - 09:24

Looking good!

 

PS.

1) color = { 000,000,000 } should be changed to { 1, 0, 0 } for true black. 0,0,0 will only be black in certain color themes.

2) there is a dedicated vb:space class that can be used instead of vb:row { width = 7 }. Good to know, but it probably doesn't matter here in practice.



#7 Raul (ulneiz)

Raul (ulneiz)

    Guruh Member

  • Normal Members
  • PipPipPipPipPipPipPipPipPipPipPipPip
  • 965 posts
  • Gender:Male
  • Location:Spain

Posted 07 June 2017 - 10:56

Looking good!

 

PS.

1) color = { 000,000,000 } should be changed to { 1, 0, 0 } for true black. 0,0,0 will only be black in certain color themes.

2) there is a dedicated vb:space class that can be used instead of vb:row { width = 7 }. Good to know, but it probably doesn't matter here in practice.

 

Thank you! I updated the comment #1 with the changes. I think I remember seeing some Danoise tool that represents some virtual piano, but it does not overlay buttons. So the virtual piano look strange.

 

...

 

Here would be beneficial a specific code to compact lines or save lines of code by avoiding to write continuously height = 66, width = 23, color = { 255,255,255 } or height = 40, width = 15, color = { 1,0,0 }. That is, a little optimization. I still do not know what would be the best way to do it...

 

...

 

Topic aside: I miss some code to be able to put the text in vertical, turned 90º. To do this I have to use the bitmap and I do not like it very much... Is there any way to do this?

 

When I have time, I will try to build a vertical piano, like this one and also a compact virtual piano with octave scroll buttons, for example: [<] [octave 3] [octave 4] [octave 5] [>] .


Edited by Raul (ulneiz), 07 June 2017 - 10:57.

:excl: Development of my tool: GT16-Colors

 

:excl: My API wishlist R3.1 (updated 24 July 2017):

Spoiler

 

:excl: My Renoise 3.1 wishlist (updated 18 July 2017):

Spoiler

#8 danoise

danoise

    Probably More God or Borg Than Human Member

  • Renoise Team
  • PipPipPipPipPipPipPipPipPipPipPipPipPipPipPip
  • 6366 posts
  • Gender:Male
  • Location:Berlin
  • Interests:wildlife + urban trekking

Posted 07 June 2017 - 12:01

Wow, that's cool. Like you said: simply the perfect looking piano widget. 

 

I think I remember seeing some Danoise tool that represents some virtual piano, but it does not overlay buttons. So the virtual piano look strange.

 

You're right - I didn't know about the negative margin/spacing technique back then. I think credit goes to afta8 for discovering that? 

And, just to confirm since I heard a few concerned whispers: negative margins are a valid design/layout technique - also in other languages. It's NOT going away from the Renoise API :)


Tracking with Stuff. API wishlist | Soundcloud


#9 joule

joule

    Guruh Motha Fakka is Levitating and Knows Everything About Renoise Member

  • Normal Members
  • PipPipPipPipPipPipPipPipPipPipPipPipPip
  • 1467 posts
  • Gender:Not Telling
  • Location:Sweden
  • Interests:music, philosophy, engineering

Posted 07 June 2017 - 12:14

You indeed must use bitmaps for the text, as far as I know. Just the fact that you can't set text color makes this the only good option for predictable results independent of color theme. Rotating vb:text or button text certainly isn't possible.

 

If you're building scroll buttons, you should imo make a piano widget class. It's much easier and more compact to handle dynamic behavior like that in a "self-contained structure" that a class is.



#10 Raul (ulneiz)

Raul (ulneiz)

    Guruh Member

  • Normal Members
  • PipPipPipPipPipPipPipPipPipPipPipPip
  • 965 posts
  • Gender:Male
  • Location:Spain

Posted 07 June 2017 - 12:20

Wow, that's cool. Like you said: simply the perfect looking piano widget. 

 

 

You're right - I didn't know about the negative margin/spacing technique back then. I think credit goes to afta8 for discovering that? 

And, just to confirm since I heard a few concerned whispers: negative margins are a valid design/layout technique - also in other languages. It's NOT going away from the Renoise API :)

 

Yes. I know CSS3 quite well. Here you can use negative margins too. I suppose it is an almost universal method for any type of code used to represent a GUI. But, certainly, I was surprised to see no piano tool with this aspect until now. And he told me over and over, that there had to be some way.

 

I invite anyone to take the code and wring the maximum. I would like to see tools with a more professional look in general. I have seen some really amazing, looking tools, one of them was of afta8, that managed dynamic points, I believe.


:excl: Development of my tool: GT16-Colors

 

:excl: My API wishlist R3.1 (updated 24 July 2017):

Spoiler

 

:excl: My Renoise 3.1 wishlist (updated 18 July 2017):

Spoiler

#11 Raul (ulneiz)

Raul (ulneiz)

    Guruh Member

  • Normal Members
  • PipPipPipPipPipPipPipPipPipPipPipPip
  • 965 posts
  • Gender:Male
  • Location:Spain

Posted 07 June 2017 - 12:37

You indeed must use bitmaps for the text, as far as I know. Just the fact that you can't set text color makes this the only good option for predictable results independent of color theme. Rotating vb:text or button text certainly isn't possible.

 

...

 

I will explain the procedure I follow to do it. Build vertical text:

  1. Create a button with large height and width and pure white color.
  2. Type in the text of the button the word you want to use.
  3. Capture the image and paste it into an image editor. I use paint.net
  4. Rotate the image 90º, invert the color, reduce the distance between letters and crop to create an icon in bmp or png format.
  5. Finally use it inside a :button or a :bitmap using bitmap...

Too bad there is no better way to control the text. This method is a bit prehistoric.  ^_^

 

 

If you're building scroll buttons, you should imo make a piano widget class. It's much easier and more compact to handle dynamic behavior like that in a "self-contained structure" that a class is.

 

I will take this topic to develop it later. The idea I have is to share several examples of different virtual pianos, to have examples available in the forums.

 

 

...

You're right - I didn't know about the negative margin/spacing technique back then. I think credit goes to afta8 for discovering that? 

...

 

I believe that these details should be well explained in the documentation in ViewBuilder.API.lua...

  • For colum: .spacing -> [ positive or negative number ]
  • For row: .spacing -> [ positive or negative number ]
  • etc

Or also in practical basic examples.


Edited by Raul (ulneiz), 07 June 2017 - 13:26.

:excl: Development of my tool: GT16-Colors

 

:excl: My API wishlist R3.1 (updated 24 July 2017):

Spoiler

 

:excl: My Renoise 3.1 wishlist (updated 18 July 2017):

Spoiler

#12 danoise

danoise

    Probably More God or Borg Than Human Member

  • Renoise Team
  • PipPipPipPipPipPipPipPipPipPipPipPipPipPipPip
  • 6366 posts
  • Gender:Male
  • Location:Berlin
  • Interests:wildlife + urban trekking

Posted 07 June 2017 - 14:26

I believe that these details should be well explained in the documentation in ViewBuilder.API.lua...

 

Well, maybe. I think it's fine that we're sharing these tips here in the scripting forum. 

Another tip : did you know that printing the following in the console yields colored text? 

print("*** Oops! An error occurred") -- this will be grey
print(">>> Processing....") -- this will be green

Pretty useful if you're doing a lot of console tracing while developing   :ph34r:


Tracking with Stuff. API wishlist | Soundcloud


#13 Raul (ulneiz)

Raul (ulneiz)

    Guruh Member

  • Normal Members
  • PipPipPipPipPipPipPipPipPipPipPipPip
  • 965 posts
  • Gender:Male
  • Location:Spain

Posted 07 June 2017 - 14:41

Well, maybe. I think it's fine that we're sharing these tips here in the scripting forum. 

Another tip : did you know that printing the following in the console yields colored text? 

print("*** Oops! An error occurred") -- this will be grey
print(">>> Processing....") -- this will be green

Pretty useful if you're doing a lot of console tracing while developing   :ph34r:

 

:D  :D  :D thanks! True!!! I had seen it in some of your tools, that the green text came out on the console, but I did not bother to see how it was done. Then there are 3 colors, right?

print("info!") - white text
print("*** error!") - grey text
print(">>> applying!") - green text

What would be very useful is to create a timer in milliseconds to determine how long a particular function takes, and to display the value printed on the console at the end of the process:

  • Function "XXX" processed in 450 ms

or

  • Function "YYY" processed in 6213 ms

This would be very useful!!!


Edited by Raul (ulneiz), 07 June 2017 - 14:47.

:excl: Development of my tool: GT16-Colors

 

:excl: My API wishlist R3.1 (updated 24 July 2017):

Spoiler

 

:excl: My Renoise 3.1 wishlist (updated 18 July 2017):

Spoiler

#14 joule

joule

    Guruh Motha Fakka is Levitating and Knows Everything About Renoise Member

  • Normal Members
  • PipPipPipPipPipPipPipPipPipPipPipPipPip
  • 1467 posts
  • Gender:Not Telling
  • Location:Sweden
  • Interests:music, philosophy, engineering

Posted 07 June 2017 - 14:59

Timing your functions can be done by using os.clock(). Example: http://forum.renoise...ative/?p=343718


  • Raul (ulneiz) likes this

#15 Raul (ulneiz)

Raul (ulneiz)

    Guruh Member

  • Normal Members
  • PipPipPipPipPipPipPipPipPipPipPipPip
  • 965 posts
  • Gender:Male
  • Location:Spain

Posted 07 June 2017 - 15:18

Timing your functions can be done by using os.clock(). Example: http://forum.renoise...ative/?p=343718

 

:blink: I read over the whole topic to tools speed optimization, but I did not remember that you just used that, thanks! I will definitely use this os.clock() to optimize my tools...

local x = os.clock()

function name_func()
  --content  
end

print(string.format("elapsed time: %.2f\n", os.clock() - x))
This is very interesting!!!

Edited by Raul (ulneiz), 07 June 2017 - 15:19.

:excl: Development of my tool: GT16-Colors

 

:excl: My API wishlist R3.1 (updated 24 July 2017):

Spoiler

 

:excl: My Renoise 3.1 wishlist (updated 18 July 2017):

Spoiler

#16 4Tey

4Tey

    Chief Above Chief Member

  • Normal Members
  • PipPipPipPipPipPip
  • 382 posts
  • Gender:Male

Posted 07 June 2017 - 16:13

Then there are 3 colors, right?

You could probably get more colors out of strings if you were to run Renoise under a color terminal and output (debugging) strings directly to stdout using ANSI escape sequences:

io.stdout:write("\27[33;1mThis is yellow!\n")
io.stdout:write("\27[31;1mThis is red!\n")
io.stdout:write("\27[35;1mThis is magenta!\n")
io.stdout:write("\27[34;1mThis is blue!\n")

Thinking more Linux here though, don't know about Windows :)

 

Good little piano 'button' keyboard btw Raul :)



#17 Raul (ulneiz)

Raul (ulneiz)

    Guruh Member

  • Normal Members
  • PipPipPipPipPipPipPipPipPipPipPipPip
  • 965 posts
  • Gender:Male
  • Location:Spain

Posted 07 June 2017 - 16:54

You could probably get more colors out of strings if you were to run Renoise under a color terminal and output (debugging) strings directly to stdout using ANSI escape sequences:

io.stdout:write("\27[33;1mThis is yellow!\n")
io.stdout:write("\27[31;1mThis is red!\n")
io.stdout:write("\27[35;1mThis is magenta!\n")
io.stdout:write("\27[34;1mThis is blue!\n")

Thinking more Linux here though, don't know about Windows :)

 

Good little piano 'button' keyboard btw Raul :)

 

Thanks 4Tey! I am using windows at all times and linux for boot with USB. So I do not have a proper machine to try Renoise under Linux or Mac.

 

...

 

I keep thinking things with colors. I have not seen the specific documentation, but there should be some way to detect that the selected instrument uses samples (not VSTi). Considering the keyzones. There should be a simple way to colorize gray (or active = false) the keys that do not have any associated samples. Disable non-serving keys... With this, in addition to adjusting the size of the piano, and being able to control the keys through MIDI (especially), USB keyboard and mouse, would be a frankly useful and attractive tool.

 

MIDI pressed and MIDI released to control the "note buttons"??? I mean all the notes of the 10 octaves, the 120 notes. The virtual piano would control the 120 notes, but visually only the necessary octaves would appear. I think 3 octaves would be enough.

 

I have used to call a function:

renoise.tool():add_midi_mapping {
  name = THE_NAME,
  invoke = function(message)
    if (message:is_trigger()) then
      name_func()
    end
  end
}

MIDI is_trigger() is equal to button released.... In Renoise.ScriptingTool.API.lua:

class "renoise.ScriptingTool.MidiMessage"
    
      -- returns if action should be invoked
      function is_trigger() -> boolean

      -- check which properties are valid
      function: is_switch() -> boolean
      function: is_rel_value() -> boolean
      function: is_abs_value() -> boolean

      -- [0 - 127] for abs values, [-63 - 63] for relative values
      -- valid when is_rel_value() or is_abs_value() returns true, else undefined
      property: int_value

      -- valid [true OR false] when :is_switch() returns true, else undefined
      property: boolean_value

is_swith() act like a button, with pressed, and released? What I would like to build is a way to control the virtual keyboard with the MIDI keyboard, all notes. Since there are 120 notes, you really only need to deal with one note. The rest is repeat. My final idea is to build a virtual piano that can control notes with the midi keyboard, but also to be able to edit in the pattern editor the notes directly with the mouse on the virtual keyboard.

  • With the mouse the sound can use the osc server.
  • With the midi keyboard I understand that the sound should "go alone".

Edited by Raul (ulneiz), 07 June 2017 - 16:57.

:excl: Development of my tool: GT16-Colors

 

:excl: My API wishlist R3.1 (updated 24 July 2017):

Spoiler

 

:excl: My Renoise 3.1 wishlist (updated 18 July 2017):

Spoiler

#18 danoise

danoise

    Probably More God or Borg Than Human Member

  • Renoise Team
  • PipPipPipPipPipPipPipPipPipPipPipPipPipPipPip
  • 6366 posts
  • Gender:Male
  • Location:Berlin
  • Interests:wildlife + urban trekking

Posted 07 June 2017 - 19:05

If you want to do a virtual-midi keyboard alike thing with MIDI input, you'll need for the tool to configure it's own MIDI input.

 

There is an example on how to do this here: 

https://github.com/r...ippets/Midi.lua

 

It lets you receive raw MIDI data, which you can then do whatever with you want. 

All the basic MIDI messages (so, not sysex and such stuff) is really just three bytes of data - so quite simple to process. 

(check the MIDI input panel to investigate incoming messages)

 

  • With the mouse the sound can use the osc server.
  • With the midi keyboard I understand that the sound should "go alone".

 

If you want to trigger notes in realtime, this is done through the OSC server, no matter what 

Remember, you tool defines it's own MIDI input port - independently of Renoise. 

 

You can send messages using the OSC server in two ways: 

1. "Raw" midi message which is received by whichever instrument is selected 

2. "Extended" message which targets a specific instrument and/or track 

 

The "extended" message is dealing with triggering notes only, so if you want to pass CC data from the keyboard (mod wheel?) to Renoise (or other tools), then you need to send as "raw" midi

Raw MIDI works like incoming midi message and can be MIDI mapped to any element that light up when pressing CTRL+M (MIDI mapping mode). 

 

 

Hope this helps!


Tracking with Stuff. API wishlist | Soundcloud


#19 joule

joule

    Guruh Motha Fakka is Levitating and Knows Everything About Renoise Member

  • Normal Members
  • PipPipPipPipPipPipPipPipPipPipPipPipPip
  • 1467 posts
  • Gender:Not Telling
  • Location:Sweden
  • Interests:music, philosophy, engineering

Posted 08 June 2017 - 09:27

@Raul,
 Here is the way to build your widget programatically, done for the fun of it :) This will also let you decide how many octaves to build.
 
 (A version that would render from any key to any key would be a bit more complex/different than this, but this is a first step)
 
Spoiler

Edited by joule, 08 June 2017 - 09:54.


#20 Raul (ulneiz)

Raul (ulneiz)

    Guruh Member

  • Normal Members
  • PipPipPipPipPipPipPipPipPipPipPipPip
  • 965 posts
  • Gender:Male
  • Location:Spain

Posted 08 June 2017 - 12:26

@Joule, thank you very much!  :)
 
I added a bit of layout:

Spoiler
tooltip = white_tooltip(key, octave), --<<
bitmap = white_bitmap(key, octave), --<<
pressed = function(key, octave)   end, --<<
released = function(key, octave)   end --<<

...

tooltip = black_tooltip(key, octave), --<<
pressed = function(key, octave)   end, --<<
released = function(key, octave)   end --<<

vb-perfect-piano-2.png

 

I think it would be all set to have a virtual piano as a base. From here, on the 10 octave piano, it is possible to add 2 side scroll buttons and display only 3 or 4 octaves to make a more compact tool. Another button on the left to deploy a bottom line with more buttons to trigger functions.

 

For now, I think I would be able to include 3 things:

  1. OSC Server for sound.
  2. Control writing in the pattern editor using the mouse with the virtual piano.
  3. Control writing in the pattern editor using the USB keyboard with the virtual piano, according the "Oct" value of Renoise.

I find it an unknown world yet for include control via MIDI input. This involves connecting a MIDI keyboard and pressing the keyboard notes that the virtual piano only can illuminate the keys (pressed and released).


:excl: Development of my tool: GT16-Colors

 

:excl: My API wishlist R3.1 (updated 24 July 2017):

Spoiler

 

:excl: My Renoise 3.1 wishlist (updated 18 July 2017):

Spoiler

#21 joule

joule

    Guruh Motha Fakka is Levitating and Knows Everything About Renoise Member

  • Normal Members
  • PipPipPipPipPipPipPipPipPipPipPipPipPip
  • 1467 posts
  • Gender:Not Telling
  • Location:Sweden
  • Interests:music, philosophy, engineering

Posted 08 June 2017 - 13:48

Yes. By making a class you can include smart properties ("first_octave", "last_octave" et c) and make sure that these will refresh the whole piano view whenever they are changed.

 

... allowing a syntax that would look something like this:

local piano_widget = PianoWidget { first_octave = 2, last_octave = 7 } -- creates an object by the PianoWidget class
piano_widget.first_octave = 3 -- set a new value for first_octave. in the class, a property setter function is used to refresh the piano view

A class can be used as an interface that makes dynamic behavior like this a breeze. You can imagine how simple it would be to scroll, increase or decrease number of octaves by just pressing a button, and with this kind of automatic rebuilding.

 

PS. I noticed that you linked a tutorial on LUA classes previously. However, Renoise allows a nicer syntax than the one found in conventional lua tutorials.


  • Raul (ulneiz) likes this

#22 Raul (ulneiz)

Raul (ulneiz)

    Guruh Member

  • Normal Members
  • PipPipPipPipPipPipPipPipPipPipPipPip
  • 965 posts
  • Gender:Male
  • Location:Spain

Posted 10 June 2017 - 13:57

If you want to do a virtual-midi keyboard alike thing with MIDI input, you'll need for the tool to configure it's own MIDI input.

 

There is an example on how to do this here: 

https://github.com/r...ippets/Midi.lua

 

It lets you receive raw MIDI data, which you can then do whatever with you want. 

All the basic MIDI messages (so, not sysex and such stuff) is really just three bytes of data - so quite simple to process. 

(check the MIDI input panel to investigate incoming messages)

 

 

If you want to trigger notes in realtime, this is done through the OSC server, no matter what 

Remember, you tool defines it's own MIDI input port - independently of Renoise. 

 

You can send messages using the OSC server in two ways: 

1. "Raw" midi message which is received by whichever instrument is selected 

2. "Extended" message which targets a specific instrument and/or track 

 

The "extended" message is dealing with triggering notes only, so if you want to pass CC data from the keyboard (mod wheel?) to Renoise (or other tools), then you need to send as "raw" midi

Raw MIDI works like incoming midi message and can be MIDI mapped to any element that light up when pressing CTRL+M (MIDI mapping mode). 

 

 

Hope this helps!

 

I have not gone into depth to control a specific tool with MIDI input. Thinking about a virtual piano, the only thing that would need to be controlled is the reaction of a button according to the note pressed with the MIDI keyboard. That's 120 buttons on the tool related keys 120 notes of the MIDI keyboard. In the end, the code is summarized in configuring a single button with the MIDI input code. Then add the remaining 119.

 

The MIDI code that is needed to run the tool, will serve for any model MIDI keyboard?


:excl: Development of my tool: GT16-Colors

 

:excl: My API wishlist R3.1 (updated 24 July 2017):

Spoiler

 

:excl: My Renoise 3.1 wishlist (updated 18 July 2017):

Spoiler

#23 Raul (ulneiz)

Raul (ulneiz)

    Guruh Member

  • Normal Members
  • PipPipPipPipPipPipPipPipPipPipPipPip
  • 965 posts
  • Gender:Male
  • Location:Spain

Posted 16 June 2017 - 17:55

Yes. By making a class you can include smart properties ("first_octave", "last_octave" et c) and make sure that these will refresh the whole piano view whenever they are changed.

 

... allowing a syntax that would look something like this:

local piano_widget = PianoWidget { first_octave = 2, last_octave = 7 } -- creates an object by the PianoWidget class
piano_widget.first_octave = 3 -- set a new value for first_octave. in the class, a property setter function is used to refresh the piano view

A class can be used as an interface that makes dynamic behavior like this a breeze. You can imagine how simple it would be to scroll, increase or decrease number of octaves by just pressing a button, and with this kind of automatic rebuilding.

 

PS. I noticed that you linked a tutorial on LUA classes previously. However, Renoise allows a nicer syntax than the one found in conventional lua tutorials.

 

I've been looking at this. It is also possible to do it as follows:

  function pw_build(first_octave, last_octave) --range 0 to 9 (10 octaves)
    local piano_widget = vb:row { margin = 5, spacing = -2 }
  
    for octave = first_octave, last_octave do
      piano_widget:add_child( pw_build_octave(octave) )
    end
  
    return piano_widget
  end
  
  my_pianowidget_content = pw_build(3,6)

With pw_build(3,6) octaves 3, 4, 5, 6 appear. It is thus possible to easily change or move it. Move one octave to the left would be pw_build(2,5). Maximize: pw_build(0,9). Only one octave (octave 4): pw_build(4,4)


:excl: Development of my tool: GT16-Colors

 

:excl: My API wishlist R3.1 (updated 24 July 2017):

Spoiler

 

:excl: My Renoise 3.1 wishlist (updated 18 July 2017):

Spoiler

#24 joule

joule

    Guruh Motha Fakka is Levitating and Knows Everything About Renoise Member

  • Normal Members
  • PipPipPipPipPipPipPipPipPipPipPipPipPip
  • 1467 posts
  • Gender:Not Telling
  • Location:Sweden
  • Interests:music, philosophy, engineering

Posted 16 June 2017 - 18:22

Yes, of course you can use function oriented programming for anything if you want to, but it's not a very good (flexible and future friendly) way of designing the code.



#25 4Tey

4Tey

    Chief Above Chief Member

  • Normal Members
  • PipPipPipPipPipPip
  • 382 posts
  • Gender:Male

Posted 16 June 2017 - 19:22

So I take it you won't be touching Clojure then Joule? ;)

C
    You shoot yourself in the foot. 

Assembly Language
    You crash the OS and overwrite the root disk. The system administrator arrives and shoots you in the foot.
    After a moment of contemplation, the administrator shoots himself in the foot and then hops around the room rabidly shooting at everyone in sight. 

C++
    You accidentally create a dozen instances of yourself and shoot them all in the foot. 
    Providing emergency medical care is impossible since you can't tell which are bitwise copies and which are just 
    pointing at others and saying "that's me, over there." 

I like good ol' assembly language :)


Edited by 4Tey, 16 June 2017 - 19:22.

  • Conner_Bw likes this