require "spec_helper" describe MidiLyrics do QUARTER_NOTE_DURATION = 0.417 HALF_NOTE_DURATION = 0.875 it "returns an array" do expect(MidiLyrics::Parser.new("spec/fixtures/one_note_one_syllable.mid").extract).to be_kind_of(Array) end context "accessing LyricSyllable attributes" do let(:lyrics) { MidiLyrics::Parser.new("spec/fixtures/repeating_lyrics.mid").extract } it "has text method" do expect(lyrics[1].text).to eq("ing") end it "has start_in_pulses method" do expect(lyrics[1].start_in_pulses).to eq(192) end it "has start method" do expect(lyrics[1].start).to eq(0.5) end it "has start2_in_pulses method" do expect(lyrics[1].start2_in_pulses).to eq(1152) end it "has start2 method" do expect(lyrics[1].start2).to eq(3.0) end it "has duration_in_pulses method" do expect(lyrics[1].duration_in_pulses).to eq(160) end it "has duration method" do expect(lyrics[1].duration).to eq(QUARTER_NOTE_DURATION) end it "has as_json method" do expect(lyrics[1].as_json).to eq({text: "ing", start: 0.5, start2: 3.0, duration: 0.417}) end end context "file parsing" do it "parses one_note_one_syllable.mid correctly" do expect( MidiLyrics::Parser.new("spec/fixtures/one_note_one_syllable.mid").extract.collect(&:as_json) ).to eq([ { text: "Test", start: 0.0, start2: 0.0, duration: QUARTER_NOTE_DURATION }, { text: "\r\n", start: QUARTER_NOTE_DURATION, start2: 0.0, duration: 0.0 } ]) end it "parses one_note_two_syllable.mid correctly" do expect( MidiLyrics::Parser.new("spec/fixtures/one_note_two_syllable.mid").extract.collect(&:as_json) ).to eq([ { text: "Test One", start: 0.0, start2: 0.0, duration: QUARTER_NOTE_DURATION }, { text: "\r\n", start: QUARTER_NOTE_DURATION, start2: 0.0, duration: 0.0 } ]) end it "parses two_notes_one_syllable.mid correctly" do expect( MidiLyrics::Parser.new("spec/fixtures/two_notes_one_syllable.mid").extract.collect(&:as_json) ).to eq([ { text: "Test", start: 0, start2: 0.0, duration: 0.5 + QUARTER_NOTE_DURATION }, { text: "\r\n", start: 0.5 + QUARTER_NOTE_DURATION, start2: 0.0, duration: 0.0 } ]) end it "parses two_notes_two_syllables.mid correctly" do expect( MidiLyrics::Parser.new("spec/fixtures/two_notes_two_syllables.mid").extract.collect(&:as_json) ).to eq([ { text: "Test", start: 0, start2: 0.0, duration: QUARTER_NOTE_DURATION }, { text: "ing", start: 0.5, start2: 0.0, duration: QUARTER_NOTE_DURATION }, { text: "\r\n", start: 0.5 + QUARTER_NOTE_DURATION, start2: 0.0, duration: 0.0 } ]) end it "parses two_notes_three_syllables.mid correctly" do expect( MidiLyrics::Parser.new("spec/fixtures/two_notes_three_syllables.mid").extract.collect(&:as_json) ).to eq([ { text: "Hello, test", start: 0, start2: 0.0, duration: QUARTER_NOTE_DURATION }, { text: "ing", start: 0.5, start2: 0.0, duration: QUARTER_NOTE_DURATION }, { text: "\r\n", start: 0.5 + QUARTER_NOTE_DURATION, start2: 0.0, duration: 0.0 } ]) end it "parses spaces_and_returns.mid correctly" do expect( MidiLyrics::Parser.new("spec/fixtures/spaces_and_returns.mid").extract.collect(&:as_json) ).to eq([ { text: "Test", start: 0.5, start2: 0.0, duration: QUARTER_NOTE_DURATION }, { text: "ing", start: 1, start2: 0.0, duration: QUARTER_NOTE_DURATION }, { text: "\r", start: 1 + QUARTER_NOTE_DURATION, start2: 0.0, duration: 0.0 }, { text: "One", start: 1.5, start2: 0.0, duration: HALF_NOTE_DURATION }, { text: " ", start: 1.5 + HALF_NOTE_DURATION, start2: 0.0, duration: 0.0 }, { text: "Two", start: 2.5, start2: 0.0, duration: HALF_NOTE_DURATION }, { text: " ", start: 2.5 + HALF_NOTE_DURATION, start2: 0.0, duration: 0.0 }, { text: "Three", start: 3.5, start2: 0.0, duration: HALF_NOTE_DURATION }, { text: "\r\n", start: 3.5 + HALF_NOTE_DURATION, start2: 0.0, duration: 0.0 } ]) end it "parses repeating_lyrics.mid correctly repeating" do expect( MidiLyrics::Parser.new("spec/fixtures/repeating_lyrics.mid", repeating: true).extract.collect(&:as_json) ).to eq([ { text: "Test", start: 0.0, start2: 0.0, duration: QUARTER_NOTE_DURATION }, { text: "ing", start: 0.5, start2: 0.0, duration: QUARTER_NOTE_DURATION }, { text: "\r", start: 0.5 + QUARTER_NOTE_DURATION, start2: 0.0, duration: 0.0 }, { text: "One", start: 1.0, start2: 0.0, duration: QUARTER_NOTE_DURATION }, { text: " ", start: 1.0 + QUARTER_NOTE_DURATION, start2: 0.0, duration: 0.0 }, { text: "Two", start: 1.5, start2: 0.0, duration: QUARTER_NOTE_DURATION }, { text: " ", start: 1.5 + QUARTER_NOTE_DURATION, start2: 0.0, duration: 0.0 }, { text: "Three", start: 2.0, start2: 0.0, duration: QUARTER_NOTE_DURATION }, { text: "\r\n", start: 2.0 + QUARTER_NOTE_DURATION, start2: 0.0, duration: 0.0 }, { text: "Test", start: 2.5, start2: 0.0, duration: QUARTER_NOTE_DURATION }, { text: "ing", start: 3.0, start2: 0.0, duration: QUARTER_NOTE_DURATION }, { text: "\r", start: 3.0 + QUARTER_NOTE_DURATION, start2: 0.0, duration: 0.0 }, { text: "One", start: 3.5, start2: 0.0, duration: QUARTER_NOTE_DURATION }, { text: " ", start: 3.5 + QUARTER_NOTE_DURATION, start2: 0.0, duration: 0.0 }, { text: "Two", start: 4.0, start2: 0.0, duration: QUARTER_NOTE_DURATION }, { text: " ", start: 4.0 + QUARTER_NOTE_DURATION, start2: 0.0, duration: 0.0 }, { text: "Three", start: 4.5, start2: 0.0, duration: QUARTER_NOTE_DURATION }, { text: "\r\n", start: 4.5 + QUARTER_NOTE_DURATION, start2: 0.0, duration: 0.0 } ]) end it "parses repeating_lyrics.mid correctly not repeating" do expect( MidiLyrics::Parser.new("spec/fixtures/repeating_lyrics.mid").extract.collect(&:as_json) ).to eq([ { text: "Test", start: 0.0, start2: 2.5, duration: QUARTER_NOTE_DURATION }, { text: "ing", start: 0.5, start2: 3.0, duration: QUARTER_NOTE_DURATION }, { text: "\r", start: 0.5 + QUARTER_NOTE_DURATION, start2: 3.0 + QUARTER_NOTE_DURATION, duration: 0.0 }, { text: "One", start: 1.0, start2: 3.5, duration: QUARTER_NOTE_DURATION }, { text: " ", start: 1.0 + QUARTER_NOTE_DURATION, start2: 3.5 + QUARTER_NOTE_DURATION, duration: 0.0 }, { text: "Two", start: 1.5, start2: 4.0, duration: QUARTER_NOTE_DURATION }, { text: " ", start: 1.5 + QUARTER_NOTE_DURATION, start2: 4.0 + QUARTER_NOTE_DURATION, duration: 0.0 }, { text: "Three", start: 2.0, start2: 4.5, duration: QUARTER_NOTE_DURATION }, { text: "\r\n", start: 2.0 + QUARTER_NOTE_DURATION, start2: 4.5 + QUARTER_NOTE_DURATION, duration: 0.0 } ]) end let :parsed_complete_example do [ { text: "Test", start: 0.5, start2: 0.0, duration: QUARTER_NOTE_DURATION }, { text: "ing", start: 1.0, start2: 0.0, duration: QUARTER_NOTE_DURATION }, { text: "\r", start: 1.0 + QUARTER_NOTE_DURATION, start2: 0.0, duration: 0.0 }, { text: "One", start: 1.5, start2: 0.0, duration: HALF_NOTE_DURATION }, { text: " ", start: 1.5 + HALF_NOTE_DURATION, start2: 0.0, duration: 0.0 }, { text: "Two", start: 2.5, start2: 0.0, duration: HALF_NOTE_DURATION }, { text: " ", start: 2.5 + HALF_NOTE_DURATION, start2: 0.0, duration: 0.0 }, { text: "Three", start: 3.5, start2: 0.0, duration: HALF_NOTE_DURATION }, { text: "\r\n", start: 3.5 + HALF_NOTE_DURATION, start2: 0.0, duration: 0.0 }, { text: "Test", start: 4.5, start2: 0.0, duration: QUARTER_NOTE_DURATION }, { text: "ing", start: 5.0, start2: 0.0, duration: QUARTER_NOTE_DURATION }, { text: "\r", start: 5.0 + QUARTER_NOTE_DURATION, start2: 0.0, duration: 0.0 }, { text: "Four", start: 5.5, start2: 0.0, duration: HALF_NOTE_DURATION }, { text: " ", start: 5.5 + HALF_NOTE_DURATION, start2: 0.0, duration: 0.0 }, { text: "Five", start: 6.5, start2: 0.0, duration: HALF_NOTE_DURATION }, { text: " ", start: 6.5 + HALF_NOTE_DURATION, start2: 0.0, duration: 0.0 }, { text: "Six", start: 7.5, start2: 0.0, duration: HALF_NOTE_DURATION }, { text: "\r\n", start: 7.5 + HALF_NOTE_DURATION, start2: 0.0, duration: 0.0 }, ] end it "parses complete_example.mid correctly repeating" do expect( MidiLyrics::Parser.new("spec/fixtures/complete_example.mid").extract.collect(&:as_json) ).to eq(parsed_complete_example) end it "parses complete_example.mid correctly not repeating" do expect( MidiLyrics::Parser.new("spec/fixtures/complete_example.mid", repeating: true).extract.collect(&:as_json) ).to eq(parsed_complete_example) end end context "error handling" do it "raises MidiLyrics::FileNotFound if file does not exist" do expect { MidiLyrics::Parser.new("test.mid").extract }.to raise_error(MidiLyrics::FileNotFound) end end end