JOCLoudness 1.0.3 → 1.0.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0cd5d2552d8fb90f3fbc2eadfaa80d37285c3120
4
- data.tar.gz: dc05cf8feb070410238e93fcb6a08899a96efccd
3
+ metadata.gz: eb8af76bd2940127a19168cf9cfb55fffd518e3b
4
+ data.tar.gz: f9899fe2b6742691e424c191858501fcfa08ae5d
5
5
  SHA512:
6
- metadata.gz: 44d689ed177c7115f5a94b6fa7dbb0222fd1032070b8a677e61f478e33a2cf33dfefa6019b4a96e092c061e17d565763870367d69c85b3062f918a3b34946fd9
7
- data.tar.gz: 3bf8dc5ea09ce4ecd48d0762200b41a13fd5f7a16ff17dbfb5ad45604b9265086a8ab96e28fc695f49642e1b38f65e31661cfb30e4ec0e5a9145c2a5ae86011e
6
+ metadata.gz: a2035f0f602259e61903eaf6c99f90832dfc1fcfd4c84ccd046fd09e97597428139b2501702cfd32e060f6097d38ad6d4d2424db28efbd2db944fcb61b736395
7
+ data.tar.gz: aa8f1600df07654bb25df636d7322ce660781bcbe3a02f7813df25614ae0534ecd4d042b2795291eb62ffe0e8a47717aa724b08ca21e102b9578a05f444dd483
data/README.md CHANGED
@@ -1,4 +1,54 @@
1
1
  JOCLoudnessRuby
2
2
  ===============
3
3
 
4
- The JOCLoudnessRuby is a native gem able to load a wav file and calculate its LKFS following the ITU-R BS.1770
4
+ The JOCLoudnessRuby is a native ruby code able to load a wav file and calculate its Loudness in LKFS following the ITU-R BS.1770
5
+
6
+ Accepted formats (.WAV):
7
+ * Headers of 16, 18, 40 bytes
8
+ * Any sampling frequency
9
+ * Any number of channels
10
+ * PCM 8,16,24 bits per sample or FLOAT 32 bits per sample
11
+
12
+ Note 1: This module recalculates automatically the filter coefficients depending on input file sampling frequency
13
+ Note 2: ITU-R BS.1770 is a NOT gated measure
14
+
15
+
16
+ Usage examples:
17
+
18
+ - Simple:
19
+ require 'JOCLoudness'
20
+
21
+ wavfilename = "c:\\Test.wav"
22
+
23
+ begin
24
+ loud = JOCLoudness.new(wavfilename)
25
+
26
+ lkfs = loud.CalcLoudness()
27
+
28
+ loud.Close()
29
+
30
+ puts "Loudness of #{ARGV[0]} = #{lkfs.round(1)} LKFS"
31
+
32
+ rescue Exception => e
33
+ puts "Error: #{e.message}, Trace: #{e.backtrace.inspect}"
34
+ end
35
+
36
+
37
+ - Advanced:
38
+ require 'JOCLoudness'
39
+
40
+ wavfilename = ARGV[0]
41
+ logfilename = ARGV[1]
42
+
43
+ begin
44
+ loud = JOCLoudness.new(wavfilename, logfilename, Logger::DEBUG)
45
+
46
+ lkfs = loud.CalcLoudness()
47
+
48
+ loud.Close()
49
+
50
+ puts "Loudness of #{ARGV[0]} = #{lkfs.round(1)} LKFS"
51
+
52
+ rescue Exception => e
53
+ puts "Error: #{e.message}, Trace: #{e.backtrace.inspect}"
54
+ end
data/lib/JOCLoudness.rb CHANGED
@@ -9,7 +9,83 @@ require 'logger'
9
9
  require_relative './WavReader/wavfile'
10
10
  require_relative './Loudness/jocLoud.rb'
11
11
 
12
- # = JOCLoudness
13
- #
14
- # This ruby native gem is able to load a wav file and calculate its LKFS following the ITU-R BS.1770
15
- #
12
+ #JOCLoudness class, used to compute the loudness of a wav file (Based on ITU-R BS.1770)
13
+ class JOCLoudness
14
+
15
+ #Initialize JOCLoudness
16
+ # @param filename [String] audio wav file to analize
17
+ # @param logfile [String] log file to save the logs (optional)
18
+ # @param loglevel log level, could be Logger::FATAL, Logger::ERROR, Logger::WARN, Logger::INFO, Logger::DEBUG (optional)
19
+ def initialize (filename, logfile = nil, loglevel = Logger::INFO)
20
+ #Instanciate wav reader
21
+ @wav = Wavfile.new(filename)
22
+
23
+ #Start logger
24
+ # Keep data for today and the past 3 days.
25
+ @log = nil
26
+ if (logfile != nil)
27
+ @log = Logger.new(logfile)
28
+ @log.level = loglevel
29
+
30
+ #Set logger (optional)
31
+ @wav.Setlogger(@log)
32
+ end
33
+
34
+ #Read wav header
35
+ @wav.ReadHeader()
36
+
37
+ #Get file info (fs, number of channels)
38
+ @fs, @nch = @wav.GetFileInfo()
39
+ end
40
+
41
+ #Calculates the loudness of the audio file
42
+ # @return [Float] the resulting loudness in LKFS
43
+ def CalcLoudness ()
44
+ #Instantiate & initialize loudness moudule
45
+ loudness = JOCLoud.new
46
+
47
+ #Set logger
48
+ if (@log != nil)
49
+ loudness.Setlogger(@log)
50
+ end
51
+
52
+ loudness.ini(@fs,@nch)
53
+
54
+ #Read wav file and send the samples to loudness module
55
+ n = 0
56
+ samples = 1
57
+
58
+ while samples != nil
59
+ samples = @wav.GetAudioSamples(n)
60
+ if (samples != nil)
61
+ if (n % @fs == 0)
62
+ puts "Processed #{n / @fs} secs"
63
+ end
64
+
65
+ loudness.Addsample(samples)
66
+
67
+ n = n + 1
68
+ end
69
+ end
70
+
71
+ loudnessLKFS = loudness.GetLoudnessLKFS()
72
+
73
+ if (@log != nil)
74
+ strloudnessdata = "Loudness = #{loudnessLKFS.round(1)} LKFS"
75
+ @log.debug(strloudnessdata)
76
+ end
77
+
78
+ return loudnessLKFS
79
+ end
80
+
81
+ #Closes the opened file
82
+ def Close()
83
+ if (@log!=nil)
84
+ @log.debug("End logger")
85
+ end
86
+
87
+ if (@wav != nil)
88
+ @wav.Close()
89
+ end
90
+ end
91
+ end
@@ -7,7 +7,7 @@ require_relative './wavsamples'
7
7
  #* Any sampling frequency
8
8
  #* Any number of channels
9
9
  #* PCM 8,16,24 bits per sample
10
- #* FLOAT 36 bits per sample
10
+ #* FLOAT 32 bits per sample
11
11
  #*Headers of 16, 18, 40 bytes
12
12
  class Wavfile
13
13
 
@@ -31,23 +31,18 @@ class Wavfile
31
31
  # Reads the wav header file
32
32
  def ReadHeader
33
33
  Log(Logger::DEBUG,"Start reading wav header of #{@filename}")
34
+
35
+ #Read wav header
36
+ @mainheader = nil
37
+ @mainheader = Wavheader.new
38
+
39
+ @wavfile = File.open(@filename, 'r')
40
+ @mainheader.read(@wavfile)
34
41
 
35
- begin
36
- #Read wav header
37
- @mainheader = nil
38
- @mainheader = Wavheader.new
39
-
40
- @wavfile = File.open(@filename, 'r')
41
- @mainheader.read(@wavfile)
42
-
43
- @lHeaderOffsetbytes = @mainheader.cfirstdatabyte.abs_offset;
44
-
45
- Log(Logger::DEBUG,"lHeaderOffsetbytes: #{@lHeaderOffsetbytes}")
46
-
47
- rescue Exception => e
48
- Log(Logger::ERROR,"Error reading wav header of #{e.message}, Trace: #{e.backtrace.inspect}")
49
- end
42
+ @lHeaderOffsetbytes = @mainheader.cfirstdatabyte.abs_offset;
50
43
 
44
+ Log(Logger::DEBUG,"lHeaderOffsetbytes: #{@lHeaderOffsetbytes}")
45
+
51
46
  Log(Logger::DEBUG,@mainheader)
52
47
 
53
48
  end
@@ -66,70 +61,66 @@ class Wavfile
66
61
  if (@wavfile == nil)
67
62
  Log(Logger::WARN, "The file is not opened")
68
63
  else
69
- begin
70
- Log(Logger::DEBUG,"Start reading sample pos #{@sampleindex}")
64
+ Log(Logger::DEBUG,"Start reading sample pos #{@sampleindex}")
65
+
66
+ #Seek to sample position channel 0
67
+ lsamplesizebytes = (@mainheader.sBitsPerSample / 8)
68
+ loffsetbytes = @lHeaderOffsetbytes + sampleindex * (@mainheader.nchannels * lsamplesizebytes)
69
+
70
+ Log(Logger::DEBUG,"loffsetbytes: #{loffsetbytes} of #{@wavfile.size}")
71
+
72
+ if (loffsetbytes >= @wavfile.size)
73
+ Log(Logger::DEBUG,"EOF reached!")
74
+ nil
75
+ else
76
+ @wavfile.seek(loffsetbytes)
77
+
78
+ #Create PCM samples
79
+ samples = nil
80
+ nmax = 1;
71
81
 
72
- #Seek to sample position channel 0
73
- lsamplesizebytes = (@mainheader.sBitsPerSample / 8)
74
- loffsetbytes = @lHeaderOffsetbytes + sampleindex * (@mainheader.nchannels * lsamplesizebytes)
82
+ if (@mainheader.nformattag == Wavheader::PCM)
83
+ #Read PCM sample 8 bits/sample (-128 ... 0 ... +127)
84
+ if (@mainheader.sBitsPerSample == 8)
85
+ samples = Wavsample8b.new(:num_channels => @mainheader.nchannels)
86
+ nmax = 128
87
+ end
88
+ #Read PCM sample 16 bits/sample (-32768 ... 0 ... +32767)
89
+ if (@mainheader.sBitsPerSample == 16)
90
+ samples = Wavsample16b.new(:num_channels => @mainheader.nchannels)
91
+ nmax = 32768
92
+ end
93
+ #Read PCM sample 24 bits/sample (-8388608 ... 0 ... +8388607)
94
+ if (@mainheader.sBitsPerSample == 24)
95
+ samples = Wavsample24b.new(:num_channels => @mainheader.nchannels)
96
+ nmax = 8388608
97
+ end
98
+ end
99
+
100
+ #Create FLOAT samples
101
+ if (@mainheader.nformattag == Wavheader::FLOAT)
102
+ samples = WavsampleFloat.new(:num_channels => @mainheader.nchannels)
103
+ end
75
104
 
76
- Log(Logger::DEBUG,"loffsetbytes: #{loffsetbytes} of #{@wavfile.size}")
77
-
78
- if (loffsetbytes >= @wavfile.size)
79
- Log(Logger::DEBUG,"EOF reached!")
80
- nil
105
+ if (samples != nil)
106
+ #Read sample from file
107
+ samples.read(@wavfile)
81
108
  else
82
- @wavfile.seek(loffsetbytes)
109
+ raise 'Sample not compatible (Is not PCM neither FLOAT)'
110
+ end
83
111
 
84
- #Create PCM samples
85
- samples = nil
86
- nmax = 1;
87
-
88
- if (@mainheader.nformattag == Wavheader::PCM)
89
- #Read PCM sample 8 bits/sample (-128 ... 0 ... +127)
90
- if (@mainheader.sBitsPerSample == 8)
91
- samples = Wavsample8b.new(:num_channels => @mainheader.nchannels)
92
- nmax = 128
93
- end
94
- #Read PCM sample 16 bits/sample (-32768 ... 0 ... +32767)
95
- if (@mainheader.sBitsPerSample == 16)
96
- samples = Wavsample16b.new(:num_channels => @mainheader.nchannels)
97
- nmax = 32768
98
- end
99
- #Read PCM sample 24 bits/sample (-8388608 ... 0 ... +8388607)
100
- if (@mainheader.sBitsPerSample == 24)
101
- samples = Wavsample24b.new(:num_channels => @mainheader.nchannels)
102
- nmax = 8388608
103
- end
104
- end
105
-
106
- #Create FLOAT samples
107
- if (@mainheader.nformattag == Wavheader::FLOAT)
108
- samples = WavsampleFloat.new(:num_channels => @mainheader.nchannels)
109
- end
110
-
111
- if (samples != nil)
112
- #Read sample from file
113
- samples.read(@wavfile)
114
- else
115
- raise 'Sample not compatible (Is not PCM neither FLOAT)'
116
- end
117
-
118
- Log(Logger::DEBUG,samples)
119
-
120
- samplesRetArray = samples.samples
121
-
122
- if (samplesRetArray != nil) and (@mainheader.nformattag == Wavheader::PCM) and (bNormalize == true)
123
- samplesRetArray = samplesRetArray.collect {|x| x.to_f / nmax.to_f}
124
- end
125
-
126
- Log(Logger::DEBUG,"Samples normalized = #{samplesRetArray.to_s}")
127
-
128
- samplesRetArray
129
-
112
+ Log(Logger::DEBUG,samples)
113
+
114
+ samplesRetArray = samples.samples
115
+
116
+ if (samplesRetArray != nil) and (@mainheader.nformattag == Wavheader::PCM) and (bNormalize == true)
117
+ samplesRetArray = samplesRetArray.collect {|x| x.to_f / nmax.to_f}
130
118
  end
131
- rescue Exception => e
132
- Log(Logger::ERROR,"Error reading wav sample in pos #{sampleindex}. Error: #{e.message}, Trace: #{e.backtrace.inspect}")
119
+
120
+ Log(Logger::DEBUG,"Samples normalized = #{samplesRetArray.to_s}")
121
+
122
+ samplesRetArray
123
+
133
124
  end
134
125
  end
135
126
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: JOCLoudness
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.3
4
+ version: 1.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jordi Cenzano