Timed Audio Field Recorder with a Raspberry Pi Cirrus Logic Audio Card

The problem is still the same as it was this time last year – the birds get up before I do in the Spring and I can only be one place at a time. Automatic recording devices let me scout locations in parallel.

A timed field recorder needs to be cheap, because somebody might nick it, it needs to be weather-resistant because it’ll be stuck outside, and it needs to be low-power, because 13A mains sockets are rare outside. Oh and it needs to be standalone, and not part of some cloud, because mobile Internet is ratty and expensive.

tl;dr the hardware performance is good but software support is dire. You can make this work but it isn’t fun at all. If you can use something like a USB stereo audio in board then do it rather than use this Cirrus Logic Audio Card, particularly if you have mains power available. I like the Behringer UCA202 and it works with the Pi

A Raspberry Pi and A Wolfson audio card sort of fitted the bill, but the Wolfson Audio card is no more. I say sort of, because I’m still looking at about £70 for a Pi 1, the audio card and enough odds and sods to power it. You can buy a Zoom H1 for about £80, although there’s still a bit more cost in powering it for long times, keeping the water out and making up some gizmo to pretend to be you pressing the big rec record button early in the morning.

But with the Pi I get to drive the recorder via cron and ssh, and transfer the files via the internet or mobile data in some places. Even if I don’t get a case, though they are to be had for the Pi/CL Audio card combination…

I don’t actually have the Cirrus Logic variant of this, I figured I may as well learn more about it using the Wolfson card on a Raspberry B since they are the same underlying hardware it seems. However, the Cirrus Logic variant scores by being A+ and B+ compatible, since these draw less power, and also it seems the new card can be used with a PiFace RTC in the field whereas the old Wolfson board won’t fit with the PiFace RTC because of the pogo pins and the P5 port. For deployment outside I’ll go with the new card.

I was cynical about that Wolfson board because shortly after I bought mine Wolfson was taken over by Cirrus Logic. In the following year they have produced a replacement, that will fit on the Pi A+ and B+ which are far less power-hungry than the old-skool Pi A and B, and they got rid of those infernal pogo pins Wolfson used to connect to the P5 port. There is no P5 port on the A,B+, but the GPIO bus is much wider, so they didn’t need them.

The manufacturer support still stinks and you have to grub about with compiling kernels or pre-built image files. There’s a fantastic post on Element 14 where poster JC has made a load of these work and got 20 out in the field recording birds, they have generally sorted all the problems down to keeping the water out. So I figured I’d dust off my old card and see if I can get it out there by Spring, now that there’s a future in these boards again. I was going to use them to scout recording locations. However, I can get the old one set up at the edge of the Oak Tree farm in Rushmere at try some remote recordings, I have a little more power available there.

Fortunately the same software build supports both the Wolfson board and the Cirrus one, as well as the old and new Pis (but not the Pi 2). At the moment the best route seems to be take the 4.1.x precompiled kernels from Reichl’s website as described here and patch these onto a stock Raspbian jessie-lite kernel from here

Steffen Müller’s summary notes on how to get the Cirrus Logic audio card going on Jessie helped me greatly.

Much to my surprise, that worked for me, even eliminating the confusion of the ratty play-only built-in sound card that always gets in the way

[email protected]:~ $ aplay -l
**** List of PLAYBACK Hardware Devices ****
card 0: sndrpiwsp [snd_rpi_wsp], device 0: WM5102 AiFi wm5102-aif1-0 []
  Subdevices: 1/1
  Subdevice #0: subdevice #0

Sweet. The combined rig draws 450mA @ 5V which isn’t so good, but it’s sort of livable with. Using the Cirrus Logic variant with a Raspberry A+ will get that down. I also issued the

sudo apt-mark hold raspberrypi-bootloader

command to stop future kernel updates clobbering the results of my hard work. Of course that will mean I will fall behind as time goes on, as Steffen said

In my opinion the hardware drivers of the Cirrus Logic Audio Card never left an experimental state and the card is not usable in production.

but the trouble is that this is the only record-capable sound board for the Pi in town. Now that the Pi USB system is better you can of course use a USB sound card, something like the venerable Behringer UCA202 will work fine with the Pi, but the combination is physically huge. And you still only have a stereo line level input. But certainly if you want decent audio in without all the hurt associated with the Cirrus Logic/Wolfson board that’s an easier and perhaps cheaper way to go, although you don’t get the array of inputs and outputs of the Cirrus Logic.

Recording with the Wolfson card

You first have to issue the Cirrus shell script to set up the input you want. I modded the Record_from_DMIC.sh script from

#!/bin/bash

# Record from onboard stereo DMICs to AP

# Set the digital input gain to -6dB
amixer $1 -Dhw:sndrpiwsp cset name='IN2L Digital Volume' 116
amixer $1 -Dhw:sndrpiwsp cset name='IN2R Digital Volume' 116
# Configure the input path for HPF with a low cut off for DC removal
amixer $1 -Dhw:sndrpiwsp cset name='LHPF1 Input 1' IN2L
amixer $1 -Dhw:sndrpiwsp cset name='LHPF2 Input 1' IN2R
amixer $1 -Dhw:sndrpiwsp cset name='LHPF1 Mode' High-pass
amixer $1 -Dhw:sndrpiwsp cset name='LHPF2 Mode' High-pass
amixer $1 -Dhw:sndrpiwsp cset name='LHPF1 Coefficients' 240,3
amixer $1 -Dhw:sndrpiwsp cset name='LHPF2 Coefficients' 240,3

to

#!/bin/bash

# Record from onboard stereo DMICs to AP

# Set the digital input gain to -6dB + 20dB
amixer $1 -Dhw:sndrpiwsp cset name='IN2L Digital Volume' 186
amixer $1 -Dhw:sndrpiwsp cset name='IN2R Digital Volume' 186
# Configure the input path for HPF with a low cut off for DC removal
amixer $1 -Dhw:sndrpiwsp cset name='LHPF1 Input 1' IN2L
amixer $1 -Dhw:sndrpiwsp cset name='LHPF2 Input 1' IN2R
amixer $1 -Dhw:sndrpiwsp cset name='LHPF1 Mode' High-pass
amixer $1 -Dhw:sndrpiwsp cset name='LHPF2 Mode' High-pass
amixer $1 -Dhw:sndrpiwsp cset name='LHPF1 Coefficients' 240,3
amixer $1 -Dhw:sndrpiwsp cset name='LHPF2 Coefficients' 240,3

and sure enough, I got more gain from those mics. They are noisy so I got more noise as well 😉 They would be absolutely fine for voice. What is interesting is perhaps I get the DSP filtering too, I am assuming that two high pass filters are allocated, one to the left and one to the right, possibly 240Hz third order but the dearth of information means that’s guesswork.

After that it’s relatively easy. The command

arecord -Dhw:sndrpiwsp -r 48000 -c 2 -f S16_LE -d 5 testy.wav

gives you a 5 second stereo 48kHz test recording in testy.wav. the -d sets the duration in seconds. I mounted a USB stick and recorded onto that, because SD cards are slow and failure prone.

Setting the input levels for an analogue mic

If you have the Cirrus Logic variant, you can enable plug in power for an electret mic on the Line in port. That doesn’t work on my Wolfson card. I modded the Cirrus scripts to push the analogue programmable gain amp as high gain as possible. Levels are then usable for close miked speech, but for wildlife sound or pretty much anything else you will need more gain from an analogue mic preamp, another 20dB is probably about right. At this point you should be seriously asking yourself why not use a Behringer UCA202 and stick your preamp in front of the line inputs 😉

There’s no point in pumping up the digital gain after the PGA else the noise will just come up

#!/bin/bash

# $1 added to support 1st line argument. i.e. "./Record_from_linein.sh -q" will stop all the control information being displayed on screen

#Record from onboard Line Input to AP
# +20dB input PGA gain, give it all we've got
amixer $1 -Dhw:sndrpiwsp cset name='IN3L Volume' 31
amixer $1 -Dhw:sndrpiwsp cset name='IN3R Volume' 31

# better THD in normal mode vs lower noise floor in high performance
amixer $1 -Dhw:sndrpiwsp cset name='IN3 High Performance Switch' on
# Configure the input path for 0dB Gain,  HPF with a low cut off for DC removal
amixer $1 -Dhw:sndrpiwsp cset name='IN3L Digital Volume' 128
amixer $1 -Dhw:sndrpiwsp cset name='IN3R Digital Volume' 128
amixer $1 -Dhw:sndrpiwsp cset name='LHPF1 Input 1' IN3L
amixer $1 -Dhw:sndrpiwsp cset name='LHPF2 Input 1' IN3R
amixer $1 -Dhw:sndrpiwsp cset name='LHPF1 Mode' High-pass
amixer $1 -Dhw:sndrpiwsp cset name='LHPF2 Mode' High-pass
amixer $1 -Dhw:sndrpiwsp cset name='LHPF1 Coefficients' 240,3
amixer $1 -Dhw:sndrpiwsp cset name='LHPF2 Coefficients' 240,3
# Configure the Audio Interface and volume 0dB
amixer $1 -Dhw:sndrpiwsp cset name='AIF1TX1 Input 1' LHPF1
amixer $1 -Dhw:sndrpiwsp cset name='AIF1TX1 Input 1 Volume' 32
amixer $1 -Dhw:sndrpiwsp cset name='AIF1TX2 Input 1' LHPF2
amixer $1 -Dhw:sndrpiwsp cset name='AIF1TX2 Input 1 Volume' 32


# The following command should be used to test
# arecord -Dhw:sndrpiwsp -r 44100 -c 2 -f S32_LE <file>

 

Nice DSP, but not for us…

Cirrus have a datasheet on the WM1502 but it’s more hardware that software oriented, it describes the registers and that there are dedicated filter channels but not how to configure these, and of course we’d be doing that through the driver. On this thread the problem is basically you need to sign a NDA and pay up for a dev kit.

At the current time, the toolkit to develop code for the DSP is very expensive and requires various legal agreements to be in place.

We (Wolfson) are actively looking at ways to try and reduce this cost and to make the DSP more accessible to individuals.

I’m afraid that’s the only info I have at the moment.

I guess that’s not going to happen, then. This is a piece of gear you have to be grateful if you can get going at all, and the only reason you put up with it is because it does what it does do well. You can get some hints from wm1502.c but without knowing what the DSP microcode is meant to do it’s all guesswork, like everything else to do with this board.

I am tempted to measure the analogue frequency response with a few different settings of the 240,3 parameter. I’m not trying to make a graphic equaliser out of it, and the biggest thumps to wind blast need to be filtered before they overload the input amps 2 but it would be nice to be able to use higher order filtering on demand. Firing up alsamixer is impressive – on the record side I have

part of the massive alsamixer panel

part of the massive alsamixer record panel

SPKR (the usual record from the speaker out path?)
DRE Low [100] (dynamic range expansion low threshold I guess)
DRE High [100]
EPOUT Di [28} (no idea)
EQ1 B1 [50] (presumably a five band equaliser – where do I set frequency bands?)
EQ1 B2 [50]
EQ1 B3 [50]
EQ1 B4 [50]
EQ1 B5 [50]
EQ2 B1..5[50]
EQ3 B1..5[50]
EQ4 B1..5[50]
HPOUT1 Digital[28] (this corresponds to 0dB, seems a stereo signal)
HPOUT1 Digital[28] (this corresponds to 0dB, seems a stereo signal)
IN1L [0] (Left analogue line input at a guess, gain right down)
IN1L Dig[28] (Left digital input, gain 0dB, this is the MEMS Dmic)
IN1R [0] (Right analogue line input, gain right down?)
IN1R Dig[28] (Rightdigital input, gain 0dB, this is the MEMS Dmic)
IN2L [0] (Left analogue line input at a guess, gain right down)
IN2L Dig[91] (Left digital input, gain 29dB?)
IN2R [0] (Right analogue line input, gain right down?)
IN2R Dig[91] (Right digital input, gain 29dB?)
IN3L [0] (Left analogue line input at a guess, gain right down)
IN3L Dig[28] (Left digital input, gain 0dB?)
IN3R [0] (Right analogue line input, gain right down?)
IN3R Dig[28] (Rightdigital input, gain 0dB?)
Noise Gate Threshold[15] (-90dB)
Noise Generator[0](-123dB thankfully)
SPKDAT1[28,28](0dB,0dB – no idea what this is)

tinkering with the Cirrus Use Case scripts and seeing what happens

Like the rest of this card, the shell scripts are obscure. Take that LHPF1 instruction, which I would hazard a guess is give me a 240Hz high pass filter, third order. I amended the script, allocated the noise generator as a test source, and tried different filter coefficients, like so

#!/bin/bash

#Noise Generator
amixer $1 -Dhw:sndrpiwsp cset name='Noise Generator Volume' 14

# Set the digital input gain to -6dB + 40dB
#amixer $1 -Dhw:sndrpiwsp cset name='IN2L Digital Volume' 186
#amixer $1 -Dhw:sndrpiwsp cset name='IN2R Digital Volume' 186
# Configure the input path for HPF with a low cut off for DC removal
amixer $1 -Dhw:sndrpiwsp cset name='LHPF1 Input 1' 'Noise Generator'
amixer $1 -Dhw:sndrpiwsp cset name='LHPF2 Input 1' 'Noise Generator'
amixer $1 -Dhw:sndrpiwsp cset name='LHPF1 Mode' High-pass
amixer $1 -Dhw:sndrpiwsp cset name='LHPF2 Mode' High-pass
amixer $1 -Dhw:sndrpiwsp cset name='LHPF1 Coefficients' 240,3
amixer $1 -Dhw:sndrpiwsp cset name='LHPF2 Coefficients' 254,5
# Configure the Audio Interface and volume 0dB
amixer $1 -Dhw:sndrpiwsp cset name='AIF1TX1 Input 1' LHPF1
amixer $1 -Dhw:sndrpiwsp cset name='AIF1TX1 Input 1 Volume' 32
amixer $1 -Dhw:sndrpiwsp cset name='AIF1TX2 Input 1' LHPF2
amixer $1 -Dhw:sndrpiwsp cset name='AIF1TX2 Input 1 Volume' 32
amixer $1 -Dhw:sndrpiwsp cset name='DMIC Switch' off

In alsamixer the noise generator settings go from 0 to 100. So I tried 50, and got loads and loads of noise, maxed out. What actually happens when you look at the cruft that gets spat back at you is

numid=115,iface=MIXER,name='Noise Generator Volume'
  ; type=INTEGER,access=rw---R--,values=1,min=0,max=22,step=0
  : values=14
  | dBscale-min=-132.00dB,step=6.00dB,mute=0

where it becomes apparent that the maximum setting for this thing is 22 in its own arbitrary units, presumably all the other stuff tells alsamixer to remap 0-22 to whatever it wants to show. Hence I selected a middling value of 14 for the noise. On to the filters,

numid=101,iface=MIXER,name='LHPF1 Mode'
  ; type=ENUMERATED,access=rw------,values=1,items=2
  ; Item #0 'Low-pass'
  ; Item #1 'High-pass'
  : values=1
numid=102,iface=MIXER,name='LHPF2 Mode'
  ; type=ENUMERATED,access=rw------,values=1,items=2
  ; Item #0 'Low-pass'
  ; Item #1 'High-pass'
  : values=1
numid=89,iface=MIXER,name='LHPF1 Coefficients'
  ; type=BYTES,access=rw------,values=2
  : values=0xf0,0x03
numid=90,iface=MIXER,name='LHPF2 Coefficients'
  ; type=BYTES,access=rw------,values=2
  : values=0xfe,0x05

so my assumption that the value for the filter frequency is hertz is clearly wrong, it is a straight decimal representation of a 8-bit hex value. Nice to have the mode explained though – I can use LHPF1 in low or high-pass by setting mode. So I reset these to 240,3 (original cirrus) and 240,5 for the right channel, expecting a fifth order filter

changing the coefficients make a difference I guess

changing the coefficients makes a difference I guess – the magenta trace is the RHS

Ho hum, more as if the second parameter changes frequency. So I tried

amixer $1 -Dhw:sndrpiwsp cset name='LHPF1 Coefficients' 240,3
amixer $1 -Dhw:sndrpiwsp cset name='LHPF2 Coefficients' 120,3

and now the right channel becomes full scale sinewave at fs/2, and it’s time to give up. Somewhere, in the specification of the Cirrus driver that we aren’t privy to there’s a table of what all this means. Without that it is arbitrary guesswork. At least I seem to be able to control the switching and routeing functions, and volume. So it isn’t all a waste of time, but that DSP isn’t going to be doing anything much for me.

Overall the card is worth it for its compactness and freeing up the USB port of an A+ to use a read-only SD card and save recordings to a USB stick. It will be more compact than the UCA202 variant. The Raspberry Pi could do with a decent sound card, but this isn’t it, because of the terrible software support. Maybe it will be third time lucky for Cirrus and they will release a Hat which will automatically install the drivers. We aren’t there yet.

Notes:

  1. HiFi world clock it in at £220!
  2. which obviously isn’t going to happen on the digital mics, I was just using them for fun 😉

Leave a Reply

Your email address will not be published. Required fields are marked *