Homemade Tortillas have been one of my greatest cooking endeavors of all time. Let me detail the long story that lead me to uncovering a simple yet supreme recipe for real corn Tortillas.


I like to iteratively refine recipes and gradually improve them over time. With the goal of reaching perfection, I keep on tweaking only one isolated parameter, and assess the outcome over and over again.

It is always room for improvement, but some constraints usually prevents the home chef from continuing the optimization process indefinitely. The main constraint may be cost. In my case, the cost of importing the right corn to Norway, but mainly the fact that grinding corn fine enough is hard, and as we will see, also requires very special industrial equipment.

Store-bought corn Tortillas in Europe are usually made from a mixture of corn flour and wheat flour. The traditional corn flour is typically made directly from dried sweet corn, which is completely different from the type of corn being a staple in South-America. In fact, the main reason for also adding wheat flour to the corn flour in Europe is to make the dough cohesive (sticks to itself).

The secret to real corn Tortillas is not only the right corn, but also the corn treating process called Nixtamalisation. One common belief is that the technique arose by serendipity on a rainy day when the Aztecs left their corn contaminated with some ashes from the fireplace. Nixtamalisation is the process where dried corn reacts with an alkaline solution (base plus water). Today, calcium hydroxide (Ca(OH)2) is the commonly used base. See the excellent in-depth article by Dave Arnold to learn even more.

The Mexican jargon for calcium hydroxide is “Cal”. For Mexicans (OK, presumably at least for grandmothers) it is about as normal to have a pack of Cal in the closet as it is to have baking-soda. By mixing a small amount of Cal with water and corn in a pot and bringing it to boil, you start the Nixtamalisation process. You then put the lid on the pot and let the corn soak till the day after.

The process has several benefits. First, the flavor is completely transformed (into the better!). Second, the hull of the corn will erode — making it easier digest. And third, it ensures that the dough after grinding will be adhesive and in-cohesive (won’t stick to your fingers).

In Mexico, the corn dough you get from grinding fresh Nixtamal is called Masa (“dough”). Alternatively, the grinded Nixtamal is dried and grinded a second time and becomes Masa Harina (“dough flour”). Maseca is one of the most well known brands of Masa Harina.

Very recently, a few stores have started to offer Masa Harina in Norway and Europe generally. For a long time, GMO (genetically modified organism) restrictions prevented this from happening, at least on a legal basis. Now Gruma, the company behind Maseca, has started to produce from non-GMO corn in Italy making it more widespread.

However, as with most of semi-finished food products, the result is usually inadequate. The quality level not even close to what you can achieve if you make it from scratch. Tortillas from Maseca are simply not authentic. They have a hint of synthetic smell and flavor, and is why you should stay away from them. I believe the artificially short shelflife of Maseca also is a symptom of the same disease.

So, if Maseca is really not an option, should you make your own Nixtamal then? This is where the twist comes in: for the rest of this post I will argue that you should neither attempt to make your own Nixtamal, mainly due to the grinding challenges you will face afterwards. On top of that, you won’t need to import the right type of corn nor get hold of Cal.

If you are still not convinced and want to pursue Nixtamalisation, you can order corn from Rovey Seed Co. But be aware, the shipping cost to Europe will be more than a ten-fold that of the corn. And by the way, you can order Cal on Amazon under the name Mrs. Wages pickling lime — or if you happen to live in Norway and want to go big, get hold of a large bag of Hydratkalk from Franzefoss Minerals sold at Felleskjøpet. In fact, I asked both Franzefoss and Mattilsynet — the Food Safety Authority in Norway — whether Franzefoss’ Cal was graded for food use, but never got any confirmation. However, it has later come to my ears that a large snacks company in Norway had ordered half a ton of Cal from Franzefoss!

Originally, grinding Nixtamal was done by women spending all day on their knees over the Metate y Mano. This stone-carved device – which resembles a small table on short legs – consists of a relatively large working surface (the Metate) and a small hand-held stone (the Mano). To grind, you put a small amount of Nixtamal on the Metate followed by an intensive workout of horizontal rubbing using the Mano.

I first did some experiments with my rather large lava stone mortar and pestle, and quickly realized that this would take forever. Not even with a large Metacorngrinderte would you be able to produce more Masa than enough for a single Tortilla in 15 minutes. Very laborious and time consuming, so I instead got myself a traditional corn grinder. As you can see in the image, it looks just like a meat grinder, but has a small milling stone rather than a blade.

Also using the corn grinder, the process is quite laborious. But this is not the main problem. Even if you grind twice, you won’t manage to grind the Masa fine enough. A very finely grained Masa is required to get a soft and pliable Tortilla. You end up with a quite dry Tortilla because they won’t puff when you cook them. This is the secret, when you flip the Tortilla the second time, bubbles are supposed to form – indicating a two-layered structure. But it won’t happen as long as you don’t have the right grinding equipment. Nixtamalfunction. End of story.

So unless you want to invest in Tortilleria industrial equipment, read on because its time to present the short-cut.

By soaking traditional Tortilla chips in water until they become soggy, and then using achips hand blender you quickly get a surprisingly nice Masa! The only requirement here is that the Tortilla chips are out of best quality and not made from corn flour, but from Nixtamal. The brand shown in the image is well suited and should be available in most countries. If you can find corn  (and not corn flour) on the ingredients list you should be home safe.


Recipe: Real Corn Tortillas from Nixtamal-Based Tortilla Chips


  • 1 bag of Nixtamal-based Tortilla chips
  • Water
  • Salt (optional)


  • Hand blender
  • Tortilla press (or two flat surfaces, plastic wrapped)
  • Comal (or frying pan)


  1. Put the Tortilla chips in a container and crunch them to small pieces using your fist.
  2. Add a minimum amount of water to the chips. Just enough for all of it to become soggy after a few minutes.
  3. Use a hand blender, and repeatedly run it through the chips mixture until it becomes Masa.
  4. Put plastic wrap on both sides of the Tortilla press
  5. Form a golf ball sized ball of Masa and press flat using the Tortilla press
  6. Cook for ~30 seconds, flip, cook ~30 seconds more. Flip a second time – now cook for only 10-15 seconds. At this point the Tortilla should start to puff up (bubbles formation).




…and, serve!



The Theisen Transform

One of my mathematics lecturers once invited us to solve a problem that has fascinated me ever since. If you create a digital sound clip by recording your own voice, how can you transform that to mimic the celebrated Norwegian weather forecaster Vidar Theisen?


For those of us never having heard about dear Mr. Theisen, or even wasn’t born before he passed away, you can watch one of his daily NRK weather forecasts below.

It is pretty obvious that Mr. Theisen had a very distinct way of talking. A voice of slow tempo accompanied by a monotonic pitch. Nobody, at least at that time, would be unsure who you pretended to be if you slowly and flat-voiced said something about the weather at Spitsbergen.

The lecturer also happened to be my adviser, and his name is Prof. Hans Munthe-Kaas. Hans is a very good man, and he has opened many doors for students that has knocked on his door. He is on my list of personal relationships I could not have been without.

To get the wheels rolling in his students heads, Mr. Munthe-Kaas outlined several incorrect strategies you could try to begin with: to slow things down by a factor two, try to repeat the digital samples one-by-one so that the net duration will be doubled. Or even better, try to interpolate?

It turns out that both strategies actually works in terms of doubling the duration, but has the inevitable side effect of also shifting down the pitch of audio signals. It is analogous to slowing down the rotational speed of a record player: it obviously decreases the tempo of the sound, but the tone will also be darker. If you happen to own a record player, you are probably nodding affirmative at this point. In other words, we approach Mr. Theisen in terms of tempo, but not by tone. For pure sinusoidal waves, what we want is to extend the number of periods rather than increasing the length of one period.

Red leaf

Virtually, the tempo and pitch of a tune is inseparable. If you change the tempo, the pitch will also change. The figure on the right illustrates the concept: modifications can seemingly only be done along the green diagonal line.

Until the mid 60s, this was accepted as the truth. Then suddenly a paper disturbed the community; two bright guys named Flanagan and Golden solved the problem in the context of telecommunication. Thanks to it, we can separate the two parameters. Controlling the Theisen tempo independently of the tone is now easy. And the invention’s name? The Phase Vocoder.

According to the theory, and some years of trial and error for my part, if what you want is to change the tempo of a signal by a factor Pt/Qt, and shift the pitch by a factor Pp/Qp, all you have to do is the following:

  1. Transform the signal over to the time-frequency plane using the Short-Time Fourier Transform (STFT).
  2. Linearly interpolate the magnitude of the STFT by a factor Pt/Qt*Qp/Pp across the time dimension.
  3. Go over the phase of the STFT and make sure that the partial time derivative across the time dimension is preserved.
  4. Transform the modified STFT back into the time domain
  5. Re-sample the resulting waveform by a factor Qp/Pp to get the final waveform.

We definitely need some test data to try this out. I have recorded my own voice saying the following in Norwegian:

“Som vi ser har det blitt kuldegrader over omtrent hele landet”.

Translated to English this corresponds to something like: “As you can see, we now have temperatures below zero degrees across the whole country”. You can listen to the original sound clip in the player below.

This Matlab code implements the Theisen Transform following the step-by-step Phase Vocoder recipe above:

function y = theisen(x)
% Geir K. Nilsen, 2006

Ns = length(x);
Nw = 1024;  % Window width
hop = Nw/4; % Overlap width
Pt = 2; 
Qt = 5;
Pp = 5; 
Qp = 6;
r = Pt/Qt * Qp / Pp; % Tempo-pitch shift factor

win = hann(Nw, 'periodic');

Nf = floor((Ns + hop - Nw) / hop);

fframe = zeros(Nw,Nf);
pframe = zeros(Nw,Nf);

% Step 1: STFT
c = 1;
for i = 0:hop:((Nf-1)*hop);
    fframe(:,c) = 2/3*fft(x(1+i:i+Nw).*win');
    c = c + 1;

% Step 2 & 3: Linear interpolation & phase preservation
phase = angle(fframe(:,1)); 
c = 1;
x = [fframe zeros(size(fframe, 1),1)]; 
for i = 0:r:Nf-1;                        
    x1 = x(:,floor(i)+1);                
    x2 = x(:,floor(i)+2);
    scale = i - floor(i);
    mag = (1-scale)*abs(x1) + scale*(abs(x2)); 
    pframe(:,c) = mag .* exp(j*phase); 
    c = c + 1;
    phase_adv = angle(x2) - angle(x1); 
    % Accumulate the phase
    phase = phase + phase_adv;

% Step 4: synthesize frames to get back waveform. Known as the Inverse
% Short Time Fourier Transform.
c = 1;
Nf = size(pframe,2);
Ns = Nf*hop - hop + Nw;
y = zeros(1,Ns);

for i = 0:hop:((Nf-1)*hop);
    pframe(:,c) = real(ifft(pframe(:,c)));          
    y(1+i:i+Nw) = y(1+i:i+Nw) + pframe(:,c)'.*win'; 
    c = c + 1;

% Step 5: finally resample the waveform to adjust according
% to the pitch shift factor.
y = resample(y, Pp, Qp);

When applied to the original recording, the result is quite impressing. Listen to the modified sound clip below and judge yourself.


The Riddle

I was scanning through an old hard drive when I came across it. A large file of assembly code I had written many years ago. Its code section was tiny, but its data section huge.

Image credit:
Image credit:

It was my good old Linux audio player where the raw audio data was baked into the source itself. Or the other way around, a raw audio file with a built-in player. An interesting but sort of pathetic attempt to an executable audio file with no form of compression.

Skipping most of the data section (i.e. …), it looks like this:

; Minimalistic (or maximalistic?) Linux OSS audio player 
; by Geir K. Nilsen (2006)

dsp dd "/dev/dsp", 0
on  dd 1
fmt dd 0x00000010
sfr dd 44100
buf db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,...

global _start 
        mov eax, 5	    ; Open DSP for read/write. System call
        mov ebx, dsp	    ; no 5. Set pointer to dsp string
        mov ecx, 02	    ; O_RDWR is defined to be 2 according
	int 0x80	    ; to asm/fcntl.h

			    ; File descriptor number now in eax.
	push eax            ; Take four copies for later system
	push eax            ; calls.
	push eax
	push eax
	push eax
			    ; OSS configuration
	mov eax, 54	    ; Set stereo, sys call ioctl is 54
	pop ebx
	mov ecx, 0xC0045003 ; See man ioctl_list, 
	mov edx, on         ; SNDCTL_DSP_STEREO
	int 0x80
	mov eax, 54	    ; Set format, 16 bit little endian
	pop ebx		    ; Format of buf is 8 bit, but 2-by-2
	mov ecx, 0xC0045005 ; samples are multiplexed to 16 bits
	mov edx, fmt        ; stereo samples.
	int 0x80

	mov eax, 54	    ; Set sampling frequency, 44100 Hz.
	pop ebx
	mov ecx, 0xC0045002
	mov edx, sfr
	int 0x80	
	mov eax, 4	    ; Prepare and write to DSP.
	pop ebx
	mov ecx, buf
	mov edx, 0x000AC440 
	int 0x80	    ; ..and play!

	mov eax, 6	    ; Close DSP. Sys call number 6.
	pop ebx
	int 0x80

	mov eax, 1	    ; Exit
	mov ebx, 0 
	int 0x80 

The file can be downloaded using the link (wait until loaded completely, then copy-paste into a plain text file):

I tried to recall what audio could be included in the file. Must boot up Linux to find the answer. Then assemble the file, and execute it. But I only have Windows on my laptop these days, so need to install it. This calls for WMware, or will it work under Cygwin? Heck, is OSS still supported by the kernel? And what assembler to use, Nasm? Or was it gas back then?

Wait, I will just parse and extract buf instead, the long string of comma-separated numbers. All the required information is provided by my comments: 16-bits samples, little endian, stereo (2 channels), sampling rate of 44100 Hz. Must be an easy job in Matlab using fscanf() and sound(). On the other hand, to recognize what will be played can turn out to be tricky. Given the file size and sampling rate, not so many audible seconds there will be. But Shazam can probably help, since I am quite sure it is a song.

I decided to challenge my team instead. They can solve my riddle outside normal working hours. Good learning for them it might be. Speaking about killing two birds with one stone.

Later the same night, me having forgotten all about the audio riddle, senior software engineer Øyvind Rørtveit sent out an e-mail containing just a short and incomprehensible sentence – “Blame it on me”. Yikes, what has he done now? I Will never blame it on you buddy, but come on, why so tight-lipped?

Øyvind is one of the best programmers I have ever known. He is like Mel,

The Story of Mel

but also with the ability to understand and translate complex mathematical concepts into working code. More about him sometime later.

I grabbed the phone and called him. I asked what was going on, and he said, “Isn’t it correct?” — “Correct what?”, I responded. “The riddle”, he said with a disappointed voice. But I was confused and struggled to find the harmony in all this.

It turned out that the brilliant riddle-maker had completely lost the solution to his own riddle, and that Øyvind had to convince him of the answer. “Yes! You are right!” — “But no, I know the answer and it isn’t this”, I said with a hint of despair, simultaneously not able to tell him the actual solution.

But he was right, and after listening to the whole song after we hung up, it again reminded me why I had chosen this song as the solution to the riddle.

Simply because the lady is a genius.