All posts for the month November, 2021

Had an application where I had to convert a ton of CSV logs to JSON format for ingestion by another system. I didn’t have good luck with Python, so I tried PHP. Posting this work here in the hopes it will help someone else. Keep in mind, this is a basic example and the following warning applies should this be considered for production use:

Stern Warning: This example assumes the source of the CSV files is doing any error handling before writing records in the CSV source files. It is also assumed that the source CSV files each have a KEY as the first row in each file so that fields in the data rows are properly represented. If this is not the case in your application, the below example will require further enhancement. Only use the example as shown if you are confident that your application/process creating the CSV source input files is doing proper data validation and handling!

The Code: (convert.php)

// php function to convert csv to json format.  Takes 2 arguments:
// arg1 = input csv file     arg2 = output json file

$fin = $argv[1];
$fout = $argv[2];

function csvToJson($fin,$fout) {
    // File Handles
    if (!($fp = fopen($fin, 'r'))) {
        die("Can't open file...");

    $fo = fopen($fout, 'a');

    // Processing
    $key = fgetcsv($fp,"0",",");

    while ($row = fgetcsv($fp,"0",",")) {
            $json = array_combine($key, $row);
            $json = json_encode($json) . "\n";
            fwrite($fo, $json);

    // release file handles
    // phone a friend

To use this script, here’s an example from my shell:

for FILE in /var/convert/csv/*.csv; do php /var/convert/convert.php $FILE /var/convert/json/$(basename $FILE).json; done

If this helped you, or if you have suggestions for refinement, please let me know in the comments below! 🙂


The technology discussed in this article has serious potential to land you in trouble under possible state and federal wiretap statutes. Your use of this information is at your own risk and I cannot be held liable for your failure to use this information in accordance with local/federal laws. You agree that any use of this information is at your risk and that you agree to follow laws in your area when using the materials and software technology discussed herein. This information is published for educational purposes only.

I wanted to build a super sensitive microphone to pickup sounds and transmit them via my cloud streaming server so that I could monitor an area remotely. The project goals were:

  • had to be inexpensive, compared to commercially available “off the shelf” offerings
  • had to use existing open source components (software/hardware)
  • had to be sensitive enough to pickup sounds from adjacent rooms
  • had to be wireless
  • had to use an efficient sound codec to transmit picked up audio
  • had to be easy to operate

Parts List:

  • Raspberry Pi Zero 2W (any small ARM board should work, but it’s got to have wifi) $15
  • 32GB MicroSD card – you can use smaller, but this is what I had on hand $8
  • Dupont ribbon cables – $1
  • 5V wall wart – I had these on hand, but you should be able to source for about $5
  • MEMS Mic element – (INMP441) – $4
  • Polycarbonate project case – (BUD Industries PIP-11760-C) $15
  • Raspbian OS 11 – (based on Debian Linux) FREE
  • Liquidsoap audio toolkit – (installed via OPAM) FREE

Total Project Cost: $48USD Here’s a picture of the finished unit (I built 2):

Mic McCloud

The mic element is held in place by a bead of super glue around the edge. In this project, I did not build a stereo mic, but rather just a mono pickup. (I only wired one mic element and set it to the LEFT channel) It would be fairly easy to wire a second element and do a stereo version. Refer to the wiring diagram for how to wire a stereo version:

For stereo, wire as shown with two elements. For mono, just wire one element as LEFT

Here’s a picture of the hardware kit. I built two units, so what is shown are two Raspberry Pi Zero 2W and two INMP441 MEMS elements:

Why build one, when you can build 2?

The Final Production Version

Here’s a close-up of the MEMS mic element:

Don’t let the tiny hole fool you, this mic hears EVERYTHING!


For software, I wanted to keep things simple: no GUIs, no top heavy libraries or applications, just bare Linux, minimal ALSA config, I2S driver, and one of my favorite audio tools: liquidsoap. Follow these steps to prepare your system:

Deploy your OS

I used Raspbian OS 11 as the OS, it is based on Debian so that makes it a familiar and logical choice. I won’t get into how to deploy the OS, as that’s not really the scope of this article, but you can get this information on the raspbian website. Once you have the OS deployed to your card, you will need a temporary Pi to use that has more RAM (NOTE: the Raspberry Pi Zero 2W only has 512MB ram, which is NOT enough to do the compilation of the software you will need. I suggest you put the SD card into a Pi 3 or Pi 4 with at least 2GB of RAM and do all the steps herein before finally transferring the card to your Raspberry Pi Zero 2W for production use.

Install required packages

Now that you have your OS loaded on your SD card, put the card in your temporary Pi unit and perform these steps logged in as your default “pi” user:

sudo apt update
sudo apt install opam screen aptitude make gcc git bc libncurses5-dev bison flex libssl-dev debhelper-compat linux-headers dkms
sudo usermod -aG audio pi

At this point, go ahead and reboot the Pi by issuing: sudo reboot. When the Pi reboots, we need to uncomment the source deb repository so we can install libfdk-aac-dev from the source packages. Debian is not able to distribute these as binary packages because AAC+ codec is not free. We can however easily get it from the source packages and have debhelper compile it for us. Follow these steps as your “pi” user:

sudo nano /etc/apt/sources.list

(uncomment the source deb package repo as shown):

deb bullseye main contrib non-free rpi
# Uncomment line below then 'apt-get update' to enable 'apt-get source'
deb-src bullseye main contrib non-free rpi

(save the file in nano by doing CTRL-O then exit by doing CTRL-X), and run the following command:

sudo apt update
sudo apt-get source libfdk-aac-dev
sudo apt-get --build source fdk-aac

(after the packages are downloaded and built, you will have the following packages in your current directory), run the following commands to finally install them:

sudo dpkg -i libfdk-aac2_2.0.1-1_armhf.deb
sudo dpkg -i libfdk-aac-dev_2.0.1-1_armhf.deb

At this point, we should have the minimum necessary packages installed. We can now go ahead and setup the I2S driver:

sudo nano /boot/config.txt

(you need to ensure the following are set as shown):


(after any changes, save the file and exit)

sudo dpkg -i snd-i2s-rpi-dkms_0.0.2_all.deb
sudo modprobe snd-i2s_rpi

(edit /etc/modules and add the following, then save and close the file):

sudo reboot

Last, we create a very simple ALSA config file:

(open for editing: /etc/asound.conf and REPLACE all contents with, save and close the file):

pcm.!default {
        type hw
        card 0
ctl.!default {
        type hw
        card 0

At this point, your Pi is ready to support I2S sound input. Reboot the Pi once more and then you can do the following command to verify:

arecord -l
**** List of CAPTURE Hardware Devices ****
card 0: sndrpii2scard [snd_rpi_i2s_card], device 0: simple-card_codec_link snd-soc-dummy-dai-0 [simple-card_codec_link snd-soc-dummy-dai-0]
  Subdevices: 0/1
  Subdevice #0: subdevice #0

The last software bits we need to add are Liquidsoap via OPAM:

opam init
opam switch create 4.10.0
opam depext taglib mad lame vorbis cry samplerate ocurl liquidsoap fdkaac alsa
opam install taglib mad lame vorbis cry samplerate ocurl liquidsoap fdkaac alsa
sudo ln -s ~/.opam/4.10.0/bin/liquidsoap /sbin/liquidsoap

At this point Liquidsoap should be installed, and now we can create a .liq file to define the output stream. I assume you already have an icecast server and this article assumes you know how to setup an icecast streaming server and connect sources to it. To define your mic’s liquidsoap stream output create a file in “pi”s home directory with the following content:

input = mksafe(input.alsa()) 
input = amplify(10.0,override="replay_gain",input)
input = filter.iir.butterworth.low(frequency = 10000.0, order = 8, input)
input = filter.iir.butterworth.high(frequency = 200.0, order = 8, input)

  %fdkaac(channels=2, samplerate=44100, bandwidth="auto", bitrate=32, afterburner=true, aot="mpeg4_he_aac_v2", transmux="adts", sbr_mode=false),
  port=8000, password="P@55w0rd", genre="live",
  description="LIVE", mount="/mic2",
  name="MIC 2", user="source",
  url="", input)


Once you have this file set, you can test your install by doing:

liquidsoap -v mic.liq

If all is good, you should see the stream start. To automate it to start at boot time, you can place a file in /etc/cron.d:


@reboot         pi      screen -d -m liquidsoap -v /home/pi/mic.liq

Save the file and reboot. Your live mic stream should now startup after reboot. You can then use any media endpoint you wish to tune in the stream and listen to the mic, or record the stream using VLC

After you have the Mic setup, you may wish to enable the overlay filesystem to protect your SD card from excessive writes or unplanned power loss. To do so:

run raspi-config >> Performance Options >> Overlay FS. Set /boot to read only if asked, once this is done, reboot the Pi. Your mic and now be unplugged without worry of corrupting your SD card.

A quick howto for setting up liquidsoap to create your own online radio station and transmit using the efficient and awesome AAC+ audio codec. I’ve made it super simple to create an encoder that can take program audio and create an AAC+ encoded stream that you can send to one or more icecast distribution servers – to broadcast around the world! Read on:

Install an up to date OS (as of this writing, Ubuntu 20.04 is what I used). Just the bare command line only server install is all you need. You could even do this on a Raspberry Pi with a USB audio pickup and then connect your program audio from the output of your processed audio chain. Installation is quite simple by following these commands:

sudo apt install opam screen
opam init
opam switch create 4.10.0
opam depext taglib mad lame ffmpeg vorbis cry samplerate ocurl liquidsoap fdkaac alsa
opam install taglib mad lame ffmpeg vorbis cry samplerate ocurl liquidsoap fdkaac alsa
sudo ln -s ~/.opam/4.10.0/bin/liquidsoap /sbin/liquidsoap

Answer Yes to any yes/no prompts, and once complete, you will have a working copy of liquidsoap with full AAC+ support. Now that liquidsoap is installed, you can now create a .liq file to set the parameters of your stream. Once you create this file, launching your stream becomes quite simple. Here’s an example .liq file. You can change any of the parameters to suit your needs:


input = mksafe(input.alsa()) 

  %fdkaac(channels=2, samplerate=44100, bandwidth="auto", bitrate=96, afterburner=true, aot="mpeg4_he_aac_v2", transmux="adts", sbr_mode=false),
  port=8000, password="my.P@ssw0rd", genre="live",
  description="LIVE", mount="/live",
  name="MY STATION NAME", user="source",
  url="", input)

Now that you have your liquidsoap and .liq file installed and ready, simply launch a screen session and invoke the following command:

liquidsoap -v ./myliqfile.liq

You can disconnect from your screen session and the stream should still continue running. To reconnect to your detached screen session, you can simply do: screen -r You can have multiple streams running on the same host by opening more screen sessions and invoking additional liquidsoap instances. If running multiple screens, you can list them by running: screen -ls