JOCLoudness 1.0.3 → 1.0.4

Sign up to get free protection for your applications and to get access to all the features.
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