Hacker Public Radio

Your ideas, projects, opinions - podcasted.

New episodes Monday through Friday.


HPR4638: Simple Podcasting - Episode 3 - Analyzing and Filtering

Hosted by Whiskeyjack on 2026-05-13 01:00:00
Download or Listen

This show has been flagged as Clean by the host.

01

This is the third in a four part series on simple podcasting.

02

In this episode we will cover the following topics:

Analysis of audio noise problems and filtering methods used to deal with specific problems that we may find.

Command line recording.

Command line playback.

Getting information about an audio recording.

03 Introduction

When I did my first couple of podcasts I didn't notice that there was a quiet high pitched whine or buzz in the background.

Nobody complained about it, but I thought I could do better in subsequent episodes.

04 Creating an Audio Sample

If you have a similar problem, the first step is to find out where it is coming from.

If there is no audible noise where you are recording, there is a good chance the problem is in the microphone or another part of the audio system.

Plug in your microphone and record 2 or 3 seconds of quiet audio where you do not speak into the microphone or make other noise.

05

You will need a minimum amount of data in order to analyze it.

For a flac file sampled at 44.1 kHz, 2 to 3 seconds of data should be enough.

To get a sample of just electronic noise you can put the microphone in a drawer or somewhere like that if you want to be sure of getting a quiet signal.

Any sound recorded in this way should be mainly from the microphone or other electronic elements in the analogue pathway.

To get a sample of possible ambient noise, such as fans, make sure the microphone is in the open air in an area which is representative of where it will be when you are recording.

--------------------

06 Analyzing using Fourier Transforms

Next you need to look at the wave form.

At this point I will describe this using Audacity.

I will show other ways later, but Audacity is actually the easiest if you are starting from nothing.

You don't need to become an expert in Audacity to use it, just follow the steps I will describe.

I myself don't know how to use Audacity beyond using this one feature.

07

We are going to analyze the sound spectrum in our sample.

The technique being used is a Fourier Transform.

A Fourier transform, often called an "FFT" for fast fourier transform, is a mathematical method of showing a signal in terms of frequency along the x axis instead of time.

This allows us to spot troublesome noise frequencies which appear when we don't want them to.

The FFT is a very common mathematical technique which is widely used in signal processing, not just in audio.

08

There is software which will create pretty coloured animations of sound waves, but this is not what you want. These are simply decorative patterns and won't tell us what we want to know.

--------------------

09 Using Audacity

Install Audacity if you haven't already.

Start Audacity.

Select file > import > audio,

then navigate to your sample and select "open".

The file should load.

10

In the wave form part of the window, click anywhere and then type Ctrl-S to select all data points.

The chart should turn a slightly darker colour.

From the menu, select Analyze > Plot Spectrum.

A new window will open, showing magnitude in db on the Y axis, and frequency in hertz on the x axis.

For "algorithm" be sure it is set to "spectrum"

11

There are now two settings that we need to play with while we look for problems.

One is "size"

The default for this is 1024.

The other is "axis".

The default for this is "log frequency".

--------------------

12 What to Look For

What we are looking for are large obvious spikes that stand out in the data.

Since our test signal has very little to no actual audio data, any spikes should represent electrical or other noise that doesn't belong there.

13

I have found two combinations of settings to be most helpful in finding problems.

These are

Size 2048, axis linear frequency.

Size 32768, axis log frequency.

14

A small size value can help very narrow spikes stand out from the background more, while a large size value can help separate spikes from surrounding noise.

A linear frequency axis can help with seeing all spikes across the full frequency range, while a log frequency axis can help to better see what is happening in the often very crowded lowest frequency range.

--------------------

15 A Real Example of an Audio Problem

If you have good audio equipment you may find nothing obvious. If you cannot hear any noise in the signal, there may be none of any consequence and there is nothing for you to do.

16

However, in my case I found two main problems and one lesser one.

One problem was a spike at 60 Hz, which is the AC line frequency.

There is also a lesser problem of a collection of a broad frequency range of noise below 60Hz.

Both of these however will be taken care of by the basic filtering that we looked at earlier so we do not need to worry about them here.

17

The other main problem is I had a large spike at every 1 kHz interval from 1 kHz to 19 KHz.

This was noise generated within the head set electronics, or the result of noise on the USB power supply.

This is the product of a cheap headset.

18

These spikes are not very large compared to the volume of my voice, but if I do the same sort of analysis of samples where I am speaking, they appear in the intervals between words.

This results in a high pitched whine or buzz.

This was the source of the background noise or buzz in my first two podcast episodes.

I need to get rid of this.

19

One option would be to get a better microphone, but, well, that wouldn't be any fun would it. It would also cost money and I don't want to spend any of that if I don't have to.

If you analyze your own signal, you may find a different pattern, or even no noise at all.

If you did not find anything when shielding your microphone from ambient audio noise, repeat the same test but with the microphone exposed to acoustic noise in the room.

--------------------

20 Advanced Filtering

The next step is to figure out how to get rid of this noise.

I have called this section "advanced filtering", but we are actually just making use of a technique that was already covered in basic filtering.

21

To deal with the remaining spikes we can use additional "band reject" filters, each of which removes a specific frequency at 1 kHz intervals from 1 kHz to 12 kHz.

We will use this in combination with the filtering that we have already done previously, so we don't need to worry about anything above 12 kHz as we already remove that with a low pass filter.

After a small amount of experimenting I came up with the following.

22

Because I am applying a total of 16 filters, 4 for basic filtering and 12 to deal with the specific microphone problems that I have, I have broken up the filters into separate strings.

I then generate the 12 new band reject filters from a template.

Note that I don't show the "de-esser" filter here.

I would recommend adding it as a separate step after doing the sort of filtering we are talking about here.

23

Rather than reading out multiple lines of bash script, I will post them in the show notes.

I will give a brief description of them here which you can refer to when reading the show notes.

The FFMPEG and Sox versions are very similar in concept so I don't need to go over the Sox version in detail. See the show notes for it.

FFMPEG Version

Here's the FFMPEG version.

# The high and low pass filters.

hlpfil="highpass=f=80, lowpass=f=12000"

# Band reject filters filter for 60Hz and another for 50Hz.

linefil="bandreject=f=60:width_type=h:w=20, bandreject=f=50:width_type=h:w=20"

# Create a series of band reject filters, from 1 kHz to 12 kHz.

# Change or remove this part if your recording hardware does not require it.

ftemplate="bandreject=f=%s000:width_type=h:w=100"

kilospikefil=$( seq 1 12 | xargs printf "$ftemplate," )

# Using ffmpeg

ffmpeg -i input.flac -af "$hlpfil, $linefil, $kilospikefil" output.flac

24

There are a total of 5 lines of bash script.

In the first line, we create a string called "hlpfil" which is just the high and low pass filters copied from our previous discussion on basic filtering.

In the second line, we create a string called "linefil" which is just the simple bandreject filters to cover 50 and 60 hertz AC line noise filters also from basic filtering.

25

In the third and fourth lines, we create a string called "kilospikefil" containing the new filters.

The "f" parameter represents the frequency we are targeting.

The "w" parameter represents the "width" of the frequency range we are filtering in terms of hertz.

The filter is applied gradually rather than with a sharp cut-off, so to get more filtering action we need to have larger width. In this case I decided to hammer the spike quite aggressively and so used a relatively wide width of 100 hertz. Testing with a voice file did not show any noticeable distortion, so it's an acceptable solution.

26

For this filter we need to create a dozen filter command so we use the shell "seq" command to generate a sequence of numbers from 1 to 12.

We then pipe that into the xargs command which applies each number to the next command.

The next command is "printf", which takes the number it gets from xargs and applies it to the "ftemplate" string template in a manner very similar to C programming printf string templates.

27

We also have a comma in there to separate each of the individual filters.

We then surround this with a $ and () so we can run the command and capture the output into a variable.

Then we call ffmpeg and pass it the filters we created by putting the variable names inside a double quoted string, separated by commas.

All of this will be in the show notes, so don't worry about trying to get the exact details right now.

Sox Version

Here's the Sox version.

# The high and low pass filters.

sxhlpfil="highpass 80 lowpass 12000"

# Band reject filters filter for 60Hz and another for 50Hz.

sxfilter="$sxhlpfil $sxkilospikefil bandreject 60 20 bandreject 50 20"

# Create a series of reject filters filters, from 1 kHz to 12 kHz.

sxftemplate="bandreject %s000 100"

sxkilospikefil=$( seq 1 12 | xargs printf "$sxftemplate " )

# Using SOX.

sox input.flac output.flac $sxhlpfil $sxfilter $sxkilospikefil

28

The Sox version is very similar with the exception that the command arguments representing the filters must not be in quoted strings as Sox wants to see them as separate arguments instead of parsing a string.

--------------------

29 Confirming the Effect

If we apply the above filters and look at this headset noise output file in the Audacity spectrum analyzer we will now see that these noise spikes are almost completely gone.

We can now confirm how well this works by using a test audio file. Any normal short voice audio file will do for this. Just talk into the microphone normally and create a voice sample file that is 5 or 10 seconds long, or whatever you feel comfortable with.

30

With the original unfiltered voice audio I can hear a distinct high pitched whine overlaying the voice.

With the filtered audio that whine or hum is not detectable.

If we then look at the voice file in the Audacity spectrum analyzer, we can see distinct "notches" at the 50 Hz and 60 Hz frequencies, and at every 1 kHz from 1 kHz to 12 kHz.

These notches are narrow enough that they won't cause a noticeable problem with voice signals.

If we apply this filter to voice samples, the buzz or whine is gone and the voice signal sounds fine.

Despite using a very cheap microphone, I now have acceptable quality audio for a podcast.

31

Again I want to emphasize that in this instance I am dealing with deficiencies with my hardware instead of buying a better microphone.

These additional filters are intended to deal with the specific hardware problem I am facing.

You don't need these additional filters if you cannot detect an audible problem.

On the other hand, if you have a different problem you may wish to deal with a different set of frequencies.

Finding these problems is the reason for using a spectrum analyzer.

32

FFMPEG has other filtering methods as well.

However, as I didn't end up using them I can't really do an adequate job of describing them.

If anyone has used them successfully, they are welcome to make a podcast on the subject.

--------------------

33 Completing the Process

With these new filters added into the middle of the processing steps, you can now complete the processing by doing the de-essing, normalizing, and review steps as described in the previous episode.

--------------------

34 Command Line Recording

I will now cover a separate topic, which is recording using command line programs.

I am covering it in this episode as it is a short topic and it is convenient to talk about it here.

35

As well as using GUI based recording programs such as Gnome Sound Recorder, it is possible to record podcast episodes using command line tools such as FFMPEG.

As for why you may wish to use command line tools to record audio, there are several reasons.

One is that you may simply prefer to do it this way because it pleases you to do so.

Another is that it allows the recording step to be included in a script that encompasses other parts of the process, automating what may have otherwise been separate manual steps.

36

However, if you don't find these arguments particularly compelling, then I'm not going to attempt to persuade you to use the command line to record audio. I am doing this part of this episode out of a desire to have a bit of fun and I probably won't be using it much myself.

I will however use one of these methods to record this part of this episode.

37 Recording with FFMPEG - The Basics

One of the common command line tools you can use is FFMPEG, a package which I have previously mentioned with respect to filtering audio files.

Here is an example of how to record using FFMPEG. We call FFMPEG specifying the audio input system as the FFMPEG input, and then specify a file to output to.

38

# Record audio.

ffmpeg -f pulse -i default ff.flac

39

Press 'q' to stop.

This uses pulse audio on Linux for input "-f pulse",

and the default input "-i default".

However, this does not specify the the sample rate or mono recording. To do that we need to add a few more parameters as in the following

40

ffmpeg -f pulse -i default -ac 1 -ar 44100 ff.flac

41

"-ac 1" specifies mono output

"-ar 44100" specifies 44.1 khz bit rate.

42 Playback with FFMPEG - The Basics

FFMPEG can also play back music. In this case however we need to call the "ffplay" program rather than FFMPEG itself.

To play an audio file, simply call ffplay and give it the name of the audio file as an argument to the command.

For example:

43

# Play an audio file.

ffplay podcast.flac

44

We can also call it with the "autoexit" option, which tells ffplay to automatically exit when the audio file has finished playing.

ffplay -autoexit ff.flac

45

-autoexit means Exit when the audio file is done playing.

46

To exit in the middle of the recording, press "q' or ESC.

To pause the playback, press "p" or space bar.

To decrease the volume press "9" or "/".

To increase the volume press "0" or "*".

47

To seek forward 10 seconds, press the right cursor button.

To seek backward 10 seconds, press the left cursor button.

To seek forward 1 minute, press the up cursor button.

To seek backward 1 minute, press the down cursor button.

48

The "0" and "9" keys mentioned above are those on the top row of the keyboard, not the ones on the separate numeric pad.

49

While the recording is playing, a graphical window will open which shows a cascading waveform based on the current content. This is purely decorative and does not serve any particularly useful purpose.

--------------------

#!/bin/bash

# Record a podcast episode segment.

# Get the next file name.

# First we check if any matching file patterns exist. If they don't,

# then we create the first one starting counting at 1.

fcount=$( ls [0-9][0-9].flac 2>/dev/null | wc -l )

if (( $fcount < 1 )); then

fname="01.flac"

else

# If there are any matching file patterns, we find the highest number

# and increment it by 1.

filenum=$( ls [0-9][0-9].flac 2>&1 | cut -d. -f1 | sort | tail -1 )

newfilecount=$(( 10#$filenum + 1 ))

fname=$( printf "%02d.flac" $newfilecount )

fi

echo "Recording to: $fname"

# Record using ffmpeg.

# This makes use of pulse audio and the input is the default audio input.

# The sample rate is set to 44.1 kHz, and it is recorded as mono (1 channel).

ffmpeg -f pulse -i default -ar 44100 -ac 1 $fname

echo "Recorded audio to: $fname"

# Report on basic information about the audio file that was just recorded.

ffprobe -hide_banner $fname

--------------------

50 Sox - Not so Good

I did not find the recording or playback features of Sox to be as useful as those of FFMPEG, so I won't bother to cover them here.

--------------------

51 Getting Information About an Audio Recording

There are also command line tools which can be used to retrieve information about audio recordings.

52 FFMPEG Version

With FFMPEG this is called "ffprobe". For example:

53

ffprobe hpr4566.mp3

54

This will print out a lot of information about FFMPEG itself. To skip that use the hide_banner option.

55

ffprobe -hide_banner hpr4566.mp3

56

This will print out information about the audio recording. This will include things like the duration, bit rate, sample rate, stereo or mono, etc.

If the author added metadata tags to the file, it will also show those. HPR add things like the title, author, copyright license, comment, etc. You can extract the ones you want using something like grep and cut.

57 Sox Version

Sox has a similar feature, called "soxi".

58

soxi ff.flac

59

However, it may not work on mp3 files if you do not have an mp3 handler for it installed.

--------------------

60 Conclusion

In this episode we took a brief look at an example of how to solve an audio problem through filtering.

We looked at how to use Audacity to find where the problems were.

We then looked at how to apply filters to remove these sources of noise.

We also looked at how to record podcasts and get information about audio files using command line tools.

61

In the next episode we will look at alternatives to Audacity for analyzing audio. While Audacity works just fine, this is an opportunity to have a bit fun with some gratuitous hackery.

62

This has been the third episode in a four part series on simple podcasting.

--------------------

--------------------

Full Audio Processing Pipeline

This version includes the special filters used to fix my headset problems.

Use the version from the previous episode if you do not have the same

audio hardware problems.

#!/bin/bash

# Full processing pipeline for making simple podcasts.

# ======================================================================

# Concatenate multiple flac files into a single flac file.

# This is used to combine podcast recorded segments into a single

# flac file for uploading to HPR.

concataudio ()

{

outputname="$1"

# First create the list file.

printf "file '%s'\n" [0-9][0-9].flac > podseglist.txt

# Now concatenate them

ffmpeg -f concat -safe 0 -i podseglist.txt "$outputname"

rm podseglist.txt

}

# ======================================================================

# Basic and advanced filters.

filter ()

{

inputfile=$1

outputname=$2

# Using ffmpeg.

# The high and low pass filters.

hlpfil="highpass=f=80, lowpass=f=12000"

# Band reject filters filter for 60Hz and another for 50Hz.

linefil="bandreject=f=60:width_type=h:w=20, bandreject=f=50:width_type=h:w=20"

# Create a series of band reject filters, from 1 kHz to 11 kHz.

ftemplate="bandreject=f=%s000:width_type=h:w=100"

kilospikefil=$( seq 1 11 | xargs printf "$ftemplate," )

# Using ffmpeg

ffmpeg -i $inputfile -af "$hlpfil, $linefil, $kilospikefil" $outputname

}

# ======================================================================

# De-Essing.

deessing ()

{

inputfile=$1

outputname=$2

option=$3

# De-essing filter.

ffmpeg -i $inputfile -filter_complex "deesser=i=0.5:m=0.5:f=0.5:s=$option" -b:a 336k -sample_fmt s16 $outputname

}

# ======================================================================

# Normalizing the audio to EBU R128 standard for review using ffmpeg.

normffmpeg ()

{

inputfile=$1

outputname=$2

# Normalize to EBU R128 standard.

ffmpeg -i $inputfile -af loudnorm=I=-17:TP=-2.0:LRA=4.0 -ar 44.1k $outputname

}

# ======================================================================

# Output an MP3 version to help with reviewing.

mp3convert ()

{

inputfile=$1

# Get the name of the file and then create the output file name.

j=$( basename $inputfile ".flac" )

outputname="$j"".mp3"

# Convert to MP3.

ffmpeg -i $inputfile $outputname

}

# ======================================================================

# Concatenate the separate audio files.

concataudio fullpod-unfiltered.flac

# Basic filtering.

filter fullpod-unfiltered.flac filtered.flac

# De-essing. This is the version to send for publishing.

# The third argument should be "o" for de-essing, or "i" for pass through without de-essing.

deessing filtered.flac fullpod.flac o

# Normalized for review.

normffmpeg fullpod.flac fullpod-norm.flac

# Output an MP3 copy for review.

mp3convert fullpod-norm.flac

--------------------

--------------------

Provide feedback on this episode.

HPR Comments

Mastodon Comments



More Information...


Copyright Information

Unless otherwise stated, our shows are released under a Creative Commons Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0) license.

The HPR Website Design is released to the Public Domain.