Friday, June 27, 2014


Whoops, I haven't posted in over a week!  I guess I haven't really felt like spending even more time sitting at my computer.

So since my first app is finished, I've spent most of the past week working on a new project.  It was much more... theoretical than the last one, so I spent the entire week simply trying to create a proof of concept to see if it was actually feasible.  Turns out... it wasn't.  So I spent the entire week working and I have nothing to show for it besides a bunch of code that I will probably never look at again.

I was trying to create an app that sampled noise from the microphone and cancelled it when listening with headphones.  If everything worked out, I was going to try to make a noise-cancelling music player or something similar.  This is another reason I haven't posted in a while; this has never been done before, so I didn't really want to give away anything that I was working on.

Looking back, I suppose that there is a reason it has never been done before.  I guess the way that noise-cancelling headphones work is that there is a direct relationship between the outer microphone and the inner speaker, so that any incoming sound is immediately cancelled.  I knew I didn't have this kind of control in Android; the closest you can get is by using AudioRecord and AudioTrack to work with the individual samples of sound, and those require a buffer.  The buffer has a minimum size (>1), so there's no way you can process the incoming sound before the outside noise has already hit your ear.  So I didn't even try to mess with a direct relationship.  That wasn't my original idea anyway, so I wasn't discouraged.

My plan was to take a fairly small sample and apply the Fast Fourier Transform to get it in the frequency domain.  From there, I was hoping that some frequencies would stand out more than others, and I could use those to create a generic noise wave that could cancel a decent amount of the incoming noise.  However, after transforming the signal, nothing really stood out.  The noise was comprised of frequencies basically spanning the whole spectrum.  I should have just stopped right there, because that should have tipped me off that my next idea would not work either.

Plan B was to use the Levenberg-Marquardt algorithm to try to fit a generic signal directly to the data.  If you aren't familiar with the algorithm, the TL;DR is that it is used to minimize the sum of squares between empirical data and any arbitrary function.  It iteratively adjusts the function's parameters until the function is considered "close enough" or until the parameters stop changing very much.  So I figured, "sound is just a bunch of sinusoidal waves put together, so I can use a linear combination of sinusoids as the input."  The problem here is that noise doesn't really look like "a bunch of sinusoidal waves."  Noise is so random that it would take thousands of different waves, each with a different frequency and/or phase, to even come close to modelling it.  And the Levenberg-Marquardt algorithm has a complexity somewhere in the order of O(N^2) (Disclaimer: that is a complete guess).  In my implementation, trying to fit a function with 7 parameters to a 1-second sample took about 25 seconds.  I was aiming for 10-15, and the resulting function was not even close because of the randomness of the noise.

So that's my past week in a nutshell.  It's a bit disappointing, because it would have been awesome to create something with that level of technical complexity, instead of the rather trivial stuff I have been working on.  Oh well, nothing I can do about it I guess.

Oh yeah, now I'm working on a game.  I'll write more about it soon (assuming I remember to post).

No comments:

Post a Comment