|
6 | 6 | """ |
7 | 7 |
|
8 | 8 | # Standard library import |
9 | | -import numpy as np |
| 9 | +from numpy import mean, sqrt, log10, linspace |
10 | 10 |
|
11 | | -# Local import |
12 | | -from mosqito.functions.shared.conversion import spectrum2dBA |
13 | 11 |
|
14 | | - |
15 | | -def comp_level(is_stationary, spec_third, fs, unit): |
16 | | - """Overall Sound Pressure Level calculation in the chosen unit |
17 | | - from the signal's third-octave spectrum |
| 12 | +def comp_level(signal, fs, nb_points=[], start=[], stop=[]): |
| 13 | + """Overall Sound Pressure Level calculation from the time signal |
| 14 | + The SPL can be computed according to a specified number of points or |
| 15 | + during a given time frame |
18 | 16 |
|
19 | 17 | Parameter: |
20 | 18 | ---------- |
21 | | - spec_third_dB: numpy.array |
22 | | - third octave spectrum of the signal |
| 19 | + signal : numpy.array |
| 20 | + time signal value |
23 | 21 | fs: integer |
24 | 22 | sampling frequency |
25 | | - unit : string |
26 | | - 'dB' or 'dBA' |
| 23 | +
|
| 24 | + Output: |
| 25 | + ------- |
| 26 | + level : numpy.array |
| 27 | + SPL in dB |
27 | 28 |
|
28 | 29 | """ |
| 30 | + # Check the inputs |
| 31 | + if nb_points != []: |
| 32 | + if type(nb_points) != int: |
| 33 | + raise TypeError("ERROR : Number of points should be an integer") |
| 34 | + |
| 35 | + if nb_points < 1 or nb_points > len(signal): |
| 36 | + raise ValueError( |
| 37 | + "ERROR : Number of points should be between 1 and the length of the given signal" |
| 38 | + ) |
| 39 | + |
| 40 | + if start != [] and stop != []: |
| 41 | + if type(start) != int and type(start) != float: |
| 42 | + raise TypeError("ERROR : Start (in sec) should be an integer or a float ") |
| 43 | + |
| 44 | + if type(stop) != int and type(stop) != float: |
| 45 | + raise TypeError("ERROR : Stop (in sec) should be an integer or a float ") |
| 46 | + |
| 47 | + if start < 0 or stop < 0 or start > len(signal) / fs or stop > len(signal) / fs: |
| 48 | + raise ValueError( |
| 49 | + "ERROR : Time frame should be between 0s and the duration of the signal" |
| 50 | + ) |
| 51 | + |
| 52 | + if start == stop: |
| 53 | + raise ValueError("ERROR : Start and stop values must be different") |
| 54 | + |
| 55 | + # Initialization |
| 56 | + level = [] |
| 57 | + |
| 58 | + # Case of a given time frame |
| 59 | + if start != [] and stop != []: |
| 60 | + frame = signal[int(start * fs) : int(stop * fs)] |
| 61 | + else: |
| 62 | + start = 0 |
| 63 | + stop = len(signal) / fs |
| 64 | + frame = signal |
| 65 | + |
| 66 | + # Case of a given number of points |
| 67 | + if nb_points != []: |
| 68 | + |
| 69 | + time_axis = linspace(start, stop, num=nb_points) |
| 70 | + |
| 71 | + frame_size = int(len(frame) / nb_points) |
| 72 | + for i in range(nb_points): |
| 73 | + frame_i = frame[i * frame_size : i * frame_size + frame_size] |
| 74 | + peff = sqrt(mean(frame_i ** 2)) |
| 75 | + level.append(10 * log10((peff ** 2 / (2e-05) ** 2))) |
29 | 76 |
|
30 | | - if unit == "dB": |
31 | | - level = 10 * np.log10(sum(np.power(10, spec_third["values"] / 10))) |
| 77 | + else: |
| 78 | + peff = sqrt(mean(frame ** 2)) |
| 79 | + level = 10 * log10((peff ** 2 / (2e-05) ** 2)) |
32 | 80 |
|
33 | | - elif unit == "dBA": |
34 | | - # spectrum A-weighting |
35 | | - spec_third_dBA = spectrum2dBA(spec_third["values"], fs) |
36 | | - level = 10 * np.log10(sum(np.power(10, spec_third_dBA / 10))) |
| 81 | + output = { |
| 82 | + "name": "Sound Pressure Level", |
| 83 | + "values": level, |
| 84 | + "time": time_axis, |
| 85 | + } |
37 | 86 |
|
38 | | - return level |
| 87 | + return output |
0 commit comments