Hi everyone.
This is DEMO code for getting the RMS value of a symmetrical sampled waveform. It works a treat except see below.
I have used awk
as the prime mover as CygWin does not havd 'bc' or 'dc' yet and this is going into AudioScope.sh soon.
However, I hit an anomaly.
In the code below parts B, C, D and G are more than acceptable and E was as expected and also within limits acceptable.
However I never expected this, assume the waveform starts at centreline 0V...
View part F in the code and using just 4 samples with the input waveform being an isosceles triangle then a stepped squarewave becomes the sample.
(The results on editing each waveform are in the code.)
Actual waveform.
----------------
+V /\
/ \
0V / \
\ /
-V \/
Sampled waveform.
-----------------
255 +-+
| |
128 -+ +-+ +-
| |
0 +-+
RMS results are close to a sinewave using sinewave peak to peak values...
-------------------------------------------------------------------------
255 _
/ \
128 | |
\_/
0
As far as I am concerned there is no way of the sample knowing that the original signal was
either a sinewave or a triangle wave but the RMS result is that of a sinewave.
I can't find anything on a sample size of 4 on a triangle waveform and and its inversion so this anomaly stays.
Bazza.
#!/bin/bash
# rms.sh
# 'number' is an unsigned decimal integer from 0 to 255, newline delimited.
# 'RMS' the RMS value of a symmetrical wave, sine, square or triangle, (ignore the random one).
# 'Volts_P2P' a derived value from a captured signal, just a number in this demo.
# 'Volts_RMS' the RMS voltage
# 'Volts_P2P', set for a sinewave. Result should be 1.000 or close, (RMS value = 0.707).
# Set for squarewave. Result should be 1.000 or close, (RMS value = 1.000).
# Set for tringlwe wave. Result should be 1.000 or close, (RMS value = 0.577).
# Set a general value for Volts peak to peak.
Volts_P2P=2.000
Volts_RMS=0
waveform="Random"
number=0
RMS=0
# A ------------------------------------- #
# Just a random signal test. Not required.
#waveform="Random"
#for number in range{0..7999}
#do
# echo "$(( $RANDOM / 127 ))"
#done > "$HOME/sample.txt"
# B ------------------------------------- #
# Crude sinewave test. Results for 8 samples: RMS value = 0.707, RMS Volts = 0.996.
#Volts_P2P=2.818
#waveform="Sinewave"
#echo -n '128
#217
#255
#217
#128
#38
#0
#38' > "$HOME/sample.txt"
# C ------------------------------------- #
# Simple squarewave test. Results for 4 samples: RMS value = 1.004, RMS Volts = 1.004.
#waveform="Squarewave"
#echo -n '255
#255
#0
#0' > "$HOME/sample.txt"
# D ------------------------------------- #
# Fairly accurate triangle wave test. Results for 510 samples: RMS value = 0.580, RMS Volts = 1.005.
#Volts_P2P=3.464
#waveform="Accurate triangle"
#for number in {0..255}
#do
# echo "$number"
#done > "$HOME/sample.txt"
#for number in {254..1}
#do
# echo "$number"
#done >> "$HOME/sample.txt"
# E ------------------------------------- #
# Poor triangle wave test, 8 samples. Results for 8 samples: RMS value = 0.616, RMS Volts = 1.067.
#Volts_P2P=3.464
#waveform="Poor triange"
#echo -n '128
#192
#255
#192
#128
#64
#0
#64' > "$HOME/sample.txt"
# F ------------------------------------- #
# Very poor triangle wave test, 4 samples. Results for 4 samples: RMS value = 0.710, RMS Volts = 1.000.
# USE SINEWAVE PEAK TO PEAK VALUE HERE...
Volts_P2P=2.818
waveform="Poor sinewave or very poor triangle"
echo -n '128
255
128
0' > "$HOME/sample.txt"
# G ------------------------------------- #
# Squarewave test, 2 samples only. Results for 2 samples: RMS value = 1.004, RMS Volts = 1.004.
#waveform="Squarewave, 2 samples only"
#echo '255
#0' > "$HOME/sample.txt"
# --------------------------------------- #
# Awk calculation script.
RMS=$( awk 'BEGIN \
{
# Initialise variables.
N = 0;
sum_quares = 0;
}
{
# Convert 0 to 255 to -128 to 127 and divide by 127.
# 0 is now the the centreline instead of 128.
number = ( ( $1 - 128 ) / 127 );
sum_squares = sum_squares + ( number * number );
N = N + 1;
}
END \
{
printf "%.3f", ( sqrt ( sum_squares / N ) );
}' < "$HOME/sample.txt" )
# Do a simple awk conversion to RMS votage knowing the peak to peak value.
Volts_RMS=$( awk -v Volts="$Volts_P2P" -v rms="$RMS" 'BEGIN { printf "%.3f", ( ( Volts / 2 ) * rms ); }' )
echo "$waveform wave: RMS value = $RMS, RMS Volts = $Volts_RMS."