Инструмент режима текста -для просмотра уровня аудиовхода

В первый раз в вашем цикле вы устанавливаете energy=( $(awk...) ), и вывод из awkсостоит из нескольких строк, каждая из которых содержит одно число и заканчивается символом новой строки, как это всегда делают строки в Unix. Подстановка команд $(... )удаляет завершающую новую строку (с ), а когда она не заключена в двойные -кавычки, то разбивает результат на «слова» в любой из пробелов на новой строке (у вас есть новые строки ), и, наконец, если какое-либо слово является «шаблоном» (, содержащим ?*[..]), которое соответствует любому имени файла (s ), оно заменяется этими именами файлов (s )как отдельные «слова» (у вас нет таких шаблонов 'glob' ). Назначение массива energy=(... )затем сохраняет эти слова как элементы массива.

Во второй раз через IFS устанавливается запятая. Теперь, когда $(... )пытается разбить на слова, он использует (только запятую )и в выводе awk нет запятых, поэтому весь вывод (, включая новые строки ), остается как одно слово и присваивается массиву как один элемент.

Вам необходимо возвращать IFS для каждой итерации. Кроме того, вам необходимо установить стандартное значение IFS или, по крайней мере, значение, содержащее новую строку, в записи этого скрипта. OTOH откат IFS непосредственно перед выходом из скрипта в основном бесполезен; сценарий обычно запускается в отдельном процессе оболочки, и любые настройки переменных или другие изменения процесса -, сделанные сценарием, отбрасываются при выходе из сценария.

Или , вместо изменения IFS и явного возврата, вы можете сделать это в подоболочке , чтобы изменение отбрасывалось после завершения подоболочки. Синтаксис оболочки для подоболочки: также круглые скобки, на этот раз сами по себе:

( IFS=","; echo "${energy[*]};" >> $energies )
# you don't actually need to quote, here but 
# it's a good habit for string literals in general

Также в целом printfбезопаснее, чем echo, потому что в зависимости от используемой оболочки и/или системы echoможет исказить некоторые строковые значения. Однако значения, которые вы здесь --ограничены десятичными числами --, безопасны для echo.

Для bash есть еще одна возможность обрабатывать данные как одну строку, а не как массив:

energy=$( awk '/Total energy/{print $3}' output )
# command substitution strips the last newline
# scalar assignment does NOT do wordsplit and glob 
echo "${energy//$'\n'/,};" >>energies_blah 
# replaces all other newlines with commas, and adds semicolon 
echo "${energy##*$'\n'}" >>final_energies_blah 
# removes everything up to and including the last newline, 
# leaving only the last number

Или вы можете выполнять всю работу с помощью awk, особенно не -древнего GNU awk с 'endfile':

# read simcount,simend and set energies,fenergies
infiles=$( printf 'sim%d/output ' $( seq $simcount $simend ) )
awk -vf1=$energies -vf2=$fenergies '/Total Energy/ {e=e","$3; f=$3} ENDFILE {print substr(e,2)";">>f1; print f>>f2; e=f=""}' $infiles

С другими awk вы можете сделать то же самое с немного более уродливым кодом (сначала! )проверка FNR==1&&NR>1конца каждого файла, кроме последнего, и (где угодно)ENDконца последнего файла.

0
22.05.2020, 13:53
2 ответа

С помощью команд arecordи soxвы можете записать выборку единиц и измерить ее уровень:

arecord -qd 1 file && sox file -n stat 

Вот пример вывода:

Samples read:              8000
Length (seconds):      1.000000
Scaled by:         2147483647.0
Maximum amplitude:     0.992188
Minimum amplitude:    -0.992188
Midline amplitude:     0.000000
Mean    norm:          0.093221
Mean    amplitude:    -0.015338
RMS     amplitude:     0.232947
Maximum delta:         0.617188
Minimum delta:         0.000000
Mean    delta:         0.001067
RMS     delta:         0.009643
Rough   frequency:           52
Volume adjustment:        1.008

Если вас интересует только уровень/максимальная амплитуда, вы можете передать результат в awkдля вывода только второго поля четвертой строки:

arecord -qd 1 /tmp/rec.waw && sox /tmp/rec.waw -n stat 2>&1 | awk 'BEGIN{FS=":"} NR==4 {print $2}'

И если вы хотите отслеживать его эволюцию, вы можете поместить эту команду в цикл while:

while :; do
    arecord -qd 1 /tmp/rec.waw && sox /tmp/rec.waw -n stat 2>&1 | awk 'BEGIN{FS=":"} NR==4 {print $2}'
    sleep 1 # repeat every one second
done

Выход:

0.992188
0.023438
0.046875
0.375000
0.523438
0.109375
0.242188

Если вы хотите, чтобы выходной сигнал был в дБ, вы можете рассчитать его с помощьюawk:

while :; do
    arecord -qd 1 /tmp/rec.waw && sox /tmp/rec.waw -n stat 2>&1 | awk 'BEGIN{FS=":"} NR==4 {db=20*log($2)/log(10); printf("%0.4f\n",db}'
    sleep 1 # repeat every one second
done

Выход в дБ:

-12.6467
-13.4366
-13.2010
-14.4959
1
18.03.2021, 23:33

Вы можете использовать sox. Пример с Pulseaudio и моей веб-камерой в качестве источника:

sox -S -t pulseaudio alsa_input.usb-046d_0809_23E942AD-02.analog-mono -n stats

Также работает с устройствами ALSA, вы можете указать устройство по умолчанию и т. д. Подробнее см. man sox. Используйте pactl list short sourcesдля получения списка источников Pulseaudio.

1
18.03.2021, 23:33

Теги

Похожие вопросы