+2  A: 

Perform an autocorrelation to find the fundamental frequency, measure the RMS level, find the first zero-crossing, and then try subtracting common waveforms at that frequency, phase, and level. Whichever cancels out the best (and more than some threshold) wins.

endolith
I think this is the most practical approach, assuming you also vary the phase of the comparison waveforms.
MusiGenesis
You could figure out the phase by finding a zero crossing first so you aren't wasting time shifting the waves to every possible phase.
endolith
+3  A: 

Do an FFT, find the odd and even harmonic peaks, and compare the rate at which they decrease to a library of common waveform.. peak... ratios.

endolith
This method seems more robust than working in the time domain, since you could still identify waves that had been through phase shift and filtering.
endolith
+4  A: 

You definitely want to start by taking an autocorrelation to find the fundamental.

With that, take one period (approximately) of the waveform.

Now take a DFT of that signal, and immediately compensate for the phase shift of the first bin (the first bin being the fundamental, your task will be simpler if all phases are relative). Now normalise all the bins so that the fundamental has unity gain.

Now compare and contrast the rest of the bins (representing the harmonics) against a set of pre-stored waveshapes that you're interested in testing for. Accept the closest, and reject overall if it fails to meet some threshold for accuracy determined by measurements of the noisefloor.

Dave Gamble
You'd need to keep track of that phase shift, too, though, to identify different polarities of waves, right?
endolith
Indeed. That'll be a lot easier too if you've compensated for the phase of the fundamental.
Dave Gamble
It would be better to take the FFT of several periods of the wave, as far as noise rejection.
endolith
Alternatively, if you can align them, you would do better to sum several periods of the wave (and average) and then FFT.
Dave Gamble
A: 

arm yourself with more information...

I am assuming that you already know that a theoretically perfect sine wave has no harmonic partials (ie only a fundamental)... but since you are going through an ADC you can throw the idea of a theoretically perfect sine wave out the window... you have to fight against aliasing and determining what are "real" partials and what are artifacts... good luck.

the following information comes from this link about csound.

(*) A sawtooth wave contains (theoretically) an infinite number of harmonic partials, each in the ratio of the reciprocal of the partial number. Thus, the fundamental (1) has an amplitude of 1, the second partial 1/2, the third 1/3, and the nth 1/n.

(**) A square wave contains (theoretically) an infinite number of harmonic partials, but only odd-numbered harmonics (1,3,5,7,...) The amplitudes are in the ratio of the reciprocal of the partial number, just as sawtooth waves. Thus, the fundamental (1) has an amplitude of 1, the third partial 1/3, the fifth 1/5, and the nth 1/n.

kent
+2  A: 

This answer presumes no noise and that this is a simple academic exercise.

In the time domain, take the sample by sample difference of the waveform. Histogram the results. If the distribution has a sharply defined peak (mode) at zero, it is a square wave. If the distribution has a sharply defined peak at a positive value, it is a sawtooth. If the distribution has two sharply defined peaks, one negative and one positive,it is a triangle. If the distribution is broad and is peaked at either side, it is a sine wave.

A: 

I think that all of these answers so far are quite bad (including my own previous...) after having thought the problem through a bit more I would suggest the following:

1) take a 1 second sample of the input signal (doesn't need to be so big, but it simplifies a few things)

2) over the entire second, count the zero-crossings. at this point you have the cps (cycles per second) and know the frequency of the oscillator. (in case that's something you wanted to know)

3) now take a smaller segment of the sample to work with: take precisely 7 zero-crossings worth. (so your work buffer should now, if visualized, look like one of the graphical representations you posted with the original question.) use this small work buffer to perform the following tests. (normalizing the work buffer at this point could make life easier)

4) test for square-wave: zero crossings for a square wave are always very large differences, look for a large signal delta followed by little to no movement until the next zero crossing.

5) test for saw-wave: similar to square-wave, but a large signal delta will be followed by a linear constant signal delta.

6) test for triangle-wave: linear constant (small) signal deltas. find the peaks, divide by the distance between them and calculate what the triangle wave should look like (ideally) now test the actual signal for deviance. set a deviance tolerance threshold and you can determine whether you are looking at a triangle or a sine (or something parabolic).

kent
Assuming this is anything like real audio data, counting zero-crossings won't work very well. As Dave Gamble pointed out, autocorrelation is the best way to determine an audio signal's fundamental frequency.
MusiGenesis
Unless the signal is really noisy, counting zero crossings should work. It would be better to measure the distance between zero crossings, throw out any outliers, and average, though.
endolith