Electronic Voice Phenomena, or EVP, are "voices" detected and recorded by ghost hunters using electronic audio recording equipment.

Here's an example of EVP, courtesy of Hayley Stevens (from her website Hayley is a Ghost). Can you figure out what's supposedly being said?

Voice Recorder

Supposedly ghosts can talk in a way that humans can't hear, but that can be picked up and recorded by some modern dictaphones (more properly called a Dictation Machine or Voice Recorder). A more boring, but plausible, explanation for this phenomenon is that some dictaphones have a setting that, when the audio level is low, cranks up the gain on the input, in order to try to amplify the audio. This would be helpful, for example, if someone using a dictaphone walked away from it. Automatically increasing the gain when this happens would help to ensure a consistent audio volume during playback, despite the source audio having a varying volume.

This gain increase has the potential to cause the dictaphone to pick up more than just quiet voices. It will also amplify any internal electronics noise being created by the dictaphone's internal electronics. It is these spurious noises that are believed to be a common source of the "ghost voices" that ghost hunters end up capturing.

I wondered if I could write a simple recreation of this by wiring a PC's microphone into its speakers, via a DSP filter to increase the gain. With modern day web technology, this can all be done in a browser. Below is my simple effort to recreate EVP, with a slider to change the gain of the incoming audio. Just slide the slider to the right to increase the volume, which should cause some ungodly noises to emanate from your PC.

Volume: 1 %

Spirit Box

Station: Dimes on Mars offline stream

Number of Stations: 6

Switches per second: 2

Code

Here's the Vue component I put together to make this happen.

Voice Recorder

<template>
	<form>
		<button type='button' v-on:click="start">{{status}}</button>
		<h2>Volume: {{volume}}</h2>
		<input id="slider" type="range" min="-1" max="10" v-model.number="power" :title="volume" />
	</form>
</template>

<script>
	export default {
		data() {
			return {
				power: -1,
				filter: null,
				destination: null,
				status: 'Play'
			};
		},
		computed: {
			gain() {
				return Math.pow(10, this.power - 1);
			},
			volume() {
				return (this.gain * 100).toLocaleString() + ' %';
			}
		},
		methods: {
			start: function() {
				if (this.status == 'Play') {
					if (!this.destination) {
						if (navigator.getUserMedia) {
							navigator.getUserMedia(
								{audio: true},
								(stream) => {
									const audioCtx = new AudioContext();
									const source = audioCtx.createMediaStreamSource(stream);
									this.filter = audioCtx.createGain();
									this.filter.gain.value = this.gain;
									this.destination = audioCtx.destination;
									source.connect(this.filter);
									this.filter.connect(this.destination);
									this.status = "Pause";
								},
								function() {
									console.log("Error");
								}
							);
						}
					} else {
						this.filter.connect(this.destination);
						this.status = "Pause";
					}
				} else {
					this.filter.disconnect(this.destination);
					this.status = "Play";
				}
			}
		},
		watch: {
			gain: function(val, old) {
				if (this.filter) this.filter.gain.value = val;
			}
		}
	};
</script>

<style scoped>
	#slider {
		width: 80%;
		margin-right: 1em;
		margin-bottom: 2em;
	}
</style>

Spirit Box