Socket
Socket
Sign inDemoInstall

midiviz-prepare

Package Overview
Dependencies
Maintainers
1
Versions
7
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

midiviz-prepare - npm Package Compare versions

Comparing version 0.0.4 to 0.0.5

test/output.mid

133

build/main.js

@@ -6,9 +6,22 @@ #!/usr/bin/env node

var MidiFunctions_1 = require("./MidiFunctions");
function displayHelp() {
console.error("Usage:");
console.error();
console.error("midiviz-prepare", "<input filename>", "<output filename> [<wanted start time>]");
}
function parseArgs() {
if (process.argv.length < 4) {
throw new Error("Missing parameters! Please submit input and output file name.");
var argv = process.argv;
var args = argv.length;
if (args < 4 || args > 5) {
displayHelp();
return;
}
var wantedStartTime;
if (args === 5) {
wantedStartTime = parseFloat(argv[4]);
}
return {
inputFileName: process.argv[2],
outputFileName: process.argv[3],
wantedStartTime: wantedStartTime,
};

@@ -27,35 +40,99 @@ }

/**
* Split the minor notes from the first track a separate second track
* Returns the minimum of two values that might be missing.
*
* The missing values are _not_ considered as a candidate.
* If both values are missing, undefined is returned.
*/
function splitMinors(music) {
// const keys = Object.keys(music);
// console.log("Objects in main scope: ", keys);
// keys
// .filter((key) => key !== "0")
// .forEach((key) => console.log(key, ":", music[key]));
var newMusic = MidiFunctions_1.createMusic(1, music.ppqn);
var primaryTrack = MidiFunctions_1.addTrack(newMusic);
var secondaryTrack = MidiFunctions_1.addTrack(newMusic);
music[0]
.filter(function (event) { return isMajorNote(event); }) // !isMinorNote(event))
.forEach(function (event) {
primaryTrack.add(event.tt, event);
});
music[0]
.filter(function (event) { return isMinorNote(event); }) // !isMajorNote(event))
.forEach(function (event) {
secondaryTrack.add(event.tt, event);
});
console.log("Moved", primaryTrack.length, "major note events to primary track;", secondaryTrack.length, "minor note events to secondary track.");
return newMusic;
function saneMin(a1, a2) {
if (a1 === undefined) {
if (a2 === undefined) {
// None of the input values are defined; we have nothing better to do than returning undefined
return undefined;
}
else {
// A1 is undefined, A2 is defined
return a2;
}
}
else {
if (a2 === undefined) {
// A1 is defined, A2 is undefined
return a1;
}
else {
// Both A1 and A2 are defined
return Math.min(a1, a2);
}
}
}
function main() {
var _a, _b;
// Parse the args
var args = parseArgs();
var music = MidiFunctions_1.loadMusic(args.inputFileName);
if (!args) {
return;
}
var inputFileName = args.inputFileName, outputFileName = args.outputFileName, wantedStartTime = args.wantedStartTime;
// Load the music
var music;
try {
music = MidiFunctions_1.loadMusic(inputFileName);
}
catch (error) {
console.error("Error while reading specified input file:", error.message);
return;
}
// Do the processing
if (music.length !== 1) {
throw new Error("Sorry, but I can only handle single-track MIDI files!");
console.error("Sorry, but I can only handle single-track MIDI files!");
return;
}
var newMusic = splitMinors(music);
MidiFunctions_1.saveMusic(newMusic, args.outputFileName);
var tempo = music.ppqn;
// Filter the notes
var majors = music[0].filter(function (event) { return isMajorNote(event); });
var minors = music[0].filter(function (event) { return isMinorNote(event); });
// Calculating required time adjustment
var timeOffset = 0;
if (wantedStartTime !== undefined) {
console.log("Tempo is:", tempo, "ticks per half second");
var tickLength = 0.5 / tempo;
var currentStartTicks = saneMin((_a = majors[0]) === null || _a === void 0 ? void 0 : _a.tt, (_b = minors[0]) === null || _b === void 0 ? void 0 : _b.tt);
if (currentStartTicks === undefined) {
console.log("There are no notes; not doing time adjustment.");
}
else {
var wantedStartTicks = wantedStartTime / tickLength;
timeOffset = wantedStartTicks - currentStartTicks;
console.log("Current start time:", currentStartTicks, "ticks");
console.log("Wanted start time:", wantedStartTime, "secs,", wantedStartTicks, "ticks");
console.log("Adjusting timestamps with", timeOffset, "ticks");
}
}
else {
console.log("No time adjustment requested.");
}
// Create a new MIDI file
var newMusic = MidiFunctions_1.createMusic(1, tempo);
// Add the track for the major notes
var primaryTrack = MidiFunctions_1.addTrack(newMusic);
majors.forEach(function (event) {
primaryTrack.add(event.tt + timeOffset, event);
});
// Add the tract for the minor notes
var secondaryTrack = MidiFunctions_1.addTrack(newMusic);
minors.forEach(function (event) {
secondaryTrack.add(event.tt + timeOffset, event);
});
// Log the results
console.log("Moved", primaryTrack.length, "major note events to primary track;", secondaryTrack.length, "minor note events to secondary track.");
// Save the result
try {
MidiFunctions_1.saveMusic(newMusic, outputFileName);
console.log("Output saved to", outputFileName);
}
catch (error) {
console.error("Error while writing specified output file:", error.message);
return;
}
}
main();
{
"name": "midiviz-prepare",
"author": "Kristof Csillag <csillag.kristof@gmail.com>",
"version": "0.0.4",
"version": "0.0.5",
"description": "A preprocessor for MIDIVisualizer",

@@ -6,0 +6,0 @@ "main": "build/main.js",

`midiviz-prepare` is a MIDI file pre-processor for [MIDIVisualizer](https://github.com/ekuiter/MIDIVisualizer).
## Background
## Problem

@@ -10,3 +10,3 @@ - Once upon a time, there was a great utility called [MIDIVisualizer](https://github.com/kosua20/MIDIVisualizer), by [@kosua20](https://github.com/kosua20).

## Solution
## Reaction

@@ -18,7 +18,9 @@ My answer is that I choose _both_. I need the fancy new features, _and_ the correct coloring.

So instead of that, I just created a small MIDI pre-processor utility, which is able to move the minor keys to a separate track, and thus achieve the desired coloring with the new version.
## Solution
So I just created a small MIDI pre-processor utility, which is able to move the minor keys to a separate track, and thus achieve the desired coloring with the new version.
## Installation
Just install with npm. The command with appear in your normal npm binary directory.
Just install with `npm`. The command with appear in your normal npm binary directory.

@@ -34,4 +36,8 @@ ```

```
midiviz-prepare input.mid output.mid
midiviz-prepare input.mid output.mid [start time in seconds]
```
### But what does it do?
Well, it reads the music in the input (single-track) MIDI file, and creates a new MIDI file out of it, by copying all the major notes on the first track, and all the minor notes to the second track. It can optionally adjust the timestamps, so that the music starts at the requested time. (Which can be helpful to get more deterministic timing, in case you want to mix the resulting animation with sound.)

@@ -6,9 +6,3 @@ #!/usr/bin/env node

import { SMF } from "./MidiTypes";
import {
addTrack,
createMusic,
describe,
loadMusic,
saveMusic,
} from "./MidiFunctions";
import { addTrack, createMusic, loadMusic, saveMusic } from "./MidiFunctions";
import { MIDI } from "./JZZTypes";

@@ -19,13 +13,30 @@

outputFileName: string;
wantedStartTime?: number;
}
function parseArgs(): Parameters {
if (process.argv.length < 4) {
throw new Error(
"Missing parameters! Please submit input and output file name."
);
function displayHelp() {
console.error("Usage:");
console.error();
console.error(
"midiviz-prepare",
"<input filename>",
"<output filename> [<wanted start time>]"
);
}
function parseArgs(): Parameters | undefined {
const { argv } = process;
const args = argv.length;
if (args < 4 || args > 5) {
displayHelp();
return;
}
let wantedStartTime: number | undefined;
if (args === 5) {
wantedStartTime = parseFloat(argv[4]);
}
return {
inputFileName: process.argv[2],
outputFileName: process.argv[3],
wantedStartTime,
};

@@ -48,23 +59,97 @@ }

/**
* Split the minor notes from the first track a separate second track
* Returns the minimum of two values that might be missing.
*
* The missing values are _not_ considered as a candidate.
* If both values are missing, undefined is returned.
*/
function splitMinors(music: SMF): SMF {
// const keys = Object.keys(music);
// console.log("Objects in main scope: ", keys);
// keys
// .filter((key) => key !== "0")
// .forEach((key) => console.log(key, ":", music[key]));
const newMusic = createMusic(1, music.ppqn);
function saneMin(a1: number, a2: number): number | undefined {
if (a1 === undefined) {
if (a2 === undefined) {
// None of the input values are defined; we have nothing better to do than returning undefined
return undefined;
} else {
// A1 is undefined, A2 is defined
return a2;
}
} else {
if (a2 === undefined) {
// A1 is defined, A2 is undefined
return a1;
} else {
// Both A1 and A2 are defined
return Math.min(a1, a2);
}
}
}
function main() {
// Parse the args
const args = parseArgs();
if (!args) {
return;
}
const { inputFileName, outputFileName, wantedStartTime } = args;
// Load the music
let music: SMF | undefined;
try {
music = loadMusic(inputFileName);
} catch (error) {
console.error("Error while reading specified input file:", error.message);
return;
}
// Do the processing
if (music.length !== 1) {
console.error("Sorry, but I can only handle single-track MIDI files!");
return;
}
const tempo = music.ppqn;
// Filter the notes
const majors = music[0].filter((event) => isMajorNote(event));
const minors = music[0].filter((event) => isMinorNote(event));
// Calculating required time adjustment
let timeOffset = 0;
if (wantedStartTime !== undefined) {
console.log("Tempo is:", tempo, "ticks per half second");
const tickLength = 0.5 / tempo;
const currentStartTicks = saneMin(majors[0]?.tt, minors[0]?.tt);
if (currentStartTicks === undefined) {
console.log("There are no notes; not doing time adjustment.");
} else {
const wantedStartTicks = wantedStartTime / tickLength;
timeOffset = wantedStartTicks - currentStartTicks;
console.log("Current start time:", currentStartTicks, "ticks");
console.log(
"Wanted start time:",
wantedStartTime,
"secs,",
wantedStartTicks,
"ticks"
);
console.log("Adjusting timestamps with", timeOffset, "ticks");
}
} else {
console.log("No time adjustment requested.");
}
// Create a new MIDI file
const newMusic = createMusic(1, tempo);
// Add the track for the major notes
const primaryTrack = addTrack(newMusic);
majors.forEach((event) => {
primaryTrack.add(event.tt + timeOffset, event);
});
// Add the tract for the minor notes
const secondaryTrack = addTrack(newMusic);
music[0]
.filter((event) => isMajorNote(event)) // !isMinorNote(event))
.forEach((event) => {
primaryTrack.add(event.tt, event);
});
music[0]
.filter((event) => isMinorNote(event)) // !isMajorNote(event))
.forEach((event) => {
secondaryTrack.add(event.tt, event);
});
minors.forEach((event) => {
secondaryTrack.add(event.tt + timeOffset, event);
});
// Log the results
console.log(

@@ -77,15 +162,13 @@ "Moved",

);
return newMusic;
}
function main() {
const args = parseArgs();
const music = loadMusic(args.inputFileName);
if (music.length !== 1) {
throw new Error("Sorry, but I can only handle single-track MIDI files!");
// Save the result
try {
saveMusic(newMusic, outputFileName);
console.log("Output saved to", outputFileName);
} catch (error) {
console.error("Error while writing specified output file:", error.message);
return;
}
const newMusic = splitMinors(music);
saveMusic(newMusic, args.outputFileName);
}
main();

@@ -38,3 +38,3 @@ {

/* Additional Checks */
// "noUnusedLocals": true, /* Report errors on unused locals. */
"noUnusedLocals": true, /* Report errors on unused locals. */
// "noUnusedParameters": true, /* Report errors on unused parameters. */

@@ -41,0 +41,0 @@ // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc