I am faced with a tricky challenge: To extract binary data from an iPhone magnetic strip card reader. This is what the magnetisation on the card looks like:

enter image description here

Here is the .WAV the iPhone receives when you swipe a card (don't get your hopes up too much, it is a bonus loyalty card ;)). That's three swipes by the way, at different speeds. This is the raw SInt16 dump for the swipe I am using.

Someone seems to have done it here but the actual data I capture isn't particularly easy to process.

The reading starts (and finishes) with an indeterminate number of 'zeros ' -- note that the wave only repeats after 2 ZEROS have been collected, this represents N-S followed by S-N:

enter image description here

(note that each of the three lines represents me swiping a different card; the bottom card in this image is 15 years old, so the magnetic field is clearly severely degraded in some places, not visible in this shot)

This will allow an algorithm to ascertain a clock tick.

The magnetic field reverses on each clock tick. Also for a binary 1, the magnetic field reverses exactly in the middle of a tick:

enter image description here

The sequence always starts with a 1101+0(parity bit) start sentinel. You can pick this out in all three readings in the above graph. It is indicated more clearly in the cosmodro article I linked at the top of the question.

Here is an example of magnetic degradation (taken further along on the bottom card reading): enter image description here

I am trying to figure out a sensible way to convert this waveform into its corresponding binary sequence.

I have found one PDF that goes into some detail, but I can't figure out the algorithm they are using.

This PDF contains one interesting image: enter image description here

If I could extract the red and blue lines as per this diagram, I could use either one of them to extract the data, but I can't figure out the logic behind the construction.

So this is my question: How do I extract the binary sequence?

PS. Note that the swipe speed is not going to be constant. So once the clock has been determined, in needs to be constantly adjusted from one tick to the next.

PPS. Would autocorrelation catch pairs of ticks? (seeing as ticks will alternate N-S S-N ... )

EDIT (June '12): I needed a lot of help on this one, but finally I have completed a solid reader ( http://www.magstripedecoder.com/ ). Thanks for everyone who helped! I recommend #musicdsp on IRC's efnet channel for anyone dedicated enough to take the challenge of getting to grips with the maths -- it's really really hard!


This is called biphase mark code, and you have to focus on the zero-crossings instead of the pulse amplitudes. You have multiple zero crossings per pulse, though, because of the low-cut filters inherent to the pickup and the phone's mic input. Yours drop farther than this between transitions, and cross zero:

enter image description here

You could restore a more pulsy shape by using a low-boost filter:

enter image description here

and then measure the pulse lengths by how long they spend above some threshold. Maybe a better idea is to differentiate the input to make the transitions into large spikes, take the absolute value, and detect them when they go above some threshold:

enter image description here

Then measure the time between pulses, and when the time between two pulses is approximately the same as the last two pulses, it's a 0, when it's approximately half of what it was between the last two pulses, it's a 1.

The magnetic degradation you talk about should be easy to remove with a low-pass filter.

  • $\begingroup$ Thanks! I have found some very interesting correlations working with the second derivative which I will post in due course. Can you elaborate on the low-boost filter? I don't have any idea how I would implement this... $\endgroup$ – P i Nov 28 '11 at 18:27
  • $\begingroup$ @endolith Could you please add better tags for the question? I tagged it differential-coding, based on your answer, but you know this topic better. $\endgroup$ – Lorem Ipsum Nov 28 '11 at 19:06
  • $\begingroup$ @yoda: Haha no I don't. I just learned about it a few hours ago to write this answer. $\endgroup$ – endolith Nov 28 '11 at 19:17
  • $\begingroup$ @endolith I just came across this - this is nice - however can you explain this 'low boost filter'? Seems really interesting, and google isnt of much help... $\endgroup$ – Spacey Jun 15 '12 at 0:27
  • $\begingroup$ @Mohammad: Just a filter that boosts the low frequencies while leaving the highs unchanged. I think I used a graphic equalizer in Adobe Audition. Try a shelving filter crca.ucsd.edu/~msp/techniques/latest/book-html/node142.html $\endgroup$ – endolith Jun 15 '12 at 10:43

This was quite a challenge. I tried at least four approaches before cracking it. This is how I did it:

enter image description here

I start by smoothing the data (first reading) with a simple...

x_new = 0.9 * x_prev + 0.1 * x_in

... IIR filter. I do this in both directions (second reading). This gets rid of all the fuzzy noise, however it creates discontinuities which come back with a vengeance in the derivatives.

I then get all derivatives up to the fourth (third and fourth readings represent the third and fourth derivative), and create a new function:

g(x) = f'''(x)^2 + k*f''''(x)^2

Why? because I noticed that by the time we get to the third derivative, what we have is effectively a sinusoid inside an envelope:

enter image description here

...and everyone knows from high school that:

sin^2 + cos^2=1 

enter image description here

and that sin and cos differentiate into each other:

enter image description here

Hence the implied envelope can be recovered.

Why derivatives 3 and 4? basically each higher derivative purifies the signal. That which is sinusoidal remains sinusoidal (just shifts phase 90° so sin->cos etc) whereas that which isn't falls away.

I wanted to use 11 & 12 or something crazy, but the derivatives fall apart quite quickly, 4 is the highest I can get before things go haywire, even then the little derivative lines you see in the picture are heavily smoothed.

This produces a wonderful little bump on every flux transition (fifth reading).

Next I walk through the turning points, rejecting duds (sixth reading)..

Finally I walk through the maxima (seventh reading), evaluating whether each skip is a half step or a whole step, and then reconstruct the binary.


EDIT: It is now several months since I completed this project. the most difficult challenge is to construct some transform that isolates flux transitions; technically speaking, ' retrieving the amplitude envelope '. this is done by constructing the π/2 phase shift signal from the original (this is also known as quadrature signal). then E(t)^2 = S(t)^2 + Q(S(t))^2.

To get the quadrature signal, I simply did an FFT, and rotated each bin a quarter turn, then recombined the modified spectral components.

There is a lot of confusing abusive terminology in this field; keywords are ' analytic signal ', ' Hilbert transform '... I've avoided using those keywords as different disciplines assign different meanings to them.

There is a much smarter way of achieving this amplitude envelope using digital filters, thus avoiding the Fourier transform. This allows the algorithm to run on very low powered microcontrollers.

This process produces a waveform that should have a unique bump over each flux transition.

Decoding this waveform into a binary sequence is still a nontrivial task. the complexity and this component is algorithmic rather than mathematical; the difficulty is comparable.

All in all this is an extremely difficult problem. It took me the best part of three months to achieve on their performance algorithm. I will in the fullness of time document my approach and produce a publicly available decoder engine.

  • 1
    $\begingroup$ Read heads can be affected by adjacent magnetic domains as well as the transition currently under the read head, which tends to push the read transitions back and forth in time, depending on the surrounding bit pattern. $\endgroup$ – hotpaw2 Nov 29 '11 at 1:06
  • $\begingroup$ note that this technique is not reliable. Although it gives excellent results for most of the track, it fails to produce a unique bump for each flux transition early on. ie it creates a double bump. I'm guessing because the input waveform is not suitably sinusoidal at this point. so I'm still looking for techniques. $\endgroup$ – P i Jan 9 '12 at 19:14
  • $\begingroup$ Just curious, what other definitions of "analytic signal" or "Hilbert transform" have you found? If you're looking for the envelope of the signal, you can find that by first converting it to a (complex) analytic signal. There are a few ways to do this, but what you've indicated isn't typically used. $\endgroup$ – Jason R Apr 16 '12 at 17:45
  • $\begingroup$ @JR some sources seem to define the analytic signal as the 90° phase shift ie Quad(f(x)). others as f(x) + i.Quad(f(x)). I think I've seen the Hilbert transform defined as both of these also. Not completely sure, so I've stuck with a notation that should be unambiguous. I'm interested in other techniques of retrieving the envelope of the signal; dsp.stackexchange.com/questions/424/… seems the right place to pursue this thread. $\endgroup$ – P i Apr 16 '12 at 18:17
