Analyzing an SSTV recording…

March 12, 2014 | SSTV | By: Mark VandeWettering

Inspired by this webpage, I decided to write a simple zero-crossing analyzer, just like his. The code turns out to be remarkably simple, and would allow me to reverse engineer modes that aren’t adequately documented. I called this program “analyze”:

[sourcecode lang=”C”]
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <sndfile.h>

int
main(int argc, char *argv[])
{
SNDFILE *sf ;
SF_INFO sfinfo ;
float *inp ;
float t, dt ;
float x ;
int i ;
float pcross=0, cross, freq ;

if ((sf = sf_open(argv[1], SFM_READ, &sfinfo)) == NULL) {
perror(argv[1]) ;
exit(1) ;
}

fprintf(stderr, "%s: %d channel%s\n", argv[1], sfinfo.channels,
sfinfo.channels > 1 ? "s" : "") ;
fprintf(stderr, "%s: %dHz\n", argv[1], sfinfo.samplerate) ;
fprintf(stderr, "%s: %lld samples\n", argv[1], sfinfo.frames) ;

inp = (float *) calloc(sfinfo.frames, sizeof(float)) ;
fprintf(stderr, "::: reading %lld frames\n", sfinfo.frames) ;
sf_read_float(sf, inp, sfinfo.frames) ;
sf_close(sf) ;

dt = 1.0 / sfinfo.samplerate ;

for (i=0, t=0; i<sfinfo.frames-1; i++, t+=dt) {
if (inp[i]*inp[i+1] < 0) {
/* we have a zero crossing */
x = -inp[i] / (inp[i+1]-inp[i]) ;
cross = t + x * dt ;
freq = 1.0 / (2 * (cross – pcross)) ;
printf("%f %f\n", cross, freq) ;
pcross = cross ;
}
}
}
[/sourcecode]

The code is dead simple. It loads the sound file into memory and then figures out (via linear interpolation) the location of all the places where the signal crosses zero (via simple linear interpolation). Each time we have a zero crossing, we compute the frequency of the signal, which is just the reciprocal of twice the difference in the two latest crossing times. This program dumps out the time and frequency of each zero crossing, which you can then easily visualize with gnuplot. Like this:

test

Next step: generate some example sound files, and use them to reverse engineer some of the less well documented modes.