How to Resample Audio Using FFT or DFT
The first step is to verify that both your starting sample rate and your target sample rate are rational numbers.  Since they are integers they are automatically rational numbers.  If one of them wasn't a rational number it would still be possible to make the sample rate change, but it is a much different process and more difficult.

The next step is to factor the two sample rates.  The starting sample rate, in this case, is 44100, which factors to $2^2*3^2*5^2*7^2$.  The target sample rate, 16000, factors to $2^7*5^3$.  Thus, to convert from the starting sample rate to the target rate we must decimate by $3^2*7^2$ and interpolate by $2^5*5$.

The previous steps have to be done no matter how you want to resample the data.  Now let's talk about how to do it with FFT's.  The trick to resampling with FFT's is to pick FFT lengths that make everything work out nicely.  That means picking an FFT length that is a multiple of the decimation rate (441, in this case).  For the sake of the example, let's pick an FFT length of 441, though we could have picked 882, or 1323, or any other positive multiple of 441.

To understand how this works it helps to visualize it.  You start out with an audio signal that looks, in the frequency domain, something like the figure below.


When you're done with your processing you want to decrease the sample rate to 16 kHz, but you want as little distortion as possible.  In other words, you simply want to keep everything from the picture above from -8 kHz to +8 kHz and drop everything else.  That results in the picture below.


Please note that the sample rates are not to scale, they are just there to illustrate the concepts.

The beauty of picking an FFT length that is a multiple of the decimation factor is that you can resample simply by dropping portions of the FFT result, and then inverse FFT what is left.  In the case of our example you FFT 441 samples of data, which gets you 441 complex samples in the frequency domain.  We want to decimate by 441 and interpolate by 160 ($2^5*5$), so we keep the 160 samples that represent the frequencies from -8 kHz to +8 kHz.  We then inverse FFT those samples and presto!  You have 160 time domain samples that are sampled at 16 kHz.

As you might suspect, there are a couple of potential problems.  I will go through each one and explain how you can overcome them.


What do you do if your data is not a nice multiple of the decimation factor?  You can easily overcome this by padding the end of your data with enough zeros to make it a multiple of the decimation factor.  The data is padded BEFORE it is FFT'ed.
Even though the method I explained is very simple, it is also non-ideal in that it can introduce ringing and other nasty artifacts in the time domain.  You can avoid that by filtering the frequency domain data before dropping the high frequency data.  You do this by FFT'ing your filter of length $l$, padding your data (before FFT'ing it) with at least $l-1$ zeros (please note that the number of data samples and the number of padding samples must BOTH be a positive multiple of the decimation factor- you can increase the padding length to meet this constraint), FFT'ing the padded data, multiplying the frequency domain data and filter, and then aliasing the high frequency (> 8 kHz) results down into the low frequency (&lt; 8 kHz) results before dropping the high frequency results.  Unfortunately, since filtering in the frequency domain is a big topic in its own right, I won't be able to go into more detail in this answer.  I will say, though, that if you filter and are processing the data in more than one chunk, you will need to implement Overlap-and-Add or Overlap-and-Save to make the filtering continuous.


I hope this helps.

EDIT:  The difference between the starting number of frequency domain samples and the target number of frequency domain samples needs to be even so that you can remove the same number of samples from the positive side of the results as the negative side of the results.  In the case of our example, the starting number of samples was the decimation rate, or 441, and the target number of samples was the interpolation rate, or 160.  The difference is 279, which is not even.  The solution is to double the FFT length to 882, which causes the target number of samples to also double to 320.  Now the difference is even, and you can drop the appropriate frequency domain samples with no problems.