12 Steps to OS X Acceptance for the Reluctant Windows Expatriate by Daniel Ehrman

Jesus Christ pleads to Bill Gates at the Procession to Calvary.

No…there aren't really 12 steps. But sometimes coming from a Windows-and-Linux-only lifestyle full-bore into Macworld can feel as though it must come with such a process. So after using OS X for nearly 3 months, I've accumulated my list of tweaks that make this operating system, for me, something I can work with….

1. Red X Quits

For whatever reason, Apple decided that when a person sees this

the appropriate 21st-century interpretation is, "Hey, I'd love to hang out, but now's just not a good time. Mind sticking around for a while in the other room?" Click this button, and the OS will close the window but not the program itself.

The fix: As a Windows user, you know damn well what this little button means, and so you're going to need RedQuits to keep yourself from going crazy trying to figure out why ⌘ - Tab is showing 35 programs open when you only see 3.

2. Change Finder preferences to search in current folder

Ever lost something but you're pretty sure you know where you left itsay your car? The first place you start looking is…everywhere else, right?

For reasons I can't imagine, in implementing the search function in the Finder (i.e. Windows Explorer minus usability), Apple substituted unpredictability for context awareness. Try navigating to a folder, then search for a file and see what happens. Enjoy the wait while it scans all of your files.

The fix: In Finder, navigate to Finder->Preferences->Advanced, and change the Finder to "Search the Current Folder."

Search the Current Folder.png


3. HyperDock

For all its cute features, OS X seems to struggle in one of the most important areas of productivitywindows management. In OS X, all of the windows owned by a given app are grouped into a single icon. So in the common case of, say, having several Chrome windows open, the only way of getting back to one hidden in the background is to right click the dock icon and select the (text-only) title of the window you want.

The fix: install Hyperdock to get the Windows-style windows previews you know and love:

Note: the black and white look is an effect of my own retro theme and not Hyperdock itself.

4. Hyperdock (again)

Windows managementagain. OS X has no out-of-the-box support for snapping windows to the edges of the screen like Windows does. And as anyone knows, resizing windows manually can be a tremendous pain if done on a continuous basis.

The fix: Fortunately, if you've already completed Step 3, you're covered. In addition to providing Windows previews, Hyperdock also supports the Windows-like "Aero Snap" feature, which will snap your windows to edges (as well as maximize them if dragged to the top) via dragging and/or shortcut keys.

5. Alfred

One of the features I truly appreciate in OS X is Spotlight. For this one, there isn't so much a fix as their is room for improvement. At its core, Spotlight is really just an easily accessible file search box. (And it does a great job at that.)

But Alfred takes this concept so much further. A Spotlight-like feature, which can be accessed with ⌥ - Space, Alfred adds web search and math to the typical file search functionality. I think of it like an instant Google that has access to your Mac's disk too (in a non-creepy way):

Alfred math.png

6. Auto-hide the dock

I've found that the Dock feels like it takes up more space than it deserves. I think part of the cause is that, whereas in Windows the full screen-width task bar gives the impression of a clear lower boundary, the OS X Dock doesn't stretch to the edges of the screen. The result is that a Mac's windows will only consume space up to the top of Dock and leave inaccessible negative space on the bottom left and right corners.

The fix: Right-click an empty space on the Dock to open Dock Preferences, and select "Automatically hide and show the Dock." 

7. Learn the new hotkeys

There's software out there that will help you remap shortcut keys to those that you're used to from your former life as a Windows user (e.g. Enter to open a selected file), but it helps to know the keys that Apples wants you to use out of the box:

  1. Cut and paste a file: ⌘ - C, then  - ⌥ - V

  2. Delete a file: ⌘ Delete (Backspace)

  3. Open a file: ⌘ - O

Those seem to be the most annoying to get used to; for the rest, do as you would do with any new software, and check out the documentation.


And that about does it. Please leave comments and suggestions about what you find to be the most essential tweaks to making your Mac as useful as possible!

How To Give Your Mac Some Mid-80's Style by Daniel Ehrman

Black and white icon pack + tweaked window stylings = 2.7GHz of 1980's awesomeness

I've never been a huge Mac fan (sorry, guys). But I've long been obsessed with vintage computers, and I keep a collection of 4 old (1980-1997) Apple computers in storage—hopefully some day on display.

So that's why when I was given my first Macbook Pro at my new job, I couldn't wait to make it feel a little more familiar. Fortunately, I found a great start with Ben Vessey's "Mac OS (Old School)" icon pack.

Unfortunately, most of Ben's work just covers some basic Mac app icons, so I extended the look by adding 15 more "engineery" icons—Eclipse, Android Studio, Emacs, etc.—and by building my own window and menu theme to yield a (nearly) complete Macintosh immersion.

For those of you interested in giving it a shot, here are the complete steps:

1. Initial setup

2. Install the icons

Navigate to the icon pack you downloaded earlier, and drag and drop the desired icons over their respective applications in LiteIcon. Apply changes when done.

3. Update the desktop

  1. Right click the desktop and select Change Desktop Background...
  2. Click the + icon to add the folder you extracted from the zip file.
  3. Click on the only image that appears in the main window, and select Tile as the display mode.

4. Tweak the windows

  1. Open Flavours and click Get More...
  2. Search for "macintosh classic" (without the quotes); double click on the Macintosh Classic B&W theme; and click Apply.
  3. Uncheck Menu Image and Desktop, and click Apply.
  4. You will be prompted to log out to apply your changes. Do as it says.

How do I undo my changes (revert to defaults)?

  1. To revert back to the default icons, open LiteIcon, select the Tools drop-down menu, and click Restore All System Icons...
  2. (Desktop background—no explanation needed)
  3. To restore the default windows theme, simply open Flavours and click the on/off toggle at the top right of the window.

Issues (cosmetic only)

  • Chrome, and potentially some other strange programs, use their own custom window borders, and thus their windows look...funky with the theme. I've kind of learned to deal with it, but I'd be lying if I said it didn't annoy me.
  • The classic stripe look you see in the screenshots is achieved in part by placing a white rectangle in the middle of the window. Unfortunately, there's no way to resize this rectangle to fit the window text, so I picked a size of roughly half of the window width to try to work for about 99% of the use cases. Occasionally though, you may have a window with a really long title that simply can't fit in that white box. To accommodate this, I've set the opacity of the title bar stripes to 50% so that you can still read the whole title. But yes, it will be annoying if/when you come across a long title (hopefully rarely).
  • There are some inconsistencies between the icons (e.g. some circles are drawn slightly different than others). I wasn't as careful as I should've been, but if anyone has any serious interest in using the icons, I'd be more than happy to clean them up for you. Again, I'd be lying if I said this didn't bother me.

A Millennial's Outlook on the Changing Market for Tech Jobs by Daniel Ehrman

NOTE: I took a break from writing for 3 months to focus on a big move for a new job on the other side of the country. On the off-chance that someone was actually reading this blog, I extend my apology and thank you for your patience....


First off, I want to say that I don't like calling myself a millennial because of the negative connotation it often bears: the word tends to evoke imagery of trophy-laden kids whose upbringing of unconditional encouragement and positive feedback is now leaving thousands of employers feeling like workplace parents (or worse, babysitters). But for better or for worse, that's what I am--born in '88, entering the new-graduate job market in 2012, and now a computer engineer 2 years out of school moving onto his next job.

So what does this (largely uninformed) millennial have to say about the job landscape for new (tech) grads of the 21st century? Well, let's take a look at 5 key concerns that we're thinking about as we join this new workforce from the ground floor.


1. "I'm Feeling Lucky"


The scope of knowledge now contained across the entire tech industry is so overwhelming that college is more of a sampler of the "real world" than anything else. We study everything from transistor-based amplifier design to SQL databases. So when we finally make it to that on-campus career fair, we're pretty much taking a shot in the dark. Internships tend to make the decision a little easier, but after just a few brief work experiences, it's still tough to hit the target spot on. Especially in this modern climate of seemingly endless opportunities, it's difficult to expect your millennial employees to truly know what they want...which brings me to my second point....

2. The Dream Job

We want that dream job. We've grown up being told--truthfully or not--that we're special and that we deserve the best. This of course creates complications for both the employee and the employer. From our perspective, there's no "dream job handbook," and so the best we can do is guess and reassess. From the employer's perspective, it's a big leap of faith. You're hoping you've snagged that one diehard-loyal super-energetic rockstar game-changer who's in it for the long haul.

But the truth is that no company today truly expects that. It's old news that millennials are hard to please, and they have no problem moving on if their expectations aren't fully met. (Note: I am not endorsing this job-hopper mentality. For further reading, it's worth checking out this interesting, and controversial, take on the issue from entrepreneur and venture capitalist Mark Suster.)

The trouble with this dream-job expectation though is that at some point, life happens (marriage, kids, etc.). Eventually, life trumps work, and at that point, there's not much room left for pivoting. So for us millennials, this creates a very real need to find the perfect career before we've exhausted the runway. We've seen our parents' midlife crises, and we're working (perhaps naively) to avoid it.

3. Specialization and Commoditization

Although we may have thought we were special being able to write code in middle school, as soon as we got to college, we discovered that there are many, many people who can do what we do--and do it better. And the competition is even more real when we consider the rapidly expanding workforce in newly industrialized countries. Add to that the fact that this generation is highly mobile, and you have a truly massive pool of talent to pick from--and compete with.

This commoditization of basic programming skills means that rather than looking for good programmers, big-name companies like Google and Facebook are looking for quirky, creative candidates who founded their school's unicycling club or recorded an album of original yodling songs. Writing stellar code just gets you past the filter; it's not going to get you the interview (let alone the job). In response, we have to specialize to prove our worth--to build an arsenal of skills and hobbies that make us truly unique and valuable.

4. Estimating an Education's Worth

There is a remarkable trend unfolding right now in the tech industry. More and more, companies are posting job descriptions which list every conceivable major (e.g. "BS, MS, PhD") or in some cases list no degree requirement at all, opting instead for "applicable experience."

Tech companies know that an MS or a PhD alone does not necessarily yield a more creative thinker than the BS candidate. However, this message is confusing to those of us who have grown up in the era of dime-a-dozen degrees, hearing that a post-graduate education is an effective means of differentiating yourself from the competition.

So what do we do? Stay in school or enter the real world, perhaps prematurely? Fortunately, there's a third choice: online distance education (of which I am a user). More than ever now, people have the means to continue their education as they work, perhaps ushering a new phrase into our lexicon: work-school-life balance.

But is it worth it?

Technically, employees holding master's degrees in the field of computer engineering are earning incrementally more than those without, so even if the company doesn't foot the bill, the cost of the education could be amortized over the course of 5 to 10 years at a higher salary.

But more importantly, the standards are changing. Other than the fact that a bachelor's degree is almost universally held among applicants in the field, prestigious universities are now distributing course material to thousands of remote students for free. It's only a matter of time before a master's degree is the new standard for passing the automated resume filters.

5. Joe Startup vs. Established Player

Recall: millennials are the best (or so they've been told), and with that mentality comes some bit of narcissism--believing that we are destined to do truly great things with our lives. So it stands to reason that millennials are perhaps more likely than prior generations to seek out roles in relatively smaller organizations where there is a lot of high-priority visible work to be done.

The democratization of software publishing within the last few years has made these kinds of opportunities even more attainable. As the barriers of entry to starting your own company have reduced to little more than pushing your app to the Google Play Store, Silicon Valley and similar tech hubs have been exploding with fresh, viable, exciting jobs for thousands of recent grads.

While there is no universal algorithm for making the choice--startup or big guy--it's becoming clear that the sentiment among young people is changing quickly. Whereas merely 5 years ago, Apple may have been the coolest place in town, today, they're somewhat of a bore among the new class of engineers. And it's not just Apple: one colleague of mine described Google as "the Walmart of Silicon Valley." "So many people work there," he said, "it's just not cool anymore."


So what?

So what does this all mean? Well, in short, we have a rapidly expanding job market being filled with a dramatically different generation of engineers. We're also experiencing somewhat of a tech bubble at the moment wherein multi-billion dollar valuations are enabling small companies to offer their young adult employees extravagant benefits, the likes of which their parents never could have imagined.

Yet, when the bubble has popped, and the benefits have lost their luster, what will remain is a vast pool of millennial techies remembering again what matters most--the work, the challenge, and the joy of creation.

11 Must-Haves for Every Power Programmer by Daniel Ehrman

As developers, programmers, engineers—whatever you want to call us—we spend a lot of time programming. And seeing as we spend more waking hours with our editors than we do with our families, it's important that we take a close look at that experience and make sure that we're getting the most out of it that we can.

DISCLAIMER: This post is targeted at the Emacs crowd. If you're not an Emacs user, I hope that you can at least still learn a thing or two from this list and maybe find a way of achieving the same functionality in your own editor. If this list happens to provoke an interest in switching over, great. But this post is not intended to persuade readers one way or the other—simply to share some heavily used features that can make those hours away from home a little bit happier.

In Emacs, the customization comes from your ~/.emacs configuration file. Emacs users spend years building up these config files, and a senior developer's .emacs file can be a highly sought-after resource. (One of my last correspondences with a departing engineer consisted of "Good luck," and "Can I get the path to your .emacs?") With that in mind, I've listed some useful key bindings to pass on where applicable.

Figure 1: Evidence of generational learning through .emacs configuration files.

Figure 1: Evidence of generational learning through .emacs configuration files.


1. goto-line

Even the superhuman developer likely spends at least half of his time debugging code. And although some IDEs will highlight the failing line, it's not always a compiler that's flagging a problem. Whether it's grepping through a list of files or simply looking for a problematic section of code that someone brought to your attention, the "goto-line" operation is all too frequent.

(define-key global-map (kbd "M-g l") 'goto-line)

2. revert-buffer

Ever re-run a program after making a bug fix? How about 20 times a day? Having a quick way to reload a run-time log (or any frequently changing file) can be a huge time-saver.

(global-set-key (kbd "C-S-r") 'revert-buffer)

3. The macro

Serious developer know well the power of the macro. Non-power programmers cringe at the thought of it. The concept of the macro tends to evoke a sense of heavy up-front cost that's only useful in the rarest, most tedious circumstances. But in a given day, a few good macros may save you an hour of work. (If your managers knew how much time you waste by not using macros, they would insist on it!)

We could spend pages discussing the use cases of macros, but suffice it to say that for pretty much any task which takes more than 10 seconds and will be repeated at least 10 times in one sitting, you're better off using a macro. In Emacs, this couldn't be easier:

  1. Start recording: C-x (
  2. Do whatever you want to repeat, using regular expressions and generic operations wherever possible.
  3. End recording: C-x )
  4. Run the macro n times: C-u n C-x e

This whole process creates a throwaway macro that you can keep until you create a new one. If, however, you decide that it's generic and useful enough to save for later, this bit of config code will help:

(defun save-macro (name)                  
    "save a macro. Take a name as argument
     and save the last defined macro under 
     this name at the end of your .emacs"
     (interactive "SName of the macro :")  ; ask for the name of the macro    
     (name-last-kbd-macro name)            ; use this name for the macro    
     (find-file user-init-file)            ; open ~/.emacs or other user init file 
     (goto-char (point-max))               ; go to the end of the .emacs
     (newline)                             ; insert a newline
     (insert-kbd-macro name)               ; copy the macro 
     (newline)                             ; insert a newline
     (switch-to-buffer nil))               ; return to the initial buffer

4. increment-number-at-point

The true Emacs user will look at an incredibly tedious task like generating repeating blocks of code with sequentially incrementing numbers with enthusiasm! When recording the macro, simply place the cursor over the applicable number and increment-number-at-point:

(defun increment-number-at-point ()
      (skip-chars-backward "0123456789")
      (or (looking-at "[0123456789]+")
          (error "No number at point"))
      (replace-match (number-to-string (1+ (string-to-number (match-string 0))))))
(global-set-key (kbd "C-c +") 'increment-number-at-point)

Note that the same can be achieved for hexadecimal numbers as well: http://www.emacswiki.org/emacs/IncrementNumber

5. ansi-term

This one is my personal favorite. Couple the macro with a terminal embedded in your editor, and you're poised to be the most powerful developer in the office. Once your terminal is contained within your editor (and once you've spawned several simultaneous terminals in there too), you'll realize you no longer have reason to live outside the editor (though your spouse may disagree).

My typical development environment is a split window with code on one side and a terminal on the other (all within a single Emacs instance). Using the "C-x o" key binding I can then quickly switch between editing and performing the usual command line operations in Linux.

Like I said, this is where the beauty of Emacs truly starts to come together. Ever had a bunch of errors dumped to the terminal that you need to cross reference with your code to apply a series of fixes? Automate that! Suppose that the compiler is complaining about a bunch of variables in our code not being declared yet. Easy:

  1. In the terminal buffer grep for "Error:"
  2. Use a regex to search for the variable name, and copy it.
  3. Switch over to the code buffer with C-x o.
  4. Declare the variable, and make a new line.
  5. Switch back to the terminal.
  6. Rinse and repeat.

Note that in Emacs, there are a variety of terminal types you can use. I prefer the ansi-term mode due to its smooth support of telnet, but I'm sure there are ways of customizing the other terminals (e.g. shell-mode) to behave in the same way as my beloved ansi-term.

6. rename-buffer

Since I'm typically working on five different tasks at once, it helps to have named buffers to keep track of things. This becomes even more useful when I want to switch to a specific terminal with a specific environment in a specific directory:

M-x rename-buffer

Emacs will then prompt you for a new name for the buffer. Then getting to the file/terminal you need doesn't involve sifting through tens of windows and tabs. Simply…

C-x b <name of buffer>

Note also that if you don't provide the name of the buffer, you can simply press RETURN to view a searchable list of open buffers, which helps if you can't remember what a file was called. This is also useful if you want to, say, have a macro quickly close all buffers matching a given regex.

7. Auto indent

Ever carefully align every block of code to paint your file like a Georges Seurat? If so, you're wasting your time. Even with a preexisting poorly formatted file from another developer, there's no need to do any heavy lifting. Kick back and let your editor do it for you. In Emacs simply highlight the lines you want and…



8. upcase/downcase-region

Ever need to change a bunch of variables to constants or vice versa? In most circumstances, this involves changing the case, and Emacs makes this very easy for us. Simply select the applicable text and "C-x-u" to convert to uppercase or "C-x-l" to convert to lowercase. You'll also need to add these lines to your .emacs:

(put 'downcase-region 'disabled nil)
(put 'upcase-region 'disabled nil)

One can also imagine how useful this would be if you wanted to convert an entire file from underscore-based variable names to CamelCase or vice versa. Combining this case-conversion functionality with macros would make the task a trivial operation.

9. The Mark Ring

Rarely does a file of code fit on a single page. So it should come as no surprise that a reasonable amount of the average developer's time is spent navigating back and forth between pages in a file. Often this operation consists of either paging up or down or grepping for a phrase near the line of interest (not to mention the dreaded journey from keyboard to mouse!).

Luckily, Emacs remembers where we've been. If you know you're going to come back to your current location in a file, simply "C-<SPC> C-<SPC>" to push the current point onto the "mark ring," and "C-u C-<SPC>" to pop it off. Emacs will take you back to where you left off. (Note that if it's a multi-hop trip, you can push multiple points onto the mark ring to retrace each step on your way back home.)

10. Dired (File Explorer)

If you're still browsing for files in your terminal—or worse, a GUI—you're missing out. Because Emacs serves as an interactive file explorer too. Simply "C-x-f" to open a file, but press RETURN without supplying a name, and Emacs will open a buffer with a listing of the current directory. From there, you can navigate through the directory with cursor keys, regular expressions, or even (horrified gulp) the mouse to find what you're looking for.

11. The regex

Finally, no list would be complete without mention of regular expressions. Although it may go without saying, the regex search within your editor is such a commonplace necessity that most of us may take it as second nature—almost a cyborgial extension of the developer's motoneural system. I would imagine that very few real editors out there lack regex searching, but for the record, it's achieved in Emacs via "C-M-s" for forward/downward search and "C-M-r" for reverse/upward search.


Well, I hope that helped. These were just the few Emacs features that I use on a regular enough basis that I couldn't go without them. Please leave comments with suggestions on items I might have forgotten. As is often the case with these sorts of things, it's the actions we take for granted that, by definition, we are most likely to overlook.

The Pipelined Brain by Daniel Ehrman

While at work today I thought to myself, "How marvelous is it that if we as logic designers want more processing power out of a chip, we can simply add more logic?" It seems simple, but it's really quite remarkable when you think about it. (Imagine choosing to giving your child more neurons as needed.) Sure there is an area and power trade-off to consider, but if we need to do more work in parallel, there's nothing stopping us from building a few extra gates to get what we want.

Note that this approach is fundamentally different than software: extra code means extra time. On the other hand, transistors are a dime a dozen these days, and on chips with more than a billion of them, the added cost—for no added processing time—is truly quite trivial.

So then I thought, "What if we could do this with our brains? What if like hardware, we could think in parallel? What if I could pipeline my brain so that while one block of my consciousness were busy processing Problem A, another block could be working on Problem B? What would that look like?"

But then it occurred to me: we already do this every day. Yes, we know that our brains are busy processing thousands of patterns in parallel far beneath our consciousness, but that's not what interests me here. I'm interested in the collective brain.

Complex "intelligent" behaviors have long been observed in relatively simple species like ants via their larger actions as a community. And in humans, it has been shown that while no one of us may be an expert in a particular field, through the power of numbers, we can together achieve highly accurate results. So it really shouldn't be any great leap to think of our brains as individual workers contributing to massive results on a supercomputer scale.

I use that word intentionally—supercomputer—because that's what we are, all 7 billion of us combined. What else could be capable of achievements as miraculous as flying three people to the moon and back with less than a decade of preparation, while simultaneously managing the concerns of everyday life here on Earth?

In fact, from a computer architect's perspective, there is tremendous insight to be gleaned from the ways in which we work together to achieve results beyond the power of any one brain. Perhaps no company better exemplifies the spirit of pipelined processing than Taiwanese news animators Next Media Animations, who now go from "story conception to a finished product in less than 2 1/2 hours." This remarkable pace is achieved only by treating each worker as a distinct, specialized unit capable of solving a problem in isolation from, and in parallel to, the other members of their team, much in the same way that we design microprocessors.

The success of Next Media Animations is a glimpse at what can be accomplished when a production process is constructed to remove as much serialization and dependencies as possible. With advanced tools at our disposal, such as 3D rendering software, which dramatically reduce the pipeline latency of product development, we are poised more and more every day to function like a high speed computer, moving with microprocessors along Moore's curve rather than watching them pass from the sidelines.

It's now up to the entrepreneurs, the managers, and the creative thinkers of tomorrow to match the evolution of computers with equivalent developments in our workflow, growing in tandem with the technology to ensure that we are as efficient and as productive as we can be.

Guitar Synthesizer by Daniel Ehrman

Since purchasing my function generator, I've been doing a lot of thinking about what kinds of creative projects I can accomplish with this seemingly simple device.

One concept that struck me almost immediately was using the Voltage Controlled Frequency (VCF) input of the function generator to vary the sound via some external source, and since I'm a guitar player, naturally I looked to my guitar as the ideal controller.

This isn't a very new idea. In fact, the Roland GR-55 puts to shame pretty much any hypothetical device I could imagine:

Clearly something of that caliber is out of my ballpark, but I might be able to achieve something simpler.

My idea (again, nothing incredibly novel) is to use a simple Frequency Controlled Voltage (FCV) chip to convert my guitar signal to a specific voltage and then provide that to the function generator's VCF input. The ideal result would be a clean synth sound coming straight from my guitar.

The reality of course is much more complicated.

Unfortunately, the function generator is monophonic: it is only capable of playing one "note" at a time. So it's imperative that whatever voltage input I provide it is a clean representation of a single guitar note rather than the complex assortment of frequencies that are present in an actual guitar's sound. This is no trivial problem. Even if I focus on plucking only a single string, a single note is actual comprised of a variety of overtones that pollute the sound and could potentially distract the circuitry from the fundamental frequency:

Plucking the open D string of a Fender Stratocaster

Plucking the open D string of a Fender Stratocaster

So the next thought is, "Well, that's OK: I'll just pass the signal through a few band pass filters and choose the band with the maximum output as my fundamental frequency." While that may sound like a perfectly simple solution to the problem, this is where things get much harrier. Let's take a look at the spectrum of frequencies that are actually comprising this signal:

Ouch. Take a look at that. The fundamental frequency of our D3 note, approximately 147 Hz, isn't even the peak frequency in the spectrum! To be fair, we have to pay attention to the fact that of all of the partial frequencies, the group of tones around the D3 clearly have the largest area; therefore, that collection of closely aligned frequencies will together cut through the mess to create what we perceive as a single D.

If only band pass filters worked like human ears….Look what happens when we try to cut a slice out of the spectrum that should represent a D3 note (144 to 150 Hz):

Top: original complete guitar D note. Bottom: Extracted frequencies in the range of 144-150 Hz.

Top: original complete guitar D note. Bottom: Extracted frequencies in the range of 144-150 Hz.

What?? Things certainly aren't looking good here. The extracted range (D3) is of such a low volume, it's hard to believe that we could even categorize the original signal as a D at all. And if we were to expand the band any wider, we'd start to pick up the surrounding notes (C# and D#) and in turn detract from the cleanliness of our signal.

To put it simply, reducing a raw analog guitar signal—even just one note—to a single frequency that can be cleanly converted by an FCV chip may require some more advanced circuitry.

However, there is a bit of hope: if you look carefully at the figure above, you'll notice that the smaller signal at the bottom representing the D3 note has a period that directly aligns with that of the big spikes in the top signal. This could be very good news: if the FCV chip can trigger on peaks, it will accurately detect the fundamental frequency and provide the single voltage we need.

Unfortunately I'll need to do more investigation into the problem before I have a complete answer (for another blog post). But in the meantime, while we're in the business of deconstructing guitar signals, I thought it would be a fun wrap-up to work our way back up to that original dirty signal from scratch.

In referring to the frequency spectrum shown above, I chose the ten loudest frequencies and combined them in Audacity to produce an artificial guitar sound:

Artificial guitar D3 note: 10 simple sine waves and a single additive composite.

Artificial guitar D3 note: 10 simple sine waves and a single additive composite.

Comparing the resulting composite wave to the original actual guitar sample, we can see that the synthesis isn't that far off:

Top: artificial guitar. Bottom: actual guitar

Top: artificial guitar. Bottom: actual guitar

The primary sources of difference between the two waves is merely the magnitude of each of the partial frequencies, which for the sake of simplicity, I kept nearly the same across the entire spectrum. This shortcut results in "fuller" bands (louder notes), such as the D3, being underrepresented and "narrower" bands (softer notes) being overrepresented.

Here are the audio samples of the two different waves:

Function Generator Music in 5 Minutes by Daniel Ehrman

Forget oscilloscopes. Ever wondered what it sounds like to play a function generator through a guitar amp?

In my undergrad, while working on the Purdue Solar Racing team back in 2011, I borrowed the team's function generator when it wasn't in use and carried out some "musical experiments" back at home.

I have a Fender Cyber Champ amp, which has a whole host of effects built in: phaser, flange, chorus, various kinds of reverb, and a lot more. So the thought was that if I could combine a box of essentially unlimited sounds with these spacey guitar effects, I could cook up some pretty cool live music, or at the very least, synthesized effects to lay over whatever other music I was working on at the time.

Of course I eventually had to give back it back, but I never stopped thinking about all of the unique sounds I could make with that function generator. I'd once seen a documentary on the making of The Dark Side of the Moon, and the idea of crafting an entire composition from little hand-made sonic components truly lit a fire in my engineer's brain.

Back to the present day.

Last week, I finally ordered my own function generator for $25 on eBay and started right where I left off three years ago.

Clockwise from top left: (1) GW GFG-8015G function generator, (2) Boss RC-2 Loop Station, (3) Fender Cyber Champ amp, (4) Presonus AudioBox USB interface, (5) headphones, (6) PC.

Clockwise from top left: (1) GW GFG-8015G function generator, (2) Boss RC-2 Loop Station, (3) Fender Cyber Champ amp, (4) Presonus AudioBox USB interface, (5) headphones, (6) PC.

The diagram above shows the final setup with all of the required pieces for recording the music. The loop station (top center) is the key: it lets me loop back what I've previously recorded without the help of a computer so I can compose everything live in one shot. The computer in the diagram, and in fact the entire bottom row, is only present for recording purposes.

Also note that technically, you would want any effects—including the amp—placed before the looper so that different effects could be saved with each track rather than the same effects being applied to the entire composition, but I just wanted a quick and simple setup here. The only effects I actually used were very small amounts of reverb, delay, and chorus.

I start with a 2 Hz square wave with a non-50% duty cycle to create a heart-beat-like bass drum. (Listen to this beginning section of Dark Side for comparison.) Typically, this wouldn't be audible due to its being below the 20 Hz human hearing cutoff, but the quick changes in the line level create some residual precussive frequencies that we can hear quite well.

Then, in remembering the repetitive, but beautiful, two-chord droning of Pink Floyd's "Breathe," I set the frequency knob to A for four beats and E for four beats. (Note: it seems like these notes all came out half a step lower, which I'll have to investigate further.)

With the basic notes down, I start overlaying more of the notes that comprise the A major and E minor chords, with the pleasant surprise of some phaser effect as I double-record the same, but phase-shifted, notes.

Add on top of that a couple "slides" into notes and some (admittedly atonal) quickly changing frequencies, and we're pretty much done.

So here's the final 15-second composition (that loops ad infinitum):

Ultimately, I have much bigger plans for this function generator, but this is a nice kick-off to what will hopefully become a seriously fun audio engineering project.

What Discrete Math and Lisp Can Teach Us About Good Coding Habits by Daniel Ehrman

When I was in my undergrad, I had the pleasure of reading, and to be honest, writing, countless lines of confusing code written in a variety of languages. To be fair, I had inherited some pretty bad habits from when I taught myself BASIC as a kid, but it seems like college courses never did a really great job of pushing clean coding style. Sure, heavy emphasis was always placed on designing scalable, efficient programs, but algorithmic complexity is quite distinct from code complexity, and generally a quality coding style was almost always left as an exercise to the student.

That is until my senior year—Introduction to Artificial Intelligence. Building on a foundation in Discrete Math, where students are educated in the laws and techniques of formal logic, this course sought to remove from our minds the baggage of sequential programming (C, FORTRAN, Python, etc.) and instead see the computer as an executor of logic—returning a decision from a single logical function.

As it turns out, thinking about programs this way has profound effects on the way we write our code: specifically, it enforces a logical structure. Let's take a look at a very simple function in C that computes the length of a linked list:

int length_of_list(t_linked_list *some_list)
  int length = 0;
  while(some_list != NULL)
      some_list = some_list->next;
  return length;

Efficient? Sure. Straightforward? Eh. Honestly, with an algorithm so simple, it would be hard to get lost in this code. But the point here is to think about the result we're trying to achieve and to question whether the structure of the code is representative of that goal. Is it?

We'll come back to that thought in a moment. But for now, let's look at an equivalent function in Lisp:

(defun length-of-list (some-list)
  (if (null some-list)
      (+ 1 (length-of-list (rest some-list)))))

Pay attention to the way this code is structured (like a logical proof):

  1. Base case: Does the list have any elements?
  2. Inductive step: What is the length of the list if we remove an element?

While this is a pretty simple function, thinking about our code this way—as a set of "propositions," if you will—can deeply shape the way we plan and organize our code.

"But wait!" says the code-savvy reader. "That's not fair! You're comparing an iterative algorithm in one language to a recursive (and less efficient) algorithm in another!"

Guilty. The truth is that while recursion can result in some truly beautiful programs, it seldom results in the most space- or time-efficient program. And the truth is that Lisp is designed to work with lists, so I've intentionally chosen an unfair example.

But the point here is not to start a language war or, as I said earlier, discuss algorithmic complexity; the point is to demonstrate what we can learn from a (less-than-popular) language that tends to enforce good behavior.

For kicks, here is the recursive variant of the original C function:

int length_of_list(t_linked_list *some_list)
  if(some_list == NULL)
      return 0;
      return (1 + length_of_list(some_list->next));

Alright, so again (as I often ask myself at the end of these posts), what's the point? All I see are two versions of the same function, and the one style that I'm supposedly pushing is actually the least efficient of the two.

Well, the key here is to break out of the algorithm design box and instead think of our code like an expository essay. We've got a lot to say; we can choose a thousand different ways to say it; and we want to find the most effective way to make our point.

So when I begin writing a function, like writing an essay, I develop a plan. I ask myself, "What are we trying to achieve here? What are the possible cases? What are the possible results?" What I've found is that thinking of my programs at this higher organizational level yields a body of code that is easier to follow and perhaps more importantly, easier to update.

Give it a shot sometime; I think you'll like what you see.