BBB and ADS InstantFM Music

So, I got a cheap FM USB radio tuner. The InstantFM Music USB modules from ADS.
I plug it into the BBB running kernel 3.14.19-ti-r24
I try running the QT 5.3.2 example for radio, but it fails to detect a tuner.
Is there a kernel build that supports kernel option radio-usb-si470x?
Or, do I download the kernel from git and build it with the new options?

OK, so you apparently do need to build the kernel and add radio support.
I added the option for Silicon labs Si470x USB radio and re-built the kernel. (3.14.19-ti-r27 this time)
I deployed the new kernel to the BBB and it now has a /dev/radio0 directory.

However, qt 5.3.2 doesn’t see it (I’m running the example under examples/multimedia/radio: sudo ./radio -platform eglfs)
I’ll keep digging…

Not much luck.
As far as I can tell, it should be working.
I installed the console radio application on BBB and it will scan stations, but never detects any.
I tried to get it work work on the BBB, Linux VM on my mac, a Windows 7 VM on the mac and the mac itself.
No luck.
Hopefully someone else has gotten this device to work.
For now, I’m admitting defeat.

I found some new information and got it to work better, but not quite.
It looks like this is an OSS device, so you need alsa-oss.
This creates the /dev/dsp and /dev/dsp1 files.
Also, since I have USB sound and USB radio tuner, the system doesn't know which should be primary.
It wants to choose the radio tune.
You will need the vid and pId of the devices.
You have to modify /etc/modprobe.d/alsa-base.conf

options and-usb-audio index=0,1 vid=0x0d8c,0x06e1 pid=0x000c,0x0a155

That will order the two devices in the proper order and make the USB sound the primary sound in the system.
That gets me further.
After installing the packages

sudo apt-get install libasound2 alsa-base alsa-utils alsamixergui alsaplayer-text alsaplayer-common firmware-realtek radio v4l-utils fmtools lirc alsa-oss oss-compat

I can see the /dev/radio
I can attempt to tune it using

v4l2-ctl -d /dev/radio0 --set-ctrl=volume=10,mute=0 --set-freq=90.1 --all

Which runs without error, but does not change the tuner value - it seems stuck at the max setting.

sox --endianness little -c 2 -S -r 96000 -t alsa hw:1 -t alsa -r 96000 hw:0

Just makes popping noises, like is it is not tuned.

It works!

The trick was: The firmware was bricked and needed to be restarted (unplugged & plugged back in after the system was configured & started up).
Once I got it restarted, I could power down & up and it would continue to work.

So, the trick to getting this device to work on the Beaglebone Black is the following:

Build a custom kernel and include the radio drivers for the si470x

install base image: bone-debian-7.6-console-armhf-2014-09-04-2gb.img on a SD card

On a linux box:

Load pre-requisites for building ti graphics SDK and build it for the kernel
#sudo apt-get install git build-essential device-tree-compiler lzma lzop u-boot-tools libncurses5-dev
#git config —global user.name “name”
#git config —global user.email “email”
#git clone https://github.com/RobertCNelson/ti-linux-kernel-dev.git
#cd ti-linux-kernel-dev
#git checkout 3.14.19-ti-r27
#./build_kernel

Select kernel modules to enable si470x radio tuner hardware (more stuff will be added after that)
Check Device Drivers → Multimedia Support → AM/FM radio receivers/transmitter support
Radio Adaptors will be added.
Check Radio Adaptors → Silicon Labs Si470x FM Radio Receiver Support
Check Radio Adaptors → Silicon Labs Si470x FM Radio Receiver Support → Silicon Labs Si470x FM Radio Receiver Support with USB

Build the kernel
Insert the SD card on the Linux system

#nano system.sh
MMC=/dev/sdb

Deploy the new kernel

#sudo ./tools/install_kernel.sh

Remove the SD card and insert into Beaglebone and boot it

Upgrade the image to latest repositories

#sudo apt-get update

#sudo apt-get upgrade

Install alsa sound drivers (support for playing wav and mp3)

#sudo apt-get install libasound2 alsa-base alsa-utils alsamixergui alsaplayer-text alsaplayer-common

Install FM radio tuner drivers

#sudo apt-get install firmware-realtek radio v4l-utils fmtools

Modify the ALSA config to allow the USB sound card to be the primary sound card
Skip this step is you are using HDMI or a cape as your sound card
USB Sound card = vid 0xd8c pid 0x000c (use dmesg to find the vid and pid of your device)
InstantFM = vid 0x06e1 pid 0xa155

#sudo nano /etc/modprobe.d/alsa-base.conf
options snd-usb-audio index=0,1 vid=0x0d8c,0x06e1 pid=0x000c,0xa155

#sudo reboot

After the reboot and login, if this is the first time you’ve attempted to use the device,
unplug it, wait a bit and plug it back in.
This will reset the device and make it functional.

Test the radio

Open a terminal and run radio to scan for stations and bring up an interface to select a station

#radio -s

To tune from the command line, use the following:

#v4l2-ctl -d /dev/radio0 --set-ctrl=volume=10,mute=0 --set-freq=90.1 --all

Open another terminal and run a mixer to set the volume levels

#alsamixer

Open another terminal to re-direct the audio stream from the USB tuner to the audio card

#arecord -D hw:1,0 -c2 --format=S16_LE -r48000 | aplay

You can change stations using radio (or v4l2-ctl), change volume using mixer

^^ this is now taken care of. :wink:

sudo apt-get update
sudo apt-get install linux-image-3.14.19-ti-r28

Regards,

Awwww,
Here I was thinking I was so clever!

So, just installing the kernel linux-image-3.14.19-ti-r28 will have the si470x module loaded by default? Sweet!

I’m glad it is baked into the new release now.

Makes setting it up much easier.

Yeap, i was just waiting for one user, before i enabled the 'media'
kitchen sink config, i think every "usb" multimedia device is now
enabled...

Regards,

A strange issue.
I can tune the radio using
v4l2-ctl -d /dev/radio0 -c volume=10,mute=0 -f 91.1 --all

I can then stream the radio audio to a file using
arecord -D hw:1,0 -c2 -fS16_LE -r48000 > audio.wav

When I play back the recorded file, it sounds great.
aplay audio.wav

I should be able to stream the audio live using
arecord -D hw:1,0 -c2 -fS16_LE -r48000 | aplay

however, all I get is a blip of noise each sample instead of the whole sample.
Something about piping the input from record to aplay is failing.
Anyone know what is going on?

Beaglebone Black
Debian 7.6 Kernel 3.14 Alsa drivers.
Sound card: USB sound adapter HW:0
Radio Tuner: USB InstantFM Radio HW:1

A strange issue.
I can tune the radio using
v4l2-ctl -d /dev/radio0 -c volume=10,mute=0 -f 91.1 --all

I can then stream the radio audio to a file using
arecord -D hw:1,0 -c2 -fS16_LE -r48000 > audio.wav

When I play back the recorded file, it sounds great.
aplay audio.wav

I should be able to stream the audio live using
arecord -D hw:1,0 -c2 -fS16_LE -r48000 | aplay

however, all I get is a blip of noise each sample instead of the whole sample.
Something about piping the input from record to aplay is failing.
Anyone know what is going on?

Probably something to do with automatic format conversion. Use the -vv option to see what the hardware format is and then what the audio file format is. The sound subsystem can do both rate and format conversion. Are you sure your hardware is outputting signed 16bit Little Endian format and that the rate is 48kHz? My bet is that your hardware is outputting something different, and arecord is doing the conversion to store in S16_LE and at a rate of 48KHz.

Regards,
John

I think you are on to something here.
The radio device records at 96000. It won’t record at any other rate.
The playback device only plays back at 48000. It won’t play at 96000.
It looks like the player down-converts the sample rate.

If I record and pipe it to aplay with -v on, it plays a pop each second or so with no music, just the pop and silence, I get:

debian@beaglebone:~$ arecord -D hw:1,0 -c2 -fS16_LE -r96000 | aplay -c2 -fS16_LE -r96000 -v

Recording WAVE ‘stdin’ : Signed 16 bit Little Endian, Rate 96000 Hz, Stereo

Playing WAVE ‘stdin’ : Signed 16 bit Little Endian, Rate 96000 Hz, Stereo

Plug PCM: Rate conversion PCM (48000, sformat=S16_LE)

Converter: libspeex (builtin)

Protocol version: 10002

Its setup is:

stream : PLAYBACK

access : RW_INTERLEAVED

format : S16_LE

subformat : STD

channels : 2

rate : 96000

exact rate : 96000 (96000/1)

msbits : 16

buffer_size : 32768

period_size : 2048

period_time : 21333

tstamp_mode : NONE

period_step : 1

avail_min : 2048

period_event : 0

start_threshold : 32768

stop_threshold : 32768

silence_threshold: 0

silence_size : 0

boundary : 1073741824

Slave: Direct Stream Mixing PCM

Its setup is:

stream : PLAYBACK

access : MMAP_INTERLEAVED

format : S16_LE

subformat : STD

channels : 2

rate : 48000

exact rate : 48000 (48000/1)

msbits : 16

buffer_size : 16384

period_size : 1024

period_time : 21333

tstamp_mode : NONE

period_step : 1

avail_min : 1024

period_event : 0

start_threshold : 16384

stop_threshold : 16384

silence_threshold: 0

silence_size : 0

boundary : 1073741824

Hardware PCM card 0 ‘C-Media USB Headphone Set’ device 0 subdevice 0

Its setup is:

stream : PLAYBACK

access : MMAP_INTERLEAVED

format : S16_LE

subformat : STD

channels : 2

rate : 48000

exact rate : 48000 (48000/1)

msbits : 16

buffer_size : 16384

period_size : 1024

period_time : 21333

tstamp_mode : ENABLE

period_step : 1

avail_min : 1024

period_event : 0

start_threshold : 1

stop_threshold : 1073741824

silence_threshold: 0

silence_size : 1073741824

boundary : 1073741824

appl_ptr : 0

hw_ptr : 0

But the interesting part is when I record to a file, then play back the file successfully, I get:

debian@beaglebone:~$ aplay radio.wav -v

Playing WAVE ‘radio.wav’ : Signed 16 bit Little Endian, Rate 96000 Hz, Stereo

Plug PCM: Rate conversion PCM (48000, sformat=S16_LE)

Converter: libspeex (builtin)

Protocol version: 10002

Its setup is:

stream : PLAYBACK

access : RW_INTERLEAVED

format : S16_LE

subformat : STD

channels : 2

rate : 96000

exact rate : 96000 (96000/1)

msbits : 16

buffer_size : 32768

period_size : 2048

period_time : 21333

tstamp_mode : NONE

period_step : 1

avail_min : 2048

period_event : 0

start_threshold : 32768

stop_threshold : 32768

silence_threshold: 0

silence_size : 0

boundary : 1073741824

Slave: Direct Stream Mixing PCM

Its setup is:

stream : PLAYBACK

access : MMAP_INTERLEAVED

format : S16_LE

subformat : STD

channels : 2

rate : 48000

exact rate : 48000 (48000/1)

msbits : 16

buffer_size : 16384

period_size : 1024

period_time : 21333

tstamp_mode : NONE

period_step : 1

avail_min : 1024

period_event : 0

start_threshold : 16384

stop_threshold : 16384

silence_threshold: 0

silence_size : 0

boundary : 1073741824

Hardware PCM card 0 ‘C-Media USB Headphone Set’ device 0 subdevice 0

Its setup is:

stream : PLAYBACK

access : MMAP_INTERLEAVED

format : S16_LE

subformat : STD

channels : 2

rate : 48000

exact rate : 48000 (48000/1)

msbits : 16

buffer_size : 16384

period_size : 1024

period_time : 21333

tstamp_mode : ENABLE

period_step : 1

avail_min : 1024

period_event : 0

start_threshold : 1

stop_threshold : 1073741824

silence_threshold: 0

silence_size : 1073741824

boundary : 1073741824

appl_ptr : 0

hw_ptr : 0

It does the down-convert both times, but fails when using the pipe.

Any clue why it does this?

I think you are on to something here.
The radio device records at 96000. It won’t record at any other rate.
The playback device only plays back at 48000. It won’t play at 96000.
It looks like the player down-converts the sample rate.

If I record and pipe it to aplay with -v on, it plays a pop each second or so with no music, just the pop and silence, I get:

debian@beaglebone:~$ arecord -D hw:1,0 -c2 -fS16_LE -r96000 | aplay -c2 -fS16_LE -r96000 -v

Recording WAVE ‘stdin’ : Signed 16 bit Little Endian, Rate 96000 Hz, Stereo

Playing WAVE ‘stdin’ : Signed 16 bit Little Endian, Rate 96000 Hz, Stereo

Plug PCM: Rate conversion PCM (48000, sformat=S16_LE)

Converter: libspeex (builtin)

Protocol version: 10002

Its setup is:

stream : PLAYBACK

access : RW_INTERLEAVED

format : S16_LE

subformat : STD

channels : 2

rate : 96000

exact rate : 96000 (96000/1)

msbits : 16

buffer_size : 32768

period_size : 2048

period_time : 21333

tstamp_mode : NONE

period_step : 1

avail_min : 2048

period_event : 0

start_threshold : 32768

stop_threshold : 32768

silence_threshold: 0

silence_size : 0

boundary : 1073741824

Slave: Direct Stream Mixing PCM

Its setup is:

stream : PLAYBACK

access : MMAP_INTERLEAVED

format : S16_LE

subformat : STD

channels : 2

rate : 48000

exact rate : 48000 (48000/1)

msbits : 16

buffer_size : 16384

period_size : 1024

period_time : 21333

tstamp_mode : NONE

period_step : 1

avail_min : 1024

period_event : 0

start_threshold : 16384

stop_threshold : 16384

silence_threshold: 0

silence_size : 0

boundary : 1073741824

Hardware PCM card 0 ‘C-Media USB Headphone Set’ device 0 subdevice 0

Its setup is:

stream : PLAYBACK

access : MMAP_INTERLEAVED

format : S16_LE

subformat : STD

channels : 2

rate : 48000

exact rate : 48000 (48000/1)

msbits : 16

buffer_size : 16384

period_size : 1024

period_time : 21333

tstamp_mode : ENABLE

period_step : 1

avail_min : 1024

period_event : 0

start_threshold : 1

stop_threshold : 1073741824

silence_threshold: 0

silence_size : 1073741824

boundary : 1073741824

appl_ptr : 0

hw_ptr : 0

But the interesting part is when I record to a file, then play back the file successfully, I get:

debian@beaglebone:~$ aplay radio.wav -v

Playing WAVE ‘radio.wav’ : Signed 16 bit Little Endian, Rate 96000 Hz, Stereo

Plug PCM: Rate conversion PCM (48000, sformat=S16_LE)

Converter: libspeex (builtin)

Protocol version: 10002

Its setup is:

stream : PLAYBACK

access : RW_INTERLEAVED

format : S16_LE

subformat : STD

channels : 2

rate : 96000

exact rate : 96000 (96000/1)

msbits : 16

buffer_size : 32768

period_size : 2048

period_time : 21333

tstamp_mode : NONE

period_step : 1

avail_min : 2048

period_event : 0

start_threshold : 32768

stop_threshold : 32768

silence_threshold: 0

silence_size : 0

boundary : 1073741824

Slave: Direct Stream Mixing PCM

Its setup is:

stream : PLAYBACK

access : MMAP_INTERLEAVED

format : S16_LE

subformat : STD

channels : 2

rate : 48000

exact rate : 48000 (48000/1)

msbits : 16

buffer_size : 16384

period_size : 1024

period_time : 21333

tstamp_mode : NONE

period_step : 1

avail_min : 1024

period_event : 0

start_threshold : 16384

stop_threshold : 16384

silence_threshold: 0

silence_size : 0

boundary : 1073741824

Hardware PCM card 0 ‘C-Media USB Headphone Set’ device 0 subdevice 0

Its setup is:

stream : PLAYBACK

access : MMAP_INTERLEAVED

format : S16_LE

subformat : STD

channels : 2

rate : 48000

exact rate : 48000 (48000/1)

msbits : 16

buffer_size : 16384

period_size : 1024

period_time : 21333

tstamp_mode : ENABLE

period_step : 1

avail_min : 1024

period_event : 0

start_threshold : 1

stop_threshold : 1073741824

silence_threshold: 0

silence_size : 1073741824

boundary : 1073741824

appl_ptr : 0

hw_ptr : 0

It does the down-convert both times, but fails when using the pipe.

Any clue why it does this?

You will have to find a rate that both your radio and sound card can support. I don’t believe you can do streaming rate conversion because the buffer will grow continuously if sound rate < radio rate or the buffer will block if the sound rate > radio rate. What audio codec are you using? The TLV320AIC3104 on the audio cape can support 96KHz sampling rate.

Regards,
John

I think you are on to something here.
The radio device records at 96000. It won’t record at any other rate.
The playback device only plays back at 48000. It won’t play at 96000.
It looks like the player down-converts the sample rate.

If I record and pipe it to aplay with -v on, it plays a pop each second or so with no music, just the pop and silence, I get:

debian@beaglebone:~$ arecord -D hw:1,0 -c2 -fS16_LE -r96000 | aplay -c2 -fS16_LE -r96000 -v

Recording WAVE ‘stdin’ : Signed 16 bit Little Endian, Rate 96000 Hz, Stereo

Playing WAVE ‘stdin’ : Signed 16 bit Little Endian, Rate 96000 Hz, Stereo

Plug PCM: Rate conversion PCM (48000, sformat=S16_LE)

Converter: libspeex (builtin)

Protocol version: 10002

Its setup is:

stream : PLAYBACK

access : RW_INTERLEAVED

format : S16_LE

subformat : STD

channels : 2

rate : 96000

exact rate : 96000 (96000/1)

msbits : 16

buffer_size : 32768

period_size : 2048

period_time : 21333

tstamp_mode : NONE

period_step : 1

avail_min : 2048

period_event : 0

start_threshold : 32768

stop_threshold : 32768

silence_threshold: 0

silence_size : 0

boundary : 1073741824

Slave: Direct Stream Mixing PCM

Its setup is:

stream : PLAYBACK

access : MMAP_INTERLEAVED

format : S16_LE

subformat : STD

channels : 2

rate : 48000

exact rate : 48000 (48000/1)

msbits : 16

buffer_size : 16384

period_size : 1024

period_time : 21333

tstamp_mode : NONE

period_step : 1

avail_min : 1024

period_event : 0

start_threshold : 16384

stop_threshold : 16384

silence_threshold: 0

silence_size : 0

boundary : 1073741824

Hardware PCM card 0 ‘C-Media USB Headphone Set’ device 0 subdevice 0

Its setup is:

stream : PLAYBACK

access : MMAP_INTERLEAVED

format : S16_LE

subformat : STD

channels : 2

rate : 48000

exact rate : 48000 (48000/1)

msbits : 16

buffer_size : 16384

period_size : 1024

period_time : 21333

tstamp_mode : ENABLE

period_step : 1

avail_min : 1024

period_event : 0

start_threshold : 1

stop_threshold : 1073741824

silence_threshold: 0

silence_size : 1073741824

boundary : 1073741824

appl_ptr : 0

hw_ptr : 0

But the interesting part is when I record to a file, then play back the file successfully, I get:

debian@beaglebone:~$ aplay radio.wav -v

Playing WAVE ‘radio.wav’ : Signed 16 bit Little Endian, Rate 96000 Hz, Stereo

Plug PCM: Rate conversion PCM (48000, sformat=S16_LE)

Converter: libspeex (builtin)

Protocol version: 10002

Its setup is:

stream : PLAYBACK

access : RW_INTERLEAVED

format : S16_LE

subformat : STD

channels : 2

rate : 96000

exact rate : 96000 (96000/1)

msbits : 16

buffer_size : 32768

period_size : 2048

period_time : 21333

tstamp_mode : NONE

period_step : 1

avail_min : 2048

period_event : 0

start_threshold : 32768

stop_threshold : 32768

silence_threshold: 0

silence_size : 0

boundary : 1073741824

Slave: Direct Stream Mixing PCM

Its setup is:

stream : PLAYBACK

access : MMAP_INTERLEAVED

format : S16_LE

subformat : STD

channels : 2

rate : 48000

exact rate : 48000 (48000/1)

msbits : 16

buffer_size : 16384

period_size : 1024

period_time : 21333

tstamp_mode : NONE

period_step : 1

avail_min : 1024

period_event : 0

start_threshold : 16384

stop_threshold : 16384

silence_threshold: 0

silence_size : 0

boundary : 1073741824

Hardware PCM card 0 ‘C-Media USB Headphone Set’ device 0 subdevice 0

Its setup is:

stream : PLAYBACK

access : MMAP_INTERLEAVED

format : S16_LE

subformat : STD

channels : 2

rate : 48000

exact rate : 48000 (48000/1)

msbits : 16

buffer_size : 16384

period_size : 1024

period_time : 21333

tstamp_mode : ENABLE

period_step : 1

avail_min : 1024

period_event : 0

start_threshold : 1

stop_threshold : 1073741824

silence_threshold: 0

silence_size : 1073741824

boundary : 1073741824

appl_ptr : 0

hw_ptr : 0

It does the down-convert both times, but fails when using the pipe.

Any clue why it does this?

When you record, use —disable-resample and —disable-format, and then try to play that file, also with —disable-resample and —disable-format and you will probably get the same popping sound.

Regards,
John

It is definitely a resample issue.
The radio device only streams at 96000.
Specifying any other rate results in 96000.
I see no record options to resample on the recording side.
The raw stream is at 96000.

The USB audio device refuses to stream at 96000 and streams at 48000.
Does this have something to do with USB limitations? It should be able to stream at 96000, it refuses to do it.

So, a resample is needed.
It looks like the arecord | aplay will not work.

I’ll probably have to write a program to stream / resample / play.

It is definitely a resample issue.
The radio device only streams at 96000.
Specifying any other rate results in 96000.
I see no record options to resample on the recording side.
The raw stream is at 96000.

The USB audio device refuses to stream at 96000 and streams at 48000.
Does this have something to do with USB limitations? It should be able to stream at 96000, it refuses to do it.

It has to be something to do with the codec or the driver, but USB can handle the higher sampling rate.

So, a resample is needed.
It looks like the arecord | aplay will not work.

I’ll probably have to write a program to stream / resample / play.

Have a look at the driver to see what sampling rates are supported. Perhaps you should use a different audio device.

Regards,
John