Search by Tags

Audio (Linux)

 

Article updated at 26 Nov 2021
Compare with Revision




Introduction

Our Embedded Linux BSPs use the regular Linux audio subsystem Advanced Linux Sound Architecture (ALSA). The ALSA subsystem can be configured using amixer or alsamixer whereas playing and recording is possible using the ALSA utilities aplay and arecord. Higher-level frameworks such as GStreamer allow to convert audio streams (e.g. sample rate) and play/record encoded audio streams such as MP3, FLAC, or Ogg/Vorbis file formats. This article provides some example commands showing how to control and use audio with a Toradex Embedded Linux BSP.

Audio on TorizonCore

If you want to use audio interfaces on Torizon, there is a complementary article with a sample application and remarks: How to play audio on TorizonCore using Alsa and C/C++. The Torizon article does not replace the current one, it rather extends it.

First Steps

You can use the speaker-test to test audio, or alternatively aplay if you have an audio file deployed to the board. See a simple example below.

List the available audio devices:

# cat /proc/asound/cards
 0 [DWHDMI         ]: dw-hdmi-ahb-aud - DW-HDMI
                      DW-HDMI rev 0x0a, irq 21
 1 [imxspdif       ]: imx-spdif - imx-spdif
                      imx-spdif
 2 [sgtl5000audio  ]: sgtl5000-audio - sgtl5000-audio
                      sgtl5000-audio

In the example above, sgtl5000audio, interface number 2, is the one connected to the headphone jack available on our carrier board. We'll use it. It may vary depending on your SoM; if you have questions, jump to the section specific to your SoM!

First, unmute the interface and adjust the volume:

# amixer -c 2 sset Headphone unmute
# amixer -c 2 set Headphone 50%

Then, play a test sound:

# speaker-test --device hw:2,0 --rate 48000 --channels 2 --format S16_LE --test wav

Or, if you have a wave file on the board, for instance, we'll use Gong.wav:

# aplay -Ddefault:sgtl5000audio Gong.wav

Audio Multi-channel Routing and Mixing Using alsalib

Bootlin has a great blog post on the topic, read Audio multi-channel routing and mixing using alsalib.

NVIDIA Tegra Based Modules

The Colibri T20 modules have a Wolfson WM9715L audio codec on board. To find pin assignment refer to the Hardware reference.

The Apalis T30, Apalis TK1 and Colibri T30 modules feature an on-module SGTL5000 audio codec:

root@apalis-t30:~# cat /proc/asound/cards
 0 [apalist30sgtl50]: apalis_t30-sgtl - apalis_t30-sgtl5000
                      apalis_t30-sgtl5000
 1 [Tegra          ]: HDA-Intel - HDA NVIDIA Tegra
                      HDA NVIDIA Tegra at 0x70038000 irq 113
root@apalis-t30:~# aplay -l
**** List of PLAYBACK Hardware Devices ****
card 0: apalist30sgtl50 [apalis_t30-sgtl5000], device 0: SGTL5000 PCM sgtl5000-0 []
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 0: apalist30sgtl50 [apalis_t30-sgtl5000], device 1: SPDIF PCM dit-hifi-1 []
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 1: Tegra [HDA NVIDIA Tegra], device 0: ALC898 Analog [ALC898 Analog]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 1: Tegra [HDA NVIDIA Tegra], device 1: ALC898 Digital [ALC898 Digital]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 1: Tegra [HDA NVIDIA Tegra], device 3: HDMI 0 [HDMI 0]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
root@apalis-t30:~# aplay -L
null
Discard all samples (playback) or generate zero samples (capture)
default:CARD=apalist30sgtl50
    apalis_t30-sgtl5000, 
    Default Audio Device
sysdefault:CARD=apalist30sgtl50
    apalis_t30-sgtl5000, 
    Default Audio Device
default:CARD=Tegra
    HDA NVIDIA Tegra, ALC898 Analog
    Default Audio Device
sysdefault:CARD=Tegra
    HDA NVIDIA Tegra, ALC898 Analog
    Default Audio Device
front:CARD=Tegra,DEV=0
    HDA NVIDIA Tegra, ALC898 Analog
    Front speakers
surround21:CARD=Tegra,DEV=0
    HDA NVIDIA Tegra, ALC898 Analog
    2.1 Surround output to Front and Subwoofer speakers
surround40:CARD=Tegra,DEV=0
    HDA NVIDIA Tegra, ALC898 Analog
    4.0 Surround output to Front and Rear speakers
surround41:CARD=Tegra,DEV=0
    HDA NVIDIA Tegra, ALC898 Analog
    4.1 Surround output to Front, Rear and Subwoofer speakers
surround50:CARD=Tegra,DEV=0
    HDA NVIDIA Tegra, ALC898 Analog
    5.0 Surround output to Front, Center and Rear speakers
surround51:CARD=Tegra,DEV=0
    HDA NVIDIA Tegra, ALC898 Analog
    5.1 Surround output to Front, Center, Rear and Subwoofer speakers
surround71:CARD=Tegra,DEV=0
    HDA NVIDIA Tegra, ALC898 Analog
    7.1 Surround output to Front, Center, Side, Rear and Woofer speakers
iec958:CARD=Tegra,DEV=0
    HDA NVIDIA Tegra, ALC898 Digital
    IEC958 (S/PDIF) Digital Audio Output
hdmi:CARD=Tegra,DEV=0
    HDA NVIDIA Tegra, HDMI 0
    HDMI Audio Output

HDA through HDMI

root@apalis-t30:~# speaker-test --device hw:1,3 --rate 48000 --channels 2 --format S16_LE --test wav

speaker-test 1.0.29

Playback device is hw:1,3
Stream parameters are 48000Hz, S16_LE, 2 channels
WAV file(s)
Rate set to 48000Hz (requested 48000Hz)
Buffer size range from 64 to 16384
Period size range from 32 to 8192
Using max buffer size 16384
Periods = 4
was set period_size = 4096
was set buffer_size = 16384
 0 - Front Left
 1 - Front Right
Time per period = 2.745482
^CTransfer failed: Bad address

Please note that not all pixel clock frequencies allow for HDA being streamed through HDMI. E.g. at VESA VGA resolution, you may get an error reported as follows:

[   16.245677] tegradc tegradc.1: hdmi: can't set audio to 44100 at 25175000 pix_clock

Plus the number of available channels depends on the resp. HDMI device is connected to.

SGTL5000 Capture from Line-In

root@apalis-t30:~# amixer set 'Capture' 12
Simple mixer control 'Capture',0
  Capabilities: cvolume
  Capture channels: Front Left - Front Right
  Limits: Capture 0 - 15
  Front Left: Capture 12 [80%]
  Front Right: Capture 12 [80%]
root@apalis-t30:~# amixer set 'Capture Mux' 'LINE_IN'
Simple mixer control 'Capture Mux',0
  Capabilities: enum
  Items: 'MIC_IN' 'LINE_IN'
  Item0: 'LINE_IN'
root@apalis-t30:~# arecord -D hw:0,0 -V stereo -c 2 -f S16_LE -r 48000 -t wav linein.wav
Recording WAVE 'linein.wav' : Signed 16 bit Little Endian, Rate 48000 Hz, Stereo
                                  +00%|00%+                                   ^CAborted by signal Interrupt...

SGTL5000 Capture from Microphone

root@apalis-t30:~# amixer set 'Mic' 1
Simple mixer control 'Mic',0
  Capabilities: volume volume-joined
  Playback channels: Mono
  Capture channels: Mono
  Limits: 0 - 3
  Mono: 1 [33%] [20.00dB]
root@apalis-t30:~# amixer set 'Capture' 12
Simple mixer control 'Capture',0
  Capabilities: cvolume
  Capture channels: Front Left - Front Right
  Limits: Capture 0 - 15
  Front Left: Capture 12 [80%]
  Front Right: Capture 12 [80%]
root@apalis-t30:~# amixer set 'Capture Mux' 'MIC_IN'
Simple mixer control 'Capture Mux',0
  Capabilities: enum
  Items: 'MIC_IN' 'LINE_IN'
  Item0: 'MIC_IN'
root@apalis-t30:~# arecord -D hw:0,0 -V mono -c 2 -f S16_LE -r 48000 -t wav mic.wav
Recording WAVE 'mic.wav' : Signed 16 bit Little Endian, Rate 48000 Hz, Stereo
#                             +                    | 59%^CAborted by signal Interrupt...

SGTL5000 Playback through Headphone

root@apalis-t30:~# amixer set 'Headphone' 113
Simple mixer control 'Headphone',0
  Capabilities: pvolume
  Playback channels: Front Left - Front Right
  Limits: Playback 0 - 127
  Mono:
  Front Left: Playback 113 [89%] [5.00dB]
  Front Right: Playback 113 [89%] [5.00dB]
root@apalis-t30:~# amixer set 'Headphone Mux' 'DAC'
Simple mixer control 'Headphone Mux',0
  Capabilities: enum
  Items: 'DAC' 'LINE_IN'
  Item0: 'DAC'
root@apalis-t30:~# amixer set 'PCM' 144
Simple mixer control 'PCM',0
  Capabilities: pvolume
  Playback channels: Front Left - Front Right
  Limits: Playback 0 - 192
  Mono:
  Front Left: Playback 144 [75%]
  Front Right: Playback 144 [75%]
root@apalis-t30:~# aplay -D hw:0,0 linein.wav 
Playing WAVE 'linein.wav' : Signed 16 bit Little Endian, Rate 48000 Hz, Stereo

SPDIF through HDMI

The Colibri T20 provides SPDIF signals and Audio through HDMI.

Note that the HDMI sound card is only available if the video output is configured for HDMI and a monitor is attached.

root@colibri-t20:~# speaker-test --device hw:0,1 --rate 48000 --channels 2 --format S16_LE --test wav

Please note that not all pixel clock frequencies allow for SPDIF being streamed through HDMI. E.g. at VESA VGA resolution, you may get an error reported as follows:

[   16.245677] tegradc tegradc.1: hdmi: can't set audio to 44100 at 25175000 pix_clock

WM9715L AC97 Capture from Line-in

  • Colibri SODIMM pin 5 & 7 (LINEIN_L/R)
  • Iris: Audio header X9 pin 3 & 4 (Line IN R/L)
  • Colibri Evaluation Board: Audio jack X26 top blue
  • Orchid: Audio jack X11 top blue line in
  • MECS Tellurium: Audio jack X11 pin 1 & 2 (LINEIN_L/R)

First ALSA needs to be configured correctly using amixer.

root@colibri_t20:~# amixer set 'Left Capture Select' 'Line'
Simple mixer control 'Left Capture Select',0
  Capabilities: enum
  Items: 'Mic' 'NC' 'NC' 'Speaker Mixer' 'Line' 'Headphone Mixer' 'Phone Mixer' 'Phone'
  Item0: 'Line'
root@colibri_t20:~# amixer set 'Right Capture Select' 'Line'
Simple mixer control 'Right Capture Select',0
  Capabilities: enum
  Items: 'Mic' 'NC' 'NC' 'Speaker Mixer' 'Line' 'Headphone Mixer' 'Phone Mixer' 'Phone'
  Item0: 'Line'
root@colibri_t20:~# amixer set 'Capture ADC' on
Simple mixer control 'Capture ADC',0
  Capabilities: pswitch pswitch-joined penum
  Playback channels: Mono
  Mono: Playback [on]
root@colibri_t20:~# amixer set 'Left HP Mixer Line Bypass' on
Simple mixer control 'Left HP Mixer Line Bypass',0
  Capabilities: pswitch pswitch-joined penum
  Playback channels: Mono
  Mono: Playback [on]
root@colibri_t20:~# amixer set 'Right HP Mixer Line Bypass' on
Simple mixer control 'Right HP Mixer Line Bypass',0
  Capabilities: pswitch pswitch-joined penum
  Playback channels: Mono
  Mono: Playback [on]

Recording can then be done easily using GStreamer.

root@colibri_t20:~# gst-launch alsasrc device=hw:0,0 num-buffers=1000 ! audioconvert ! audio/x-raw-int,channels=2,width=16,depth=16 ! audioresample ! wavenc ! filesink location=linein.wav
Setting pipeline to PAUSED ...
[ 1954.087441] i2s_set_channel_bit_count: enabling non-symmetric mode
Pipeline is live and does not need PREROLL ...
Setting pipeline to PLAYING ...
New clock: GstAudioSrcClock
Got EOS from element "pipeline0".
Execution ended after 11613432000 ns.
Setting pipeline to PAUSED ...
Setting pipeline to READY ...
Setting pipeline to NULL ...
Freeing pipeline ...

ALC898 HDA Capture from Line-in

  • Apalis Evaluation Board: HDA Audio jack X27 top blue

First ALSA needs to be configured correctly using amixer.

root@apalis_t30:~# amixer -c 1 set 'Capture' 100 on
Simple mixer control 'Capture',0
  Capabilities: cvolume cswitch
  Capture channels: Front Left - Front Right
  Limits: Capture 0 - 63
  Front Left: Capture 63 [100%] [30.00dB] [on]
  Front Right: Capture 63 [100%] [30.00dB] [on]

root@apalis_t30:~# amixer -c 1 set 'Input Source' 'Line'
Simple mixer control 'Input Source',0
  Capabilities: cenum
  Items: 'Rear Mic' 'Front Mic' 'Line' 'CD'
  Item0: 'Line'

root@apalis_t30:~# amixer -c 1 set 'Line' 100 on
Simple mixer control 'Line',0
  Capabilities: pvolume pswitch
  Playback channels: Front Left - Front Right
  Limits: Playback 0 - 31
  Mono:
  Front Left: Playback 31 [100%] [12.00dB] [on]
  Front Right: Playback 31 [100%] [12.00dB] [on]

Recording can then be done easily using GStreamer.

root@apalis_t30:~# gst-launch alsasrc device=hw:1,0 num-buffers=1000 ! audioconvert ! audio/x-raw-int,channels=2,width=16,depth=16 ! audioresample ! wavenc ! filesink location=linein.wav
Setting pipeline to PAUSED ...
Pipeline is live and does not need PREROLL ...
Setting pipeline to PLAYING ...
New clock: GstAudioSrcClock
^CCaught interrupt -- handling interrupt.
Interrupt: Stopping pipeline ...
Execution ended after 3256371004 ns.
Setting pipeline to PAUSED ...
Setting pipeline to READY ...
Setting pipeline to NULL ...
Freeing pipeline ...

WM9715L AC97 Capture from Microphone

  • Colibri SODIMM pin 1 (MIC_IN)
  • Iris: Audio header X9 pin 2 (requires biasing)
  • Colibri Evaluation Board: Audio jack X26 bottom pink
  • Orchid: Audio jack X11 bottom pink MIC in
root@colibri_t20:~# amixer set 'Left Capture Select' 'Mic'
Simple mixer control 'Left Capture Select',0
  Capabilities: enum
  Items: 'Mic' 'NC' 'NC' 'Speaker Mixer' 'Line' 'Headphone Mixer' 'Phone Mixer' 'Phone'
  Item0: 'Mic'
root@colibri_t20:~# amixer set 'Right Capture Select' 'Mic'
Simple mixer control 'Right Capture Select',0
  Capabilities: enum
  Items: 'Mic' 'NC' 'NC' 'Speaker Mixer' 'Line' 'Headphone Mixer' 'Phone Mixer' 'Phone'
  Item0: 'Mic'
root@colibri_t20:~# amixer set 'Capture ADC' on
Simple mixer control 'Capture ADC',0
  Capabilities: pswitch pswitch-joined penum
  Playback channels: Mono
  Mono: Playback [on]
root@colibri_t20:~# amixer set 'Left HP Mixer Mic Sidetone' on
Simple mixer control 'Left HP Mixer Mic Sidetone',0
  Capabilities: pswitch pswitch-joined penum
  Playback channels: Mono
  Mono: Playback [on]
root@colibri_t20:~# amixer set 'Right HP Mixer Mic Sidetone' on
Simple mixer control 'Right HP Mixer Mic Sidetone',0
  Capabilities: pswitch pswitch-joined penum
  Playback channels: Mono
  Mono: Playback [on]

root@colibri_t20:~# gst-launch alsasrc device=hw:0,0 num-buffers=1000 ! audioconvert ! audio/x-raw-int,channels=2,width=16,depth=16 ! audioresample ! wavenc ! filesink location=mic.wav
Setting pipeline to PAUSED ...
[ 2037.976550] i2s_set_channel_bit_count: enabling non-symmetric mode
Pipeline is live and does not need PREROLL ...
Setting pipeline to PLAYING ...
New clock: GstAudioSrcClock
Got EOS from element "pipeline0".
Execution ended after 11613453000 ns.
Setting pipeline to PAUSED ...
Setting pipeline to READY ...
Setting pipeline to NULL ...
Freeing pipeline ...

ALC898 HDA Capture from Microphone

  • Apalis Evaluation Board: Audio jack X27 bottom pink

    root@apalis_t30:~# amixer -c 1 set 'Capture' 100 on
    Simple mixer control 'Capture',0
      Capabilities: cvolume cswitch
      Capture channels: Front Left - Front Right
      Limits: Capture 0 - 63
      Front Left: Capture 63 [100%] [30.00dB] [on]
      Front Right: Capture 63 [100%] [30.00dB] [on]
    
    root@apalis_t30:~# amixer -c 1 set 'Input Source' 'Rear Mic'
    Simple mixer control 'Input Source',0
      Capabilities: cenum
      Items: 'Rear Mic' 'Front Mic' 'Line' 'CD'
      Item0: 'Rear Mic'
    
    root@apalis_t30:~# amixer -c 1 set 'Rear Mic' 100 on
    Simple mixer control 'Rear Mic',0
      Capabilities: pvolume pswitch
      Playback channels: Front Left - Front Right
      Limits: Playback 0 - 31
      Mono:
      Front Left: Playback 31 [100%] [12.00dB] [on]
      Front Right: Playback 31 [100%] [12.00dB] [on]
    
    root@apalis_t30:~# amixer -c 1 set 'Rear Mic Boost' 100 on
    Simple mixer control 'Rear Mic Boost',0
      Capabilities: volume
      Playback channels: Front Left - Front Right
      Capture channels: Front Left - Front Right
      Limits: 0 - 3
      Front Left: 3 [100%] [30.00dB]
      Front Right: 3 [100%] [30.00dB]
    
    root@apalis_t30:~# gst-launch alsasrc device=hw:1,0 num-buffers=1000 ! audioconvert ! audio/x-raw-int,channels=2,width=16,depth=16 ! audioresample ! wavenc ! filesink location=mic.wav
    Setting pipeline to PAUSED ...
    Pipeline is live and does not need PREROLL ...
    Setting pipeline to PLAYING ...
    New clock: GstAudioSrcClock
    ^CCaught interrupt -- handling interrupt.
    Interrupt: Stopping pipeline ...
    Execution ended after 3256371004 ns.
    Setting pipeline to PAUSED ...
    Setting pipeline to READY ...
    Setting pipeline to NULL ...
    Freeing pipeline ...
    

WM9715L AC97 Playback through Headphone

  • Colibri SODIMM pin 15 & 17 (HEADPHONE_L/R)
  • Iris: Audio jack X8
  • Colibri Evaluation Board: Audio jack X26 middle green
  • Orchid: Audio jack X11 middle green line out
  • Protea: Audio jack X53 line out
  • MECS Tellurium: Audio jack X11 pin 4 & 5 (HEADPHONE_LF/RF)

    root@colibri_t20:~# amixer set 'Headphone' 8 on
    Simple mixer control 'Headphone',0
      Capabilities: pvolume pswitch pswitch-joined penum
      Playback channels: Front Left - Front Right
      Limits: Playback 0 - 31
      Mono:
      Front Left: Playback 8 [26%] [on]
      Front Right: Playback 8 [26%] [on]
    root@colibri_t20:~# amixer set 'Left HP Mixer PCM' on
    Simple mixer control 'Left HP Mixer PCM',0
      Capabilities: pswitch pswitch-joined penum
      Playback channels: Mono
      Mono: Playback [on]
    root@colibri_t20:~# amixer set 'Right HP Mixer PCM' on
    Simple mixer control 'Right HP Mixer PCM',0
      Capabilities: pswitch pswitch-joined penum
      Playback channels: Mono
      Mono: Playback [on]
    
    root@colibri_t20:~# aplay bach.au
    [ 2924.023213] i2s_set_channel_bit_count: enabling non-symmetric mode
    Playing Sparc Audio 'bach.au' : Mu-Law, Rate 8000 Hz, Mono
    
    root@colibri_t20:~# gst-launch filesrc location=mic.wav ! wavparse ! audioconvert ! alsasink device=hw:0,0
    Setting pipeline to PAUSED ...
    [ 2459.620319] i2s_set_channel_bit_count: enabling non-symmetric mode
    Pipeline is PREROLLING ...
    Pipeline is PREROLLED ...
    Setting pipeline to PLAYING ...
    New clock: GstAudioSinkClock
    Got EOS from element "pipeline0".
    Execution ended after 11611505001 ns.
    Setting pipeline to PAUSED ...
    Setting pipeline to READY ...
    Setting pipeline to NULL ...
    Freeing pipeline ...
    

ALC898 HDA Playback through Headphone

  • Apalis Evaluation Board: Audio jack X27 middle green

    root@apalis_t30:~# amixer -c 1 set 'Front' 100 on
    Simple mixer control 'Front',0
      Capabilities: pvolume pswitch
      Playback channels: Front Left - Front Right
      Limits: Playback 0 - 87
      Mono:
      Front Left: Playback 87 [100%] [0.00dB] [on]
      Front Right: Playback 87 [100%] [0.00dB] [on]
    
    root@apalis_t30:~# gst-launch filesrc location=mic.wav ! wavparse ! audioconvert ! alsasink device=hw:1,0
    Setting pipeline to PAUSED ...
    Pipeline is PREROLLING ...
    Pipeline is PREROLLED ...
    Setting pipeline to PLAYING ...
    New clock: GstAudioSinkClock
    Got EOS from element "pipeline0".
    Execution ended after 3258022000 ns.
    Setting pipeline to PAUSED ...
    Setting pipeline to READY ...
    Setting pipeline to NULL ...
    Freeing pipeline ...
    

MP3 Playback

The following example shows how to playback MP3 audio via GStreamer using hardware-accelerated MP3 decoding. Please note that the two numbers at the end specify which ALSA card and device to use for audio (e.g. alsasink device=hw:0,0 for WM9715L AC97 through headphones and alsasink device=hw:1,0 for SPDIF through HDMI).

root@colibri-t20:~# gst-launch filesrc location=/home/root/03_Scar_Tissue.mp3 ! mpegaudioparse ! nv_omx_mp3dec ! alsasink device=hw:0,0
Setting pipeline to PAUSED ...
Pipeline is PREROLLING ...
[26776.345823] avp_init: Using AVP MMU to relocate AVP kernel
[26776.428892] avp_init: Reading firmware from 'nvrm_avp.bin' (46612 bytes)
[26776.441076] avp_init: Loading AVP kernel at vaddr=d7a00000 paddr=18100000
[26776.488814] avp_reset: Resetting AVP: reset_addr=100000
[26776.506561] process_connect_locked: got connect (111794)
[26776.506746] avp_node_try_connect: trying connect from RPC_AVP_PORT
[26776.518587] avp_svc_thread: got remote peer
[26776.523229] [AVP]: AVP kernel (Nov  2 2012 16:47:31)
[26776.537301] avp_node_try_connect: got conn ack 'RPC_AVP_PORT' (cd049b60 <-> 111758)
[26776.545378] avp_init: avp init done
[26776.548917] avp_lib: loading library 'nvmm_manager.axf'
[26776.596783] avp_lib: Successfully loaded library nvmm_manager.axf (lib_id=118960)
[26776.605064] avp_node_try_connect: trying connect from NVMM_MANAGER_SRV
[26776.621815] avp_node_try_connect: got conn ack 'NVMM_MANAGER_SRV' (cdb48f80 <-> 119c00)
[26776.714101] tegra20_ac97_hw_params(): dai->id=0, play
Pipeline is PREROLLED ...
Setting pipeline to PLAYING ...
New clock: GstAudioSinkClock
[26776.803786] tegra20_ac97_trigger()
[26776.807247] tegra20_ac97_start_playback()
[26776.811295] ac97_fifo_set_attention_level()
[26776.815502] ac97_slot_enable()
Got EOS from element "pipeline0".
Execution ended after 236898907001 ns.
Setting pipeline to PAUSED ...
[27013.681352] tegra20_ac97_trigger()
[27013.684795] tegra20_ac97_stop_playback()
[27013.688743] ac97_fifo_set_attention_level()
[27013.693968] ac97_slot_enable()
Setting pipeline to READY ...
[27013.719878] process_disconnect_locked: got disconnect (cdb48f80)
[27013.741936] avp_lib: Successfully unloaded 'nvmm_manager.axf'
[27013.748859] avp_lib: unloaded 'nvmm_manager.axf'
[27013.754949] avp_svc_thread: AVP seems to be down; wait for kthread_stop
[27013.762933] avp_svc_thread: exiting
[27013.767639] avp_uninit: avp teardown done
Setting pipeline to NULL ...
Freeing pipeline ...

NXP/Freescale i.MX 6/7 Based Modules

All modules based on the NXP/Freescale i.MX 6 SoC or i.MX 7 SoC provides an on-module NXP/Freescale SGTL5000 audio codec. The SPDIF signals and Audio through HDMI are available only on modules based on i.MX 6 Soc.

HW accelerated decoding and encoding are provided by GStreamer plugins.

Note that the HDMI sound card is only available if the video output is configured for HDMI and a monitor is attached.

root@apalis-imx6:~# cat /proc/asound/cards
 0 [imx6qapalissgtl]: imx6q-apalis-sg - imx6q-apalis-sgtl5000
                      imx6q-apalis-sgtl5000
 1 [imxspdif       ]: imx-spdif - imx-spdif
                      imx-spdif
 2 [imxhdmisoc     ]: imx-hdmi-soc - imx-hdmi-soc
                      imx-hdmi-soc
root@apalis-imx6:~# aplay -L
null
    Discard all samples (playback) or generate zero samples (capture)
sysdefault:CARD=imx6qapalissgtl
    imx6q-apalis-sgtl5000,
    Default Audio Device
sysdefault:CARD=imxspdif
    imx-spdif,
    Default Audio Device
sysdefault:CARD=imxhdmisoc
    imx-hdmi-soc,
    Default Audio Device
surround40:CARD=imxhdmisoc,DEV=0
    imx-hdmi-soc,
    4.0 Surround output to Front and Rear speakers
...

SGTL5000 Playback

The SGTL5000 is the default sound device, thus one does not need to specify it explicitly on the command line.

Playback of a wave file:

root@apalis-imx6:~# aplay Gong.wav
Playing WAVE 'Gong.wav' : Signed 16 bit Little Endian, Rate 44100 Hz, Stereo
root@apalis-imx6:~# aplay -D sysdefault:CARD=imx6qapalissgtl Gong.wav
Playing WAVE 'Gong.wav' : Signed 16 bit Little Endian, Rate 44100 Hz, Stereo

SGTL5000 Capture from Line-in

Stereo capture can be achieved using Line-in functionality. First, "Capture Select" needs to be selected correctly in ALSA mixer:

root@apalis-imx6:~# amixer set 'Capture Mux' 'LINE_IN'
Simple mixer control 'Capture Mux',0
  Capabilities: enum
  Items: 'MIC_IN' 'LINE_IN'
  Item0: 'LINE_IN'

Then recording in various sample rates is natively possible:

root@apalis-imx6:~# arecord -r 48000 -f S16_LE -c 2 Capture48kHz.wav
Recording WAVE 'Capture48kHz.wav' : Signed 16 bit Little Endian, Rate 48000 Hz, Stereo
^C
root@apalis-imx6:~# arecord -r 8000 -f S16_LE -c 2 Capture8kHz.wav
Recording WAVE 'Capture8kHz.wav' : Signed 16 bit Little Endian, Rate 8000 Hz, Stereo
^C

SGTL5000 Capture from Microphone

Change the input channel to MIC_IN:

root@apalis-imx6:~# amixer set 'Capture Mux' 'MIC_IN'
...

In contrast to Line-in, Microphone capture is mono anyway, hence we can save some space by only recording one channel. The argument -V offers a VU meter which helps to see whether there is any input and if its volume is at a reasonable level.

root@apalis-imx6:~# arecord  -V mono -r 8000 -f S16_LE -c 1 Capture8kHz.wav
Recording WAVE 'Capture8kHz.wav' : Signed 16 bit Little Endian, Rate 8000 Hz, Mono
###                                             +  | 94%
^C

SPDIF Playback

Apalis features dedicated SPDIF pins and the Apalis Evaluation board provides an Optical Transmitter. Thus the Apalis iMX6 image has the SPDIF feature enabled in our default device tree, while for the Colibri iMX6 and Colibri iMX7 it is not enabled.

root@apalis-imx6:~# aplay -D sysdefault:CARD=imxspdif Gong.wav
Playing WAVE 'Gong.wav' : Signed 16 bit Little Endian, Rate 44100 Hz, Stereo

HDMI Playback

In addition to the video data stream, HDMI is able to carry audio data as well. Note that depending on the video resolution/framerate used, that feature might not be available. HDMI Playback is currently unavailable for Colibri i.MX7.

root@apalis-imx6:~# aplay -D sysdefault:CARD=imxhdmisoc Gong.wav
Playing WAVE 'Gong.wav' : Signed 16 bit Little Endian, Rate 44100 Hz, Stereo

MP3 Playback

The following example shows how to playback MP3 audio via GStreamer using hardware-accelerated MP3 decoding. Please note that the two numbers at the end specify which ALSA card and device to use for audio (e.g. alsasink device=hw:0,0 for SGTL5000, alsasink device=hw:1,0 for SPDIF and, alsasink device=hw:2,0 for audio through HDMI, compare with /proc/asound/cards).

Additional GStreamer pipelines can be found on the Freescale community website here.

Additional encoders and decoders can be verified with GStreamer command gst-inspect.

gst-launch filesrc location=Gong.mp3 typefind=true ! beepdec ! alsasink device=hw:0,0
...

Alternatively, using the playbin plugin, which sets up the pipeline automatically:

root@apalis-imx6:~# gst-launch playbin uri=file:///home/root/Gong.mp3
Setting pipeline to PAUSED ...
Pipeline is PREROLLING ...
WARNING: from element /GstPlayBin2:playbin20/GstPlaySink:playsink0: No volume control found
Additional debug info:
/build/linuxdev/oe-core/build/out-glibc/work/armv7at2hf-vfp-neon-mx6qdl-angstrom-linux-gnueabi/gst-plugins-base/0.10.36-r8/gst-plugins-base-0.10.36/gst/playback/gstplaysink.c(1869): gen_audio_chain (): /GstPlayBin2:playbin20/GstPlaySink:playsink0:
Volume/mute is not available
Beep: 3.0.11
Core: MP3 decoder Wrapper  build on Mar 21 2014 15:04:50
  mime: audio/mpeg, mpegversion = (int)1
  file: /usr/lib/imx-mm/audio-codec/wrap/lib_mp3d_wrap_arm12_elinux.so.3
CODEC: BLN_MAD-MMCODECS_MP3D_ARM_02.13.00_CORTEX-A8  build on Apr 10 2014 15:26:15.
Pipeline is PREROLLED ...
Setting pipeline to PLAYING ...
New clock: GstAudioSinkClock
Got EOS from element "playbin0".
Execution ended after 9596381667 ns.
Setting pipeline to PAUSED ...
Setting pipeline to READY ...
Setting pipeline to NULL ...
Freeing pipeline ...

Recording MP3

To record and encode to MP3, the following GStreamer command can be used:

root@apalis-imx6:~# gst-launch alsasrc ! imxmp3enc ! filesink location= audio.mp3
...
^C

NXP/Freescale i.MX 6ULL Based Modules

The Colibri iMX6ULL does not feature an audio codec on the module. However, it is possible to access all three audio interfaces by placing an external audio codec.

However, the Colibri iMX6ULL features a Medium Quality Sound (MQS) interface that can be used to generate medium-quality audio via a standard GPIO. Please refer to the module datasheet for more information.

NXP/Freescale i.MX 8/8X Family Based Modules

Note: This section currently only applies to Apalis iMX8

root@apalis-imx8:~# cat /proc/asound/cards
 0 [imxhdmiarc     ]: imx-hdmi-arc - imx-hdmi-arc
                      imx-hdmi-arc
 1 [imxspdif       ]: imx-spdif - imx-spdif
                      imx-spdif
 2 [amixaudiosai   ]: amix-audio-sai - amix-audio-sai
                      amix-audio-sai
 3 [imxaudiohdmitx ]: imx-audio-hdmi- - imx-audio-hdmi-tx
                      imx-audio-hdmi-tx
 4 [apalisimx8qmsgt]: apalis-imx8qm-s - apalis-imx8qm-sgtl5000
                      apalis-imx8qm-sgtl5000
root@apalis-imx8:~# aplay -L
null
    Discard all samples (playback) or generate zero samples (capture)
pulse
    PulseAudio Sound Server
sysdefault:CARD=imxhdmiarc
    imx-hdmi-arc, 
    Default Audio Device
sysdefault:CARD=imxspdif
    imx-spdif, 
    Default Audio Device
sysdefault:CARD=amixaudiosai
    amix-audio-sai, 
    Default Audio Device
sysdefault:CARD=imxaudiohdmitx
    imx-audio-hdmi-tx, 
    Default Audio Device
sysdefault:CARD=apalisimx8qmsgt
    apalis-imx8qm-sgtl5000, 
    Default Audio Device

SGTL5000 Playback

root@apalis-imx8:~# aplay Gong.wav 
Playing WAVE 'Gong.wav' : Signed 16 bit Little Endian, Rate 44100 Hz, Stereo
root@apalis-imx8:~# aplay -D sysdefault:CARD=apalisimx8qmsgt Gong.wav 
Playing WAVE 'Gong.wav' : Signed 16 bit Little Endian, Rate 44100 Hz, Stereo

SGTL5000 Capture from Line-in

amixer set 'Capture Mux' 'LINE_IN'
arecord -D hw:4,0 -V mono -c 2 -f S16_LE -r 44100 -t wav line.wav

SGTL5000 Capture from Microphone

amixer set 'Capture Mux' 'MIC_IN'
amixer set 'Mic' '20.00dB'
arecord -D hw:4,0 -V mono -c 2 -f S16_LE -r 44100 -t wav mic.wav

SPDIF Playback

aplay -D sysdefault:CARD=imxspdif Gong.wav

SPDIF Recording

This was done with an optical to the electronic medium converter and the signal hooked up to MXM3_217

arecord -D sysdefault:CARD=imxspdif -V mono -c 2 -f S32_LE -r 44100 -t wav spdif_input.wav

HDMI Playback

aplay -D sysdefault:CARD=imxaudiohdmitx Gong.wav

NXP/Freescale i.MX 8M Mini/Plus Based Modules

The Verdin iMX8M Mini and Verdin iMX8M Plus do not feature an audio codec on the module. However, it is possible to access all Synchronous Audio Interfaces (SAI) by placing an external audio codec. The SAI interfaces can be used as I2S (Recommended) or AC97. An I2S is connected to the Wi-Fi module for Bluetooth audio features. Please refer to the module datasheet for more information.

WM8904 Audio Codec

Verdin Development Board V1.0 and Dahlia Carrier Board features an analog audio interface based on the WM8904CGEFL/RV audio codec IC from Cirrus Logic.

To check the available sound cards, use the cat /proc/asound/cards command. The expected result on a Verdin iMX8M Mini:

root@verdin-imx8mm:~# cat /proc/asound/cards
 0 [imx8mmwm8904   ]: imx8mm-wm8904 - imx8mm-wm8904
                      imx8mm-wm8904

To record audio, you might need to run the following command to unmute the capture device:

root@verdin-imx8mm:~# amixer set "Capture" cap

WM8904 Capture from Microphone

# amixer set 'Left Capture Inverting Mux' 'IN1L'
# amixer set 'Right Capture Inverting Mux' 'IN1R'
# amixer set 'Capture' '31'
# arecord -D hw:0,0 -V mono -c 2 -f S16_LE -r 48000 -t wav mic.wav

WM8904 Capture from Line-in

# amixer set 'Left Capture Inverting Mux' 'IN2L'
# amixer set 'Right Capture Inverting Mux' 'IN2R'
# amixer set 'Capture' '16'
# arecord -D hw:0,0 -V mono -c 2 -f S16_LE -r 48000 -t wav line.wav

WM8904 Playback

# aplay mic.wav
# aplay line.wav

WM8904 (MP3) Playback

# gst-launch-1.0 playbin uri=file:///media/sda1/Gong.mp3
# aplay /media/sda1/Gong.wav
# gst-launch-1.0 playbin uri=file:///media/sda1/Gong.mp3 audio-sink="alsasink device=hw:0,0"
# aplay -D sysdefault:CARD=imx8mmwm8904 /media/sda1/Gong.wav

NAU8822 Audio Codec

[Verdin Development Board] V1.1 features an analog audio interface based on the NAU8822 24-bit audio codec IC with integrated DSP with specific functions from Nuvoton:

  • 90dB/94dB SNR ADC/DAC
  • Upto 48 Khz sampling rate
  • 5-band equalizer
  • 3-D audio enhancement
  • Input automatic level control (ALC/AGC)/limiter
  • Output dynamic-range-compressor/limiter
  • Notch filter and high pass filter

Check for the available sound cards.

To check the available sound cards, use the cat /proc/asound/cards command. The expected result on a Verdin iMX8M Plus:

# cat /proc/asound/cards
 0 [imx8mpnau8822  ]: imx8mp-nau8822 - imx8mp-nau8822
                      imx8mp-nau8822

NAU8822 Record from Microphone, MIC1.

Note that without a connected mic on X22 the onboard one is used.

# amixer set 'PGA',0 '63'
# amixer set 'PGA Boost',0 '0'
# amixer set 'Aux Boost',0 '0'
# arecord -D hw:0,0 -V mono -c 2 -f S16_LE -r 48000 -t wav mic.wav

NAU8822 Record from LINEIN

X21 what is played from AUX_OUT, X14. → connect X21 with X14

# amixer set 'PGA',0 '0'
# amixer set 'PGA Boost',0 '0'
# amixer set 'Aux Boost',0 '5'
# gst-launch-1.0 audiotestsrc ! audio/x-raw, rate=48000 ! alsasink -v &
# arecord -D hw:0,0 -V mono -c 2 -f S16_LE -r 48000 -t wav line.wav
<ctrl C>
# killall gst-launch-1.0

NAU8822 Playback, X20/X14, X28/X29 or X13

The speaker output can be used in a Mono, bridged mode configuration (One loudspeaker on X28/X29) or in a Stereo configuration (Two loudspeakers on X13)

  • Configure for one loudspeaker
# amixer set 'Speaker RInversion',0 on
  • Configure for two loudspeakers
# amixer set 'Speaker RInversion',0 off

NAU8822 Audio Playback

aplay mic.wav
aplay line.wav

NAU8822 (MP3) Playback

gst-launch-1.0 playbin uri=file:///home/root/sound/Gong.mp3
aplay /home/root/sound/Gong.wav
gst-launch-1.0 playbin uri=file:///home/root/sound/Gong.mp3 audio-sink="alsasink device=hw:0,0"
aplay -D sysdefault:CARD=imx8mpnau8822 /home/root/sound/Gong.wap

NXP/Freescale Vybrid Based Modules

Within the Vybrid module family, only Colibri VF61 supports analog audio. Audio is handled by the onboard Wolfson WM9715L audio codec connected via a AC97 audio link to the Vybrid SoC. The audio codec driver is called wm9712-codec, since it was initially created for the almost identical WM9712L codec.

WM9715L AC97 Playback

Playback of a WAVE file:

root@colibri-vf:~# aplay Test48kHz.wav
Playing WAVE 'Test48kHz.wav' : Signed 16 bit Little Endian, Rate 48000 Hz, Stereo
root@colibri-vf:~# aplay Test44.1kHz.wav
Playing WAVE 'Test44.1kHz.wav' : Signed 16 bit Little Endian, Rate 44100 Hz, Stereo

Note: Some parts of the AC97 protocol are realized in software. To make Software AC97 efficient, a rather large buffer is used to prepare several AC97 frames in a batch. However, using buffering does not allow the use of the variable sample rate (VRA) feature of the AC97 link during playback since that would require a response that depends on the request flag of the last received frame. Therefore, the hardware is only able to transfer 48kHz sample rate PCM streams. The ALSA audio stack is able to re-sample the sample rate dynamically, the only difference is that a file with a sample rate other than 48kHz requires somewhat more CPU resources while playback (<1% vs ~3%). Implementing the AC97 protocol without buffering would lead to a much higher CPU load than relying on ALSA's re-sampling feature.

The hardware parameter of the PCM stream during playback can be seen via the proc file system:

root@colibri-vf:~# cat /proc/asound/card0/pcm0p/sub0/hw_params
access: MMAP_INTERLEAVED
format: S16_LE
subformat: STD
channels: 2
rate: 48000 (48000/1)
period_size: 1024
buffer_size: 4096

Playback of encoded audio formats can be achieved using GStreamer. The Colibri VF61 root filesystem does not provide GStreamer by default, however it is installable via Angstrom feeds:

root@colibri-vf:~# opkg install gst-plugins-base-playbin gst-plugins-base-alsa gst-plugins-base-audioconvert gst-plugins-base-audioresample gst-plugins-base-vorbis gst-plugins-base-ogg gst-plugins-good-wavenc

The following GStreamer pipeline allows to playback Ogg Vorbis encoded audio files:

root@colibri-vf:~# gst-launch filesrc location=./vorbis.ogg ! oggdemux ! vorbisdec ! audioconvert ! alsasink

WM9715L AC97 Capture

The WM9715L has two audio ADCs hence allowing stereo audio capture. The input to these capture ADCS can be individually selected through the ALSA Capture Select controls. Capture volume and boost are handled after the channel selection, hence the volume applies for the Microphone as well as for Line-In capturing.

Two record volume modes can be selected, a standard AC97 1.5dB gain steps and an extended mode using 0.75dB gain steps. The extended mode (0.75dB gain steps) has also a larger gain range (-17.25-+30db), so we recommend using the extended mode.

root@colibri-vf:~# amixer set 'Capture Volume Steps' '+0.75dB Steps'

The record volume can then be set to a value between 0-63 (which mappings linearly to the gain ranges above).

root@colibri-vf:~# amixer set 'Capture' 50

Depending on the input (e.g. microphones) a boost might be necessary to increase the ADC signal by +20dB.

root@colibri-vf:~# amixer set 'Capture Boost' unmute

Line-in

Stereo capture can be achieved using Line-in functionality. First, the "Capture Select" needs to be selected correctly in ALSA mixer:

root@colibri-vf:~# amixer set 'Left Capture Select' 'Line'
Simple mixer control 'Left Capture Select',0
  Capabilities: enum
  Items: 'Mic' 'NC' 'NC' 'Speaker Mixer' 'Line' 'Headphone Mixer' 'Phone Mixer' 'Phone'
  Item0: 'Line'
root@colibri-vf:~# amixer set 'Right Capture Select' 'Line'
...

Then recording in various sample rates is natively possible:

root@colibri-vf:~# arecord -r 48000  -V mono -f S16_LE -c 2 Capture48kHz.wav
Recording WAVE 'Capture48kHz.wav' : Signed 16 bit Little Endian, Rate 48000 Hz, Stereo
^C
root@colibri-vf:~# arecord -r 8000 -f S16_LE -c 2 Capture8kHz.wav
Recording WAVE 'Capture8kHz.wav' : Signed 16 bit Little Endian, Rate 8000 Hz, Stereo
^C

To record the Ogg Vorbis audio format, the following GStreamer command can be used

root@colibri-vf:~# gst-launch alsasrc do-timestamp=true ! audioconvert ! vorbisenc quality=0.4 ! oggmux ! filesink location=vorbis.ogg
...

Microphone

root@colibri-vf:~# amixer set 'Left Capture Select' 'Mic'
...
root@colibri-vf:~# amixer set 'Right Capture Select' 'Mic'
...

The Colibri standard has only one microphone input, which is connected to Mic 1 of the audio codec. The codec internally samples the same signal with both ADCs, hence the ALSA stack receives a stereo signal. However, since the signals are the same, we can save some space by only recording one channel. The argument -V offers a VU meter which helps to see whether there is any input and if its volume is on a reasonable level.

root@colibri-vf:~# arecord  -V mono -r 8000 -f S16_LE -c 1 Capture8kHz.wav
#######             +                              | 38%
^C

Note: The volume controls "Mic 1" and "Mic 2" do not change the volume when capturing from the microphone. Those volume controls are only active if the sidetone path is enabled (e.g. direct path from microphone to headphone). Use the main capture volume to control the microphone volume.

USB Audio Hardware

CONFIG_SND_USB_AUDIO is enabled, so you may use USB audio hardware.
If you get the following error when recording from USB, enable the CONFIG_USB_EHCI_TT_NEWSCHED kernel configuration.

root@colibri_t20:~# arecord -D hw:3,0 -c 2 -f S16_LE -r 44100 -t wav usbin.wav
Recording WAVE 'usbin.wav' : Signed 16 bit Little Endian, Rate 44100 Hz, Stereo
[ 3187.734697] cannot submit datapipe for urb 0, error -28: not enough bandwidth