Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 14 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ expect alsa-utils python3 python3-construct python3-graphviz
```
sudo apt install expect alsa-utils python3 python3-construct python3-graphviz
```
If you would like to use tinyALSA for testing, install tinyALSA and SoX.
- How to install tinyALSA: https://github.com/tinyalsa/tinyalsa
- To install SoX run below command:
```
sudo apt-install sox
```
#### user group
sudo adm audio

Expand Down Expand Up @@ -52,12 +58,14 @@ Usage: ./check-playback.sh [OPTION]
2020-03-19 22:13:32 UTC [COMMAND] aplay -q --fatal-errors -Dhw:0,0 -r 48000 -c 2 -f S16_LE -d 4 /dev/zero -v -q
...
```

Some tests support SOF_ALSA_OPTS, SOF_APLAY_OPTS and SOF_ARECORD_OPTS,
work in progress. Where supported, optional parameters in SOF_APLAY_OPTS
and SOF_ARECORD_OPTS are passed to all aplay and arecord
invocations. SOF_ALSA_OPTS parameters are passed to both aplay and
arecord. Warning these environments variables do NOT support parameters
Some tests support these environment variables (work in progress):
- SOF_ALSA_TOOL is used to select the audio tool for testing.
Set this variable to 'alsa' (default value) or 'tinyalsa' to choose between the ALSA and TinyALSA toolsets.
- SOF_ALSA_OPTS contains optional parameters passed on both play and record.
- SOF_APLAY_OPTS and SOF_ARECORD_OPTS contain optional parameters passed additionally on play and record respectively.
These options are applied to the selected tool (alsa or tinyalsa) based on the value of SOF_ALSA_TOOL

Warning, these environment variables do NOT support parameters
with whitespace or globbing characters, in other words this does NOT
work:

Expand Down
119 changes: 103 additions & 16 deletions case-lib/lib.sh
Original file line number Diff line number Diff line change
Expand Up @@ -752,17 +752,88 @@ func_lib_check_pa()
# However, 1. arrays would complicate the user interface 2. ALSA does not
# seem to need arguments with whitespace or globbing characters.

# SOF_ALSA_TOOL:
# This option is used for selecting tool for testing,
# So far, supported tools are 'alsa' and 'tinyalsa'
# To select appropriate tool, set SOF_ALSA_TOOL to one of above
# before using 'aplay_opts' or 'arecord_opts' function.
# Default is SOF_ALSA_TOOL='alsa'


# Function to extract the card number and device number from $dev option (e.g., hw:0,10)
parse_audio_device() {
# Extract the card number (e.g., "0" from hw:0,10)
card_nr=$(printf '%s' "$1" | cut -d ':' -f2 | cut -d ',' -f1)

# Extract the device number (e.g., "10" from hw:0,10)
dev_nr=$(printf '%s' "$1" | cut -d ',' -f2)
}

# Function to extract the numeric format value from the PCM sample formats
# There is passes PCM sample format while using ALSA tool (arecord)
# While using TinyALSA (tinycap -b) we need to convert PCM sample fomrat to bits.
extract_format_number() {
# (e.g., extracting '16' from 'S16_LE')
printf '%s' "$1" | grep '[0-9]\+' -o
}

# Initialize the parameters using for audio testing.
# shellcheck disable=SC2034
initialize_audio_params()
{
local idx="$1"

channel=$(func_pipeline_parse_value "$idx" channel)
rate=$(func_pipeline_parse_value "$idx" rate)
fmts=$(func_pipeline_parse_value "$idx" fmt)
dev=$(func_pipeline_parse_value "$idx" dev)
pcm=$(func_pipeline_parse_value "$idx" pcm)
type=$(func_pipeline_parse_value "$idx" type)
snd=$(func_pipeline_parse_value "$idx" snd)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a lot of global variables with very short names...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


: "${SOF_ALSA_TOOL:="alsa"}"
if [[ "$SOF_ALSA_TOOL" = "tinyalsa" ]]; then
parse_audio_device "$dev"
fi
}

aplay_opts()
{
dlogc "aplay $SOF_ALSA_OPTS $SOF_APLAY_OPTS $*"
# shellcheck disable=SC2086
aplay $SOF_ALSA_OPTS $SOF_APLAY_OPTS "$@"
if [[ "$SOF_ALSA_TOOL" = "tinyalsa" ]]; then
# shellcheck disable=SC2154
if ! sox -n -r "$rate" -c "$channel" noise.wav synth "$duration" white; then
printf 'Error: sox command failed.\n' >&2
return 1
fi
dlogc "tinyplay $SOF_ALSA_OPTS $SOF_APLAY_OPTS -D $card_nr -d $dev_nr -i wav noise.wav"
# shellcheck disable=SC2086
tinyplay $SOF_ALSA_OPTS $SOF_APLAY_OPTS -D "$card_nr" -d "$dev_nr" -i wav noise.wav
elif [[ "$SOF_ALSA_TOOL" = "alsa" ]]; then
dlogc "aplay $SOF_ALSA_OPTS $SOF_APLAY_OPTS $*"
# shellcheck disable=SC2086
aplay $SOF_ALSA_OPTS $SOF_APLAY_OPTS "$@"
else
die "Unknown ALSA tool: $SOF_ALSA_TOOL"
fi
}

arecord_opts()
{
dlogc "arecord $SOF_ALSA_OPTS $SOF_ARECORD_OPTS $*"
# shellcheck disable=SC2086
arecord $SOF_ALSA_OPTS $SOF_ARECORD_OPTS "$@"

if [[ "$SOF_ALSA_TOOL" = "tinyalsa" ]]; then
# shellcheck disable=SC2154
# Global variable "$fmt_elem" from check_capture.sh test script
format=$(extract_format_number "$fmt_elem")
dlogc "tinycap $SOF_ALSA_OPTS $SOF_ARECORD_OPTS $file -D $card_nr -d $dev_nr -c $channel -t $duration -r $rate -b $format"
# shellcheck disable=SC2086
tinycap $SOF_ALSA_OPTS $SOF_ARECORD_OPTS "$file" -D "$card_nr" -d "$dev_nr" -c "$channel" -t "$duration" -r "$rate" -b "$format"
elif [[ "$SOF_ALSA_TOOL" = "alsa" ]]; then
dlogc "arecord $SOF_ALSA_OPTS $SOF_ARECORD_OPTS $*"
# shellcheck disable=SC2086
arecord $SOF_ALSA_OPTS $SOF_ARECORD_OPTS "$@"
else
die "Unknown ALSA tool: $SOF_ALSA_TOOL"
fi
}

die()
Expand Down Expand Up @@ -952,7 +1023,7 @@ is_ipc4()
logger_disabled()
{
# Disable logging when available...
if [ ${OPT_VAL['s']} -eq 0 ]; then
if [ "${OPT_VAL['s']}" -eq 0 ]; then
return 0
fi

Expand Down Expand Up @@ -1063,15 +1134,31 @@ set_alsa_settings()
reset_sof_volume()
{
# set all PGA* volume to 0dB
amixer -Dhw:0 scontrols | sed -e "s/^.*'\(.*\)'.*/\1/" |grep -E 'PGA|gain' |
while read -r mixer_name
do
if is_ipc4; then
amixer -Dhw:0 -- sset "$mixer_name" 100%
else
amixer -Dhw:0 -- sset "$mixer_name" 0dB
fi
done
if [[ "$SOF_ALSA_TOOL" = "alsa" ]]; then
amixer -Dhw:0 scontrols | sed -e "s/^.*'\(.*\)'.*/\1/" |grep -E 'PGA|gain' |

while read -r mixer_name
do
if is_ipc4; then
amixer -Dhw:0 -- sset "$mixer_name" 100%
else
amixer -Dhw:0 -- sset "$mixer_name" 0dB
fi
done
elif [[ "$SOF_ALSA_TOOL" = "tinyalsa" ]]; then
tinymix -D0 controls | sed -e "s/^.*'\(.*\)'.*/\1/" |grep -E 'PGA|gain' |
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: later, it would be nice to de-duplicate the sed+grep bit with a function. No need to do it now.


while read -r mixer_name
do
if is_ipc4; then
tinymix -D0 set "$mixer_name" 100%
else
tinymix -D0 set "$mixer_name" 0dB
fi
done
else
echo "Unknown alsa tool $SOF_ALSA_TOOL"
fi
}

DO_PERF_ANALYSIS=0
Expand Down
3 changes: 3 additions & 0 deletions env-check.sh
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ out_str="" check_res=0
printf "Checking for some OS packages:\t\t"
func_check_pkg expect
func_check_pkg aplay
func_check_pkg sox
func_check_pkg tinycap
func_check_pkg tinyplay
func_check_pkg python3
# jq is command-line json parser
func_check_pkg jq
Expand Down
25 changes: 10 additions & 15 deletions test-case/check-capture.sh
Original file line number Diff line number Diff line change
Expand Up @@ -64,38 +64,33 @@ setup_kernel_check_point
func_lib_check_sudo
func_pipeline_export "$tplg" "type:capture & ${OPT_VAL['S']}"

for round in $(seq 1 $round_cnt)
for round in $(seq 1 "$round_cnt")
do
for idx in $(seq 0 $((PIPELINE_COUNT - 1)))
do
channel=$(func_pipeline_parse_value "$idx" channel)
rate=$(func_pipeline_parse_value "$idx" rate)
fmt=$(func_pipeline_parse_value "$idx" fmt)
dev=$(func_pipeline_parse_value "$idx" dev)
pcm=$(func_pipeline_parse_value "$idx" pcm)
type=$(func_pipeline_parse_value "$idx" type)
snd=$(func_pipeline_parse_value "$idx" snd)

if [ ${OPT_VAL['F']} = '1' ]; then
fmt=$(func_pipeline_parse_value "$idx" fmts)

initialize_audio_params "$idx"

if [ "${OPT_VAL['F']}" = '1' ]; then
fmts=$(func_pipeline_parse_value "$idx" fmts)
fi

for fmt_elem in $fmt
for fmt_elem in $fmts
do
for i in $(seq 1 $loop_cnt)
for i in $(seq 1 "$loop_cnt")
do
dlogi "===== Testing: (Round: $round/$round_cnt) (PCM: $pcm [$dev]<$type>) (Loop: $i/$loop_cnt) ====="
# get the output file
if [[ -z $file_prefix ]]; then
dlogi "no file prefix, use /dev/null as dummy capture output"
file=/dev/null
else
mkdir -p $out_dir
mkdir -p "$out_dir"
file=$out_dir/${file_prefix}_${dev}_${i}.wav
dlogi "using $file as capture output"
fi

if ! arecord_opts -D"$dev" -r "$rate" -c "$channel" -f "$fmt_elem" -d $duration "$file" -v -q;
if ! arecord_opts -D"$dev" -r "$rate" -c "$channel" -f "$fmt_elem" -d "$duration" "$file" -v -q;
then
func_lib_lsof_error_dump "$snd"
die "arecord on PCM $dev failed at $i/$loop_cnt."
Expand Down
17 changes: 6 additions & 11 deletions test-case/check-playback.sh
Original file line number Diff line number Diff line change
Expand Up @@ -71,25 +71,20 @@ setup_kernel_check_point
func_lib_check_sudo
func_pipeline_export "$tplg" "type:playback & ${OPT_VAL['S']}"

for round in $(seq 1 $round_cnt)
for round in $(seq 1 "$round_cnt")
do
for idx in $(seq 0 $((PIPELINE_COUNT - 1)))
do
channel=$(func_pipeline_parse_value "$idx" channel)
rate=$(func_pipeline_parse_value "$idx" rate)
fmts=$(func_pipeline_parse_value "$idx" fmt)
dev=$(func_pipeline_parse_value "$idx" dev)
pcm=$(func_pipeline_parse_value "$idx" pcm)
type=$(func_pipeline_parse_value "$idx" type)
snd=$(func_pipeline_parse_value "$idx" snd)

if [ ${OPT_VAL['F']} = '1' ]; then

initialize_audio_params "$idx"

if [ "${OPT_VAL['F']}" = '1' ]; then
fmts=$(func_pipeline_parse_value "$idx" fmts)
fi

for fmt_elem in $fmts
do
for i in $(seq 1 $loop_cnt)
for i in $(seq 1 "$loop_cnt")
do
dlogi "===== Testing: (Round: $round/$round_cnt) (PCM: $pcm [$dev]<$type>) (Loop: $i/$loop_cnt) ====="
aplay_opts -D"$dev" -r "$rate" -c "$channel" -f "$fmt_elem" \
Expand Down
31 changes: 31 additions & 0 deletions test-case/tinyalsa-wrapper.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#!/bin/bash

##
## Case Name: Wrapper to run a test case given with TinyALSA
## Preconditions:
## TinyALSA and SoX are installed.
## Description:
## This script serves as a wrapper to execute a test case script using TinyALSA.
## It expects the test case script file name (without path) as the first parameter,
## followed by other parameters required for that test case.
## Case step:
## 1. SOF_ALSA_TOOL environment variable is set to TinyALSA
## 2. The test case script is executed.
## Expect result:
## The test case script is executed using TinyALSA
##

set -e

# Ensure the test case script file name is provided
if [ -z "$1" ]; then
echo "Error: No test case script file name provided. Exiting..."
exit 1
fi

export SOF_ALSA_TOOL=tinyalsa

TESTDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)

# shellcheck disable=SC2145
[ -x "$TESTDIR/test-case/$(basename "$1")" ] && exec "$TESTDIR"/test-case/"$@"