|
Posted
about 2 months
ago
I have been using the Glove80 keyboard for a few years now, and it suits me very well.
I have some quibbles about the software1 and hardware. This blog post is about fixing the hardware.
The keyboard has function keys F1 through F10. This
... [More]
design decision — detailed at Why are there no F11 and F12 keys? — was to reduce the height of the keyboard for portability. Personally, I wouldn’t mind an extra 12mm in keyboard height; I would prefer to have the extra keys. I wondered if I could add them.
The Glove80 designers cleverly left an “escape hatch” to facilitate extra buttons and other peripherals. I wondered if I could use that to add F6 and F7 keys.
The keyboard is expensive, so I did not want to drill holes or dremel the case or solder directly onto any PCB. My idea was to use the provided GPIO pin header and sneak thin (30 AWG) wires through the power LED case holes such that I could undo everything cleanly if necessary.
For the software side of the modifications, I used the generic ZMK port so I could follow the “west” tool setup instructions verbatim and build the firmware on my own machine (avoiding the recommended proprietary build pipelines). Once I found the right area of the documentation website the instructions were up-to-date and easy-to-follow. I wrote a ZMK patch I thought should work. Update 2026-09-29: I created another patch, for the official MoErgo ZMK firmware.
Now that the software was ready to test, I bought some supplies:
Supplies needed to convert Glove80 to Glove82. Some 30 AWG wire, a 2×6 1.27mm ribbon cable, and two Kailh Low Profile Choc switches.
I opened the case, connected the ribbon cable, and performed a test with multimeter probes:
Hardware setup for probing Glove80 extension pinout.
After orienting myself to the pin-numbering scheme,
Ribbon cable pinouts.
I determined the correct pins and connected them. xev showed the new F6 key registering!:
Running xev while probing ribbon cable.
I started work hacking together a cable (with some soldering help from my son and daughter). Here is the result:
Glove82 wiring harness installed in chassis.
One more test of shorting the exported wires and I felt confident enough to tape the new harness to the inside of the case. Next, I screwed the cover back on, and routed and secured with Kapton tape the extra wire length I left for further mounting experimentation:
Routing of wires outside chassis.
To mount the key to the keyboard, I had been conceptualizing something 3D-printed and clip-on. However for the prototype my daughter suggested double-sided sticky tape (“the foam kind”). It turned out to be strong enough to support the key itself and key presses (I use the lightest 35gf switches):
Key mounting test.
I did the second half of the keyboard and… Behold, the final prototype:
Working Glove82 prototype.
It looks funny because the new keys are raised off the board. It turns out this doesn’t actually bother me or negatively impact usability. The risk of cutting into the case to make the new keys flush would bother me!
When making a window fullscreen during testing it was immediately satisfying to mash F11 exactly where I expected it, instead of searching the web for the layout of the Glove80 lower layer.
Potential Future Improvements
Maybe I will find the motivation to design a clip-on 3D-printed mount to replace the tape.
At some point I might create a fork of the official MoErgo firmware with my Glove82 patch, to get back the extra features that the vanilla ZMK port is missing (e.g., LED support). Upstream ZMK and the MoErgo branch have diverged though so this isn’t trivial. Update 2026-09-29: Done.
For now though, the keyboard is usable as-is, so I will use it for a while and see how the modifications hold up.
1. I wish some heroes of the Internet would reverse engineer and re-implement the nRF52840 Bluetooth stack under a GPL-compatible license.
Thank you to mtegel, lexano, and my daughter, for reviewing a draft of this post.
[Less]
|
|
Posted
6 months
ago
We’ll release Valgrind 3.27.0 later today. While making sure the NEWS file was up to date I wrote about all the contributions made this release.
Thanks all, and apologies if I missed something or someone.
Aaron Merey added two new options to
... [More]
helgrind.
To control helgrind tracing of internal synchronization, threading and memory events use –show-events=1|2|3.
Use –track-destroy=no|yes|all to checks for missing pthread_mutex_destroy and pthread_rwlock_destroy calls. With yes, helgrind warns when pthread_mutex_init or pthread_rwlock_init is called on the address of a live (undestroyed) lock. With all, Helgrind also reports undestroyed locks at process exit.
Valgrind has separate VEX IR translators for AMD64 and x86 (32 bit) code. While the AMD64 translator has seen support for new encodings and instruction sets, the x86 translator has not.
Alexandra Hájková decided to port the SSE4.1 instruction set from the AMD64 translator to the x86 translator and add backend support. This is ongoing work, see the bug dependency tree.
But many more 32bit programs using SSE4.1 should now run under Valgrind.
Andreas Arnez and Florian Krohm did a lot of work on the s390x support.
Andreas added support for new s390x z/Architecture features from the 15th edition. This enables running binaries compiled with -march=arch15 or -march=z17 and exploiting the new MSA extensions 10-13.
Florian Krohm integrated binutils objdump for s390x disassembly in VEX. And did a lot of s390x code and facilities cleanups.s390x machine models older than z196 are no longer supported.
Andreas also showed there are still meaningful optimizations to be made on how memcheck tracks undefinedness bits as outlined in the original “Using Valgrind to detect undefined value errors with bit-precision” paper.
His optimization of memcheck instrumenting a bitwise AND/OR with a constant is clever and simplifies the generated code.
Martin Cermak maintains the Linux Test Program (LTP) valgrind integration, which checks our syscall wrappers work correctly. And he makes sure newer linux syscalls are wrapped. Valgrind 3.27.0 adds support for file_getattr, file_setattr, lsm_get_self_attr, lsm_set_self_attr, lsm_list_modules. And corrects various syscall and ioctl corner cases.
Martin also added Valgrind address space manager support for tracking linux kernel lightweight guard pages, created through madvise (MADV_GUARD_INSTALL).
These guard pages are very low overhead for the kernel because they aren’t tracked as separate VMAs and don’t show up in the process proc maps. But Valgrind does still need to know whether the addresses are accessible. A new –max-guard-pages option controls the memory Valgrind reserves for tracking these pages.
Paul Floyd had more commits than all others combined for this release. Paul takes care of the alternative toolchains, Solaris/illumos, FreeBSD and Darwin/MacOS ports.
Tested Oracle Solaris 11.4, OpenIndiana Hipster and OmniOS.FreeBSD works on both amd64 and arm64, support for 16.0-CURRENT has been added.
Supported MacOS versions, 10.13 (bug fixes), 10.14, 10.15, 11.0 (Intel only), 12.0 (Intel only), 13.0 (Intel only, preliminary). No arm64 support yet.
A lot of code in valgrind 3.27.0 to support MacOS was previously maintained by Louis Brunner out of tree.
There are two new client requests (macros defined in valgrind.h)
VALGRIND_REPLACES_MALLOC Returns 1 if the tool replaces malloc (e.g., memcheck). Returns 0 if the tool does not replace malloc (e.g., cachegrind and callgrind) or if the executable is not running under Valgrind.
VALGRIND_GET_TOOLNAME Get the running tool name as a string. Takes two arguments, an input buffer pointer and the length of that buffer.
[Less]
|
|
Posted
9 months
ago
AI GoF disclaimer: I don’t expect this blog post to contribute to frontier AI gain-of-function research or I would refrain from publishing it. Please consider supporting Doom Debates to improve the quality of discourse around the risks of frontier AI
... [More]
research, and MIRI to try to mitigate the risks.
I have been wanting to experiment with open weights language models on the Talos II.
I have a gfx803 card that I always wanted to use for compute, but it is now out-of-support for ROCm. I have made progress getting a gfx1201 card working on this machine and I wanted to write up all the interesting error messages for reference.
I took a risk and bought a new GPU, the AMD Radeon AI Pro R9700 (ASRock Creator 32GB), without knowing if I could get it working with the Talos II mainboard, which is now seven years old.
First I realized my existing power supply did not have enough free connectors; I needed a new “modular” power supply for the GPU’s new-style 12v-2x6 power connector (which is actually a 16 pin connector, with an array of 2 x 6 main big pins and 4 little pins at the top). That prerequisite project was nerve-racking but successful. Physically, the card fit fine in the mainboard and EATX chassis.
With the latest Debian Trixie kernel driver, the card showed up as a PCIe device in lspci (validating the physical installation) but without displaying the card’s name. I figured the driver was not new enough to recognize the card’s product identifier. I read online that a Debian-derivative’s 6.17 kernel recognized the card on a different CPU architecture, so I temporarily enabled the Debian testing repository, installed linux-image, and rebooted. Now lspci displayed the card’s name, so that was progress. But as a side effect of the kernel upgrade, my virtual machines failed to start up. The libvirtd message was:
qemu-system-ppc64: Can't support 64 kiB guest pages with 4 kiB host pages with this KVM implementation
It turned out Debian ppc64le had changed the default page size from 64KiB to 4KiB. Debian though, with its characteristic flexibility, still provided a 64KiB page-size linux-image variant. With that the virtual machines worked again and the GPU continued to be recognized.
Next I shifted to userspace; the Debian-packaged rocminfo segfaulted early during its initialization, so I looked upstream and found TheRock.
I had lots of initial trouble with TheRock‘s CMake monorepo/subprojects; I am not yet sure what’s up with that, but I suspect it may be ppc64le-specific. That said, I was able to make progress by building individual subprojects one-by-one (this is probably a better approach anyway, at this stage of porting).
Eventually I got amd-llvm bootstrapped, built with a minimal configuration with Trixie‘s gcc 14.2.0. Then I built amd-llvm with itself, in the TheRock-recommended configuration, except for the PowerPC and AMDGPU targets. Next I built rocminfo. It segfaulted in the same place as Debian‘s package! Some debugging resulted in a patch to accommodate ppc64‘s vDSO naming; that eliminated the segault.
Then rocminfo ran and showed both the CPUs as “Agents” 0 and 1. But no sign of the GPU.
I further debugged rocminfo and found it was traversing sysfs, and specifically the AMD Kernel Fusion Driver (kfd) topology. The card did not have an entry there.
I looked at dmesg and noticed:
[...] amdgpu 0033:03:00.0: amdgpu: Error parsing VCRAT
[...] kfd kfd: amdgpu: Error adding device to topology
[...] kfd kfd: amdgpu: Error initializing KFD node
[...] kfd kfd: amdgpu: device 1002:7551 NOT added due to errors
First I tried building and updating a .deb of the linux-firmware from its Git repository, to rule out the parsing error being caused by an outdated binary-only firmware blob. (This is my one disappointment with the ROCm stack; it would be great if the firmware and firmware toolchains were free software.) Rebooting with the new firmware produced the same result.
I looked at the kernel source for that driver, and noticed extra debug printks. Debian helpfully enables the CONFIG_DYNAMIC_DEBUG kernel option. I tried dynamically reloading the amdgpu driver and various PCIe and GPU reset approaches, but I could not get the card back to its after-boot state. I would have to reboot to test each change.
I added amdgpu.dyndbg="+p" to the kernel command line, and that gave me some extra kfd messages; with those I narrowed down the failure to the IO link entry of the Virtual Component Resource Association Table (VCRAT).
I re-reviewed dmesg and, earlier than the parsing error, there was another clue:
[...] amdgpu: IO link not available for non x86 platforms
That message was printed during the creation of the CPU VCRAT (in kfd_create_vcrat_image_cpu). That was the #else branch of a platform-specific #ifdef. kfd_create_vcrat_image_gpu which did not have a corresponding #ifdef; “this could explain the subsequent parsing failure on the VCRAT IO link entry, on ppc64le, a non-x86 platform”, I thought.
It was time to recompile the Linux kernel. Debian makes this surprisingly easy; I followed the official instructions to build a custom kernel .deb with my attempted fix applied to the amdgpu.ko module. Another reboot and no more VCRAT parsing failure message in dmesg. That seemed like more progress. (Perhaps a more proper solution would be to add IO link support to ppc64le upstream; I don’t know if there is an equivalent POWER9 capability, hardware-wise. For my purposes, I have not yet needed an IO link.)
rocminfo still failed though, albeit in a new way:
hsa api call failure at: /TheRock/rocm-systems/projects/rocminfo/rocminfo.cc:1329
Call returned HSA_STATUS_ERROR_OUT_OF_RESOURCES: The runtime failed to allocate the necessary resources. This error may also occur when the core runtime library needs to spawn threads or create internal OS-specific events.
The co-timed dmesg messages were:
[...] amdgpu 0033:03:00.0: amdgpu: bo 00000000bdd46d97 va 0x0ffffffbfe-0x0ffffffc1d conflict with 0x0ffffffc00-0x0ffffffe00
[...] amdgpu: Failed to map VA 0xffffffbfe000 in vm. ret -22
[...] amdgpu: Failed to map bo to gpuvm
I analyzed the section of kernel driver code that generated those messages and noticed the use of AMDGPU_GPU_PAGE_SIZE in range calculations. It is hard-coded to 4096.
I had a hunch that the driver needed the kernel’s page size to match. I did a quick side quest to change all my virtual machines to use 4KiB pages, reconfigured my custom Debian kernel for 4KiB pages, and rebooted again.
Now the virtual machines loaded, and finally rocminfo showed the card’s information!
[...]
*******
Agent 3
*******
Name: gfx1201
Uuid: GPU-6413e1798933ffe0
Marketing Name: AMD Radeon Graphics
[...]
I think Debian‘s decision to use 4KiB pages is sensible, likewise amdgpu‘s assuming 4KiB pages, so I’m happy to have done this reconfiguration. I was only using 64KiB pages because it was the default when I first installed the operating system on the Talos II.
The rest of the process was a grind through TheRock subprojects with a bunch of build failure workarounds. The hardest one was fixing static_assert failures about __bf16, reported by clang, when building hipblaslt:
In file included from /TheRock/rocm-libraries/projects/hipblaslt/tensilelite/include/Tensile/DataTypes.hpp:42:
In file included from /opt/rocm/include/hip/hip_fp8.h:30:
In file included from /opt/rocm/include/hip/amd_detail/amd_hip_fp8.h:67:
/opt/rocm/include/hip/amd_detail/amd_hip_bf16.h:155:15: error: static assertion failed due to
requirement 'sizeof(__bf16) == sizeof(unsigned short)'
155 | static_assert(sizeof(__bf16) == sizeof(unsigned short));
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/rocm/include/hip/amd_detail/amd_hip_bf16.h:155:30: note: expression evaluates to
'0 == 2'
155 | static_assert(sizeof(__bf16) == sizeof(unsigned short));
| ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
Debugging led me to a workaround; this must be a configuration issue with how I built amd-llvm. It needs further investigation, but building amd-llvm with that hack meant that I could successfully build hipblaslt.
The other TheRock dependencies were easier to build; I continued until I had all the dependencies of llama.cpp as-configured for ROCm, per this wiki entry.
At this point llama.cpp built successfully and ran, with good performance!
Here is an example run with a simple prompt:
$ uname -srom
Linux 6.17.13 ppc64le GNU/Linux
$ build/bin/llama-cli -fa 1 -m ~/models/chatgpt-oss-20b/gpt-oss-20b-F16.gguf
LoadLib(libhsa-amd-aqlprofile64.so) failed: libhsa-amd-aqlprofile64.so: cannot open shared object file: No such file or directory
ggml_cuda_init: GGML_CUDA_FORCE_MMQ: no
ggml_cuda_init: GGML_CUDA_FORCE_CUBLAS: no
ggml_cuda_init: found 1 ROCm devices:
Device 0: AMD Radeon Graphics, gfx1201 (0x1201), VMM: no, Wave Size: 32
Loading model...
?? ??
?? ??
?? ?? ???? ???????? ???? ????? ????? ?????
?? ?? ????? ?? ?? ?? ????? ?? ?? ?? ?? ??
?? ?? ????? ?? ?? ?? ????? ?? ????? ????? ?????
?? ??
?? ??
build : b7533-c18428423
model : gpt-oss-20b-F16.gguf
modalities : text
available commands:
/exit or Ctrl+C stop or exit
/regen regenerate the last response
/clear clear the chat history
/read add a text file
> write hello world in common lisp
write hello world in common lisp
<|channel|>analysis<|message|>We need to answer: "write hello world in common lisp". The user wants a "Hello, world" program in Common Lisp. Likely they want code snippet. We should provide simple Common Lisp code: `(print "Hello, World!")` or `(format t "Hello, World~%")`. Provide explanation. Also maybe show how to run with SBCL. Let's produce a response.<|end|><|start|>assistant<|channel|>final<|message|>Here’s a minimal “Hello, World!” program in **Common?Lisp**.
You can copy it into a file (e.g. `hello.lisp`) and run it with any Common?Lisp implementation such as SBCL, CLisp, or CCL.
```lisp
;; hello.lisp
;; Common Lisp "Hello, World!" example
;; Print the string to the default output stream.
(format t "Hello, World!~%")
```
### How to run it
```bash
# Using SBCL
sbcl --script hello.lisp
# Using CLisp
clisp hello.lisp
# Using CCL
ccl hello.lisp
```
### What each part does
- `format` – a versatile printing function.
- `t` – the target output stream (`*standard-output*`).
- `"Hello, World!~%"` – the string to print, where `~%` inserts a newline.
- `--script` (SBCL) or similar options let the interpreter treat the file as a script and exit automatically after execution.
That’s all you need to see “Hello, World!” on your terminal in Common?Lisp!
[ Prompt: 8.7 t/s | Generation: 103.1 t/s ]
>
I am very happy with this result! I will see how stable it is in the coming days.
Now that I have a working proof-of-concept I will try to upstream some patches and ideally make the top-level TheRock build “just work” on ppc64le Debian.
Thank yous:
ROCm and amdgpu teams for making TheRock and the Linux kernel drivers free software, portable and well-documented.
Debian maintainers for a highly-adaptable operating system.
Raptor Computer Systems team for making Talos II future-proof.
#talos-workstation and #debian-ai participants for support and feedback.
Rene Cheng for power supply advice.
Matthew Tegelberg for editing.
[Less]
|
|
Posted
about 1 year
ago
The classpath.org domain expired a couple of days ago and none of the subdomain, like planet, devel, icedtea resolved. Oops. It has been renewed for at least 5 years now.
|
|
Posted
over 1 year
ago
A while ago, I wrote about my work to speed up GDB’s DWARF reader. I thought I’d write again with a few updates.
Sharding
Back then, I wrote: “maybe GDB could trade memory for performance and shard the resulting index and do separate
... [More]
canonicalizations in each worker thread”.
I did end up doing this. Recall that the canonicalization step goes through all the discovered DWARF entries of interest — basically, all the objects in the program that both have a name and are not in a function scope (except in some languages, there is always an exception with DWARF) — and ensures the names are in a normal form. For Ada, this step includes synthesizing the package hierarchy (something that should probably be done for Go as well, except nobody really works on the Go support in GDB).
As an aside, sometime in the last few years we realized that this canonicalization has to be done for C as well, because in C there are multiple spellings of types like “short”. This is also implemented.
Because GDB already reads DWARF CUs in chunks in separate threads, the sharding idea is that we can speed up canonicalization a bit by doing this separately. Previously, GDB combined all the results before processing. Sharding means that lookups are a little more complicated; but it turns out not to be too hard, because the number of shards is typically low (for reasons I haven’t yet investigated, the reader doesn’t scale past 8 threads or so).
Background Reading
The other major change I made is to do all the DWARF reading in the background. This is a trick to make gdb feel faster to users. The basic idea here is that in many cases, gdb does not immediately need the DWARF from the various files. So, if we push the reading into worker threads, maybe it will be completely read in by the time gdb does need it.
This also somewhat benefits the situation where several shared libraries are loaded at once into the inferior. In this case, gdb already defers breakpoint re-setting until all the DWARF has been read — and with this change, all that work will be done in parallel.
Making this work wasn’t entirely straightforward. The main issue here is that gdb determines the initial language and location for “list” (et al) based on the debug info. The patches arrange to set these things lazily as well. I also had to add some rudimentary thread-safety to BFD.
Now, this can be defeated in a few ways. If you have a .gdbinit that sets a breakpoint, then that will cause the familiar pause, because setting a breakpoint will wait for the workers to complete. Or, if you debug a large executable and type very quickly, you may have to wait for the parsing to finish.
However, when it does work, it feels like gdb starts instantly.
[Less]
|
|
Posted
over 1 year
ago
I was curious about DWARF abbrev table efficiency the other day, so I instrumented gdb to record some simple stats about abbrevs: how many are seen, how many duplicates are seen, and how many bytes are used.
Running gdb on itself, I discovered
... [More]
that abbrevs are largely redundant. In particular, removing redundant abbrevs will remove 95% of abbrevs (10238 unique of 230714 total). Similarly the size of the abbrev tables reduces similarly (230714 bytes needed for the de-duplicated abbrevs, compared to 3848152 as seen in the executable).
Something to think about when you consider the effort DWARF puts in to save a single byte in .debug_info, say by using a 1-byte form rather than a uleb.
I was considering having gdb intern abbrevs and pre-reading all abbrevs so that later steps wouldn’t have to re-read these; but interning turns out to be too slow and so re-reading on demand seems like the way to go. [Less]
|
|
Posted
about 3 years
ago
Finally I got around implementing and committing badge support in GNUStep! I think it is one of the fine additions Apple did to the original OpenStep spec While Apple had it since MacOS 10.5, GNUstep didn't and GNUMail had to manage 3 different code
... [More]
paths: One for GNUstep, one for 10.4 Mac and one for 10.5 and later which I implemented myself, since GNUMail originally didn't have it.
First, I with Fred and Richard brought up GNUmail code to match the 10.4 code path, which is generic and just draws the Icon. To do this, I had to change the code, since ImageReps are not writable in GNUstep, so NSCustomImageRep had to be used and it woks both on GNUstep and on Mac.
Later, proper badges support has been added in GNUstep, here the look with GNUMail and with a small test application, which is ported directly from Mac and compiled using xcode buildtool. As we were tried to match certain Apple behaviours, like ellipsis, but also an addition: I made the colors themable.Here a nice screenshot of the two things working with the Sonne theme. Thematic was enhanced to handle the badgeColor with its three shades matching the ring, text and badge background. [Less]
|
|
Posted
over 3 years
ago
Working on most platforms! ArcticFox 42.1 is out.
Here in action with WebGL on MacBook with 10.6 SnowLeopard.
The WebGL test in question has been fixed with 42.0 release.
While here it is running om the CI20 MIPS Board natively!
What is still
... [More]
broken? You can help!
PowerPC is crashy...
SPARC64 crashes on startup
FreeBSD doesn't compile on recent versions anymore
[Less]
|
|
Posted
about 5 years
ago
Four years ago we shifted Java to a strict, time-based release
model with a feature release every six months, update releases every
quarter, and a long-term support (LTS) release every three years.
That change was designed to provide regular
... [More]
, predictable releases to both
developers and enterprises. Developers prefer rapid innovation, and
would like to upgrade frequently so that they can use the latest
features. Enterprises, by contrast, prefer stability and would rather
upgrade every few years so that they can migrate when they are ready.
Over the past four years, Oracle and the OpenJDK Community have
shown that we can execute on that model. We’ve delivered eight
high-quality, production-ready releases containing a broad range of new
features, smaller enhancements, and bug fixes. We’ve also delivered
stable quarterly update releases for both LTS and non-LTS releases.
During this time the wider ecosystem has, in turn, begun to adapt to the
new model. Many popular IDEs, tools, frameworks, and libraries support
the very latest six-month feature release — even when it’s not an LTS
release — shortly after it becomes available.
Developers are excited about the new features — which is great! Many are
frustrated, however, that they cannot use them right away since their
employers are only willing to deploy applications on LTS releases, which
only ship once every three years.
So, let’s ship an LTS release every two years.
This change will give both enterprises, and their developers, more
opportunities to move forward.
It will also increase the attractiveness of the non-LTS feature releases.
Developers working on a new application in a slow-moving enterprise can
start with the latest non-LTS release, upgrade every six months to those
that follow, and know that there will be an LTS release within two years
which their employer can put into production.
(Oracle, for its part, will continue to offer the usual minimum of eight
years of paid support for each LTS release. Other vendors could, of
course, offer different support timelines.)
This proposal will, if accepted and if successful, accelerate the entire
Java ecosystem.
Comments and questions are welcome, either on the OpenJDK general
discussion list (please subscribe to that list in order to
post to it) or on Twitter, with the hashtag #javatrain.
[Less]
|
|
Posted
over 5 years
ago
Logic Pro X is a fantastic application, not only every new release is packed with features, quality plugins and an awesome collection of sounds and loops, but is also very affordable compared to the alternatives, especially considering the fact that
... [More]
Apple has been giving away for free every release so far, if you bought that in 2013, when Logic Pro X was releases, your investment has costed you a whopping 29 € per year! If you live in Hamburg that’s less than a coffee per month, but even if you happen to come from south Italy where coffee still cost about 80 cents it won’t bankrupt you either! Of course, the cost of the Mac to run this beast may have bankrupted you instead but that’s probably a story for another time, isn’t it?
The 10.4 update comes in with an incredible number of features and some welcomed redesign, which I find particularly useful for retina iMacs where the previous versions didn’t exactly feel snappier. I will explore some of those features, in particular the new tempo mapping and the new ARA support (Melodyne anyone?) in future posts as well but I will start in this one with the new Articulations feature.
The term articulations refers to the different ways of playing an instrument, styles like flautando or collegno for example, or the use of different brushes and sticks for drums, but of course there is nothing in stone that says that an articulation switch can’t be used to control a patch on your synth or an a MIDI outboard delay unit – particularly in the way they have been implemented in Logic Pro X – since an articulation switch is just a special key switch or trigger (like a CC command) that causes a change in the setting of the target component in some way. For most Kontakt based libraries this is a key switch on the keyboard outside the playable range of the instrument (a Note On message in MIDI terms).
Articulations are a great way to enable expressivity, especially when using sampled instruments like orchestral ensembles or solo instruments, because it is very likely that players will be using a multitude of different styles during their performances, and in fact composers do add the common styles in the music notation as part of the performance instructions, and so being able to change them dynamically in your MIDI score brings you a little bit closer to reality, beside being an invaluable inspirational tool. To understand better what I mean, just try to do the following without ever changing articulations (in particular the fantastic performance at about 7:08 and over):
Logic has had some form of support for articulation switching for a long time, and of course is always possible to send MIDI CC via automation or to draw key switches on the piano roll editor, but the drawback of this approach is that you need to remember which note for which instrument does what, and if you ever rearrange a section you need to remember to also rearrange the articulation key switch. Also, if the key switch is on the piano roll editor, it will appear in the music sheet if you create one from the MIDI data, but of course, this may be a benefit too if you work with other composers by exchanging said MIDI data. With the release of 10.4 the articulation has received a very useful user interface update and now is easily possible to create articulation sets (and save/recall them as needed), without the need to manually remember and find the actual MIDI note, which is even more useful when you don’t have an 88 keyboard, but a shorter one, at hand!
The feature works by recording the articulation ID for each note, so that you can change, per note, the articulation of any instrument plugin. The mapping between an articulation ID and the actual key switch is done on a dedicated mapping editor, and again, since those are essentially control messages you can signal those changes to anything, including external hardware, and decide that the key switches are send only over a specific MIDI channel, for instance.
Let’s see practically how to use this feature works then, I’ll be using as an example the very beautiful Albion V Tundra from Spitfire Audio, this is a fantastic Kontakt based instrument that offer a full orchestra recorded in a very peculiar way (at the edge of silence as they say), and here is their interface for their high woods section:
You can see in peach colour the articulations available in this instrument, and yes, they don’t really have standard names, at least not all of them.
To add a new articulation, open the inspector view, either pressing the “i” key (assuming the default key commands) or by clicking on the “i” sign on the control bar on a MIDI instrument track. At the bottom of the inspector, panel you will now see an “Articulation Set” entry, like in the following screenshot:
Clicking on this will show a menu with the option to create a new articulation set, or, if you already have one, to edit its parameters, save and do other operations. Let’s start with adding a new one, click on “New”:
This will open an editor in a new window with three tabs named “Switches”, “Articulations” and “Output”. The “Switches” tab is where we can define the actual key switches, this is useful for instruments that don’t have articulations mapped for example, or probably most interestingly can be used to remap the articulation switches in an effort to standardise across multiple libraries. I admit, however, I never used this tab, and clearly the next two are the most interesting for us.
The central tab, “Articulations” is where it is possible to add a number of articulations and associate an ID to them; the ID will be unique for the articulation set and will be used by Logic to decide what message to send for the articulation change, which is then defined in the “Output” tab. Double click on the default name to change it to suit our needs and then add new articulations as necessary. Each library will have different articulations and switches, and it mostly depend on your provider; in the case of Tundra, the Spitfire website contains a list of all the articulations, but you can also find out the names by clicking on the symbols or on the key switch in the Kontakt user interface, those are in order (again for the high woods):
Long – Air
Long – Aleatoric Overblown
Long – Bursts
Long – Doodle Tonguing
Long – Finger Trills
Long – Fltz
Long – Hollow
Long – Mini Cresc
Long – Multiphonics
Long – Overblowing
Long – Overblown
Long – Pulsing Semi Cresc
Long – Slight Bend
Long – Super Air
Long – Vibrato
Short – Overblown
Short – V Short
Short
It is not necessary to follow this order, since at this phase we are only creating the IDs, the important step of the mapping will be done in the “Output” tab in a second. However, it certainly help to keep consistency, as this is all a very manual and boring step and if you enter things out of order it will be easier to mess things up. Now on to the Output tab:
With the full list of articulation IDs we can now proceed to the mapping. Spitfire Audio mention a “standard” for their articulations, this is UACC, but I don’t think this is an actual real standard, I believe what they actually mean is that this is a convention used in all of their own libraries. I do find this very useful however and I hope other providers will conform to this convention too, we will certainly do for our libraries where this is applicable. I recommend to check out their support page too to see how to configure specifically for Spitfire Audio libraries and UACC.
The first steps are basically the common to most libraries, in the “Type” field of the “Output” page we need to select the type of MIDI message that the instrument accept for the articulation change. In our case, we will set the type to “Note On”, however Note Off, Poly Pressure, Controller, Program, Pressure and Pitch Bend are also available. The “Channel” field can be left blank here, this is to restrict to a specific MIDI channel (up to 16 channels, from 0 to 15) the articulation switch message, for example if an instrument supports a full 88 keys playable range on Channel 1 but allows for articulation changes via Note On on Channel 2.
The “Selector” in this case is the note identifier. For Tundra the first identifier is C-2, the second is C#-2 and so on in ascending order, or you can use the UACC as defined in the Tundra manual which means setting the note to the same value for each articulation. The final filed is the “Value”, you can leave this blank too or just fill it up with 0, it doesn’t really matter in this case since we are using different notes, however if we were using the UACC convention mentioned above, or if your library uses for some reason the same note for two separate articulations, we would then need a different “Value” to differentiate (say 0 and 127, for example).
This is it! Once you have filled up all the details, you should have the articulations appear in the “articulations” drop down control in the piano roll, as well as at the top of the instrument plugin window:
When you play, you can actively change the articulation per note, this means the data for the articulation switch will be stored in the metadata for the note, however as far as I can see it is not exported to the MIDI track, it is nevertheless noted in score editor if you add the proper symbol in the “Articulations” tab; also, I found out that this last drop down menu is only filled with the names (as opposed to just the IDs) when you are on an active MIDI region, I think that this may be a bug and will be fixed (hopefully) in a future update, but in case you only see numbers and not names, try to create an empty MIDI region first and select it in the track lane.
The final step is to save this articulation set, this is once again done in the Inspector, selecting “Save As …” from the drop down menu. An added bonus that I suggest is to also save the full instrument as a library patch. This way all the settings, including the articulation set, will reappear next time you load the instrument, as some form of mini template (assuming you will be using this library more than once, in the case of Tundra I certainly would do!): just press “y” or click on the library button on the control bar, and press “save” at the bottom on this panel, this will create a user preset that can be recalled any time.
That’s all for today! [Less]
|