Tom Almeida

Tom Almeida's website

On the experience of good audio

I recently started listening to music with my Sennheiser 6XXs after around six months of using nothing but earbuds (Sennheiser Momentums and Momentum True Wirelesses).

Now, I love the sound on my earbuds, especially compared to the many other earbuds that I've tried, something about Sennheiser's audio engineering just works particularly well for my musical tastes. I had found, however, that as time went on I used my earbuds less and less, and was generally more happy to listen to music and podcasts using nothing but the speakers of the device they're playing on. Part of the reason for this is that my Pixel 5 doesn't have a headphone jack (although I do have wireless earbuds) and my experience of bluetooth audio on my desktop and laptop (regardless of operating system) has left a lot to be desired, so the easiest common ground was just the speakers.

Since I've restarted my use of my Sennheiser 6XXs, I've spent the days doing nothing but listening to music for the sake of the audio experience, which I never really did with the various earbuds. The songs I'm listening to I have heard before, but with the better audio quality and dynamic range comes a whole new range of experience that I simply didn't have access to before - and its hard to quantify how much better it is.

I think that's part of the reason that "audio quality" is so difficult to sell - it's an almost unquantifiable metric that is both incredibly subjective and extremely expensive. High quality audio gear sells for thousands of dollars, and the curve of how much more needs to be invested for a substantial difference is such that gear that is "good enough" sells for less than a hundred dollars. How on earth could you convince anyone that hasn't already invested into audio gear that it is worth it?

I'm certainly going to try to start using my headphones more, and that's also going to involve a level of investment and care from me. My house gets extremely dusty (especially in the summer) - which is part of the reason that I put my headphones away in the first place - and so I'll have to figure out a way to make using them both easy and largely dust proof.


Moving to zsh

I recently transitioned away from the ion shell to zsh, and I figured it might be a good idea to float some of the advantages and disadvantages that I've found during this time.


  1. Mostly POSIX compliant.
    I'll touch on this more later, but in general the ability have portable scripts that work across systems and shells has been incredibly useful - especially as I expand the number of machines I use and prepare to start working after finishing my masters. For those wondering, ion is explicitly not POSIX compliant.
  2. I can reclaim the @ symbol and not worry as much about quoting ssh.
    This is a part of ion's lack of POSIX compliance, and it claims the @ sigil for use in array specific functions and variables. I've generally found throughout my use of ion that I use array variables much less than I do the @ sigil, and getting it back for ssh, git and the like has been a major boon.
    (It isn't so much that I'm against arrays per say, just that I'd prefer that it somehow reused a symbol that's already typically used by shells instead of nomming another character)
  3. Its much easier to get setup on new computers.
    I've just put Alpine Linux on a Raspberry Pi 2B, and have begun migrating some recurring tasks to its crontab. Last time I checked, ion still had some issues building on arm-based platforms, so unfortunately I can't quite port my dotfiles to it. I've also recently completed my masters and will begin working in the middle of January. Knowing the company that I'm working for, there's a chance that I might be getting one of the new-fangled Apple Silicon Macs, and at the time of writing this post, there are still issues with porting even just the Rust compiler to the new platform.
  4. Completion.
    Oh boy this is a big one. ion "has" completion, in that you can tab complete files and commands. What it doesn't have - however - is the ability to tab-complete arguments (which can be an absolute life-saver) nor other more specific completions such as man pages.


  1. Slower start times.
    I open a lot of shell prompts - anyone who basically lives in the terminal and incessantly uses tmux does. Something that I've definitely noticed is that the time it takes to open a new window or prompt is much lower with ion than it is with zsh - and indeed hyperfine backs this up. An invocation of hyperfine 'zsh -i -c ". ~/.zshrc; exit"' takes around 70ms (with approximately half of that being completion pre-processing), whilst running hyperfine 'ion -i -c "source ~/.config/ion/initrc; exit"' only takes around 20ms. And that's despite my ion config doing more than zsh's as well as not being as well optimised.
  2. Visible history completion.
    One of my favourite features of ion is that (similar to fish) it shows you the most recent matching command in your prompt. As of yet, I haven't been able to figure out a way enable a similar behaviour in zsh without loading an extension module, which has me weary due to the potential additional startup latency I might end up with.


I think I'm probably going to stick with zsh until I find a better shell to move to. Something like mrsh seems like a great idea of something to move to eventually, especially as dash will likely never implement any form of completion, whilst imrsh names good completion as one of its goals.

Interestingly, one of ion's major advertised features - its inbuilt data structures - are actually something that I've found myself rarely using, especially whilst actually at the shell. I usually find that should a hashmap or the like be required, then that script should probably be converted to a language like Python, even if only for clarity and the rich inbuilt libraries.


The different approaches between `emacs` and `vim` packages

I recently tried using emacs for the first time in many years (the last time I used emacs was back in early 2017, and I moved to using vim later that year). Many of my colleagues at my last internship use emacs - there was even an internal minor mode for editing and using many of the internal tools - and a number of friends at university are also emacs evangelists, so I thought that it'd be a good idea to re-acquaint myself with the editor that I left behind.

Long story short - I've decided to stick with neovim. There's actually a bunch of reasons why (which I can probably go into at a later date), but my brief foray back into the world of emacs showed me an interesting difference in philosophy between emacs and vim packages.

As someone who (of course) wants to use vim bindings in every text editor that I use, I of course installed evil-mode, the vim compatibility layer for emacs. This went along quite swimmingly until I had to install other packages, all because they all automatically overrode keybinds.

This was a pattern that tended to find throughout my emacs experience. Packages create their own major or minor mode, and then provide a number of key-binds within that mode to interface with its functionality - which can cause a lot of problems for me when I've remapped a good number of the keys because I don't use a QWERTY keyboard.

It's become like a game for me. See how many plugins I can find that all try to override the same key-bind.

In my experience, vim packages have the exact opposite approach - although I will fully admit to not using very many packages. coc.nvim, for example, doesn't set any keybinds and instead requires the user to assign their own binds to the functions that it provides. FZF does exactly the same thing, as does vista.vim.

This has actually been really surprising to me, as I would have likely expected the exact opposite. I often hear emacs talked about as being an "elisp interpreter with an editor attached" - which to me suggests that the primary focus of emacs would be on elisp functions - whereas vim's major selling point is its excellent keybindings.

I think that if emacs packages had taken a similar approach to what vim packages seem to - that I'd have expected them to take - then I'd almost certainly switch to emacs for the additional flexibility of having the power of lisp at my fingertips. As it is, however, it would take far too much work every time I install a package for me to want to move.


Tracking myself

Partly inspired by Julian Lehr's quantified self, I'm planning on trying to track myself. I don't expect that I'll actually start on this for a while, as there are a number of tools I have to figure out before I can properly get into the swing of things, but I figured that it'd be worth writing down my reasons why I want to do this. In future weeks, I'll cover how I'm building the tools to let me track myself.

I'm generally a pretty privacy-focused person. Any applications that I use always have telemetry turned off, my social media is basically whisper quiet unless its via private messages, and I even borrowed a laptop from the university so I wouldn't have to use exam software that required root privileges on my own hardware.
Tracking myself - and posting it on this blog like Julian Lehr does - seems to run pretty contrary to all sorts of privacy principles. So why on earth would I want to do it?

I've always sort of considered myself a numbers guy. In primary school (in Australia, that's ages 4-12), I was the "math guy" in the class, and had by far the best marks in maths in my school (although I don't think I even made the top quartile in high school), and have always found maths that I can apply to be fun and interesting. It's part of the reason that I got into programming in the first place.

I'm also generally well convinced by numbers that are put before me in order to inspire some continued positive action. Watching the numbers on the weights at the gym go up, how good I felt as I ran 5km slightly faster than before, and my weight go down (even if only a bit) has encouraged me to regularly exercise far more than the nebulas "it's good for you" that my parents always told me throughout my teenage years.

As such, I am somewhat convinced that tracking myself - and watching trends for various metrics of how my time is spent - will help me be able to narrow down and improve things that in my life. Perhaps I can see if I've spent too long on a particular weight at the gym, and should go to the next weight up. Maybe I can spot transport routes that would be slightly more efficient than what I currently have. I could even find that I spend half my time doing nothing useful at all, and thus need to come up with strategies to improve productivity.

There's an extent to which doing this is good for my privacy as well. By tracking myself, I will be able to get a better understanding of what sort of data companies have on me. My smart-watch (a Garmin VivoActive 4) will probably be used for most of the data, and frankly the amount of data that it can/does have on me is slightly terrifying - especially now that I've gone through what I can get from Garmin's API. I'll be able to go digging to see what Amazon has on me (Kindle/Audible), what Google has figured out (Android/Google Assistant), and how Spotify could figure me out. In the process of tracking myself, I'll become more aware of how others can track me too.

In addition, as long as my data isn't too fine-grained, privacy shouldn't be too much of an issue. I don't plan on writing detailed logs of exactly where I've been - if my house shows up anywhere, then you know that my data collection has gone too far. I don't even plan on sharing any GPS-type metrics at all, save what city I'm in.

I imagine that it might take me some time to be able to even get the right sort of data for any useful analysis, and whilst I don't really know what I might find out, but I'm excited to see!


The changing scope of my research

I started on my Masters research project back in March, and the progress of both the project itself and how I've felt about it since that time has been somewhat interesting.

For some context, the codebase that I've been contributing to as a part of my research is approximately 50 thousand lines of code long, and the PhD thesis that much of my work is based on is 204 pages long (as I've previously mentioned), so even getting a grasp on what exactly research project entailed took quite a long time.

Whilst students do pick their own research projects (and I selected the research team that I joined), the projects themselves are selected by the supervisors and then advertised. This unfortunately meant that whilst my supervisor had somewhat of a grasp on the project that I had selected, I myself had basically no clue. I have no background in physics (the most that I've done is high school physics, and definitely nothing to do with gravitational waves), so even understanding how everything fit together to do what it was intended to do was incredibly difficult - and it was made worse by the fact that the codebase has very few comments.

As such, a large part of my time up until now was simply me trying to get up to speed. I did a complexity analysis of a part of the codebase, with the sole purpose of attempting to understand the small section which that analysis encompassed. It definitely worked, but as time has continued and I've gotten a better idea of how everything fits together, it turned out that the section of code I analysed actually has little to do with my main part of my research - so all that work was for nothing.

To me, it always felt like the scope of my project was changing, even though in actually that scope never changed. More files moved into what felt like the scope of my project at exactly the same time other files were suddenly discounted. I went from expecting my entire project to be in C and CUDA to it being in only Python, and then back again. Most of this change was because of my understanding of what exactly my project entailed didn't fully mature until I had a full understanding of how everything was put together, and that understanding was vital to figuring out how exactly I was meant to go about solving the problem I was given.

I think that this is likely the case for lots of people in more theoretical research than my more implementation-focused research. As your understanding of the thing you are researching increases, the more likely it is that things that you may have previously thought important suddenly become irrelevant, and ideas that only seemed to be tangential are suddenly vital - and this seems to be the pattern of any complex long-term project.

I think that this is part of the reason why senior (or at least experienced) software engineers are so coveted. Whilst they may not be burning many story points for their own managers to see, they have enough experience with the codebase and exposure to different ways to solve problems to be able to make the scope for other people much smaller, and their entire team more efficient because of it. It's also why there's always an "on-boarding" period for new employees, so they are able to have a rudimentary understanding of the potential scopes of any problems they encounter.

With this in mind, I think there's a few items that I think massively help with preventing the sort of scope creep that I've experienced. In many ways these are probably just some more common sense general guidelines, and can probably be found in any "programming processes" textbook, but will still be helpful to list here.

Have useful comments and documentation

The codebase I've been working on has very very few comments, and those that it does have are generally just commenting out old versions of the code. This means that almost all the sources for how things work need to come from outside the codebase itself, and are usually one of two things - people or papers (as in peer-reviewed papers).

The massive downside to this is that if you want to find out how one very specific part of the codebase works, you either need to have someone who hasn't worked on that part of the code for potentially many years sit down and work through it with you, or you need to trawl one of 50 research papers in the hope that it mentions the specific function that you're looking for (and spoiler alert, chances are that none of them do). Having no useful comments and no useful documentation means that the process of on-boarding is incredibly time consuming and takes valuable work hours away from people that know the codebase well in order to explain the minutia of the code to the newcomers.

This is something that I've attempted to rectify with my research project - every addition has been commented on in its function and sometimes how/why it works. My hope is that the next person that needs to work on the same area of code would be able to make use of the work I've already done and not need to retrace my steps, but unfortunately the entire codebase is so massive in comparison to the scope of my work that the chance of any overlap is minute.

Have useful commit messages

This is another area that definitely needed improving. Before I began on this research project, commit messages often looked like this:

postcoh.c: fix a bug for output trigger->ifos when the ifos are LV

or change Virgo quality bits with latest suggestion

For the first one, what was the bug? How does this change fix it? Or for the second one, what's the "latest suggestion"? What problem does it solve?

The commit messages that are in the repository are as useful documentation as the comments in the code themselves in many cases. If you can clearly articulate the reasoning behind changes, the problems that they solve and perhaps possible alternatives, then it makes understanding the progression of the codebase significantly easier - and running git blame actually would return useful information.

When it comes to writing commit messages, I try to follow this excellent blog post on commit messages, which suggests that you should try to use a text body of a commit message whenever possible to explain "what" and "why" the change has been made. There's also been a push from some of the other members of the research team to follow similar guidelines. The project goes under an external code review every 1.5 years or so, and being able to clearly show the reasoning for changes is something that helps with the efficiency of that review in addition to helping new team members understand what they're looking at.

Provide early and timely feedback to direct efforts

One of the reasons why the area of code that I did a complexity analysis on ended up being irrelevant for my project is because I had absolutely no idea what I was being asked to do in my project. I'd written a project proposal, had talked to my supervisors about doing a complexity analysis, did the complexity analysis, and the only feedback that I got the entire time was "no one has done a complexity analysis for this type of project before, I look forward to the results!". Whilst this was nice to hear, and the complexity analysis was fun to do, it felt all for naught when I realised that it wasn't really under the purview of my project. The many hours that I spent pouring over that part of the code, trying to understand every part and running some of my own benchmarks and performance analysis ended up being for something entirely irrelevant.

I don't think that this is entirely the fault of my supervisors - a large part of it also falls on to me for not clarifying what exactly was being asked of me, especially as I didn't really understand how the whole project fit together at the time - but some early feedback to properly direct my efforts into something that was actually relevant would have allowed me to finish my project significantly earlier than it was, and possibly even have time to extend the project.


I know I've spent the last thousand or so words complaining about things in my research project, but I have genuinely enjoyed my time doing research this year. The value of good comments and documentation, commit messages and the role of feedback in directing efforts are lessons that I will take onto my future projects and work to ensure that the feeling of massively changing scope in a static project does not happen again to me, nor anyone else.