Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sndfile-spectrogram produces poor spectrograms for some inputs. #15

Closed
erikd opened this issue Nov 12, 2012 · 13 comments
Closed

sndfile-spectrogram produces poor spectrograms for some inputs. #15

erikd opened this issue Nov 12, 2012 · 13 comments
Assignees

Comments

@erikd
Copy link
Member

erikd commented Nov 12, 2012

For instance this pair of commands produces a spectrogram with a bunch of rubbish in it.

$ sndfile-generate-chirp -amp 1.0 -linear -from 22000 -to 26000 96000 10 chirp96.wav
Start frequency :  22000.0 Hz (1.439897 rad/sec)
End   frequency :  26000.0 Hz (1.701696 rad/sec)
$ sndfile-spectrogram chirp96.wav 800 600 chirp96.png
@martinwguy
Copy link
Contributor

I've tried changing the window function in case it was related to that, both with success

Kaiser window:
chirp96-kaiser
Nuttall window (enabled from oxbow code in the source):
chirp96-nuttall
Hanning window from WikiPedia { data [k] = 0.5 * (1.0 - cos(2.0 * M_PI * k / (datalen - 1))); }
chirp96-hanning
It looks from these that the Nuttall window gives better frequency-domain separation than Hanning, though Kaiser is even tighter that that.

Is this a property of the Kaiser window itself, to resonate at certain frequencies?
Zooming in on one of the frequency bands, it looks chaotic.
24025-24075:
chirp24025-24075-kaiser
24050-24056:
chirp24050-24056-kaiser

@erikd
Copy link
Member Author

erikd commented Dec 6, 2015

Thanks. Applied.

@erikd erikd closed this as completed Dec 6, 2015
@martinwguy
Copy link
Contributor

This issue is still with us unfortunately.
Analysing http://martinwguy.co.uk/test/50Hz.wav
sndfile-spectrogram --no-border --dyn-range=100 50Hz.wav 480 480 50Hz-kaiser-480-480.png
50hz-kaiser-480-480
With --nuttall:
50hz-nuttall-480-480
With --hanning:
50hz-hanning-480-480

Note: the above interpolate from spec_len==2880 to heignt==480. However, the results are just as bad at size 480x2880 so it doesn't look like the interpolator.

I'd like to get to the bottom of this. Erik, can you reopen this issue please?

@erikd erikd reopened this Dec 10, 2015
@erikd
Copy link
Member Author

erikd commented Dec 10, 2015

The is an extremely artificial signal. I think what you are seeing is the effect of the transient at the onset of sine tone.

@martinwguy
Copy link
Contributor

I don't think it's the onset (which is brusque, yes) because the erroneous vertical lines only appear when the FFT window only covers an area with pure 50Hz sine tone. It's only when a constant 50Hz tone is the only signal in town that the effect occurs, the same as with the "chirp" test piece. A gut felling says "integer overflow", but it can't be because we are in floating point world!

@erikd
Copy link
Member Author

erikd commented Dec 10, 2015

For the 50Hz signal, I wonder is the window length is too small to capture a full cycle of the sine wave.

@erikd
Copy link
Member Author

erikd commented Dec 11, 2015

A good experiment would be to do exactly this test for something around 200Hz> If there is no problem there, then reduce the frequency until it becomes a problem.

That might give us an idea what speclen should actually be.

@erikd erikd closed this as completed Dec 11, 2015
@erikd erikd reopened this Dec 11, 2015
@martinwguy
Copy link
Contributor

Thanks for the input.
Hypothesis: For the 50Hz signal, the window length is too small to capture a full cycle of the sine wave.
The test piece is at 44100 samples per second so a 50th of a second is 44100/50=882 samples. The above tests select spec_len==2880 so it has 3 cycles in its window.
Experiment: run the test on a 200Hz tone. It uses speclen=2880 again, so 1 cycle is 220 samples, 2880/220==13 cycles in-window
sndfile-spectrogram --no-border --dyn-range=100 200Hz.wav 480 480 200Hz-kaiser-480-480.png
200hz-kaiser-480-480
Observation: The defect persists so it's not that it has only part of a cycle in-window.

@martinwguy
Copy link
Contributor

Observation: It's very sensitive to tiny changes in --dyn-range. For the above tests, --dyn-range=100. Without --dyn-range the artifacts are replaced by a different kind of noise:
200hz-kaiser-480-200-nodyn
and changing dyn_range but a tiny amount radically changes the noise pattern:
--dyn-range=102:
200hz-kaiser-480-200-dyn102
Hypothesis: It's a defect in the colour mapping code, not in the FFT output.
Experiment: Try the test with --gray-scale
sndfile-spectrogram --no-border --dyn-range=100 --gray-scale 200Hz.wav 480 200 200Hz-kaiser-480-200-gray.png
200hz-kaiser-480-200-gray
Adding --gray-scale to the original "chirp96" testpiece also gives clean output.

Hypothesis confirmed! Something's going screwy in the colour-mapping code.

@erikd
Copy link
Member Author

erikd commented Dec 12, 2015

Ok, I'm going to break the get_colour_map_value function into a separate file and write some tests for it.

erikd added a commit that referenced this issue Dec 12, 2015
Martin Guy did a lot of investigative work that showed that the
colour map calculation was producing a bunch of strange artifacts.

    #15

The simple fix here seems to fix at least some of those.
erikd added a commit that referenced this issue Dec 12, 2015
Martin Guy did a lot of investigative work that showed that the
colour map calculation was producing a bunch of strange artifacts.

    #15

The simple fix here seems to fix at least some of those.
@erikd
Copy link
Member Author

erikd commented Dec 12, 2015

Please test commit:

commit 9ca586748b2029b86a9b225178153953e0698f1e
Author: Erik de Castro Lopo <erikd@mega-nerd.com>
Date:   Sat Dec 12 20:11:10 2015 +1100

src/spectrogram.c: Fix colour map calculation

I think that may have fixed it.

@martinwguy
Copy link
Contributor

Yes, that fixes all the above testcases.

@erikd
Copy link
Member Author

erikd commented Dec 12, 2015

Wonderful!

@erikd erikd closed this as completed Dec 12, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants