Spaces:
Sleeping
Sleeping
| import * as fs from "fs" | |
| import { AnyEvent } from "midifile-ts" | |
| import * as path from "path" | |
| import { serialize } from "serializr" | |
| import { emptySong } from "../song/SongFactory" | |
| import { NoteEvent } from "../track" | |
| import Track from "../track/Track" | |
| import { | |
| noteOffMidiEvent, | |
| noteOnMidiEvent, | |
| setTempoMidiEvent, | |
| timeSignatureMidiEvent, | |
| } from "./MidiEvent" | |
| import { | |
| createConductorTrackIfNeeded, | |
| songFromMidi, | |
| songToMidi, | |
| songToMidiEvents, | |
| } from "./midiConversion" | |
| // id for each event will not be serialized in midi file | |
| // we change ids sorted by order in events array | |
| const reassignIDs = (track: Track) => { | |
| track.events.forEach((e, i) => { | |
| track.events[i].id = i | |
| }) | |
| } | |
| describe("SongFile", () => { | |
| it("write and read", () => { | |
| const song = emptySong() | |
| const note = song.tracks[1].addEvent<NoteEvent>({ | |
| type: "channel", | |
| subtype: "note", | |
| noteNumber: 57, | |
| tick: 960, | |
| velocity: 127, | |
| duration: 240, | |
| }) | |
| song.tracks.forEach(reassignIDs) | |
| const bytes = songToMidi(song) | |
| const song2 = songFromMidi(bytes) | |
| song2.filepath = song.filepath // filepath will not be serialized | |
| expect(serialize(song2)).toStrictEqual(serialize(song)) | |
| }) | |
| describe("songToMidiEvents", () => { | |
| const expectEveryTrackHaveEndOfTrackEvent = (tracks: AnyEvent[][]) => { | |
| for (const track of tracks) { | |
| expect( | |
| track.findIndex( | |
| (e) => e.type === "meta" && e.subtype === "endOfTrack", | |
| ), | |
| ).toBe(track.length - 1) | |
| } | |
| } | |
| const openFile = (fileName: string): AnyEvent[][] => { | |
| const song = songFromMidi( | |
| fs.readFileSync(path.join(__dirname, "../../../testdata/", fileName)) | |
| .buffer, | |
| ) | |
| return songToMidiEvents(song) | |
| } | |
| describe("format 1", () => { | |
| const rawTracks = openFile("tracks.mid") | |
| it("every tracks have endOfTrack event", () => { | |
| expect(rawTracks.length).toBe(18) | |
| expectEveryTrackHaveEndOfTrackEvent(rawTracks) | |
| }) | |
| }) | |
| describe("format 0", () => { | |
| const rawTracks = openFile("format0.mid") | |
| it("every tracks have endOfTrack event", () => { | |
| expect(rawTracks.length).toBe(17) | |
| expectEveryTrackHaveEndOfTrackEvent(rawTracks) | |
| }) | |
| }) | |
| }) | |
| describe("signal events", () => { | |
| it("should save the track color", () => { | |
| const song = emptySong() | |
| song.tracks[1].setColor({ | |
| red: 12, | |
| green: 34, | |
| blue: 56, | |
| alpha: 78, | |
| }) | |
| const bytes = songToMidi(song) | |
| const song2 = songFromMidi(bytes) | |
| expect(song2.tracks[1].color).toMatchObject({ | |
| red: 12, | |
| green: 34, | |
| blue: 56, | |
| alpha: 78, | |
| }) | |
| }) | |
| }) | |
| describe("createConductorTrackIfNeeded", () => { | |
| it("should not create the conductor track", () => { | |
| const tracks: AnyEvent[][] = [ | |
| [timeSignatureMidiEvent(0, 4, 4), setTempoMidiEvent(120, 500000)], | |
| [noteOnMidiEvent(0, 1, 60, 100), noteOffMidiEvent(120, 1, 60, 0)], | |
| ] | |
| const result = createConductorTrackIfNeeded(tracks) | |
| expect(result).toStrictEqual([ | |
| [timeSignatureMidiEvent(0, 4, 4), setTempoMidiEvent(120, 500000)], | |
| [noteOnMidiEvent(0, 1, 60, 100), noteOffMidiEvent(120, 1, 60, 0)], | |
| ]) | |
| }) | |
| it("should create the conductor track", () => { | |
| const tracks: AnyEvent[][] = [ | |
| [ | |
| timeSignatureMidiEvent(0, 4, 4), | |
| setTempoMidiEvent(120, 500000), | |
| noteOnMidiEvent(120, 5, 60, 100), | |
| noteOffMidiEvent(120, 5, 60, 0), | |
| ], | |
| [noteOnMidiEvent(0, 2, 60, 100), noteOffMidiEvent(120, 2, 60, 0)], | |
| ] | |
| const result = createConductorTrackIfNeeded(tracks) | |
| expect(result).toStrictEqual([ | |
| [timeSignatureMidiEvent(0, 4, 4), setTempoMidiEvent(120, 500000)], | |
| [noteOnMidiEvent(240, 5, 60, 100), noteOffMidiEvent(120, 5, 60, 0)], | |
| [noteOnMidiEvent(0, 2, 60, 100), noteOffMidiEvent(120, 2, 60, 0)], | |
| ]) | |
| }) | |
| }) | |
| }) | |