This is going to be a long answer.
I'm going to start with an analysis of your files and what you can do to improve the audio. I'll also try your files out on an algorithm I designed to detect heartbeats. After that, I'll describe what went into designing my algorithm and how it works. Then I'll make some general suggestions for how to get started with your own algorithm.
Analysis of existing files
I loaded each of your files into Audacity to listen to them and to see what the frequency content looks like. In general, you don't merely have a problem with static (white) noise. You have a lot of trouble with constant interference from what looks like the AC power frequency in your area (50Hz and harmonics.)
From worst to best:
Heavy interference from powerline noise. There is a heartbeat signal in there that I can see. It is too covered up with interference to be detected, though. Nothing much will save this recording. The 50Hz interference is too close to the actual signal to be separated.
Here again your biggest problem is interference from the 50Hz power line. At points, the signal is clean enough to pick out a heartbeat. If I run it through a very sharp low pass filter at 45Hz, the algorithm I use can pick out individual beats but even then there are stretches where the heartbeat is simply inaudible.
This file doesn't have the power line interference, probably because it was recorded outdoors. It can be deciphered much better than the others, although there are still sections where there is simply no signal to be detected. A steep low pass filter with a cutoff at 45 Hz gets almost perfect results from my algorithm. There are short sections where the signal is too weak to pick out of the remaining noise.
This file is also missing the power line interference. Occasional disturbances cause a beat to be lost here and there, but otherwise a very good recording.
Problems involved in detecting heartbeats
There are several basic problems involved in detecting heartbeats:
- What is a heartbeat? A heartbeat is composed of several sounds, most of which are hard to separate from background noises and interference. You have to pick a "feature" than can be reliably picked out of the garbage. Simply detecting the volume of the sound won't do (too many other things can be loud, too.) What I've found is that the "lub dub" sound is a short burst of frequencies between about 30Hz to 40Hz. That's what my algorithm looks for.
- Threshold - When have you really detected your feature that says there's been a heartbeat? The volume changes continuously, and so does the volume of the noise and interference. A fixed threshold won't do. Your threshold has to adapt to the background and the changed volume of the heartbeats. The volume of the heartbeats changes with each breath, and it changes as your microphone moves around on the chest. I have a really squirrely solution for the threshold problem.
- Noise - The algorithm must work in a fairly wide range of noisy conditions. The feature you look for should be fairly simple to pick out of nearly any noise. The algorithm I use does well up to about 20dB signal to noise ratio. It is insensitive to the absolute level of the heartbeat signal, but requires a fairly clean signal.
- Hardware - A functioning algorithm does you no good if it depends on the sensitivity and frequency response of the microphone. Whatever you do needs to work with any microphone on any phone. The algorithm I use is very nearly completely insensitive to the hardware. If the heartbeat is there, it will be found.
Point 3 is really the most important. Loud doesn't matter, absolute level doesn't matter. The whole thing lives and dies on how clean your signal is. Regardless of what algorithm you use, a clean signal is a must.
- No interference. If you are picking up power line hum, fix it. It's usually an electrical problem and can be solved with proper wiring and grounding.
- Reduce motion noise. In my experiments, I use an elastic band to hold the microphone on my chest.
- Reduce background noise. I use a small cardboard "biscuit" stuffed with cotton between the microphone and the elastic band. It is made of several rings of cardboard with a plastic covering. The back is also cardboard. The side facing my chest has only a layer of plastic between the cotton balls and the microphone. That greatly reduces the background noise.
How I detect heartbeats
The method I eventually came up with is built around some observations of some (really) clean recordings of heartbeats. What I found is that there's a sort of "burst" of frequencies for each "thump" of the heartbeat. If you filter out everything but the content of the burst, then you get a fairly reliable heartbeat detector. I use a bandpass filter for 24 to 44 Hz. That seems to deliver the best results. The range might depend on the person - I don't have enough samples to compare.
After the bandpass, I use a Hilbert transformation to get a continuous estimate of how loud the burst frequencies are. The Hilbert function gives two outputs that are rotated 90 degrees from each other. Square each, take the square root of the sum, and you have a continuous signal representing the amplitude of the "burst" frequencies. Apply a low pass filter to that to get rid of wild variations.
Getting the correct threshold was the real problem, and I tried several ways. I started with manually adjusting the threshold, but of course it changes as you breath and move so that didn't work well. I tried an automatic calibration, which helped but had to be repeated anytime the microphone moved. I tried all kinds of adaptive thresholds, and they all failed for various reasons.
What finally worked really well looks just absolutely stupid.
Take the log of the absolute value of the amplitude signal. Yes, take the logarithm of the amplitude (it doesn't matter what base logarithm you use.) Pass that through a high pass filter, and apply a fixed threshold to the output. That fixed threshold is not setting the absolute level of the signal. It is setting the signal to noise ratio. A lower value means "work with a lower signal to noise ratio" and a higher value means "require a higher signal to noise ratio." The end effect is "trigger if there is a frequency between 24Hz and 44Hz present and it is some fixed ratio louder than the current noise level."
This setup is pretty much insensitive to the absolute levels of the input signal. The frequency response of the microphone and the amplifiers pretty much doesn't matter. It adapts automatically for movement when breathing and when the microphone changes position.
This diagram shows the central part of the process:
That's a snippet of a Pure Data patch that I put together to develop the algorithm. The whole thing together with some example files is available on GitHub. If you want to experiment with it, you will need Pure Data Extended 0.43 to use the patch - it depends on several external libraries that PD Extended includes but which other versions don't.
Regardless of how you choose to implement your algorithm, you have to start by looking at the available signal in your recordings.
Look at them in the time domain (oscilloscope view) and the frequency domain (FFT.) Find out what your noise and your interference looks like.
Look at clean recordings and find characteristics that are different from the noise and interference. Find something that can be picked out with a filter of some kind.
Design a filter that can separate the characteristic from the noise.
Devise a method for adapting the threshold to the current noise level and signal level.
My method has drawbacks, of course. The biggest being that if there's no heartbeat it will "imagine" it is hearing one and start delivering false pulses. The independence from the absolute level and hardware variations comes at the cost of having to guarantee a certain minimum signal to noise ratio.