Melted Butter Cocoons – Part I

IMG_20181027_162834
Melted Butter Cocoons

I still remember the intense flavor and juiciness of that thick piece of Sirloin. Crusted in the name of Kona, Bone-In and Aged Dry. It was an exceptional dining experience at the Capitol Grill in Houston, Texas. It was the event that gave me the inspiration for this two-part blog post.

In this first part, I will introduce you to my little home project where I try to dry age Sirloin steaks at home. In part two, we will see the results. When? Well, in about 60 days my friend — when the meat is — say, middle — aged.

Dry Aging TL;DR

Dry aging of meat refers to the process of storing meat over a long period of time in a dry environment. This is different from traditional wet aging, where the meat is kept in a vacuum bag over a shorter period of time. Both ideas aim for increased tenderness, intensified flavor — not to mention the prolonged preservation time, which in fact is a common denominator behind many of the world’s culinary specialties. The Rakfisk of Norway is one golden example of this: trout is kept in a bin with sugar, salt and water. A controlled form of rotting process starts, and you can consume the fish over the course of months. One side effect is some very special taste and — uhm — smell properties! Same is true for many other specialties as well.

Dry aging is rooted in the same bio culinary paradigm as sour dough: you want your bio climate to be meat (or dough) friendly, and develop to the better over time. A good dry aging fridge (or room) can develop to the better over the years. It will be a unique bio climate colored by the natural microbiota in that environment.

Instead of going on to explain all the fancy sides of dry aging, I point you to Jess Pryles blog. Read on and you will learn everything you need to know. You will also notice a crucial “fact”: Dry aging is not for the home chef.

Why?

Because if you slice your meat into individual steaks before you proceed, they will basically come out as cured ham, eventually — dry and hard. Point is not to cure the meat! Original idea is to remove the outer dried layer before cooking and consumption. If you dry age individual steaks, they will be dry all the way through. Traditionally, dry aging calls for whole cuts of meat, and you will loose something like 5-10% from removing that outer dried layer after aging. So, either you go buy that large whole cut of meat, and accept the loss, or you stick to that boring wet aging, is it right?

Not quite! It turns out that Casper Stuhr Cobzcyk has developed a new dry aging technique where he first dips his (still) whole cuts of meat in melted butter to form a cocoon protecting the steak from drying out on the surface. It reminds me about cheese waxing!

If you combine the thoughts of Pryles and Stuhr Cobzcyk, I figured it would allow for dry aging of individual steaks at home, since the melted butter cocoon will protect the individual steaks from drying out at the surface, and, hence, you will not need to remove the outer layer nor will they be cured!

Butter probably acts like sort of a “let-moist-out, not-let-oxygen in”-barrier. This in turn, brings up a lot of questions Mr. Stuhr Cobzcyk does not answer. He probably has them, but why should he really share them with the world. For example, what is the optimal thickness of the butter cocoon? Unfortunately, I don’t know all the answers yet.

I decided to put strings around my two steaks, before dipping them in. This allowed me to hang them in the fridge rather than letting them sink into the rack and potentially create a butter mess.

Dry aging started: 27th of October, 2018.

We aim for 60 days, so dry aging stops: 26th of December, 2018.

A Double Thank You

I was reading at the library when I got a phone call from my boss. She asked me to immediately return to home because of a not-so-unusual & escalating disobedient kids situation.

I got onto my feet and started to pack my bag. I eyed the cord of my laptop charger, the way it snaked itself over the floor, and ended up in a socket overly close to the feet of a random lady.

I approached her and gesticulated it would require her attention to resolve the situation. She read it and started to unplug my charger but was not able to get it out. She gave up quickly, and I had to help her. And so I successfully managed to unplug it under grant of an informal intimate zone intrusion permission. Once unplugged, I said, “Thank You”, and she responded “Thank You”.

It was an interesting Double Thank You for the help situation: I thanked her for permitting me to enter her intimate zone, and I thanked her for her initial failed attempt of helping me. Then she thanked me back for being polite and helpful enough to help her when helping me.

Fat Man & Little Boy

On a sunny spring day, I craved for steak and went to see my good old barbecue on the patio. But I found it ill-conditioned. The rain in Bergen had finally taken its toll on the rusty little boy: the price of storing and using it outside during winters now had to be paid. So I questioned myself whether to buy a new one a larger and better one. Filled with ambivalence, I went to the retailer and found a big fat man. Upgrading is a bliss. Ka-ching.

Some years ago I used to work for an oil & gas company. In that context — I visited a site we had some cross-business activity with — located in Houston, Texas. Upon arrival I was told to settle in the empty cubicle of another engineer on vacation. On the cube wall I noticed a drawing showing a comparison between two versions of the site’s main product: the legacy 15k psi ram BOP (Blow-Out Preventer), and the next 20k psi generation. Let me add that the size of such equipment does not grow linearly with the pressure rating, so the next version was a fat man compared to the little boy.

Typically, when bad oil spill disasters take place, the BOP is likely to be in the spot. The BOP acts as the main security system resting on top of the very well head. They are used to seal wells under normal conditions, as well as in emergency situations. In case of the latter, the BOPs have strong hydraulic shear rams fitted with sharp steel blades. They can cut through any solid obstacles (e.g. drill pipe) situated — intentionally or not — in the bore. The aim is to seal the well and prevent oil spill, or even blow-outs on the rig deck — usually leading to fire, havoc and death.

I noticed, printed with small letters beneath each of the two drawings; “Little Boy”, “Fat Man”. It took me a couple of seconds before I realized the meaning. Call it irony, sarcasm or blasphemy — the reference was to the respective nukes detonated by US over Hiroshima and Nagasaki in 1945.

It also got me thinking about the two I now have on the patio back home.

Fat Man & Little Boy

Device Equals ANSI Dot Sys

tuxbsod3
Click here to download the above image in android wallpaper format!

As a kid I figured out how to edit my father’s config.sys and autoexec.bat to change font colors in MS-DOS. Without the help from the internet, it was such a mysterious age where small technological discoveries were made based solely on trial and error, gossip, obscure scripts, tools and white papers spread on LAN parties and floppies.

The trick was to load the binary file ansi.sys using the DEVICE= directive in config.sys, enabling escape sequence interpretation to the standard output — which included means for changing the background and foreground font color on the command prompt.

I later installed Red Hat Linux 5.2 in 1998, but after a while I ended up compiling my own “distro” based on Linux from Scratch. My favourite nostalgic piece of memory is still my only ANSI art creation to date, namely my /etc/issue (image shown above), born based on piping and overlying Tux from Welcome2L (c) LittleIgloo.Org on a classical Windows 9x blue screen of death replica!

UPDATED 17/8-18: Added Android wallpaper version of BSOD Tux.

The Ashlad’s Older Brothers

I tend to notice small things in life. Combined with some pondering, they can make me unusually happy. Today I proudly present one of my favourite curiosities of all time:

The priceless, harassing laughter of the Ashlad’s older brothers.

The sound clip is taken from the legendary stop-motion animated short by Ivo Caprino, which is based on the Norwegian folk tale “Askeladden og De Gode Hjelperne” (English: “The Ashlad and His Good Helpers”) [ref. 02:43].

For some reason, DailyMotion.Com has taken the liberty to publish the full original movie online. I believe Caprino would have flipped in his grave if he knew. And I wouldn’t be surprised if his family company considers even more advanced gymnastics alive!

Coding a Parametric Equalizer for Audio Applications

As a kid I was very fascinated by a particular type of electronic devices known as equalizers. These devices are used to adjust the balance between frequency components of electronic signals, and has a widespread application in audio engineering.

As I grew up the fascination continued, but shifted from wanting to own one — into wanting to build one — into wanting to code one.

eqpic.jpg
Image credit: http://www.lifewire.com

Introduction

In this article I will explain how you can code your own audio equalizer, enabling you to integrate your own variant in your own projects. Let us start with some background information and basic theory.

When you use the volume knob to pump up the volume on your stereo, it will boost all the frequency components of the audio by roughly the same amount. The bass and treble controls on some stereos take this concept one step further; they divide the whole frequency range into two parts — where the bass knob controls the volume in the lower frequency range and the treble knob controls the volume in the upper frequency range.

Now, with an audio equalizer, you have the possibility to adjust the volume on any given number of  individual frequency ranges, separately.

Physically, the front panel of an equalizer device typically consists of a collection of slider knobs, each corresponding to a given frequency range — or more specifically — to a given center frequency. The term center frequency refers to the mid point of the frequency range the slider knob controls.

By arranging the sliders in increasing center frequency order, the combined positions of the individual sliders will represent the overall frequency response of the equalizer. This is where it gets interesting, because the horizontal position of the slider now represents frequency, and the vertical position represents the response modification you wish to impose on that frequency. In other words, you can “draw” your desired frequency response by arranging the sliders accordingly.

Theory of Parametric Equalizers

An additional degree of freedom arises when the center frequency per slider also is adjustable. This is exactly what a parametric equalizer is: it lets the user specify a number of sections (think of section here as a slider), each with a frequency response adjustable by the following parameters: center frequency (f0), bandwidth (Bf), bandwidth gain (GB), reference gain (G0) and boost/cut gain (G):

  • The center frequency (f0) represents the mid-point of the section’s frequency range and is given in Hertz [Hz].
  • The bandwidth (Bf) represents the width of the section across frequency and is measured in Hertz [Hz]. A low bandwidth corresponds to a narrow frequency range meaning that the section will concentrate its operation to only the frequencies close to the center frequency. On the other hand, a high bandwidth yields a section of wide frequency range — affecting a broader range of frequencies surrounding the center frequency.
  • The bandwidth gain (GB) is given in decibels [dB] and represents the level at which the bandwidth is measured. That is, to have a meaningful measure of bandwidth, we must define the level at which it is measured. See Figure 1.
  • The reference gain (G0) is given in decibels [dB] and simply represents the level of the section’s offset. See Figure 1.
  • The boost/cut gain (G) is given in decibels [dB] and prescribes the effect imposed on the audio loudness for the section’s frequency range. A boost/cut level of 0 dB corresponds to unity (no operation), whereas negative numbers corresponds to cut (volume down) and positive numbers to boost (volume up).

section.png
Figure 1: Section Frequency Spectrum
A section is really just a filter — in our case a digital audio filter with the parameters corresponding to the elements in the list above.

Implementation in Matlab

The abstraction now is the following: a parametric audio equalizer is nothing else than a list of digital audio filters acting on the input signal to produce an output signal with the desired balance between frequency components.

This means that the smallest building block we need to create is a digital audio filter. Without going deep into the field of digital filter design, I will make it easy for you and jump straight to the crucial equation required:

Equation 1

a0*y(n) = b0*x(n) + b1*x(n-1) + b2*x(n-2)
        - a1*y(n-1) - a2*y(n-2), for n = 0, 1, 2, ...

In equation 1, x(n) represents the input signal, y(n) the output signal, a0, a1 and a2, are the feedback filter coefficients, and b0, b1 and b2, are the feedforward filter coefficients.

To calculate the filtered output signal, y(n), all you have to do is to run the input signal, x(n), through the recurrence relation given by equation 1. In Matlab, equation 1 corresponds to the filter function. We will come back to it shortly, but first we need to get hold of the filter coefficients (a0, a1, a2, b0, b1 and b2).

At this point, you can read Orfanidis paper and try to grasp the underlying mathematics, but I will make it easy for you. Firstly, we define the sampling rate of the input signal x(n) as fs, and secondly, by using the section parameters defined above, the corresponding filter coefficients can be calculated by

Equations 2 – 8

beta = tan(Df/2*pi/(fs/2))*sqrt(abs((10^(GB/20))^2
     - (10^(G0/20))^2))/sqrt(abs(10^(G/20)^2 - (10^(GB/20))^2))

b0 = (10^(G0/20) + 10^(G/20)*beta)/(1+beta)
b1 = -2*10^(G0/20)*cos(f0*pi/(fs/2))/(1+beta) 
b2 = (10^(G0/20) - 10^(G/20)*beta)/(1+beta)

a0 = 1
a1 = -2*cos(f0*pi/(fs/2))/(1+beta)
a2 = (1-beta)/(1+beta)

Note that beta in equation 2 is just used as an intermediate variable to simplify the appearance of equations 3 through 8. Also note that tan() and cos() represents the tangens and cosine functions, respectively, pi represents 3.1415…, and sqrt() is the square root.

As an example, if we define the following section parameters:

(fs, f0, Bf, GB, G0, G) = (1000, 250, 40, 9, 0, 12)

It means that we will have a section operating at a 1 kHz sampling rate with a center frequency of 250 Hz, bandwidth of 40 Hz, bandwidth gain of 9 dB, reference gain of 0 dB and boost gain of 12 dB. See Figure 2 for the frequency response (spectrum) of the section.

section_ex
Figure 2: Example Section Frequency Spectrum
Let’s say we have defined a list of many sections. How do we combine all the sections together so we can see the overall result? The following Matlab script illustrates the concept by setting up a 4-section parametric equalizer.

% Parametric Equalizer by Geir K. Nilsen (2017)
clear all;

fs = 1000; % Sampling frequency [Hz]
S = 4; % Number of sections

Bf = [5 5 5 5]; % Bandwidth [Hz]
GB = [9 9 9 9]; % Bandwidth gain (level at which the bandwidth is measured) [dB]
G0 = [0 0 0 0]; % Reference gain @ DC [dB]
G = [8 10 12 14]; % Boost/cut gain [dB]
f0 = [200 250 300 350]; % Center freqency [Hz]

h = [1; zeros(1023,1)]; % ..for impulse response
b = zeros(S,3); % ..for feedforward filter coefficients
a = zeros(S,3); % ..for feedbackward filter coefficients

for s = 1:S;
    % Equation 2
    beta = tan(Bf(s)/2 * pi / (fs / 2)) * sqrt(abs((10^(GB(s)/20))^2 - (10^(G0(s)/20))^2)) / sqrt(abs(10^(G(s)/20)^2 - (10^(GB(s)/20))^2));
    % Equation 3 through 5
    b(s,:) = [(10^(G0(s)/20) + 10^(G(s)/20)*beta), -2*10^(G0(s)/20)*cos(f0(s)*pi/(fs/2)), (10^(G0(s)/20) - 10^(G(s)/20)*beta)] / (1+beta);
    % Equation 6 through 8
    a(s,:) = [1, -2*cos(f0(s)*pi/(fs/2))/(1+beta), (1-beta)/(1+beta)];

    % apply equation 1 recursively per section.
    h = filter(b(s,:), a(s,:), h);
end;

% Plot the frequency spectrum of the combined section impulse response h
H = db(abs(fft(h)));
H = H(1:length(H)/2);
f = (0:length(H)-1)/length(H)*fs/2;
plot(f,H)
axis([0 fs/2 0 20])
xlabel('Frequency [Hz]');
ylabel('Gain [dB]');
grid on

The key to combining the sections is to run the input signal through the sections in a cascaded fashion: the output signal of the first section is fed as input to the next section, and so on. In the script above, the input signal is set to the delta function, so that the output of the first section yields its impulse response — which in turn is fed as the input to the next section, and so on. The final output of the last section is therefore the combined (total) impulse response of all the sections, i.e. the impulse response of the parametric equalizer.

The FFT is then applied on the overall impulse response to calculate the frequency response, which finally is used to produce the frequency spectrum of the equalizer shown in Figure 3.

eq response
Figure 3: Parametric Equalizer Frequency Spectrum
The next section of this article will address how to make the step from the Matlab implementation above to a practical implementation in C#. Specifically, I will address:

  • How to run the equalizer in real-time, i.e. how to apply it in a system where only few samples of the actual input signal is available at the same time — and furthermore ensure that the combined output signals will be continuous (no hiccups).
  • How to object orientate the needed parts of the implementation.

Real-time considerations

Consider equation 1 by evaluating it for n=0,1,2, and you will notice that some of the  indices on the right hand side of the equation will be negative. These terms with negative index correspond to the recurrence relation’s initial conditions. If we consider the recurrence relation as a one-go operation, it is safe to set those terms to zero. But what if we have a real system sampling a microphone at a rate of fs=1000 Hz, and where the input signal x(n) is made available in a finite length buffer of size 1000 samples — updated by the system once every second?

To ensure that the combined output signals will be continuous, the initial conditions must be set based on the previous states of the recurrence relation. In other words, the recurrence relation implementation must have some memory of its previous states. Specifically, it means that at the end of the function implementing the recurrence relation, one must store the two last samples of the current output and input signals. When the next iteration starts, it will use those values as the initial conditions y(-1), y(-2), x(-1) and x(-2).

A practical C# Implementation

I will now give a practical implementation in C#. It consists of three classes

  • Filter.cs — Implements the recurrence relation given in equation 1. And yes, it is made to deal gracefully with the initial condition problem stated in the previous section.
  • Section.cs — Implements a section as described by the parameters listed previously.
  • ParametricEqualizer.cs — Implements the parametric equalizer.

Filter.cs

/* @author Geir K. Nilsen (geir.kjetil.nilsen@gmail.com) 2017 */

namespace ParametricEqualizer
{
    public class Filter
    {
        private List a;
        private List b;

        private List x_past;
        private List y_past;

        public Filter(List a, List b)
        {
            this.a = a;
            this.b = b;
        }

        public void apply(List x, out List y)
        {
            int ord = a.Count - 1;
            int np = x.Count - 1;

            if (np < ord)
            {
                for (int k = 0; k < ord - np; k++)
                    x.Add(0.0);
                np = ord;
            }

            y = new List();
            for (int k = 0; k < np + 1; k++)
            {
                y.Add(0.0);
            }

            if (x_past == null)
            {
                x_past = new List();

                for (int s = 0; s < x.Count; s++)
                    x_past.Add(0);
            }

            if (y_past == null)
            {
                y_past = new List();

                for (int s = 0; s < y.Count; s++)
                    y_past.Add(0);
            }

            for (int i = 0; i < np + 1; i++)
            {
                y[i] = 0.0;

                for (int j = 0; j < ord + 1; j++)
                {
                    if (i - j < 0)
                        y[i] = y[i] + b[j] * x_past[x_past.Count - j];
                    else
                        y[i] = y[i] + b[j] * x[i - j];
                }

                for (int j = 0; j < ord; j++)
                {
                    if (i - j - 1 < 0)
                        y[i] = y[i] - a[j + 1] * y_past[y_past.Count - j - 1];
                    else
                        y[i] = y[i] - a[j + 1] * y[i - j - 1];
                }

                y[i] = y[i] / a[0];
            }

            x_past = x;
            y_past = y;

        }
    }
}

Section.cs

/* @author Geir K. Nilsen (geir.kjetil.nilsen@gmail.com) 2017 */

namespace ParametricEqualizer
{
    public class Section
    {
        private Filter filter;
        private double G0;
        private double G;
        private double GB;
        private double f0;
        private double Bf;
        private double fs;

        private double[][] coeffs;

        public Section(double f0, double Bf, double GB, double G0, double G, double fs)
        {
            this.f0 = f0;
            this.Bf = Bf;
            this.GB = GB;
            this.G0 = G0;
            this.G = G;
            this.fs = fs;

            this.coeffs = new double[2][];
            this.coeffs[0] = new double[3];
            this.coeffs[1] = new double[3];

            double beta = Math.Tan(Bf / 2.0 * Math.PI / (fs / 2.0)) * Math.Sqrt(Math.Abs(Math.Pow(Math.Pow(10, GB / 20.0), 2.0) - Math.Pow(Math.Pow(10.0, G0 / 20.0), 2.0))) / Math.Sqrt(Math.Abs(Math.Pow(Math.Pow(10.0, G / 20.0), 2.0) - Math.Pow(Math.Pow(10.0, GB/20.0), 2.0)));

            coeffs[0][0] = (Math.Pow(10.0, G0 / 20.0) + Math.Pow(10.0, G/20.0) * beta) / (1 + beta);
            coeffs[0][1] = (-2 * Math.Pow(10.0, G0/20.0) * Math.Cos(f0 * Math.PI / (fs / 2.0))) / (1 + beta);
            coeffs[0][2] = (Math.Pow(10.0, G0/20) - Math.Pow(10.0, G/20.0) * beta) / (1 + beta);

            coeffs[1][0] = 1.0;
            coeffs[1][1] = -2 * Math.Cos(f0 * Math.PI / (fs / 2.0)) / (1 + beta);
            coeffs[1][2] = (1 - beta) / (1 + beta);

            filter = new Filter(coeffs[1].ToList(), coeffs[0].ToList());
        }

        public List run(List x, out List y)
        {
            filter.apply(x, out y);
            return y;
        }
    }
}

ParametricEqualizer.cs

namespace ParametricEqualizer
{
    public class ParametricEqualizer
    {
        private int numberOfSections;
        private List<Section> section;
        private double[] G0;
        private double[] G;
        private double[] GB;
        private double[] f0;
        private double[] Bf;
  
        public ParametricEqualizer(int numberOfSections, int fs, double[] f0, double[] Bf, double[] GB, double[] G0, double[] G)
        {
            this.numberOfSections = numberOfSections;
            this.G0 = G0;
            this.G = G;
            this.GB = GB;
            this.f0 = f0;
            this.Bf = Bf;
            
            section = new List<Section>();
            for (int sectionNumber = 0; sectionNumber < numberOfSections; sectionNumber++)
            {
                section.Add(new Section(f0[sectionNumber], Bf[sectionNumber], GB[sectionNumber], G0[sectionNumber], G[sectionNumber], fs));
            }
        }

        public void run(List x, ref List y)
        {           
            for (int sectionNumber = 0; sectionNumber < numberOfSections; sectionNumber++)
            {
                section[sectionNumber].run(x, out y);
                x = y; // next section
            }
        }
    }
}

Usage Example

Let’s conclude the article by an example where we create a ParamtricEqualizer object and applies it on some input data. The following snippet will setup the equivalent 4-section equalizer as in the Matlab implementation above.

double[] x = new double[] { 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // input signal (delta function example)
List y = new List(); // output signal
ParametricEqualizer.ParametricEqualizer peq = new ParametricEqualizer.ParametricEqualizer(4, 1000, new double[] { 200, 250, 300, 350 }, new double[] { 5, 5, 5, 5 }, new double[] { 9, 9, 9, 9 }, new double[] {0, 0, 0, 0}, new double[] {8, 10, 12, 14});
peq.run(x.ToList(), ref y);

 

The Rocket Scientist

The following story is completely true. Long time ago, I created the image below and went to a local T-shirt shop. I handed over my USB-stick and said, “Hey Mr. T-shirt Maker, can you tailor me a T-shirt with this logo on it?”

nasatshirtlogo
While he was working on the computer, he told me that the T-shirt must be washed inside-out and at low temperature. Why so, I said — Well, this is not a true silk-print, so be careful with it. We only make true silk-prints when the motive is good enough for a thousand copies. — Don’t you think my logo is good enough?, I said with a disappointed voice. — Ha-ha, he laughed, ridiculed and continued — Who would want to walk around and advertise for NASA?

A couple of days later I walked from my apartment to the University. As I was passing the T-shirt shop, I couldn’t miss to notice it. In the very front window of the shop of the biggest T-shirt making idiot in the world, displayed at the best spot: three glorious silk-printed T-shirts chested with my ingenious pride.