Re: Realtime sound level measurement with logging

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Jonathan,
I found your request actually interesting to play with.
If you use jack, I made a little python script, which only requires you to download and compile a small program, jack-peak, that Robin Gaerus wrote a couple of years ago.
You can find it here: http://gareus.org/gitweb/?p=jack-peak.git;a=tree
Just download the tar or zip file, unpack it and type make. It might give you some erros, but don't worry: if a "jack-peak" file (without any extension) is created, it means that the build process was successful.
Then, just use the attached "meter.py" script, put it anywere you want, then copy that jack-peak compiled file in the same path, then run

./meter.py -c 1

this will just create a single input port, without jack connection, and will print the output at the default delay rate (100ms).
For example, this command line will record the value every second, connect to the first system audio input and save the data to the file "peaks.txt"
./meter.py -d 1000 -f peaks.txt system:capture_1

By default, the value is a float linear (3 digits after decimal point), from 0 to 1, you can use a custom integer scale, eg from 0 to 1000.
To stop recording, just hit ctrl+c.

For more options, look at the help documentation:
./meter.py -h

I'm actually thinking about converting it to a pure python script, by including jack-python bindings and supporting alsa too, but right now I'm in the middle of another project and I don't have much time for that right now.
Anyway, let me know if this suits your needs.

PS: Robin's program can be used even without this script, but you need to forward its output to a file and then parse every line, since it just rewrites the lines everytime the data is analyzed, which results in an unreadable output or file.

Cheers,
MaurizioB

2017-05-12 11:47 GMT+02:00 Jonathan Gazeley <Jonathan.Gazeley@xxxxxxxxxxxxx>:
Hi folks,

I'd like to set up sound level monitoring for my office, with periodic logging. I have a handheld meter but I'm really looking for a way to use a traditional condenser microphone and USB audio interface to measure the level with some kind of windowing, and log it periodically to a file (maybe once per minute). Is there a decent application that can monitor and log data in this way?

I'm also open to the idea of just recording a WAV file over 24 hours and doing the analysis afterwards, with periodic readings from the file.

Is my approach reasonable, to set up a microphone and use the gain knob to calibrate it against the handheld meter?

I don't need amazing accuracy. We've just moved into a large open-plan office for the first time and it is very noisy (handheld meter says about 50dB of air handling noise measured at my desk, rising to 60dB when there is background talking). I want to monitor sound levels throughout the day to test my theory that people are more noisy in the afternoon, and to get an overnight control reading with the people gone and only the air handling and computers running.

Thanks,
Jonathan
--
Jonathan Gazeley
Senior Systems Administrator
IT Services
University of Bristol
_______________________________________________
Linux-audio-user mailing list
Linux-audio-user@lists.linuxaudio.org
http://lists.linuxaudio.org/listinfo/linux-audio-user



--
È difficile avere una convinzione precisa quando si parla delle ragioni del cuore. - "Sostiene Pereira", Antonio Tabucchi
http://www.jidesk.net
#!/usr/bin/env python2.7
# *-* coding: utf-8 *-*

from fcntl import fcntl, F_GETFL, F_SETFL
from os import O_NONBLOCK, read
import subprocess
import argparse
from commands import getoutput

def channel_number(c):
    try:
        c = int(c)
    except:
        raise argparse.ArgumentTypeError('Channel number must be an integer')
    if c < 0:
        raise argparse.ArgumentTypeError('Please specify a channel number greater than 0')
    return c

def delay_var(d):
    try:
        d = int(d)
    except:
        raise argparse.ArgumentTypeError('Delay interval must be an integer')
    if d < 100:
        d = 100
    return d

parser = argparse.ArgumentParser()
parser.add_argument('-d', '--delay', metavar='N', type=delay_var, default=100, help='Delay interval in milliseconds')
parser.add_argument('-s', '--scale', type=int, help='use dB scale; output range 0-<SCALE> (integer); if not specified, output range is linear [0..1]')
parser.add_argument('-f', '--file', help='Output file')
parser.add_argument('-c', '--channels', metavar='C', type=int, help='Channel number', default=1)
parser.add_argument('ports', nargs='*')

args = parser.parse_args()

delay = args.delay
if not args.channels and not args.ports:
    print 'At least a channel value or output port must be specified'
    parser.print_help()
    exit()
elif args.ports:
    jack_port_list = []
    port_iter = iter(getoutput('jack_lsp -p').split('\n'))
    while True:
        try:
            port = port_iter.next().strip()
            props = port_iter.next().strip().replace('properties: ', '').rstrip(',').split(',')
            if not 'output' in props:
                continue
            jack_port_list.append(port)
        except:
            break
    not_valid = []
    not_found = []
    for port in args.ports:
        if not ':' in port:
            not_valid.append(port)
            continue
        if not port in jack_port_list:
            not_found.append(port)
    if not_valid:
        print 'The following specified port names are not valid (the ports will still be created, you have to connect them manually:'
        print '\n'.join(['- {}'.format(p) for p in not_valid])
    if not_found:
        print 'The following ports are not available (thus will not be connected, do it manually):'
        print '\n'.join(['- {}'.format(p) for p in not_found])
    ports = ' '.join(args.ports)
else:
    ports = ' '.join(['input_{}'.format(i + 1) for i in xrange(args.channels)])

cmd = './jack-peak -q {scale} -d {delay} {ports}'.format(scale='-i {}'.format(args.scale) if args.scale else '', delay=delay, ports=ports)
proc = subprocess.Popen(cmd.split(),
                        stdout=subprocess.PIPE, 
                        )
flags = fcntl(proc.stdout, F_GETFL)
fcntl(proc.stdout, F_SETFL, flags | O_NONBLOCK)

empty = 0
while True:
    try:
        output = read(proc.stdout.fileno(), 1024)
        if output:
            if args.file:
                with open(args.file, 'a') as output_file:
                    output_file.write(output)
                    output_file.write('\n')
            else:
                print output
        else:
            break
    except KeyboardInterrupt:
        proc.terminate()
        break
    except OSError:
        pass
    except:
        break
_______________________________________________
Linux-audio-user mailing list
Linux-audio-user@xxxxxxxxxxxxxxxxxxxx
http://lists.linuxaudio.org/listinfo/linux-audio-user

[Index of Archives]     [Linux Sound]     [ALSA Users]     [Pulse Audio]     [ALSA Devel]     [Sox Users]     [Linux Media]     [Kernel]     [Photo Sharing]     [Gimp]     [Yosemite News]     [Linux Media]

  Powered by Linux