@magenta/music
Advanced tools
Comparing version 1.0.3 to 1.1.1
@@ -176,3 +176,5 @@ "use strict"; | ||
'totalSteps': 8, | ||
'numVelocityBins': 0 | ||
'numVelocityBins': 0, | ||
'minPitch': 21, | ||
'maxPitch': 108 | ||
}); | ||
@@ -179,0 +181,0 @@ var multitrackTensor = multitrackConverter.toTensor(MULTITRACK_NS); |
@@ -108,2 +108,4 @@ import * as tf from '@tensorflow/tfjs-core'; | ||
numVelocityBins: number; | ||
minPitch?: number; | ||
maxPitch?: number; | ||
} | ||
@@ -116,2 +118,4 @@ export declare class MultitrackConverter extends DataConverter { | ||
readonly numVelocityBins: number; | ||
readonly minPitch: number; | ||
readonly maxPitch: number; | ||
readonly numPitches: number; | ||
@@ -118,0 +122,0 @@ readonly performanceEventDepth: number; |
@@ -410,3 +410,5 @@ "use strict"; | ||
_this.numVelocityBins = args.numVelocityBins; | ||
_this.numPitches = constants.MAX_MIDI_PITCH - constants.MIN_MIDI_PITCH + 1; | ||
_this.minPitch = args.minPitch ? args.minPitch : constants.MIN_MIDI_PITCH; | ||
_this.maxPitch = args.maxPitch ? args.maxPitch : constants.MAX_MIDI_PITCH; | ||
_this.numPitches = _this.maxPitch - _this.minPitch + 1; | ||
_this.performanceEventDepth = | ||
@@ -436,6 +438,6 @@ 2 * _this.numPitches + _this.totalSteps + _this.numVelocityBins; | ||
case 'note-on': | ||
tokens.set(event.pitch - constants.MIN_MIDI_PITCH, index + 1); | ||
tokens.set(event.pitch - _this.minPitch, index + 1); | ||
break; | ||
case 'note-off': | ||
tokens.set(_this.numPitches + event.pitch - constants.MIN_MIDI_PITCH, index + 1); | ||
tokens.set(_this.numPitches + event.pitch - _this.minPitch, index + 1); | ||
break; | ||
@@ -469,5 +471,7 @@ case 'time-shift': | ||
} | ||
var instruments = new Set(noteSequence.notes.map(function (note) { return note.instrument; })); | ||
var seq = sequences.clone(noteSequence); | ||
seq.notes = noteSequence.notes.filter(function (note) { return note.pitch >= _this.minPitch && note.pitch <= _this.maxPitch; }); | ||
var instruments = new Set(seq.notes.map(function (note) { return note.instrument; })); | ||
var tracks = Array.from(instruments) | ||
.map(function (instrument) { return performance.Performance.fromNoteSequence(noteSequence, _this.totalSteps, _this.numVelocityBins, instrument); }); | ||
.map(function (instrument) { return performance.Performance.fromNoteSequence(seq, _this.totalSteps, _this.numVelocityBins, instrument); }); | ||
var sortedTracks = tracks.sort(function (a, b) { return b.isDrum ? -1 : (a.isDrum ? 1 : a.program - b.program); }); | ||
@@ -497,3 +501,3 @@ while (sortedTracks.length > this.numSegments) { | ||
if (token < _this.numPitches) { | ||
return { type: 'note-on', pitch: constants.MIN_MIDI_PITCH + token }; | ||
return { type: 'note-on', pitch: _this.minPitch + token }; | ||
} | ||
@@ -503,3 +507,3 @@ else if (token < 2 * _this.numPitches) { | ||
type: 'note-off', | ||
pitch: constants.MIN_MIDI_PITCH + token - _this.numPitches | ||
pitch: _this.minPitch + token - _this.numPitches | ||
}; | ||
@@ -506,0 +510,0 @@ } |
@@ -129,2 +129,50 @@ "use strict"; | ||
}); | ||
var polyNs = index_1.NoteSequence.create({ | ||
ticksPerQuarter: 220, | ||
totalTime: 1.0, | ||
timeSignatures: [{ time: 0, numerator: 4, denominator: 4 }], | ||
tempos: [{ time: 0, qpm: 120 }], | ||
sourceInfo: { | ||
encodingType: index_1.NoteSequence.SourceInfo.EncodingType.MIDI, | ||
parser: index_1.NoteSequence.SourceInfo.Parser.TONEJS_MIDI_CONVERT | ||
}, | ||
notes: [ | ||
{ | ||
instrument: 0, | ||
program: 0, | ||
startTime: 0.0, | ||
endTime: 1.0, | ||
pitch: 60, | ||
velocity: 100, | ||
isDrum: false | ||
}, | ||
{ | ||
instrument: 0, | ||
program: 0, | ||
startTime: 0.125, | ||
endTime: 0.875, | ||
pitch: 62, | ||
velocity: 100, | ||
isDrum: false | ||
}, | ||
{ | ||
instrument: 0, | ||
program: 0, | ||
startTime: 0.25, | ||
endTime: 0.75, | ||
pitch: 64, | ||
velocity: 100, | ||
isDrum: false | ||
}, | ||
{ | ||
instrument: 0, | ||
program: 0, | ||
startTime: 0.375, | ||
endTime: 0.625, | ||
pitch: 67, | ||
velocity: 100, | ||
isDrum: false | ||
} | ||
] | ||
}); | ||
test('Parse Simple MIDI', function (t) { | ||
@@ -143,2 +191,7 @@ var midi = fs.readFileSync('../testdata/melody.mid', 'binary'); | ||
}); | ||
test('Create MIDI File With Polyphony', function (t) { | ||
var midiFile = midi_io.sequenceProtoToMidi(polyNs); | ||
t.deepEqual(midi_io.midiToSequenceProto(String.fromCharCode.apply(null, midiFile)), polyNs); | ||
t.end(); | ||
}); | ||
test('Write MIDI Using Defaults', function (t) { | ||
@@ -145,0 +198,0 @@ var strippedNs = sequences.clone(simpleNs); |
@@ -114,3 +114,3 @@ "use strict"; | ||
} | ||
var instruments = Array.from(tracks.keys()).sort(); | ||
var instruments = Array.from(tracks.keys()).sort(function (a, b) { return a - b; }); | ||
for (var i = 0; i < instruments.length; i++) { | ||
@@ -117,0 +117,0 @@ if (i !== instruments[i]) { |
@@ -1,14 +0,27 @@ | ||
import { INoteSequence } from '../protobuf/index'; | ||
export declare class Player { | ||
import { INoteSequence, NoteSequence } from '../protobuf/index'; | ||
export declare abstract class BasePlayer { | ||
private currentPart; | ||
private scheduledStop; | ||
private synths; | ||
private drumKit; | ||
static readonly tone: any; | ||
protected abstract playNote(time: number, note: NoteSequence.INote): void; | ||
constructor(); | ||
start(seq: INoteSequence, qpm?: number): Promise<void>; | ||
private playNote(time, note); | ||
private getSynth(instrument, program?); | ||
stop(): void; | ||
isPlaying(): boolean; | ||
} | ||
export declare class Player extends BasePlayer { | ||
private synths; | ||
private drumKit; | ||
static readonly tone: any; | ||
protected playNote(time: number, note: NoteSequence.INote): void; | ||
private getSynth(instrument, program?); | ||
} | ||
export declare class SoundFontPlayer extends BasePlayer { | ||
private soundFont; | ||
private output; | ||
private programOutputs; | ||
private drumOutputs; | ||
constructor(soundFontURL: string, output?: any, programOutputs?: Map<number, any>, drumOutputs?: Map<number, any>); | ||
loadSamples(seq: INoteSequence): Promise<void>; | ||
start(seq: INoteSequence, qpm?: number): Promise<void>; | ||
protected playNote(time: number, note: NoteSequence.INote): void; | ||
} |
"use strict"; | ||
var __extends = (this && this.__extends) || (function () { | ||
var extendStatics = Object.setPrototypeOf || | ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || | ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; | ||
return function (d, b) { | ||
extendStatics(d, b); | ||
function __() { this.constructor = d; } | ||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); | ||
}; | ||
})(); | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
var __generator = (this && this.__generator) || function (thisArg, body) { | ||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; | ||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; | ||
function verb(n) { return function (v) { return step([n, v]); }; } | ||
function step(op) { | ||
if (f) throw new TypeError("Generator is already executing."); | ||
while (_) try { | ||
if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t; | ||
if (y = 0, t) op = [0, t.value]; | ||
switch (op[0]) { | ||
case 0: case 1: t = op; break; | ||
case 4: _.label++; return { value: op[1], done: false }; | ||
case 5: _.label++; y = op[1]; op = [0]; continue; | ||
case 7: op = _.ops.pop(); _.trys.pop(); continue; | ||
default: | ||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } | ||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } | ||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } | ||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } | ||
if (t[2]) _.ops.pop(); | ||
_.trys.pop(); continue; | ||
} | ||
op = body.call(thisArg, _); | ||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } | ||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; | ||
} | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -7,2 +52,41 @@ var Tone = require("tone"); | ||
var data_1 = require("./data"); | ||
var soundfont = require("./soundfont"); | ||
var BasePlayer = (function () { | ||
function BasePlayer() { | ||
Tone.Transport.bpm.value = 60; | ||
} | ||
BasePlayer.prototype.start = function (seq, qpm) { | ||
var _this = this; | ||
if (_1.sequences.isQuantizedSequence(seq)) { | ||
seq = _1.sequences.unquantizeSequence(seq, qpm); | ||
} | ||
else if (qpm) { | ||
throw new Error('Cannot specify a `qpm` for a non-quantized sequence.'); | ||
} | ||
this.currentPart = new Tone.Part(function (t, n) { return _this.playNote(t, n); }, seq.notes.map(function (n) { return [n.startTime, n]; })); | ||
this.currentPart.start(); | ||
if (Tone.Transport.state !== 'started') { | ||
Tone.Transport.start(); | ||
} | ||
return new Promise(function (resolve) { | ||
_this.scheduledStop = Tone.Transport.schedule(function () { | ||
_this.stop(); | ||
resolve(); | ||
}, "+" + seq.totalTime); | ||
}); | ||
}; | ||
BasePlayer.prototype.stop = function () { | ||
if (this.currentPart) { | ||
this.currentPart.stop(); | ||
this.currentPart = null; | ||
} | ||
Tone.Transport.clear(this.scheduledStop); | ||
this.scheduledStop = null; | ||
}; | ||
BasePlayer.prototype.isPlaying = function () { | ||
return !!this.currentPart; | ||
}; | ||
return BasePlayer; | ||
}()); | ||
exports.BasePlayer = BasePlayer; | ||
var DrumKit = (function () { | ||
@@ -99,28 +183,10 @@ function DrumKit() { | ||
}()); | ||
var Player = (function () { | ||
var Player = (function (_super) { | ||
__extends(Player, _super); | ||
function Player() { | ||
this.synths = new Map(); | ||
this.drumKit = DrumKit.getInstance(); | ||
Tone.Transport.bpm.value = 60; | ||
var _this = _super !== null && _super.apply(this, arguments) || this; | ||
_this.synths = new Map(); | ||
_this.drumKit = DrumKit.getInstance(); | ||
return _this; | ||
} | ||
Player.prototype.start = function (seq, qpm) { | ||
var _this = this; | ||
if (_1.sequences.isQuantizedSequence(seq)) { | ||
seq = _1.sequences.unquantizeSequence(seq, qpm); | ||
} | ||
else if (qpm) { | ||
throw new Error('Cannot specify a `qpm` for a non-quantized sequence.'); | ||
} | ||
this.currentPart = new Tone.Part(function (t, n) { return _this.playNote(t, n); }, seq.notes.map(function (n) { return [n.startTime, n]; })); | ||
this.currentPart.start(); | ||
if (Tone.Transport.state !== 'started') { | ||
Tone.Transport.start(); | ||
} | ||
return new Promise(function (resolve) { | ||
_this.scheduledStop = Tone.Transport.schedule(function () { | ||
_this.stop(); | ||
resolve(); | ||
}, "+" + seq.totalTime); | ||
}); | ||
}; | ||
Player.prototype.playNote = function (time, note) { | ||
@@ -151,17 +217,55 @@ if (note.isDrum) { | ||
}; | ||
Player.prototype.stop = function () { | ||
if (this.currentPart) { | ||
this.currentPart.stop(); | ||
this.currentPart = null; | ||
} | ||
Tone.Transport.clear(this.scheduledStop); | ||
this.scheduledStop = null; | ||
}; | ||
Player.prototype.isPlaying = function () { | ||
return !!this.currentPart; | ||
}; | ||
Player.tone = Tone; | ||
return Player; | ||
}()); | ||
}(BasePlayer)); | ||
exports.Player = Player; | ||
var SoundFontPlayer = (function (_super) { | ||
__extends(SoundFontPlayer, _super); | ||
function SoundFontPlayer(soundFontURL, output, programOutputs, drumOutputs) { | ||
if (output === void 0) { output = Tone.Master; } | ||
var _this = _super.call(this) || this; | ||
_this.soundFont = new soundfont.SoundFont(soundFontURL); | ||
_this.output = output; | ||
_this.programOutputs = programOutputs; | ||
_this.drumOutputs = drumOutputs; | ||
return _this; | ||
} | ||
SoundFontPlayer.prototype.loadSamples = function (seq) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4, this.soundFont.loadSamples(seq.notes.map(function (note) { return ({ | ||
pitch: note.pitch, | ||
velocity: note.velocity, | ||
program: note.program, | ||
isDrum: note.isDrum | ||
}); }))]; | ||
case 1: | ||
_a.sent(); | ||
return [2]; | ||
} | ||
}); | ||
}); | ||
}; | ||
SoundFontPlayer.prototype.start = function (seq, qpm) { | ||
var _this = this; | ||
return this.loadSamples(seq).then(function () { return _super.prototype.start.call(_this, seq, qpm); }); | ||
}; | ||
SoundFontPlayer.prototype.playNote = function (time, note) { | ||
var output = this.output; | ||
if (this.programOutputs && !note.isDrum) { | ||
if (this.programOutputs.has(note.program)) { | ||
output = this.programOutputs.get(note.program); | ||
} | ||
} | ||
else if (this.drumOutputs && note.isDrum) { | ||
if (this.drumOutputs.has(note.pitch)) { | ||
output = this.drumOutputs.get(note.pitch); | ||
} | ||
} | ||
this.soundFont.playNote(note.pitch, note.velocity, time, note.endTime - note.startTime, note.program, note.isDrum, output); | ||
}; | ||
return SoundFontPlayer; | ||
}(BasePlayer)); | ||
exports.SoundFontPlayer = SoundFontPlayer; | ||
//# sourceMappingURL=player.js.map |
@@ -307,5 +307,5 @@ "use strict"; | ||
expected.notes[1].instrument = 0; | ||
expected.notes[2].instrument = 9; | ||
expected.notes[2].instrument = 2; | ||
expected.notes[3].instrument = 1; | ||
expected.notes[4].instrument = 9; | ||
expected.notes[4].instrument = 2; | ||
expected.notes[4].program = 0; | ||
@@ -312,0 +312,0 @@ t.deepEqual(index_1.NoteSequence.toObject(sequences.mergeInstruments(ns)), index_1.NoteSequence.toObject(expected)); |
@@ -261,7 +261,6 @@ "use strict"; | ||
e.program = 0; | ||
e.instrument = 9; | ||
e.instrument = programs.length; | ||
} | ||
else { | ||
var index = programs.indexOf(e.program); | ||
e.instrument = (index >= 9) ? index + 1 : index; | ||
e.instrument = programs.indexOf(e.program); | ||
} | ||
@@ -268,0 +267,0 @@ }); |
@@ -47,3 +47,3 @@ import * as tf from '@tensorflow/tfjs-core'; | ||
isInitialized(): boolean; | ||
interpolate(inputSequences: INoteSequence[], numInterps: number, temperature?: number, chordProgression?: string[]): Promise<INoteSequence[]>; | ||
interpolate(inputSequences: INoteSequence[], numInterps: number | number[], temperature?: number, chordProgression?: string[]): Promise<INoteSequence[]>; | ||
private getSegmentLengths(inputTensors); | ||
@@ -50,0 +50,0 @@ private encodeChordProgression(chordProgression); |
@@ -627,7 +627,15 @@ "use strict"; | ||
MusicVAE.prototype.getInterpolatedZs = function (z, numInterps) { | ||
if (typeof numInterps === 'number') { | ||
numInterps = [numInterps]; | ||
} | ||
if (z.shape[0] !== 2 && z.shape[0] !== 4) { | ||
throw new Error('Invalid number of input sequences. Requires length 2, or 4'); | ||
} | ||
if (numInterps.length !== 1 && numInterps.length !== 2) { | ||
throw new Error('Invalid number of dimensions. Requires length 1, or 2.'); | ||
} | ||
var w = numInterps[0]; | ||
var h = numInterps.length === 2 ? numInterps[1] : w; | ||
var interpolatedZs = tf.tidy(function () { | ||
var rangeArray = tf.linspace(0.0, 1.0, numInterps); | ||
var rangeX = tf.linspace(0.0, 1.0, w); | ||
var z0 = z.slice([0, 0], [1, z.shape[1]]).as1D(); | ||
@@ -637,14 +645,15 @@ var z1 = z.slice([1, 0], [1, z.shape[1]]).as1D(); | ||
var zDiff = z1.sub(z0); | ||
return tf.outerProduct(rangeArray, zDiff).add(z0); | ||
return tf.outerProduct(rangeX, zDiff).add(z0); | ||
} | ||
else if (z.shape[0] === 4) { | ||
var rangeY = tf.linspace(0.0, 1.0, h); | ||
var z2 = z.slice([2, 0], [1, z.shape[1]]).as1D(); | ||
var z3 = z.slice([3, 0], [1, z.shape[1]]).as1D(); | ||
var revRangeArray = tf.scalar(1.0).sub(rangeArray); | ||
var r = numInterps; | ||
var finalZs = z0.mul(tf.outerProduct(revRangeArray, revRangeArray).as3D(r, r, 1)); | ||
finalZs = tf.addStrict(finalZs, z1.mul(tf.outerProduct(rangeArray, revRangeArray).as3D(r, r, 1))); | ||
finalZs = tf.addStrict(finalZs, z2.mul(tf.outerProduct(revRangeArray, rangeArray).as3D(r, r, 1))); | ||
finalZs = tf.addStrict(finalZs, z3.mul(tf.outerProduct(rangeArray, rangeArray).as3D(r, r, 1))); | ||
return finalZs.as2D(r * r, z.shape[1]); | ||
var revRangeX = tf.scalar(1.0).sub(rangeX); | ||
var revRangeY = tf.scalar(1.0).sub(rangeY); | ||
var finalZs = z0.mul(tf.outerProduct(revRangeY, revRangeX).as3D(h, w, 1)); | ||
finalZs = tf.addStrict(finalZs, z1.mul(tf.outerProduct(rangeY, revRangeX).as3D(h, w, 1))); | ||
finalZs = tf.addStrict(finalZs, z2.mul(tf.outerProduct(revRangeY, rangeX).as3D(h, w, 1))); | ||
finalZs = tf.addStrict(finalZs, z3.mul(tf.outerProduct(rangeY, rangeX).as3D(h, w, 1))); | ||
return finalZs.as2D(w * h, z.shape[1]); | ||
} | ||
@@ -651,0 +660,0 @@ else { |
{ | ||
"name": "@magenta/music", | ||
"version": "1.0.3", | ||
"version": "1.1.1", | ||
"description": "Make music in the browser with machine learning.", | ||
@@ -11,3 +11,3 @@ "main": "es5/index.js", | ||
"@tensorflow/tfjs-core": "^0.8.5", | ||
"midiconvert": "^0.4.5", | ||
"midiconvert": "^0.4.7", | ||
"protobufjs": "^6.8.6", | ||
@@ -14,0 +14,0 @@ "tonal": "^1.1.3", |
@@ -56,4 +56,3 @@ # @magenta/music | ||
const model = new mm.MusicVAE( | ||
'https://storage.googleapis.com/download.magenta.tensorflow.org' + | ||
'/tfjs_checkpoints/music_vae/trio_4bar'); | ||
'https://storage.googleapis.com/magentadata/js/checkpoints/music_vae/trio_4bar'); | ||
const player = new mm.Player(); | ||
@@ -74,4 +73,5 @@ | ||
and the code will run. Click the "Play Trio" button to hear 4-bar trios that are randomly generated by MusicVAE. | ||
If you find one you like, you can download the MIDI. | ||
It's also easy to add the ability to download MIDI for generated outputs, which is demonstrated in [this example](https://goo.gl/magenta/simpletriodl). | ||
See the [Neural Drum Machine](https://codepen.io/teropa/pen/RMGxOQ) by [@teropa](https://github.com/teropa) for a complete example application with code. | ||
@@ -78,0 +78,0 @@ |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Native code
Supply chain riskContains native code (e.g., compiled binaries or shared libraries). Including native code can obscure malicious behavior.
Found 1 instance in 1 package
2826720
62611
7
Updatedmidiconvert@^0.4.7