midi_lyrics 0.0.1 → 0.0.2

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: d996919ed3cfcda1dcfda3adc2280ceb1681a5b1
4
- data.tar.gz: 3fe6246949062d40b66c03df9c68d279da5ded7e
3
+ metadata.gz: 8091e1c24da61a2790de90896d716a9f2960bc36
4
+ data.tar.gz: 4cae82d9652f322c1951d227d3f2b0fac5a4499a
5
5
  SHA512:
6
- metadata.gz: 5aec8699ca8f49b4ed1637e5a329b79f4c7941028fa4058af5572425a3b8e85d62f358b20e1c8a0e14cb850575dd54eb0a53095ba1ec2671af3445c640beb715
7
- data.tar.gz: 415d7b89ecfe943be95089f60c3f28c8a5bb2f840aa911f81bc322cfc3844a29748e04599a8e426634d7b03fa039ee07b36f9e246bf815dea2e056d9dbd85dd8
6
+ metadata.gz: 73c50e8170abeb02e49dcb2b7f58aa4119e2ed451623d98a176b0f872bdb047349e83f6b6c6790094e2fdae4d74fb8d55a857e1126759d569f7822fc06afc9e4
7
+ data.tar.gz: 741c155d2f592a7ebbc0390567a32a2ce2a991f405f050d69920f75adabfa0f0e4d3082aa124f69dda199d8ddbd2ef7c7a0d44ad3ccd5282096c341c517700cf
@@ -1,3 +1,3 @@
1
1
  module MidiLyrics
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
data/lib/midi_lyrics.rb CHANGED
@@ -5,11 +5,12 @@ module MidiLyrics
5
5
  class FileNotFound < StandardError; end
6
6
 
7
7
  class LyricSyllable
8
- attr_accessor :text, :start_in_pulses, :duration_in_pulses
8
+ attr_accessor :text, :start_in_pulses, :start2_in_pulses, :duration_in_pulses
9
9
  attr_writer :sequence
10
10
 
11
11
  def initialize(fields = {})
12
12
  self.start_in_pulses = fields[:start_in_pulses]
13
+ self.start2_in_pulses = fields[:start2_in_pulses]
13
14
  self.duration_in_pulses = fields[:duration_in_pulses]
14
15
  self.text = fields[:text]
15
16
  self.sequence = fields[:sequence]
@@ -19,10 +20,18 @@ module MidiLyrics
19
20
  format_time(start_in_pulses)
20
21
  end
21
22
 
23
+ def start2
24
+ format_time(start2_in_pulses)
25
+ end
26
+
22
27
  def duration
23
28
  format_time(duration_in_pulses)
24
29
  end
25
30
 
31
+ def similar_to?(another)
32
+ self.duration_in_pulses == another.duration_in_pulses && self.text == another.text
33
+ end
34
+
26
35
  private
27
36
  def format_time(time)
28
37
  @sequence.pulses_to_seconds(time.to_f).round(3)
@@ -30,17 +39,21 @@ module MidiLyrics
30
39
  end
31
40
 
32
41
  class Parser
33
- def initialize(file)
42
+ attr_reader :file, :repeating
43
+
44
+ def initialize(file, options = {})
45
+ options = { repeating: false }.merge(options)
34
46
  @file = file
47
+ @repeating = options[:repeating]
35
48
 
36
- unless File.exists?(@file)
49
+ unless File.exists?(file)
37
50
  raise MidiLyrics::FileNotFound
38
51
  end
39
52
  end
40
53
 
41
54
  def read_sequence_from_file
42
55
  @sequence = ::MIDI::Sequence.new()
43
- File.open(@file, "rb") do | file |
56
+ File.open(file, "rb") do | file |
44
57
  @sequence.read(file)
45
58
  end
46
59
  @sequence
@@ -72,10 +85,10 @@ module MidiLyrics
72
85
  def load_lyrics
73
86
  @lyrics = @lyrics_track.collect do |event|
74
87
  LyricSyllable.new(
75
- :sequence => @sequence,
76
- :start_in_pulses => event.time_from_start,
77
- :duration_in_pulses => @durations[event.time_from_start],
78
- :text => event.data.collect{|x| x.chr(Encoding::UTF_8)}.join,
88
+ sequence: @sequence,
89
+ start_in_pulses: event.time_from_start,
90
+ duration_in_pulses: @durations[event.time_from_start],
91
+ text: event.data.collect{|x| x.chr(Encoding::UTF_8)}.join,
79
92
  )
80
93
  end
81
94
  end
@@ -100,6 +113,29 @@ module MidiLyrics
100
113
  @lyrics = new_lyrics
101
114
  end
102
115
 
116
+ def half_is_equal
117
+ half = @lyrics.count / 2
118
+ (0..(half-1)).each do |x|
119
+ unless @lyrics[x].similar_to?(@lyrics[x + half])
120
+ return false
121
+ end
122
+ end
123
+ return true
124
+ end
125
+
126
+ def merge_half_lyrics
127
+ half = @lyrics.count / 2
128
+ (0..(half-1)).collect do |x|
129
+ @lyrics[x].start2_in_pulses = @lyrics.delete_at(half).start_in_pulses
130
+ end
131
+ end
132
+
133
+ def remove_repeating
134
+ if half_is_equal
135
+ merge_half_lyrics
136
+ end
137
+ end
138
+
103
139
  def extract
104
140
  read_sequence_from_file
105
141
  load_tracks
@@ -107,6 +143,7 @@ module MidiLyrics
107
143
  load_lyrics
108
144
  remove_heading_blank_lines
109
145
  consolidate_carriage_returns
146
+ remove_repeating unless repeating
110
147
  @lyrics
111
148
  end
112
149
  end
Binary file
Binary file
@@ -11,49 +11,120 @@ describe MidiLyrics do
11
11
  context "parsing" do
12
12
  it "parses one_note_one_syllable.mid correctly" do
13
13
  lyrics = MidiLyrics::Parser.new("spec/fixtures/one_note_one_syllable.mid").extract
14
- lyrics = lyrics.collect{|x| { text: x.text, start: x.start, duration: x.duration } }
14
+ lyrics = lyrics.collect{|x| { text: x.text, start: x.start, start2: x.start2, duration: x.duration } }
15
15
  expect(lyrics).to eq([
16
- { :text => "Test ", :start => 0.0, :duration => QUARTER_NOTE_DURATION },
17
- { :text => "\r", :start => QUARTER_NOTE_DURATION, :duration => 0.0 },
18
- { :text => "\n", :start => QUARTER_NOTE_DURATION, :duration => 0.0 }
16
+ { text: "Test ", start: 0.0, start2: 0.0, duration: QUARTER_NOTE_DURATION },
17
+ { text: "\r", start: QUARTER_NOTE_DURATION, start2: 0.0, duration: 0.0 },
18
+ { text: "\n", start: QUARTER_NOTE_DURATION, start2: 0.0, duration: 0.0 }
19
19
  ])
20
20
  end
21
21
 
22
22
  it "parses two_notes_one_syllable.mid correctly" do
23
23
  lyrics = MidiLyrics::Parser.new("spec/fixtures/two_notes_one_syllable.mid").extract
24
- lyrics = lyrics.collect{|x| { text: x.text, start: x.start, duration: x.duration } }
24
+ lyrics = lyrics.collect{|x| { text: x.text, start: x.start, start2: x.start2, duration: x.duration } }
25
25
  expect(lyrics).to eq([
26
- { text: "Test ", start: 0, duration: 0.5 + QUARTER_NOTE_DURATION },
27
- { text: "\r", start: 0.5 + QUARTER_NOTE_DURATION, duration: 0 },
28
- { text: "\n", start: 0.5 + QUARTER_NOTE_DURATION, duration: 0 }
26
+ { text: "Test ", start: 0, start2: 0.0, duration: 0.5 + QUARTER_NOTE_DURATION },
27
+ { text: "\r", start: 0.5 + QUARTER_NOTE_DURATION, start2: 0.0, duration: 0 },
28
+ { text: "\n", start: 0.5 + QUARTER_NOTE_DURATION, start2: 0.0, duration: 0 }
29
29
  ])
30
30
  end
31
31
 
32
32
  it "parses two_notes_two_syllables.mid correctly" do
33
33
  lyrics = MidiLyrics::Parser.new("spec/fixtures/two_notes_two_syllables.mid").extract
34
- lyrics = lyrics.collect{|x| { text: x.text, start: x.start, duration: x.duration } }
34
+ lyrics = lyrics.collect{|x| { text: x.text, start: x.start, start2: x.start2, duration: x.duration } }
35
35
  expect(lyrics).to eq([
36
- { text: "Test", start: 0, duration: QUARTER_NOTE_DURATION },
37
- { text: "ing ", start: 0.5, duration: QUARTER_NOTE_DURATION },
38
- { text: "\r", start: 0.5 + QUARTER_NOTE_DURATION, duration: 0 },
39
- { text: "\n", start: 0.5 + QUARTER_NOTE_DURATION, duration: 0 }
36
+ { text: "Test", start: 0, start2: 0.0, duration: QUARTER_NOTE_DURATION },
37
+ { text: "ing ", start: 0.5, start2: 0.0, duration: QUARTER_NOTE_DURATION },
38
+ { text: "\r", start: 0.5 + QUARTER_NOTE_DURATION, start2: 0.0, duration: 0 },
39
+ { text: "\n", start: 0.5 + QUARTER_NOTE_DURATION, start2: 0.0, duration: 0 }
40
40
  ])
41
41
  end
42
42
 
43
43
  it "parses spaces_and_returns.mid correctly" do
44
44
  lyrics = MidiLyrics::Parser.new("spec/fixtures/spaces_and_returns.mid").extract
45
- lyrics = lyrics.collect{|x| { text: x.text, start: x.start, duration: x.duration } }
45
+ lyrics = lyrics.collect{|x| { text: x.text, start: x.start, start2: x.start2, duration: x.duration } }
46
46
  expect(lyrics).to eq([
47
- { text: "Test", start: 0.5, duration: QUARTER_NOTE_DURATION },
48
- { text: "ing ", start: 1, duration: QUARTER_NOTE_DURATION },
49
- { text: "\r", start: 1 + QUARTER_NOTE_DURATION, duration: 0 },
50
- { text: "One", start: 1.5, duration: HALF_NOTE_DURATION },
51
- { text: "Two", start: 2.5, duration: HALF_NOTE_DURATION },
52
- { text: "Three ", start: 3.5, duration: HALF_NOTE_DURATION },
53
- { text: "\r", start: 3.5 + HALF_NOTE_DURATION, duration: 0 },
54
- { text: "\n", start: 3.5 + HALF_NOTE_DURATION, duration: 0 }
47
+ { text: "Test", start: 0.5, start2: 0.0, duration: QUARTER_NOTE_DURATION },
48
+ { text: "ing ", start: 1, start2: 0.0, duration: QUARTER_NOTE_DURATION },
49
+ { text: "\r", start: 1 + QUARTER_NOTE_DURATION, start2: 0.0, duration: 0 },
50
+ { text: "One", start: 1.5, start2: 0.0, duration: HALF_NOTE_DURATION },
51
+ { text: "Two", start: 2.5, start2: 0.0, duration: HALF_NOTE_DURATION },
52
+ { text: "Three ", start: 3.5, start2: 0.0, duration: HALF_NOTE_DURATION },
53
+ { text: "\r", start: 3.5 + HALF_NOTE_DURATION, start2: 0.0, duration: 0 },
54
+ { text: "\n", start: 3.5 + HALF_NOTE_DURATION, start2: 0.0, duration: 0 }
55
55
  ])
56
56
  end
57
+
58
+ it "parses repeating_lyrics.mid correctly repeating" do
59
+ lyrics = MidiLyrics::Parser.new("spec/fixtures/repeating_lyrics.mid", repeating: true).extract
60
+ lyrics = lyrics.collect{|x| { text: x.text, start: x.start, start2: x.start2, duration: x.duration } }
61
+ expect(lyrics).to eq([
62
+ { text: "Test", start: 0.0, start2: 0.0, duration: QUARTER_NOTE_DURATION },
63
+ { text: "ing ", start: 0.5, start2: 0.0, duration: QUARTER_NOTE_DURATION },
64
+ { text: "\r", start: 0.5 + QUARTER_NOTE_DURATION, start2: 0.0, duration: 0.0 },
65
+ { text: "One", start: 1.0, start2: 0.0, duration: QUARTER_NOTE_DURATION },
66
+ { text: "Two", start: 1.5, start2: 0.0, duration: QUARTER_NOTE_DURATION },
67
+ { text: "Three ", start: 2.0, start2: 0.0, duration: QUARTER_NOTE_DURATION },
68
+ { text: "\r", start: 2.0 + QUARTER_NOTE_DURATION, start2: 0.0, duration: 0.0 },
69
+ { text: "\n", start: 2.0 + QUARTER_NOTE_DURATION, start2: 0.0, duration: 0.0 },
70
+ { text: "Test", start: 2.5, start2: 0.0, duration: QUARTER_NOTE_DURATION },
71
+ { text: "ing ", start: 3.0, start2: 0.0, duration: QUARTER_NOTE_DURATION },
72
+ { text: "\r", start: 3.0 + QUARTER_NOTE_DURATION, start2: 0.0, duration: 0.0 },
73
+ { text: "One", start: 3.5, start2: 0.0, duration: QUARTER_NOTE_DURATION },
74
+ { text: "Two", start: 4.0, start2: 0.0, duration: QUARTER_NOTE_DURATION },
75
+ { text: "Three ", start: 4.5, start2: 0.0, duration: QUARTER_NOTE_DURATION },
76
+ { text: "\r", start: 4.5 + QUARTER_NOTE_DURATION, start2: 0.0, duration: 0.0 },
77
+ { text: "\n", start: 4.5 + QUARTER_NOTE_DURATION, start2: 0.0, duration: 0.0 },
78
+ ])
79
+ end
80
+
81
+ it "parses repeating_lyrics.mid correctly not repeating" do
82
+ lyrics = MidiLyrics::Parser.new("spec/fixtures/repeating_lyrics.mid").extract
83
+ lyrics = lyrics.collect{|x| { text: x.text, start: x.start, start2: x.start2, duration: x.duration } }
84
+ expect(lyrics).to eq([
85
+ { text: "Test", start: 0.0, start2: 2.5, duration: QUARTER_NOTE_DURATION },
86
+ { text: "ing ", start: 0.5, start2: 3.0, duration: QUARTER_NOTE_DURATION },
87
+ { text: "\r", start: 0.5 + QUARTER_NOTE_DURATION, start2: 3.0 + QUARTER_NOTE_DURATION, duration: 0.0 },
88
+ { text: "One", start: 1.0, start2: 3.5, duration: QUARTER_NOTE_DURATION },
89
+ { text: "Two", start: 1.5, start2: 4.0, duration: QUARTER_NOTE_DURATION },
90
+ { text: "Three ", start: 2.0, start2: 4.5, duration: QUARTER_NOTE_DURATION },
91
+ { text: "\r", start: 2.0 + QUARTER_NOTE_DURATION, start2: 4.5 + QUARTER_NOTE_DURATION, duration: 0.0 },
92
+ { text: "\n", start: 2.0 + QUARTER_NOTE_DURATION, start2: 4.5 + QUARTER_NOTE_DURATION, duration: 0.0 },
93
+ ])
94
+ end
95
+
96
+ let :parsed_complete_example do
97
+ [
98
+ { text: "Test", start: 0.5, start2: 0.0, duration: QUARTER_NOTE_DURATION },
99
+ { text: "ing ", start: 1.0, start2: 0.0, duration: QUARTER_NOTE_DURATION },
100
+ { text: "\r", start: 1.0 + QUARTER_NOTE_DURATION, start2: 0.0, duration: 0.0 },
101
+ { text: "One", start: 1.5, start2: 0.0, duration: HALF_NOTE_DURATION },
102
+ { text: "Two", start: 2.5, start2: 0.0, duration: HALF_NOTE_DURATION },
103
+ { text: "Three ", start: 3.5, start2: 0.0, duration: HALF_NOTE_DURATION },
104
+ { text: "\r", start: 3.5 + HALF_NOTE_DURATION, start2: 0.0, duration: 0.0 },
105
+ { text: "\n", start: 3.5 + HALF_NOTE_DURATION, start2: 0.0, duration: 0.0 },
106
+ { text: "Test", start: 4.5, start2: 0.0, duration: QUARTER_NOTE_DURATION },
107
+ { text: "ing ", start: 5.0, start2: 0.0, duration: QUARTER_NOTE_DURATION },
108
+ { text: "\r", start: 5.0 + QUARTER_NOTE_DURATION, start2: 0.0, duration: 0.0 },
109
+ { text: "Four", start: 5.5, start2: 0.0, duration: HALF_NOTE_DURATION },
110
+ { text: "Five", start: 6.5, start2: 0.0, duration: HALF_NOTE_DURATION },
111
+ { text: "Six ", start: 7.5, start2: 0.0, duration: HALF_NOTE_DURATION },
112
+ { text: "\r", start: 7.5 + HALF_NOTE_DURATION, start2: 0.0, duration: 0.0 },
113
+ { text: "\n", start: 7.5 + HALF_NOTE_DURATION, start2: 0.0, duration: 0.0 },
114
+ ]
115
+ end
116
+
117
+ it "parses complete_example.mid correctly repeating" do
118
+ lyrics = MidiLyrics::Parser.new("spec/fixtures/complete_example.mid").extract
119
+ lyrics = lyrics.collect{|x| { text: x.text, start: x.start, start2: x.start2, duration: x.duration } }
120
+ expect(lyrics).to eq(parsed_complete_example)
121
+ end
122
+
123
+ it "parses complete_example.mid correctly not repeating" do
124
+ lyrics = MidiLyrics::Parser.new("spec/fixtures/complete_example.mid", repeating: true).extract
125
+ lyrics = lyrics.collect{|x| { text: x.text, start: x.start, start2: x.start2, duration: x.duration } }
126
+ expect(lyrics).to eq(parsed_complete_example)
127
+ end
57
128
  end
58
129
 
59
130
  context "error handling" do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: midi_lyrics
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mateus Del Bianco