iso_1996 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 58b7aaecfa7460bb341e22d3fdd31cbf0c0463c7dd757324f24d61cabf955051
4
+ data.tar.gz: e01c3447842cd52d511ac7205cbc9f3191ac2cece2249c2bcbc6ceef6aa60e48
5
+ SHA512:
6
+ metadata.gz: d3623c9060b7b78c180325fea3150a92b63ab903c5ae516553a5d3cffa49613879511a7bd63e4e513d60ab1766d0e30a189775e272a2b0e8a06d7898a12623cb
7
+ data.tar.gz: 44fd1b43650fbb939d30bd15f21e846035867147a3493b30a1ac702e6a96093c986d8b5b523328497d6d2744c609b7f4f361b22cd9df054169b16c216847dd6b
data/README.md ADDED
@@ -0,0 +1,43 @@
1
+
2
+ # ISO 1996 - Acoustics — Description, measurement and assessment of environmental noise Ruby gem.
3
+
4
+ [![Gem Version](https://badge.fury.io/rb/iso_1996.svg)](https://badge.fury.io/rb/iso_1996)
5
+ [![Documentation](https://img.shields.io/badge/docs-rdoc.info-blue)](https://rubydoc.info/gems/iso_1996)
6
+
7
+ Ruby implementation of ISO 1996 - Acoustics — Description, measurement and assessment of environmental noise.
8
+
9
+ ## Features
10
+
11
+ - Complete implementation of all three parts of ISO 1996
12
+ - Fully documented with RDoc comments
13
+ - Comprehensive test suite
14
+ - MIT licensed
15
+
16
+ ## Installation
17
+
18
+ Add to your Gemfile:
19
+
20
+ ```ruby
21
+ gem 'iso_1996'
22
+ ```
23
+
24
+ Or install directly:
25
+
26
+ ```bash
27
+ gem install iso_1996
28
+ ```
29
+
30
+ ## Documentation
31
+ Full documentation available at:
32
+ https://rubydoc.info/gems/iso_1996
33
+
34
+ ## Contributing
35
+ Bug reports and pull requests are welcome on GitHub at:
36
+ https://github.com/yourusername/iso_1996
37
+
38
+ ## License
39
+ The gem is available as open source under the terms of the MIT License.
40
+
41
+ ## Author
42
+ Maciej Ciemborowicz
43
+ July 11, 2025
@@ -0,0 +1,105 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ISO_1996
4
+
5
+ ##
6
+ # == ISO 1996-1:2003 Basic Quantities and Assessment Procedures
7
+ #
8
+ # Module implementing calculations defined in ISO 1996-1:2003:
9
+ # "Acoustics - Description, measurement and assessment of environmental noise -
10
+ # Part 1: Basic quantities and assessment procedures"
11
+ #
12
+ # Author:: Maciej Ciemborowicz
13
+ # Date:: July 11, 2025
14
+ #
15
+ module Basic
16
+ ##
17
+ # Constants defined in ISO 1996-1:2003 standard
18
+ module Constants
19
+ ##
20
+ # Reference sound pressure (p₀) as defined in Section 3.1
21
+ # Value: 20 μPa (20e-6 Pa)
22
+ REFERENCE_SOUND_PRESSURE = 20e-6 # Pa
23
+
24
+ ##
25
+ # Reference time (t₀) for sound exposure level as defined in Section 3.9
26
+ # Value: 1 second
27
+ REFERENCE_TIME = 1.0 # s
28
+ end
29
+ include Constants
30
+
31
+ ##
32
+ # Calculate sound pressure level (L_p) as defined in Section 3.2
33
+ #
34
+ # L_p = 10 * log10(p² / p₀²) dB
35
+ #
36
+ # @param p [Float] Root-mean-square sound pressure (Pa)
37
+ # @return [Float] Sound pressure level in dB
38
+ #
39
+ # Example:
40
+ # Basic.sound_pressure_level(0.1) # => 74.0 dB
41
+ #
42
+ def self.sound_pressure_level(p)
43
+ 10 * Math.log10((p ** 2) / (Constants::REFERENCE_SOUND_PRESSURE ** 2))
44
+ end
45
+
46
+ ##
47
+ # Calculate A-weighted sound pressure level (L_A) as defined in Section 3.2
48
+ #
49
+ # L_A = 10 * log10( (1/T) * ∫(p_A²(t)/p₀²) dt ) dB
50
+ #
51
+ # @param p_a [Float] A-weighted sound pressure (Pa)
52
+ # @param measurement_time [Float] Measurement time interval (seconds)
53
+ # @return [Float] A-weighted sound pressure level in dB
54
+ #
55
+ def self.a_weighted_sound_pressure_level(p_a, measurement_time: 1.0)
56
+ 10 * Math.log10((1.0 / measurement_time) * (p_a ** 2) / (Constants::REFERENCE_SOUND_PRESSURE ** 2))
57
+ end
58
+
59
+ ##
60
+ # Calculate sound exposure level (L_AE) as defined in Section 3.9
61
+ #
62
+ # L_AE = 10 * log10( (1/t₀) * ∫(p_A²(t)/p₀²) dt ) dB
63
+ #
64
+ # @param p_a [Float] A-weighted sound pressure (Pa)
65
+ # @return [Float] Sound exposure level in dB
66
+ #
67
+ def self.sound_exposure_level(p_a)
68
+ 10 * Math.log10((1.0 / Constants::REFERENCE_TIME) * (p_a ** 2) / (Constants::REFERENCE_SOUND_PRESSURE ** 2))
69
+ end
70
+
71
+ ##
72
+ # Calculate equivalent continuous sound level (L_Aeq,T) as defined in Section 3.7
73
+ #
74
+ # L_Aeq,T = 10 * log10( (1/T) * Σ(10^(0.1*L_i)) ) dB
75
+ #
76
+ # @param levels [Array<Float>] Array of sound pressure levels (dB)
77
+ # @param measurement_time [Float] Total measurement time (seconds)
78
+ # @return [Float] Equivalent continuous sound level in dB
79
+ #
80
+ # Example:
81
+ # levels = [65.0, 67.0, 63.0]
82
+ # Basic.equivalent_continuous_sound_level(levels, 3.0) # => ~65.1 dB
83
+ #
84
+ def self.equivalent_continuous_sound_level(levels, measurement_time)
85
+ raise ArgumentError, "Measurement time must be positive" if measurement_time <= 0
86
+
87
+ return -Float::INFINITY if levels.empty?
88
+
89
+ energy_sum = levels.sum { |l| 10 ** (l / 10.0) }
90
+ 10 * Math.log10(energy_sum / measurement_time)
91
+ end
92
+
93
+ ##
94
+ # Calculate C-weighted peak sound pressure level (L_Cpeak) as defined in Section 3.10
95
+ #
96
+ # L_Cpeak = 20 * log10(p_Cmax / p₀) dB
97
+ #
98
+ # @param p_c_max [Float] Maximum C-weighted sound pressure (Pa)
99
+ # @return [Float] C-weighted peak sound pressure level in dB
100
+ #
101
+ def self.peak_sound_pressure_level(p_c_max)
102
+ 20 * Math.log10(p_c_max / Constants::REFERENCE_SOUND_PRESSURE)
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ISO_1996
4
+
5
+ ##
6
+ # == ISO 1996-2:2007 Determination of Sound Pressure Levels
7
+ #
8
+ # Module implementing calculations defined in ISO 1996-2:2007:
9
+ # "Acoustics - Description, measurement and assessment of environmental noise -
10
+ # Part 2: Determination of sound pressure levels"
11
+ #
12
+ # Author:: Maciej Ciemborowicz
13
+ # Date:: July 11, 2025
14
+ #
15
+ module EnvironmentalNoise
16
+ ##
17
+ # Constants defined in ISO 1996-2:2007 standard
18
+ module Constants
19
+ ##
20
+ # Minimum level difference for background correction (ΔL_min) as defined in Section 6.3
21
+ # Value: 3 dB
22
+ MIN_BACKGROUND_LEVEL_DIFFERENCE = 3.0 # dB
23
+
24
+ ##
25
+ # Threshold for background correction (ΔL_threshold) as defined in Section 6.3
26
+ # Value: 10 dB
27
+ BACKGROUND_CORRECTION_THRESHOLD = 10.0 # dB
28
+ end
29
+ include Constants
30
+
31
+ ##
32
+ # Calculate background noise correction (K₁) as defined in Section 6.3 and Annex D
33
+ #
34
+ # K₁ = -10 * log10(1 - 10^(-0.1 * ΔL)) dB
35
+ # where ΔL = L_total - L_background
36
+ #
37
+ # @param l_total [Float] Total sound pressure level (dB)
38
+ # @param l_background [Float] Background sound pressure level (dB)
39
+ # @return [Float] Background noise correction in dB
40
+ # @raise [ArgumentError] if ΔL ≤ 3 dB (measurement uncertain)
41
+ #
42
+ # Example:
43
+ # EnvironmentalNoise.background_noise_correction(65, 60) # => 1.7 dB
44
+ #
45
+ def self.background_noise_correction(l_total, l_background)
46
+ delta_l = l_total - l_background
47
+
48
+ if delta_l <= Constants::MIN_BACKGROUND_LEVEL_DIFFERENCE
49
+ raise ArgumentError, "Measurement uncertain: ΔL ≤ #{Constants::MIN_BACKGROUND_LEVEL_DIFFERENCE} dB"
50
+ elsif delta_l >= Constants::BACKGROUND_CORRECTION_THRESHOLD
51
+ 0.0
52
+ else
53
+ -10 * Math.log10(1 - 10 ** (-0.1 * delta_l))
54
+ end
55
+ end
56
+
57
+ ##
58
+ # Calculate atmospheric absorption correction (A_atm) as defined in Section 7.3 and Annex A
59
+ #
60
+ # A_atm = α * d dB
61
+ #
62
+ # @param attenuation_coefficient [Float] Atmospheric attenuation coefficient (dB/m)
63
+ # @param propagation_distance [Float] Sound propagation distance (m)
64
+ # @return [Float] Atmospheric absorption correction in dB
65
+ #
66
+ def self.atmospheric_absorption_correction(attenuation_coefficient, propagation_distance)
67
+ attenuation_coefficient * propagation_distance
68
+ end
69
+
70
+ ##
71
+ # Calculate combined measurement uncertainty as defined in Section 9
72
+ #
73
+ # u_total = √(Σ(u_i²)) dB
74
+ #
75
+ # @param uncertainty_components [Array<Float>] Array of uncertainty components (dB)
76
+ # @return [Float] Combined measurement uncertainty in dB
77
+ #
78
+ # Example:
79
+ # EnvironmentalNoise.measurement_uncertainty([0.5, 1.0, 0.7]) # => 1.28 dB
80
+ #
81
+ def self.measurement_uncertainty(uncertainty_components)
82
+ Math.sqrt(uncertainty_components.sum { |c| c ** 2 })
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,114 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ISO_1996
4
+
5
+ ##
6
+ # == ISO 1996-3:1987 Application to Noise Limits
7
+ #
8
+ # Module implementing calculations defined in ISO 1996-3:1987:
9
+ # "Acoustics - Description, measurement and assessment of environmental noise -
10
+ # Part 3: Application to noise limits"
11
+ #
12
+ # Author:: Maciej Ciemborowicz
13
+ # Date:: July 11, 2025
14
+ #
15
+ module NoiseLimits
16
+ ##
17
+ # Constants defined in ISO 1996-3:1987 standard
18
+ module Constants
19
+ ##
20
+ # Impulse correction threshold (L_Cpeak,min) as defined in Section 7.2
21
+ # Value: 130 dB
22
+ IMPULSE_CORRECTION_THRESHOLD = 130.0 # dB
23
+
24
+ ##
25
+ # Standard 24-hour period as defined in Annex A
26
+ # Value: 24 hours
27
+ STANDARD_24H_PERIOD = 24.0 # hours
28
+ end
29
+ include Constants
30
+
31
+ ##
32
+ # Determine tonal adjustment factor (K_T) as defined in Section 6 and Table 1
33
+ #
34
+ # @param delta_l [Float] Difference between tone level and background level (dB)
35
+ # @return [Float] Tonal adjustment factor in dB
36
+ #
37
+ # According to Table 1:
38
+ # ΔL ≥ 15 dB → 6 dB
39
+ # 10 ≤ ΔL ≤ 14 dB → 4-6 dB (default 5 dB)
40
+ # 5 ≤ ΔL ≤ 9 dB → 0-3 dB (default 2 dB)
41
+ # ΔL < 5 dB → 0 dB
42
+ #
43
+ def self.tonal_adjustment_factor(delta_l)
44
+ case delta_l
45
+ when 15..Float::INFINITY then 6.0
46
+ when 10..14 then 5.0
47
+ when 5..9 then 2.0
48
+ else 0.0
49
+ end
50
+ end
51
+
52
+ ##
53
+ # Determine impulsive adjustment factor (K_I) as defined in Section 7.2
54
+ #
55
+ # @param l_cpeak [Float] C-weighted peak sound pressure level (dB)
56
+ # @param is_highly_annoying [Boolean] Whether noise is subjectively assessed as highly annoying
57
+ # @return [Float] Impulsive adjustment factor in dB
58
+ #
59
+ # According to version:
60
+ # K_I = 6 dB if L_Cpeak ≥ 130 dB OR noise is highly annoying
61
+ # K_I = 0 dB otherwise
62
+ #
63
+ def self.impulsive_adjustment_factor(l_cpeak, is_highly_annoying: false)
64
+ (l_cpeak >= Constants::IMPULSE_CORRECTION_THRESHOLD || is_highly_annoying) ? 6.0 : 0.0
65
+ end
66
+
67
+ ##
68
+ # Calculate assessment level (L_r) as defined in Section 8
69
+ #
70
+ # L_r = L_AeqT + K_T + K_I dB
71
+ #
72
+ # @param l_aeq_t [Float] Equivalent continuous A-weighted sound pressure level (dB)
73
+ # @param k_t [Float] Tonal adjustment factor (dB)
74
+ # @param k_i [Float] Impulsive adjustment factor (dB)
75
+ # @return [Float] Assessment level in dB
76
+ #
77
+ def self.assessment_level(l_aeq_t, k_t, k_i)
78
+ l_aeq_t + k_t + k_i
79
+ end
80
+
81
+ ##
82
+ # Evaluate compliance with noise limits as defined in Section 9
83
+ #
84
+ # @param l_r [Float] Assessment level (dB)
85
+ # @param noise_limit [Float] Noise limit value (dB)
86
+ # @param measurement_uncertainty [Float] Measurement uncertainty (dB)
87
+ # @return [Boolean] True if limit is exceeded (L_r > L_lim + uncertainty)
88
+ #
89
+ def self.compliance_evaluation(l_r, noise_limit, measurement_uncertainty)
90
+ l_r > noise_limit + measurement_uncertainty
91
+ end
92
+
93
+ ##
94
+ # Convert sound levels between time periods as defined in Annex A
95
+ #
96
+ # L_total = 10 * log10( [Σ(t_i * 10^(0.1*L_i)] / T_total ) dB
97
+ #
98
+ # @param period_levels [Array<Hash>] Array of hashes with :level (dB) and :duration (hours)
99
+ # @param total_period [Float] Total time period for normalization (hours)
100
+ # @return [Float] Equivalent sound level for total period in dB
101
+ #
102
+ # Example:
103
+ # periods = [
104
+ # {level: 65.0, duration: 16}, # Day
105
+ # {level: 55.0, duration: 8} # Night
106
+ # ]
107
+ # NoiseLimits.time_period_conversion(periods) # => ~62.1 dB
108
+ #
109
+ def self.time_period_conversion(period_levels, total_period: Constants::STANDARD_24H_PERIOD)
110
+ energy_sum = period_levels.sum { |period| period[:duration] * (10 ** (period[:level] / 10.0)) }
111
+ 10 * Math.log10(energy_sum / total_period)
112
+ end
113
+ end
114
+ end
data/lib/iso_1996.rb ADDED
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ ##
4
+ # = ISO 1996 - Acoustics - Description, measurement and assessment of environmental noise
5
+ #
6
+ # Ruby implementation of ISO 1996 - Acoustics - Description, measurement and assessment of environmental noise.
7
+ # Includes all three parts:
8
+ # - ISO 1996-1:2003: Basic quantities and assessment procedures
9
+ # - ISO 1996-2:2007: Determination of sound pressure levels
10
+ # - ISO 1996-3:1987: Application to noise limits
11
+ #
12
+ # Author:: Maciej Ciemborowicz
13
+ # Date:: July 11, 2025
14
+ # Version:: 1.0.0
15
+ # License:: MIT
16
+ #
17
+ # == Usage
18
+ # require 'iso_1996'
19
+ #
20
+ # # Basic calculations
21
+ # level = ISO_1996::Basic.sound_pressure_level(0.1)
22
+ #
23
+ # # Environmental noise corrections
24
+ # correction = ISO_1996::EnvironmentalNoise.background_noise_correction(65, 60)
25
+ #
26
+ # # Noise limits assessment
27
+ # assessment = ISO_1996::NoiseLimits.assessment_level(65, 2, 3)
28
+ #
29
+ # @see https://www.iso.org/standard/28633.html ISO 1996-1:2003
30
+ # @see https://www.iso.org/standard/23776.html ISO 1996-2:2007
31
+ # @see https://www.iso.org/standard/6750.html ISO 1996-3:1987
32
+
33
+ require_relative 'iso_1996/basic'
34
+ require_relative 'iso_1996/environmental_noise'
35
+ require_relative 'iso_1996/noise_limits'
36
+
37
+ module ISO_1996
38
+ ##
39
+ # Current version of the gem
40
+ VERSION = "1.0.0"
41
+ end
metadata ADDED
@@ -0,0 +1,112 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: iso_1996
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Maciej Ciemborowicz
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2025-07-11 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '3.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '3.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '13.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '13.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rdoc
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '6.5'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '6.5'
55
+ - !ruby/object:Gem::Dependency
56
+ name: github-pages
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '228'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '228'
69
+ description: |2
70
+ Ruby implementation of ISO 1996 - Acoustics — Description, measurement and assessment of environmental noise.
71
+ Includes all three parts:
72
+ - ISO 1996-1:2003: Basic quantities and assessment procedures
73
+ - ISO 1996-2:2007: Determination of sound pressure levels
74
+ - ISO 1996-3:1987: Application to noise limits
75
+ email:
76
+ - maciej.ciemborowicz@gmail.com
77
+ executables: []
78
+ extensions: []
79
+ extra_rdoc_files: []
80
+ files:
81
+ - README.md
82
+ - lib/iso_1996.rb
83
+ - lib/iso_1996/basic.rb
84
+ - lib/iso_1996/environmental_noise.rb
85
+ - lib/iso_1996/noise_limits.rb
86
+ homepage: https://github.com/ciembor/iso_1996
87
+ licenses:
88
+ - MIT
89
+ metadata:
90
+ documentation_uri: https://ciembor.github.io/iso_1996
91
+ source_code_uri: https://github.com/ciembor/iso_1996
92
+ post_install_message:
93
+ rdoc_options: []
94
+ require_paths:
95
+ - lib
96
+ required_ruby_version: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ version: 3.3.0
101
+ required_rubygems_version: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ requirements: []
107
+ rubygems_version: 3.5.3
108
+ signing_key:
109
+ specification_version: 4
110
+ summary: Implementation of ISO 1996 - Acoustics — Description, measurement and assessment
111
+ of environmental noise
112
+ test_files: []