Close

[C] 3DxPoint: Sounds and Shortcuts

A project log for AirBerries and SpaceExplorer

I should start using my £80 split keyboard and £40 spacemouse more than my £32 keyboard and £16 mouse.

kelvinakelvinA 11/07/2023 at 23:310 Comments

[C] - Coding

I mainly worked on improving the ButtonRing and getting it to do things outside just mouse click events.

Sounds for click events

I was hoping that I could just piggy-back off a Windows sound, but I couldn't find anything suitable in windows/media/. Thus, I looked to see if there was anything that could be generated, and there's a function called Beep().

So I found this tone generator and started trying out some notes, and decided to go with

Yes. I had added a 3rd ring of buttons, which I'm calling the ButtonRing edge.

At first, I implemented the 100ms beeps to play on the onEntry event, but I wondered if it'll be better to get more of a live feedback and instead play the note when a threshold has been passed:

I also found a convenient place that doesn't require elevated access to use:

I've moved the log.txt to this location. This is also where I'd store the audio files.

Audio files?

Well, unfortunately, Beep() will freeze the mouse until it's made it's note. I tried a few async methods I found between BingChat and StackOverflow, but it didn't seem like the beep was being executed from a new thread. Additionally, my speakers made some kind of pop sound after Beep().

The easiest and simplest way I knew was to just go into AIR Ignite 1.3.1, pick a good (and somewhat luxurious) instrument (to complement the SpaceExplorer), and these were the 2 that I initially chose:

Spiccato sounds quite grand and posh, wheras Pizzicato sounds sharp-starting (which is the kind of sound I had in my mind for something that's supposed to represent a click event). I then made some test runs so that I could hear how it would ideally be like in practice:

Welllllll unfortunately, the PlaySound() command I used, while is asynchronous and doesn't freeze the cursor, cannot play more than one sound at a time. Research suggests I'd apparently need to be doing some complex stuff for that. Thus, Pizzicato sounded much less annoying, as it didn't sound like it was being cut off. 

Along with that, I reduced the volume of the output notes so that they were less distracting / drone-sounding, as well as turning the "brightness" of the instrument down to 0 for the C3 note (as for some reason, it's C/D/E/G3 in Ignite, not C/D/E/G4) which removes that sharp start to the note. I think it makes sense since it represents a return to 0, not a click event. G is louder than the other ones as I thought it should sound like more power went into the click.

I've set up PlaySound() so that it doesn't play anything if the file can't be found, so a user could only use D/E/G and not put C into the folder (as, without headphones, it does sound like those notes just cut off midway). Later on, I also added a boolean so that the "play note on trigger" functionality can be selected (which is what I'm using now, again due to the PlaySound() limitation).

I've been using it for a few days, and the sound effects remind me of some kind of media-player interface, like Windows Media Center or the Xbox 360. Considering I've got as much control as an airmouse, it sounds accurate, at least.

Shortcuts

So I looked at the documentation for INPUT_KEYBOARD from Microsoft, and they actually had a sample that implements a keyboard shortcut:

It took less than 50 seconds to decide that there was too much boilerplate present, and I elegantly put everything into macros:

I'd then find out a few things. Firstly, the [ ` ~ ] key on US keyboards is the [ ` ¬ ] key on UK keyboards. Even though the [ ` ] is the same on both, Windows treats them differently, so they've got to be different virtual keys. Secondly, only the ASCII alphanumerics map directly to their virtual key code counterparts. 

Thirdly, that for-each loop strat I tried doesn't work. I have to do the old fashoned 

for (int i = 0; i < ARRAYSIZE(k); i++) {}

for the INPUT types to all be set correctly. 

Fourthly, I can't use a case statement for my PC-to-compile-for selector, but an if / else implementation is fine.

I did decide to make the names more generic though:

To try and find the keycode I was looking for, I turned to the Microsoft docs again, but the sample code just didn't work:

The good news is Microsoft totally already foresaw this specific predicament and has gone out of their way to usher in the Advent of A.I., allowing me to literally ask Bing:

I created a new C++ Console App and ran it, then pressed the key in question and got this:

It technically works, but I wanted to ask Bing if a tweak could be made. It actually delivered:

The virtual key code for Escape is 27. To actually exit the program, the Escape key needs to be held down. Anyway, converting 223 into hexadecimal and then consulting the docs, I found this (but I'm 99% confident I could've just used 223):

I started making some more, but it only took me 2 of these to decide to create a new (and later shortened to) TapKey() function:

Thus, I think the final keyboard shortcut making experience looks rather nice:

I later want to implement some way of querying the .exe that the user has focused so that, like 3DxWare, 3DxPoint changes these shortcuts depending on context.

Discussions