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
on the PuTTY terminal emulator (it doesn't work on the terminal console of the ARTIK IDE).
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 controlsamixer
by itself provides a detailed list of the controls and their optionsamixer 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.
- Preset the controls from the command line as described here.
- Start recording.
Start recording using the Command Line
-
Record audio.
arecord -f dat -d 5 test.wav
-
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.
-
From the ARTIK command line, install these packages.
apt install python-pyaudio
dnf install python-devel
dnf install portaudio
dnf install portaudio-devel
dnf install redhat-rpm-config
pip install PyAudio
-
Use a text editor like
vi
to create thisrecorder.py
code file, which records a 10-sec audio clip calledtest.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() |
-
Launch it from the command line.
python recorder.py
- 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.
-
Install the ALSA development library on your ARTIK board as noted here.
-
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(¶ms); 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; } |
-
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.
- Connect an earphone or speaker to the audio jack.
- Preset the controls from the command line as described here.
- Start playback.
Start playback using the command line
-
Play a
.wav
file by usingaplay
aplay test.wav
You could also usemplayer
-- it handles a greater variety of audio formats.
Start playback over HDMI
Gateway modules with HDMI have two digital audio interfaces to play audio files: I2S and SPDIF. These interfaces are detected on booting time. You can find them with the aplay -l command.
aplay -l
**** List of PLAYBACK Hardware Devices **** card 0: Audio [Artik530 raptor Audio], device 0: c0055000.i2s-rt5659-aif1 rt5659-aif1-0 [] Subdevices: 1/1 Subdevice #0: subdevice #0 card 0: Audio [Artik530 raptor Audio], device 1: c0059000.spdiftx-dit-hifi dit-hifi-1 [] Subdevices: 1/1 Subdevice #0: subdevice #0
Examples
Play wav file with aplay
aplay --device=hw0,1 <wavefile>
Play mp3 file with mplayer
mplayer -ao alsa:device=hw=0.1 <mp3file>
Start playback using Python
Use PyAudio to play back audio programmatically.
-
If you haven't already, install packages as noted here.
-
Use a text editor like
vi
to create thisplayer.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() |
-
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.
-
Install the ALSA development library on your ARTIK board as noted here.
-
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(¶ms); 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; } |
- 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 Ubuntu and Fedora ARTIK images come with the ALSA development library pre-installed. For Fedora 22, 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.