Improved loopback test suite to support multiple configuration.
To run the test suite: ./run_test.sh sample_format sample_rate channels duration Where: sample_format can be one of S16_LE, S24_3LE, S32_LE sample_rate can be one of 44100, 48000, 96000 channels can be one of 1, 2, 4 duration is in the range 1 to 10 minutes The test suite creates a raw file with the specified parameters, runs a loopback test where the file gets played and recorded using the loopback network interface and checks that the recorded file, after the initial silence, contains the expected samples sequence. This test was developed to further investigate the issue #17.
This commit is contained in:
parent
b34efd2a45
commit
10b5749d2a
99
run_test.sh
99
run_test.sh
@ -22,8 +22,8 @@ if ! [ -x "$(command -v arecord)" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! [ -x "$(command -v speaker-test)" ]; then
|
||||
echo 'Error: speaker-test is not installed.' >&2
|
||||
if ! [ -x "$(command -v aplay)" ]; then
|
||||
echo 'Error: aplay is not installed.' >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@ -37,6 +37,59 @@ if ! [ -r "3rdparty/ravenna-alsa-lkm/driver/MergingRavennaALSA.ko" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
cd test
|
||||
echo 'Compiling tools ...' >&2
|
||||
make
|
||||
echo 'Creating test file ...' >&2
|
||||
if ! ./createtest $1 $2 $3 $4 ; then
|
||||
echo 'Usage run_test.sh sample_format sample_rate channels duration' >&2
|
||||
echo ' sample_format can be one of S16_LE, S24_3LE, S32_LE' >&2
|
||||
echo ' sample_rate can be one of 44100, 48000, 96000' >&2
|
||||
echo ' channels can be one of 1, 2, 4' >&2
|
||||
echo ' duration is in the range 1 to 10 minutes' >&2
|
||||
exit 1
|
||||
else
|
||||
echo 'test file created' >&2
|
||||
fi
|
||||
cd ..
|
||||
|
||||
SAMPLE_FORMAT=$1
|
||||
SAMPLE_RATE=$2
|
||||
CHANNELS=$3
|
||||
DURATION=$4
|
||||
SEC=$((DURATION*60))
|
||||
|
||||
if [ $SAMPLE_FORMAT == "S16_LE" ]; then
|
||||
CODEC="L16"
|
||||
elif [ $SAMPLE_FORMAT == "S24_3LE" ]; then
|
||||
CODEC="L24"
|
||||
elif [ $SAMPLE_FORMAT == "S32_LE" ] ; then
|
||||
CODEC="AM824"
|
||||
fi
|
||||
|
||||
if [ $SAMPLE_RATE == "44100" ]; then
|
||||
PTIME="1.08843537415"
|
||||
elif [ $SAMPLE_RATE == "48000" ]; then
|
||||
PTIME="1"
|
||||
elif [ $SAMPLE_RATE == "96000" ]; then
|
||||
PTIME="0.5"
|
||||
fi
|
||||
|
||||
MAP="[ "
|
||||
for (( ch=0; ch<$CHANNELS; ch++ ))
|
||||
do
|
||||
MAP+=$ch
|
||||
if (( ch != ($CHANNELS - 1) )); then
|
||||
MAP+=","
|
||||
fi
|
||||
done
|
||||
MAP+=" ]"
|
||||
|
||||
echo 'Creating configuration files ..' >&2
|
||||
sed 's/48000/'"$SAMPLE_RATE"'/g;s/status.json/status_.json/g;' test/daemon.conf > test/daemon_.conf
|
||||
sed 's/\/2/\/'"$CHANNELS"'/g;s/48000/'"$SAMPLE_RATE"'/g;s/L24/'"$CODEC"'/g;s/ptime:1/ptime:'"$PTIME"'/;s/\[ 0, 1 \]/'"$MAP"'/g' test/status.json > test/status_.json
|
||||
|
||||
trap cleanup EXIT
|
||||
|
||||
#configure system parms
|
||||
@ -52,47 +105,53 @@ if [ -x /usr/bin/pulseaudio ]; then
|
||||
systemctl --user stop pulseaudio.sservice > /dev/null 2>&1
|
||||
fi
|
||||
|
||||
#uninstall kernel module
|
||||
if sudo lsmod | grep MergingRavennaALSA > /dev/null 2>&1 ; then
|
||||
sudo rmmod MergingRavennaALSA
|
||||
fi
|
||||
|
||||
#install kernel module
|
||||
sudo insmod 3rdparty/ravenna-alsa-lkm/driver/MergingRavennaALSA.ko
|
||||
|
||||
cleanup
|
||||
if [ -f ./test/sink_test.wav ] ; then
|
||||
rm -f sink_test.wav
|
||||
if [ -f ./test/sink_test.raw ] ; then
|
||||
rm -f ./test/sink_test.raw
|
||||
fi
|
||||
|
||||
echo "Starting PTP master ..."
|
||||
sudo /usr/sbin/ptp4l -i lo -l7 -E -S &
|
||||
|
||||
#echo "Starting AES67 daemon ..."
|
||||
./daemon/aes67-daemon -c ./test/daemon.conf &
|
||||
|
||||
#open browser on configuration page
|
||||
if [ -x "$(command -v xdg-open)" ]; then
|
||||
xdg-open "http://127.0.0.1:8080/PTP"
|
||||
fi
|
||||
echo "Starting AES67 daemon ..."
|
||||
./daemon/aes67-daemon -c ./test/daemon_.conf &
|
||||
|
||||
echo "Waiting for PTP slave to sync ..."
|
||||
sleep 30
|
||||
|
||||
#starting recording on sink
|
||||
echo "Starting to record 240 secs from sink ..."
|
||||
arecord -M -d 240 -D plughw:RAVENNA -f S24_3LE -r 48000 -c 2 -t wav /tmp/sink_test.wav > /dev/null 2>&1 &
|
||||
#starting record on sink
|
||||
echo "Starting to record $SEC sec from sink ..."
|
||||
arecord -M -d $SEC -D plughw:RAVENNA -f $SAMPLE_FORMAT -r $SAMPLE_RATE -c $CHANNELS -t raw /tmp/sink_test.raw &
|
||||
sleep 10
|
||||
|
||||
#starting playback on source
|
||||
echo "Starting to playback test on source ..."
|
||||
aplay -M -D plughw:RAVENNA ./test/test.wav > /dev/null 2>&1 &
|
||||
aplay -M -D plughw:RAVENNA -f $SAMPLE_FORMAT -r $SAMPLE_RATE -c $CHANNELS ./test/test.raw > /dev/null 2>&1 &
|
||||
|
||||
while killall -0 arecord 2>/dev/null ; do
|
||||
sleep 1
|
||||
done
|
||||
killall aplay
|
||||
if [ -f /tmp/sink_test.wav ] ; then
|
||||
mv /tmp/sink_test.wav test/
|
||||
echo "Recording to file \"test/sink_test.wav\" successfull"
|
||||
while killall -0 aplay 2>/dev/null ; do
|
||||
sleep 1
|
||||
done
|
||||
if [ -f /tmp/sink_test.raw ] ; then
|
||||
mv /tmp/sink_test.raw test/
|
||||
echo "Recording to file \"test/sink_test.raw\" successfull"
|
||||
else
|
||||
echo "Recording failed"
|
||||
fi
|
||||
|
||||
echo "Terminating processes ..."
|
||||
echo "Test result:"
|
||||
cd test
|
||||
./check $SAMPLE_FORMAT $CHANNELS
|
||||
cd ..
|
||||
|
||||
echo "Terminating processes ..."
|
||||
|
8
test/Makefile
Normal file
8
test/Makefile
Normal file
@ -0,0 +1,8 @@
|
||||
CXX=g++
|
||||
CC=g++
|
||||
all: check createtest
|
||||
createtest: createtest.o
|
||||
check: check.o
|
||||
clean:
|
||||
rm *.o
|
||||
rm check createtest
|
@ -4,10 +4,34 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main ()
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
if (argc < 3) {
|
||||
cerr << "Usage: " << argv[0] << " sample_format channels" << endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int len(0);
|
||||
string format(argv[1]);
|
||||
if (format == "S16_LE")
|
||||
len = 2;
|
||||
else if (format == "S24_3LE")
|
||||
len = 3;
|
||||
else if (format == "S32_LE")
|
||||
len = 4;
|
||||
else {
|
||||
cerr << "Unsupported format " << format << endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int channels = atoi(argv[2]);
|
||||
if (channels != 1 && channels != 2 && channels != 4 && channels != 8) {
|
||||
cerr << "Unsupported channels " << channels << endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fstream fl;
|
||||
fl.open("./sink_test.wav", ios::in|ios::binary);
|
||||
fl.open("./sink_test.raw", ios::in|ios::binary);
|
||||
if (!fl.is_open()) {
|
||||
cout << "cannot open file " << endl;
|
||||
exit(1);
|
||||
@ -15,36 +39,40 @@ int main ()
|
||||
auto begin = fl.tellp();
|
||||
fl.seekp(0, ios::end);
|
||||
auto end = fl.tellp();
|
||||
fl.seekp(68, ios::beg);
|
||||
unsigned char ch = 0;
|
||||
fl.seekp(0, ios::beg);
|
||||
auto prev = fl.tellp();
|
||||
while(fl.tellp() < end && ch == 0)
|
||||
{
|
||||
prev = fl.tellp();
|
||||
ch = fl.get();
|
||||
}
|
||||
unsigned char curr = 0;
|
||||
// skip inital silence
|
||||
while((prev = fl.tellp()) != end && fl.get() == 0);
|
||||
|
||||
uint8_t curr = 0, byte = 0;
|
||||
bool first = true;
|
||||
fl.seekp(prev);
|
||||
while(fl.tellp() < end)
|
||||
{
|
||||
while(fl.tellp() != end) {
|
||||
int ch(channels);
|
||||
while (ch--) {
|
||||
if (!first) {
|
||||
ch = fl.get();
|
||||
if (ch != (uint8_t)curr) break;
|
||||
byte = fl.get();
|
||||
if (byte != (uint8_t)curr) goto end;
|
||||
}
|
||||
if (len > 1) {
|
||||
byte = fl.get();
|
||||
if (byte != (uint8_t)(curr+1)) goto end;
|
||||
if (len > 2) {
|
||||
byte = fl.get();
|
||||
if (byte != (uint8_t)(curr+2)) goto end;
|
||||
if (len > 3) {
|
||||
byte = fl.get();
|
||||
if (byte != (uint8_t)(curr+3)) goto end;
|
||||
}
|
||||
}
|
||||
}
|
||||
ch = fl.get();
|
||||
if (ch != (uint8_t)(curr+1)) break;
|
||||
ch = fl.get();
|
||||
if (ch != (uint8_t)(curr+2)) break;
|
||||
ch = fl.get();
|
||||
if (ch != (uint8_t)curr) break;
|
||||
ch = fl.get();
|
||||
if (ch != (uint8_t)(curr+1)) break;
|
||||
ch = fl.get();
|
||||
if (ch != (uint8_t)(curr+2)) break;
|
||||
curr += 3;
|
||||
first = false;
|
||||
}
|
||||
curr += len;
|
||||
}
|
||||
|
||||
end:
|
||||
//cout << "expected " << (int)curr << " byte " << (int)byte << endl;
|
||||
int rc = 0;
|
||||
if (fl.tellp() != end)
|
||||
{
|
||||
|
70
test/createtest.cc
Normal file
70
test/createtest.cc
Normal file
@ -0,0 +1,70 @@
|
||||
// basic file operations
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
if (argc < 5) {
|
||||
cerr << "Usage " << argv[0] << " sample_format sample_rate channels duration" << endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int len(0);
|
||||
string format(argv[1]);
|
||||
if (format == "S16_LE")
|
||||
len = 2;
|
||||
else if (format == "S24_3LE")
|
||||
len = 3;
|
||||
else if (format == "S32_LE")
|
||||
len = 4;
|
||||
else {
|
||||
cerr << "Unsupported format " << format << endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int rate(atoi(argv[2]));
|
||||
if (rate != 44100 && rate != 48000 && rate != 96000) {
|
||||
cerr << "Unsupported rate " << rate << endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int channels = atoi(argv[3]);
|
||||
if (channels != 1 && channels != 2 && channels != 4 && channels != 8) {
|
||||
cerr << "Unsupported channels " << channels << endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int duration = atoi(argv[4]);
|
||||
if (duration > 10 || duration < 1) {
|
||||
cerr << "Unsupported duration " << duration << " minutes" << endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int secs(duration * 60);
|
||||
unsigned char byte(0);
|
||||
fstream myfile;
|
||||
myfile.open("test.raw", ios::out|ios::binary);
|
||||
while(secs--) {
|
||||
int samples(rate);
|
||||
while (samples--) {
|
||||
int ch(channels);
|
||||
while (ch--) {
|
||||
myfile.put(byte);
|
||||
if (len > 1) {
|
||||
myfile.put(byte+1);
|
||||
if (len > 2) {
|
||||
myfile.put(byte+2);
|
||||
if (len > 3)
|
||||
myfile.put(byte+3);
|
||||
}
|
||||
}
|
||||
}
|
||||
byte+=len;
|
||||
}
|
||||
}
|
||||
myfile.close();
|
||||
return 0;
|
||||
|
||||
}
|
@ -4,19 +4,21 @@
|
||||
"http_base_dir": "./webui/build",
|
||||
"log_severity": 3,
|
||||
"playout_delay": 0,
|
||||
"tic_frame_size_at_1fs": 192,
|
||||
"tic_frame_size_at_1fs": 48,
|
||||
"max_tic_frame_size": 1024,
|
||||
"sample_rate": 48000,
|
||||
"rtp_mcast_base": "239.1.0.1",
|
||||
"rtp_port": 5004,
|
||||
"ptp_domain": 0,
|
||||
"ptp_dscp": 48,
|
||||
"sap_mcast_addr": "224.2.127.254",
|
||||
"sap_interval": 30,
|
||||
"syslog_proto": "none",
|
||||
"syslog_server": "255.255.255.254:1234",
|
||||
"status_file": "./demo/status.json",
|
||||
"mdns_enabled": false,
|
||||
"status_file": "./test/status.json",
|
||||
"interface_name": "lo",
|
||||
"mac_addr": "01:00:5e:01:00:01",
|
||||
"ip_addr": "127.0.0.1"
|
||||
"mdns_enabled": false,
|
||||
"mac_addr": "00:00:00:00:00:00",
|
||||
"ip_addr": "127.0.0.1",
|
||||
"node_id": "AES67 daemon 007f0100"
|
||||
}
|
||||
|
@ -21,7 +21,7 @@
|
||||
"use_sdp": true,
|
||||
"source": "http://127.0.0.1:8080/api/source/sdp/0",
|
||||
"sdp": "v=0\no=- 657664 657666 IN IP4 127.0.0.1\ns=AES67 daemon 000a0900 ALSA Source 0\nc=IN IP4 239.1.0.1/15\nt=0 0\na=clock-domain:PTPv2 0\nm=audio 5004 RTP/AVP 98\nc=IN IP4 239.1.0.1/15\na=rtpmap:98 L24/48000/2\na=sync-time:0\na=framecount:48\na=ptime:1\na=mediaclk:direct=0\na=ts-refclk:ptp=IEEE1588-2008:00-1D-C1-FF-FE-50-36-33:0\na=recvonly\n",
|
||||
"delay": 576,
|
||||
"delay": 960,
|
||||
"ignore_refclk_gmid": true,
|
||||
"map": [ 0, 1 ]
|
||||
} ]
|
||||
|
BIN
test/test.wav
BIN
test/test.wav
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user