Filter results by

Audio Operations

Linux®-based ARTIK development boards are readily programmed for audio input and output. They have a built in monaural microphone (on the left channel), so you only need to connect speakers or a headphone to the audio output jack to test the audio features.

artik 530/710 artik 520/1020

Click the links here to jump to your topic of interest:

The audio control names for ARTIK 520/1020 are different from those for ARTIK 530/710, so control scripts for one won't work on the other.

Set Audio Controls

The easy way to get familiar with audio subsystem controls on ARTIK development boards is to use alsamixer

For actual deployment, the mixer controls are more typically set through shell scripts; examples are provided throughout this article.

To control the audio subsystem of the ARTIK development boards, you use the amixer pre-loaded utility program.

  • amixer scontrols summarizes the available controls
  • amixer by itself provides a detailed list of the controls and their options
  • amixer help shows command line usage.

Before using amixer to fine-tune settings, it's helpful to first set the baseline audio state by running the included shell script:

/usr/bin/audio_setting.sh

Audio settings are maintained on power cycle, as long as you use reboot to make sure all file changes are written. Use alsactl store to write the setting changes without a reboot.

Selecting the microphone (ARTIK 530/710 only)

The ARTIK 530/710 platform board has a built-in microphone, and also allows connection of an external microphone through the headset jack.

You can record audio from the external, internal, or both microphones by using the appropriate script.

– external MIC only

1
2
3
4
amixer sset "RECMIX1L BST1" on
amixer sset "RECMIX1R BST1" on
amixer sset "RECMIX1L BST2" off
amixer sset "RECMIX1R BST2" off

– internal MIC only

1
2
3
4
amixer sset "RECMIX1L BST1" off
amixer sset "RECMIX1R BST1" off
amixer sset "RECMIX1L BST2" on
amixer sset "RECMIX1R BST2" on

– both MIC inputs

1
2
3
4
amixer sset "RECMIX1L BST1" on
amixer sset "RECMIX1R BST1" on
amixer sset "RECMIX1L BST2" on
amixer sset "RECMIX1R BST2" on

Setting the recording controls

These scripts indicate typical settings for recording controls and gain.

ARTIK 530/710
   (select the microphone first as noted above)

1
2
3
4
5
6
7
8
9
# Global volume setting
amixer sset "Mono ADC" 80%
amixer sset "STO1 ADC" 80%

# Internal MIC volume
amixer sset "IN2 Boost" 50

# External MIC volume
amixer sset "IN1 Boost" 50

ARTIK 520/1020

1
2
3
4
5
6
7
8
9
10
11
amixer sset "Mic Gain Control" 3
amixer sset "Mic Bias MUX" "IN1"
amixer sset "IN1 MUX" "Mic Bias"
amixer sset "Input Select MUX" "LIN1/RIN1"
amixer sset "ADC MUX1" "Mono"
amixer sset "MIC MUX" "AMIC"
amixer sset "ADCPF MUX" "ADC"
amixer sset "DACHP" "ON" 
amixer sset "MIC MUX" "AMIC"
amixer sset "ADCPF MUX" "ADC"
amixer sset "DACHP" "ON"

Setting the playback controls

These scripts indicate typical settings for playback controls and volume.

ARTIK 530/710

1
amixer sset "DAC1" 140

ARTIK 520/1020

1
2
3
amixer sset "PFDAC MUX" "SDTI"  
amixer sset "DACHP" "ON"  
amixer sset "Digital Output Volume2 L" 240

Capture Audio

Our sample code uses 44.1 kHz sampling, mono channel, and PCM signed 16-bit Little Endian format.

  1. Preset the controls from the command line as described here.
  2. Start recording.

Start recording using the Command Line

  1. Record audio.
       arecord -f dat -d 5 test.wav

  2. Play back as noted in the Play Audio section.

The noted audio file is recorded for 5 seconds using stereo recording at 48kHz sampling frequency, 16-bit little endian. You can check the default parameter settings like sample frequency and resolution using arecord –h

Start recording using Python

Use PyAudio to capture audio programmatically. It provides Python bindings for PortAudio, the cross-platform audio I/O library. With PyAudio, you can use Python to easily record and play audio on ARTIK systems.

  1. From the ARTIK command line, install these packages.

    dnf install python-devel
    dnf install portaudio
    dnf install portaudio-devel
    dnf install redhat-rpm-config

  2. Use pip to establish the PyAudio Python binding.

    pip install PyAudio

  3. Use a text editor like vi to create this recorder.py code file, which records a 10-sec audio clip called test.wav.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import pyaudio
import wave

FORMAT = pyaudio.paInt16
CHANNELS = 2
RATE = 44100
CHUNK = 1024
RECORD_SECONDS = 10
WAVE_OUTPUT_FILENAME = "test.wav"

audio = pyaudio.PyAudio()

# start Recording
stream = audio.open(format=FORMAT, channels=CHANNELS, rate=RATE, input=True, frames_per_buffer=CHUNK)
print "recording audio..."
frames = []

threshold = 800
for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
   data = stream.read(CHUNK)
   frames.append(data)
print "done recording"

# stop Recording
stream.stop_stream()
stream.close()
audio.terminate()

waveFile = wave.open(WAVE_OUTPUT_FILENAME, 'wb')
waveFile.setnchannels(CHANNELS)
waveFile.setsampwidth(audio.get_sample_size(FORMAT))
waveFile.setframerate(RATE)
waveFile.writeframes(b''.join(frames))
waveFile.close()
  1. Launch it from the command line.
       python recorder.py
  2. Play back as noted in the Play Audio section.

Start recording using C

The Linux ALSA driver and API set makes it simpler to use C code to record audio on the ARTIK platform. The example below generates raw PCM data.

  1. Install the ALSA development library on your ARTIK board as noted here.

  2. Save the code below, which records a 10-sec audio clip, to a file called recorder.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#include <alsa/asoundlib.h>
#include <stdio.h>

#define PCM_DEVICE "default"

int main(int argc, char **argv) 
{
  unsigned int pcm, tmp, dir;
  int rate, channels, seconds;
  snd_pcm_t *pcm_handle;
  snd_pcm_hw_params_t *params;
  snd_pcm_uframes_t frames;
  char *buff;
  int buff_size, loops;

  snd_mixer_t *handle;
  snd_mixer_selem_id_t *sid;
  const char *card = "default";

  rate  = 44100;
  channels = 2;
  seconds  = 10;
  frames   = 32;

  /* Open the PCM device in record mode */
  if (pcm = snd_pcm_open(&pcm_handle, PCM_DEVICE,
	SND_PCM_STREAM_CAPTURE, 0) < 0) 
      printf("ERROR: Can't open \"%s\" PCM device. %s\n",
		PCM_DEVICE, snd_strerror(pcm));

  /* Allocate parameters object and fill it with default values*/
  snd_pcm_hw_params_alloca(&params);

  snd_pcm_hw_params_any(pcm_handle, params);

  /* Set parameters */
  if (pcm = snd_pcm_hw_params_set_access(pcm_handle, params,
    SND_PCM_ACCESS_RW_INTERLEAVED) < 0) 
      printf("ERROR: Can't set interleaved mode. %s\n", snd_strerror(pcm));

  if (pcm = snd_pcm_hw_params_set_format(pcm_handle, params,
    SND_PCM_FORMAT_S16_LE) < 0) 
      printf("ERROR: Can't set format. %s\n", snd_strerror(pcm));

  if (pcm = snd_pcm_hw_params_set_channels(pcm_handle, params, channels) < 0) 
    printf("ERROR: Can't set channels number. %s\n", snd_strerror(pcm));

  if (pcm = snd_pcm_hw_params_set_rate_near(pcm_handle, params, &rate, 0) < 0) 
    printf("ERROR: Can't set rate. %s\n", snd_strerror(pcm));

  if (pcm = snd_pcm_hw_params_set_period_size_near(pcm_handle, params, &frames, 0) < 0)
    printf("ERROR: Can't set period size. %s\n", snd_strerror(pcm));

  /* Write parameters */
  if (pcm = snd_pcm_hw_params(pcm_handle, params) < 0)
    printf("ERROR: Can't set hardware parameters. %s\n", snd_strerror(pcm));

  /* Resume information */
  printf("PCM name: '%s'\n", snd_pcm_name(pcm_handle));

  printf("PCM state: %s\n", snd_pcm_state_name(snd_pcm_state(pcm_handle)));

  snd_pcm_hw_params_get_channels(params, &tmp);
  printf("channels: %i ", tmp);

  if (tmp == 1)
    printf("(mono)\n");
  else if (tmp == 2)
    printf("(stereo)\n");

  snd_pcm_hw_params_get_rate(params, &tmp, 0);
  printf("rate: %d bps\n", tmp);

  printf("seconds: %d\n", seconds);	

  /* Allocate buffer to hold single period */
  snd_pcm_hw_params_get_period_size(params, &frames, 0);

  buff_size = frames * channels * 2 /* 2 -> sample size */;
  buff = (char *) malloc(buff_size);

  snd_pcm_hw_params_get_period_time(params, &tmp, NULL);

  for (loops = (seconds * 1000000) / tmp; loops > 0; loops--) {
    pcm = snd_pcm_readi(pcm_handle, buff, frames);
    if (pcm == -EPIPE) {
      printf("XRUN. \n");
      snd_pcm_prepare(pcm_handle);
    } else if (pcm < 0) {
      printf("ERROR. Can't read from PCM device. %s\n", snd_strerror(pcm));
    } else if (pcm != (int)frames) {
      printf("short read, read %d frames\n", pcm);
    }

    pcm = write(1, buff, buff_size);
    if (pcm != buff_size)
      printf("short write, write %d bytes\n", pcm);
  }

  snd_pcm_drain(pcm_handle);
  snd_pcm_close(pcm_handle);
  free(buff);

  return 0;
}
  1. Compile and run the code from the ARTIK command line.
       gcc recorder.c -l asound -o recorder
       ./recorder > sound.raw

Compiles okay but does not record? Try running without an output file
./recorder
so that you can see any error messages.

Play Audio

Our sample code uses 44.1 kHz sampling, mono channel, and PCM signed 16-bit Little Endian format.

  1. Connect an earphone or speaker to the audio jack.
  2. Preset the controls from the command line as described here.
  3. Start playback.

Start playback using the command line

  1. Play a .wav file by using aplay
       aplay test.wav
    You could also use mplayer -- it handles a greater variety of audio formats.

Start playback using Python

Use PyAudio to play back audio programmatically.

  1. Use a text editor like vi to create this player.py code file, which implements the audio playback functionality.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import pyaudio
import wave
import sys

# length of data to read.
CHUNK = 1024

# validation. If a wave file hasn't been specified, exit.
if len(sys.argv) < 2:
    print "Plays a wave file.\n\n" +\
          "Usage: %s filename.wav" % sys.argv[0]
    sys.exit(-1)

# open the file for reading.
waveFile = wave.open(sys.argv[1], 'rb')

# create an audio object
audio = pyaudio.PyAudio()

# open stream
stream = audio.open(format = audio.get_format_from_width(waveFile.getsampwidth()),
    channels = waveFile.getnchannels(),
    rate = waveFile.getframerate(),
    output = True)

# read data (based on the chunk size)
data = waveFile.readframes(CHUNK)

# play stream)
while data != '':
    stream.write(data)
    data = waveFile.readframes(CHUNK)

# cleanup stuff.
stream.close()
audio.terminate()
  1. Run the command below to play, for example, the test.wav audio file created by the previous Python example.
       python player.py test.wav

Start playback using C

The Linux ALSA driver and API set makes it simpler to use C code to play audio on the ARTIK platform. The example below uses raw PCM data.

  1. Install the ALSA development library on your ARTIK board as noted here.

  2. Save the code below to a flle called player.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#include <alsa/asoundlib.h>
#include <stdio.h>

#define PCM_DEVICE "default"

int main(int argc, char **argv) 
{
  unsigned int pcm, tmp, dir;
  int rate, channels, seconds;
  snd_pcm_t *pcm_handle;
  snd_pcm_hw_params_t *params;
  snd_pcm_uframes_t frames;
  char *buff;
  int buff_size, loops;

  snd_mixer_t *handle;
  snd_mixer_selem_id_t *sid;
  const char *card = "default";

  rate = 44100;
  channels = 2;
  seconds  = 10;

  /* Open the PCM device in playback mode */
  if (pcm = snd_pcm_open(&pcm_handle, PCM_DEVICE,
	SND_PCM_STREAM_PLAYBACK, 0) < 0) 
      printf("ERROR: Can't open \"%s\" PCM device. %s\n",
	    PCM_DEVICE, snd_strerror(pcm));

  /* Allocate parameters object and fill it with default values*/
  snd_pcm_hw_params_alloca(&params);

  snd_pcm_hw_params_any(pcm_handle, params);

  /* Set parameters */
  if (pcm = snd_pcm_hw_params_set_access(pcm_handle, params,
    SND_PCM_ACCESS_RW_INTERLEAVED) < 0) 
      printf("ERROR: Can't set interleaved mode. %s\n", snd_strerror(pcm));

  if (pcm = snd_pcm_hw_params_set_format(pcm_handle, params,
    SND_PCM_FORMAT_S16_LE) < 0) 
      printf("ERROR: Can't set format. %s\n", snd_strerror(pcm));

  if (pcm = snd_pcm_hw_params_set_channels(pcm_handle, params, channels) < 0) 
    printf("ERROR: Can't set channels number. %s\n", snd_strerror(pcm));

  if (pcm = snd_pcm_hw_params_set_rate_near(pcm_handle, params, &rate, 0) < 0) 
    printf("ERROR: Can't set rate. %s\n", snd_strerror(pcm));

  /* Write parameters */
  if (pcm = snd_pcm_hw_params(pcm_handle, params) < 0)
    printf("ERROR: Can't set hardware parameters. %s\n", snd_strerror(pcm));

  /* Resume information */
  printf("PCM name: '%s'\n", snd_pcm_name(pcm_handle));

  printf("PCM state: %s\n", snd_pcm_state_name(snd_pcm_state(pcm_handle)));

  /* Print parameters */
  snd_pcm_hw_params_get_channels(params, &tmp);
  printf("channels: %i ", tmp);

  if (tmp == 1)
    printf("(mono)\n");
  else if (tmp == 2)
    printf("(stereo)\n");

  snd_pcm_hw_params_get_rate(params, &tmp, 0);
  printf("rate: %d bps\n", tmp);

  printf("seconds: %d\n", seconds);	

  /* Allocate buffer to hold single period */
  snd_pcm_hw_params_get_period_size(params, &frames, 0);

  buff_size = frames * channels * 2 /* 2 -> sample size */;
  buff = (char *) malloc(buff_size);

  snd_pcm_hw_params_get_period_time(params, &tmp, NULL);

  for (loops = (seconds * 1000000) / tmp; loops > 0; loops--) {
    if (pcm = read(0, buff, buff_size) == 0) {
      printf("Early end of file.\n");
      return 0;
    }

    if (pcm = snd_pcm_writei(pcm_handle, buff, frames) == -EPIPE) {
      printf("XRUN.\n");
      snd_pcm_prepare(pcm_handle);
    } else if (pcm < 0) {
      printf("ERROR. Can't write to PCM device. %s\n", snd_strerror(pcm));
    }

  } 

  snd_pcm_drain(pcm_handle);
  snd_pcm_close(pcm_handle);
  free(buff);

  return 0;
}
  1. Compile and run the code from the ARTIK command line.
       gcc player.c -l asound -o player
       ./player < sound.raw

ALSA Library

The Advanced Linux Sound Architecture (ALSA) development library consists of a set of kernel drivers, APIs, and utility programs for supporting sound under Linux. The C programming examples in this article use the PCM interfaces of ALSA.

The latest ARTIK images come with the ALSA development library pre-installed. For earlier image revisions, run this command to install.

dnf install alsa-lib-devel

Warning Messages

You may see some messages like those below when you run an ALSA-enabled application. These are normal debug messages and can be ignored.

ALSA lib pcm.c:2267:(snd_pcm_open_noupdate) ...
	... Unknown PCM cards.pcm.front
	... Unknown PCM cards.pcm.rear
	... Unknown PCM cards.pcm.center_lfe
	...

To suppress these messages, comment out the unneeded lines in /usr/share/alsa/alsa.conf

1
2
3
4
#pcm.front cards.pcm.front
#pcm.rear cards.pcm.rear  
#pcm.center_lfe cards.pcm.center_lfe  
...

Warning messages about not connecting to the server can likewise be ignored; they refer to real-time sound servers like Jackd that are not needed for simple audio recording and playback tasks. There are no configuration file settings to suppress these messages.

Last updated on: