Skip to content

Commit

Permalink
Move data.ts to core, cleanup, and fixes. (magenta#4)
Browse files Browse the repository at this point in the history
* v0.0.10

* Clean up and improve consistency across libs.

* udpate ignore

* udpate ignore

* v0.0.11

* v0.0.12

* v0.0.13

* Move data.ts to core, cleanup, and fixes.

* Fix indent

* re-add yarn.lock

* Switch to tfjs and move to core.

* fix |

* add util dep
  • Loading branch information
adarob authored Mar 30, 2018
1 parent 835206c commit c1bc3dd
Show file tree
Hide file tree
Showing 22 changed files with 3,934 additions and 645 deletions.
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,6 @@
"editor.detectIndentation": false,
"editor.wrappingIndent": "none",
"typescript.tsdk": "node_modules/typescript/lib",
"clang-format.executable": "${workspaceRoot}/node_modules/.bin/clang-format"
"clang-format.executable": "${workspaceRoot}/node_modules/.bin/clang-format",
"git.ignoreLimitWarning": true
}
6 changes: 4 additions & 2 deletions core/package.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
{
"name": "@magenta/core",
"version": "0.0.9",
"version": "0.0.13",
"description": "",
"main": "es5/index.js",
"types": "es5/index.d.ts",
"jsdelivr": "dist/magenta.js",
"unpkg": "dist/magenta.js",
"dependencies": {
"@magenta/protobuf": "^0.0.4",
"midiconvert": "^0.4.3"
"@tensorflow/tfjs": "^0.6.1",
"midiconvert": "^0.4.3",
"util": "^0.10.3"
},
"devDependencies": {
"@types/tape": "^4.2.31",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
* =============================================================================
*/
// Adds quantization support to dl.CheckpointLoader.
import {Tensor} from 'deeplearn';
import {Tensor} from '@tensorflow/tfjs';

/**
* @hidden
Expand Down
43 changes: 23 additions & 20 deletions music_vae/data.ts → core/src/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@
* limitations under the License.
* =============================================================================
*/
import * as dl from 'deeplearn';
import {INoteSequence, NoteSequence} from '@magenta/core';

export {INoteSequence};
import * as tf from '@tensorflow/tfjs';
import {tensorflow} from '@magenta/protobuf';
import NoteSequence = tensorflow.magenta.NoteSequence;
import INoteSequence = tensorflow.magenta.INoteSequence;

const DEFAULT_DRUM_PITCH_CLASSES: number[][] = [
// bass drum
Expand Down Expand Up @@ -80,8 +80,8 @@ export abstract class DataConverter {
abstract numSteps: number; // Total length of sequences.
abstract numSegments: number; // Number of steps for conductor.
abstract readonly NUM_SPLITS: number; // Number of conductor splits.
abstract toTensor(noteSequence: INoteSequence): dl.Tensor2D;
abstract toNoteSequence(tensor: dl.Tensor2D): Promise<INoteSequence>;
abstract toTensor(noteSequence: INoteSequence): tf.Tensor2D;
abstract async toNoteSequence(tensor: tf.Tensor2D): Promise<INoteSequence>;
}

/**
Expand Down Expand Up @@ -134,19 +134,20 @@ export class DrumsConverter extends DataConverter{
}

toTensor(noteSequence: INoteSequence) {
const drumRoll = dl.buffer([this.numSteps, this.pitchClasses.length + 1]);
const numSteps = this.numSteps || noteSequence.totalQuantizedSteps;
const drumRoll = tf.buffer([numSteps, this.pitchClasses.length + 1]);
// Set final values to 1 and change to 0 later if the column gets a note.
for (let i = 0; i < this.numSteps; ++i) {
for (let i = 0; i < numSteps; ++i) {
drumRoll.set(1, i, -1);
}
noteSequence.notes.forEach((note) => {
drumRoll.set(1, note.quantizedStartStep, this.pitchToClass[note.pitch]);
drumRoll.set(0, note.quantizedStartStep, -1);
});
return drumRoll.toTensor() as dl.Tensor2D;
return drumRoll.toTensor() as tf.Tensor2D;
}

async toNoteSequence(oh: dl.Tensor2D) {
async toNoteSequence(oh: tf.Tensor2D) {
const noteSequence = NoteSequence.create();
const labelsTensor = oh.argMax(1);
const labels: Int32Array = await labelsTensor.data() as Int32Array;
Expand Down Expand Up @@ -180,7 +181,7 @@ export class DrumsConverter extends DataConverter{
* pitch class are used.
*/
export class DrumRollConverter extends DrumsConverter {
async toNoteSequence(roll: dl.Tensor2D) {
async toNoteSequence(roll: tf.Tensor2D) {
const noteSequence = NoteSequence.create();
for (let s = 0; s < roll.shape[0]; ++s) { // step
const rollSlice = roll.slice([s, 0], [1, roll.shape[1]]);
Expand Down Expand Up @@ -236,41 +237,43 @@ export class MelodyConverter extends DataConverter{
minPitch: number; // inclusive
maxPitch: number; // inclusive
depth: number;
NUM_SPLITS = 0;
NOTE_OFF = 1;
FIRST_PITCH = 2;
readonly NUM_SPLITS = 0;
readonly NOTE_OFF = 1;
readonly FIRST_PITCH = 2;

constructor(args: MelodyConverterArgs) {
super();
this.numSteps = args.numSteps;
this.numSegments = args.numSegments;
this.minPitch = args.minPitch;
this.maxPitch = args.maxPitch;
this.depth = args.maxPitch - args.minPitch + 3;
this.depth = args.maxPitch - args.minPitch + 1 + this.FIRST_PITCH;
}

toTensor(noteSequence: INoteSequence) {
const numSteps = this.numSteps || noteSequence.totalQuantizedSteps;
const sortedNotes: NoteSequence.INote[] = noteSequence.notes.sort(
(n1, n2) => n1.quantizedStartStep - n2.quantizedStartStep);
const mel = dl.buffer([this.numSteps]);
const mel = tf.buffer([numSteps]);
let lastEnd = -1;
sortedNotes.forEach(n => {
if (n.quantizedStartStep < lastEnd) {
throw new Error('`NoteSequence` is not monophonic.');
}
if (n.pitch < this.minPitch || n.pitch > this.maxPitch) {
throw Error(
'`NoteSequence` has a pitch outside of the valid range: ' + n.pitch);
`\`NoteSequence\` has a pitch outside of the valid range: ${n.pitch}`
);
}
mel.set(n.pitch - this.minPitch + this.FIRST_PITCH, n.quantizedStartStep);
mel.set(this.NOTE_OFF, n.quantizedEndStep);
lastEnd = n.quantizedEndStep;
});
return dl.oneHot(
mel.toTensor() as dl.Tensor1D, this.depth) as dl.Tensor2D;
return tf.oneHot(
mel.toTensor() as tf.Tensor1D, this.depth) as tf.Tensor2D;
}

async toNoteSequence(oh: dl.Tensor2D) {
async toNoteSequence(oh: tf.Tensor2D) {
const noteSequence = NoteSequence.create();
const labelsTensor = oh.argMax(1);
const labels: Int32Array = await labelsTensor.data() as Int32Array;
Expand Down
8 changes: 8 additions & 0 deletions core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,13 @@ import INote = NoteSequence.INote;

export {NoteSequence, INoteSequence, INote};

import * as tf from '@tensorflow/tfjs';
export {tf};

export { CheckpointLoader } from './checkpoint_loader';

import * as data from './data';
export {data};

export * from './midi_io';
export * from './sequences';
2 changes: 1 addition & 1 deletion core/src/midi_io_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import {MidiIO} from './midi_io';
import fs = require('fs');

test("Parse Simple MIDI", (t:test.Test) => {
const midi = fs.readFileSync('../../music/testdata/melody.mid', "binary");
const midi = fs.readFileSync('../testdata/melody.mid', "binary");
const ns = MidiIO.midiToSequenceProto(midi);

const expectedNs = NoteSequence.create({
Expand Down
Loading

0 comments on commit c1bc3dd

Please sign in to comment.