ableton-js 3.6.0 → 3.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +15 -0
- package/midi-script/Clip.py +34 -0
- package/midi-script/Session.py +2 -2
- package/midi-script/Socket.py +27 -8
- package/midi-script/Track.py +5 -1
- package/midi-script/version.py +1 -1
- package/ns/clip.d.ts +16 -1
- package/ns/clip.js +28 -2
- package/ns/track.d.ts +15 -1
- package/ns/track.js +25 -2
- package/package.json +3 -1
- package/util/note.d.ts +11 -0
package/CHANGELOG.md
CHANGED
|
@@ -4,8 +4,23 @@ All notable changes to this project will be documented in this file. Dates are d
|
|
|
4
4
|
|
|
5
5
|
Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
|
6
6
|
|
|
7
|
+
#### [v3.7.0](https://github.com/leolabs/ableton.js/compare/v3.6.1...v3.7.0)
|
|
8
|
+
|
|
9
|
+
- Add more clip and note operation features in Ableton Live 11 and above versions [`#133`](https://github.com/leolabs/ableton.js/pull/133)
|
|
10
|
+
- Add new functions and fix bugs [`#130`](https://github.com/leolabs/ableton.js/pull/130)
|
|
11
|
+
- adds ability to launch v12 via yarn [`#131`](https://github.com/leolabs/ableton.js/pull/131)
|
|
12
|
+
|
|
13
|
+
#### [v3.6.1](https://github.com/leolabs/ableton.js/compare/v3.6.0...v3.6.1)
|
|
14
|
+
|
|
15
|
+
> 12 March 2025
|
|
16
|
+
|
|
17
|
+
- :bug: Fix zlib expecting a string on Python 2 (Live 10) [`8480ab4`](https://github.com/leolabs/ableton.js/commit/8480ab4a5b6c253a905e1ba61de53d6728c68411)
|
|
18
|
+
- :bug: Fix ableton-js not working with Live 10 anymore, due to syntax that Python 2 doesn't support [`04ba830`](https://github.com/leolabs/ableton.js/commit/04ba8309a4b7912c022aa604a90fed47a7a56ed9)
|
|
19
|
+
|
|
7
20
|
#### [v3.6.0](https://github.com/leolabs/ableton.js/compare/v3.5.0...v3.6.0)
|
|
8
21
|
|
|
22
|
+
> 16 January 2025
|
|
23
|
+
|
|
9
24
|
- :label: Mark all raw object state as readonly [`ace0efd`](https://github.com/leolabs/ableton.js/commit/ace0efde39e5b598dd0a2878e0e29ecffedd495a)
|
|
10
25
|
- :sparkles: Add options to override the caching mechanism [`85405d4`](https://github.com/leolabs/ableton.js/commit/85405d4be89bdc052f53bb862c5fe904620c554a)
|
|
11
26
|
|
package/midi-script/Clip.py
CHANGED
|
@@ -27,6 +27,39 @@ class Clip(Interface):
|
|
|
27
27
|
def get_notes(self, ns, from_time=0, from_pitch=0, time_span=99999999999999, pitch_span=128):
|
|
28
28
|
return ns.get_notes(from_time, from_pitch, time_span, pitch_span)
|
|
29
29
|
|
|
30
|
+
def get_notes_extended(self, ns, from_time=0, from_pitch=0, time_span=99999999999999, pitch_span=128):
|
|
31
|
+
midi_note_vector = ns.get_notes_extended(from_pitch, pitch_span, from_time, time_span)
|
|
32
|
+
return [
|
|
33
|
+
{
|
|
34
|
+
"duration": note.duration,
|
|
35
|
+
"mute": note.mute,
|
|
36
|
+
"note_id": note.note_id,
|
|
37
|
+
"pitch": note.pitch,
|
|
38
|
+
"probability": note.probability,
|
|
39
|
+
"release_velocity": note.release_velocity,
|
|
40
|
+
"start_time": note.start_time,
|
|
41
|
+
"velocity": note.velocity,
|
|
42
|
+
"velocity_deviation": note.velocity_deviation
|
|
43
|
+
}
|
|
44
|
+
for note in midi_note_vector
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
def apply_note_modifications(self, ns, notes):
|
|
48
|
+
existing_notes = ns.get_notes_extended(0, 128, 0, 99999999999999)
|
|
49
|
+
existing_notes_map = {note.note_id: note for note in existing_notes}
|
|
50
|
+
|
|
51
|
+
for modified_note_data in notes:
|
|
52
|
+
note_id = modified_note_data.get("note_id")
|
|
53
|
+
if note_id is None:
|
|
54
|
+
raise ValueError("The note_id parameter is required to modify the note.")
|
|
55
|
+
if note_id in existing_notes_map:
|
|
56
|
+
note_to_update = existing_notes_map[note_id]
|
|
57
|
+
for key, value in modified_note_data.items():
|
|
58
|
+
if key != "note_id" and hasattr(note_to_update, key):
|
|
59
|
+
setattr(note_to_update, key, value)
|
|
60
|
+
|
|
61
|
+
return ns.apply_note_modifications(existing_notes)
|
|
62
|
+
|
|
30
63
|
def get_warp_markers(self, ns):
|
|
31
64
|
dict_markers = []
|
|
32
65
|
for warp_marker in ns.warp_markers:
|
|
@@ -41,3 +74,4 @@ class Clip(Interface):
|
|
|
41
74
|
|
|
42
75
|
def replace_selected_notes(self, ns, notes):
|
|
43
76
|
return ns.replace_selected_notes(tuple(notes))
|
|
77
|
+
|
package/midi-script/Session.py
CHANGED
|
@@ -21,7 +21,7 @@ class Session(Interface):
|
|
|
21
21
|
"""
|
|
22
22
|
with self.controlSurface.component_guard():
|
|
23
23
|
logger.info(
|
|
24
|
-
|
|
24
|
+
"Setting up session box with " + str(num_tracks) + " tracks and " + str(num_scenes) + " scenes.")
|
|
25
25
|
self.session = self.sessionComponent(num_tracks, num_scenes)
|
|
26
26
|
self.session.set_offsets(0, 0)
|
|
27
27
|
self.controlSurface.set_highlighting_session_component(
|
|
@@ -33,7 +33,7 @@ class Session(Interface):
|
|
|
33
33
|
Sets the offset of the SessionComponent instance.
|
|
34
34
|
"""
|
|
35
35
|
logger.info(
|
|
36
|
-
|
|
36
|
+
"Moving session box offset to " + str(track_offset) + " and " + scene_offset + ".")
|
|
37
37
|
|
|
38
38
|
if hasattr(self, 'session'):
|
|
39
39
|
self.session.set_offsets(track_offset, scene_offset)
|
package/midi-script/Socket.py
CHANGED
|
@@ -4,6 +4,7 @@ import struct
|
|
|
4
4
|
import zlib
|
|
5
5
|
import os
|
|
6
6
|
import tempfile
|
|
7
|
+
import sys
|
|
7
8
|
|
|
8
9
|
from .Logging import logger
|
|
9
10
|
|
|
@@ -87,7 +88,8 @@ class Socket(object):
|
|
|
87
88
|
if self._socket:
|
|
88
89
|
self.send("connect", {"port": self._server_addr[1]})
|
|
89
90
|
except Exception as e:
|
|
90
|
-
self.log_error_once(
|
|
91
|
+
self.log_error_once(
|
|
92
|
+
"Couldn't read remote port file: " + str(e.args))
|
|
91
93
|
|
|
92
94
|
def shutdown(self):
|
|
93
95
|
logger.info("Shutting down...")
|
|
@@ -125,13 +127,15 @@ class Socket(object):
|
|
|
125
127
|
with open(server_port_path, "w") as file:
|
|
126
128
|
file.write(str(port))
|
|
127
129
|
except Exception as e:
|
|
128
|
-
self.log_error_once(
|
|
130
|
+
self.log_error_once(
|
|
131
|
+
"Couldn't save port in file: " + str(e.args))
|
|
129
132
|
raise e
|
|
130
133
|
|
|
131
134
|
try:
|
|
132
135
|
self.send("connect", {"port": self._server_addr[1]})
|
|
133
136
|
except Exception as e:
|
|
134
|
-
logger.error("Couldn't send connect to " +
|
|
137
|
+
logger.error("Couldn't send connect to " +
|
|
138
|
+
str(self._client_addr) + ":")
|
|
135
139
|
logger.exception(e)
|
|
136
140
|
|
|
137
141
|
self.show_message("Started server on port " + str(port))
|
|
@@ -143,7 +147,8 @@ class Socket(object):
|
|
|
143
147
|
str(self._server_addr) + ': ' + \
|
|
144
148
|
str(e.args) + ', trying again. ' + \
|
|
145
149
|
'If this keeps happening, try restarting your computer.'
|
|
146
|
-
self.log_error_once(
|
|
150
|
+
self.log_error_once(
|
|
151
|
+
msg + " (Client address: " + str(self._client_addr) + ")")
|
|
147
152
|
self.show_message(msg)
|
|
148
153
|
t = Live.Base.Timer(
|
|
149
154
|
callback=self.init_socket, interval=5000, repeat=False)
|
|
@@ -160,15 +165,18 @@ class Socket(object):
|
|
|
160
165
|
message_id_byte = struct.pack("B", self._message_id)
|
|
161
166
|
|
|
162
167
|
if len(compressed) < self._chunk_limit:
|
|
163
|
-
self._socket.sendto(
|
|
168
|
+
self._socket.sendto(
|
|
169
|
+
message_id_byte + b'\x00\x01' + compressed, self._client_addr)
|
|
164
170
|
else:
|
|
165
171
|
chunks = list(split_by_n(compressed, self._chunk_limit))
|
|
166
172
|
count = len(chunks)
|
|
167
173
|
count_byte = struct.pack("B", count)
|
|
168
174
|
for i, chunk in enumerate(chunks):
|
|
169
|
-
logger.info("Sending packet " + str(self._message_id) +
|
|
175
|
+
logger.info("Sending packet " + str(self._message_id) +
|
|
176
|
+
" - " + str(i) + "/" + str(count))
|
|
170
177
|
packet_byte = struct.pack("B", i)
|
|
171
|
-
self._socket.sendto(
|
|
178
|
+
self._socket.sendto(
|
|
179
|
+
message_id_byte + packet_byte + count_byte + chunk, self._client_addr)
|
|
172
180
|
|
|
173
181
|
def send(self, name, obj=None, uuid=None):
|
|
174
182
|
def jsonReplace(o):
|
|
@@ -188,7 +196,8 @@ class Socket(object):
|
|
|
188
196
|
except socket.error as e:
|
|
189
197
|
logger.error("Socket error:")
|
|
190
198
|
logger.exception(e)
|
|
191
|
-
logger.error("Server: " + str(self._server_addr) + ", client: " +
|
|
199
|
+
logger.error("Server: " + str(self._server_addr) + ", client: " +
|
|
200
|
+
str(self._client_addr) + ", socket: " + str(self._socket))
|
|
192
201
|
logger.error("Data:" + data)
|
|
193
202
|
except Exception as e:
|
|
194
203
|
logger.error("Error " + name + "(" + str(uuid) + "):")
|
|
@@ -205,7 +214,17 @@ class Socket(object):
|
|
|
205
214
|
if (data[0] == b'\xFF' or data[0] == 255):
|
|
206
215
|
packet = self._receive_buffer
|
|
207
216
|
self._receive_buffer = bytearray()
|
|
217
|
+
|
|
218
|
+
# Handle Python 2/3 compatibility for zlib.decompress
|
|
219
|
+
if sys.version_info[0] < 3:
|
|
220
|
+
packet = str(packet)
|
|
221
|
+
|
|
208
222
|
unzipped = zlib.decompress(packet)
|
|
223
|
+
|
|
224
|
+
# Handle bytes to string conversion for Python 3
|
|
225
|
+
if sys.version_info[0] >= 3 and isinstance(unzipped, bytes):
|
|
226
|
+
unzipped = unzipped.decode('utf-8')
|
|
227
|
+
|
|
209
228
|
payload = json.loads(unzipped)
|
|
210
229
|
self.input_handler(payload)
|
|
211
230
|
|
package/midi-script/Track.py
CHANGED
|
@@ -78,4 +78,8 @@ class Track(Interface):
|
|
|
78
78
|
return MixerDevice.serialize_mixer_device(ns.mixer_device)
|
|
79
79
|
|
|
80
80
|
def duplicate_clip_to_arrangement(self, ns, clip_id, time):
|
|
81
|
-
|
|
81
|
+
clip = ns.duplicate_clip_to_arrangement(self.get_obj(clip_id), time)
|
|
82
|
+
return Clip.serialize_clip(clip)
|
|
83
|
+
|
|
84
|
+
def delete_clip(self, ns, clip_id):
|
|
85
|
+
return ns.delete_clip(self.get_obj(clip_id))
|
package/midi-script/version.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
version = "3.
|
|
1
|
+
version = "3.7.0"
|
package/ns/clip.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { Ableton } from "..";
|
|
|
2
2
|
import { Namespace } from ".";
|
|
3
3
|
import { Color } from "../util/color";
|
|
4
4
|
import { DeviceParameter } from "./device-parameter";
|
|
5
|
-
import { Note, NoteTuple } from "../util/note";
|
|
5
|
+
import { Note, NoteExtended, NoteTuple } from "../util/note";
|
|
6
6
|
export declare enum WarpMode {
|
|
7
7
|
Beats = 0,
|
|
8
8
|
Tones = 1,
|
|
@@ -201,8 +201,18 @@ export declare class Clip extends Namespace<GettableProperties, TransformedPrope
|
|
|
201
201
|
fire(): Promise<void>;
|
|
202
202
|
/**
|
|
203
203
|
* Returns all notes that match the given range.
|
|
204
|
+
* @deprecated starting with Live 11, use `getNotesExtended` instead
|
|
204
205
|
*/
|
|
205
206
|
getNotes(fromTime: number, fromPitch: number, timeSpan: number, pitchSpan: number): Promise<Note[]>;
|
|
207
|
+
/**
|
|
208
|
+
* Returns all notes matching the given range with extended properties.
|
|
209
|
+
* Compared to getNotes, this method returns additional note information.
|
|
210
|
+
*/
|
|
211
|
+
getNotesExtended(fromTime: number, fromPitch: number, timeSpan: number, pitchSpan: number): Promise<NoteExtended[]>;
|
|
212
|
+
/**
|
|
213
|
+
* Available since Live 11.0. Replaces modifying notes with remove_notes followed by set_notes.
|
|
214
|
+
*/
|
|
215
|
+
applyNoteModifications(notes: NoteExtended[]): Promise<any>;
|
|
206
216
|
/**
|
|
207
217
|
* Jump forward or backward by the specified relative amount in beats.
|
|
208
218
|
* Will do nothing if the clip is not playing.
|
|
@@ -226,6 +236,11 @@ export declare class Clip extends Namespace<GettableProperties, TransformedPrope
|
|
|
226
236
|
* Deletes all notes that start in the given area.
|
|
227
237
|
*/
|
|
228
238
|
removeNotesExtended(fromTime: number, fromPitch: number, timeSpan: number, pitchSpan: number): Promise<any>;
|
|
239
|
+
/**
|
|
240
|
+
* Remove notes by given note ids.
|
|
241
|
+
* Available since Live 11.0.
|
|
242
|
+
*/
|
|
243
|
+
removeNotesById(ids: number[]): Promise<any>;
|
|
229
244
|
/**
|
|
230
245
|
* Replaces selected notes with an array of new notes.
|
|
231
246
|
*/
|
package/ns/clip.js
CHANGED
|
@@ -124,6 +124,7 @@ class Clip extends _1.Namespace {
|
|
|
124
124
|
}
|
|
125
125
|
/**
|
|
126
126
|
* Returns all notes that match the given range.
|
|
127
|
+
* @deprecated starting with Live 11, use `getNotesExtended` instead
|
|
127
128
|
*/
|
|
128
129
|
async getNotes(fromTime, fromPitch, timeSpan, pitchSpan) {
|
|
129
130
|
const notes = await this.sendCommand("get_notes", {
|
|
@@ -134,6 +135,24 @@ class Clip extends _1.Namespace {
|
|
|
134
135
|
});
|
|
135
136
|
return notes.map(note_1.tupleToNote);
|
|
136
137
|
}
|
|
138
|
+
/**
|
|
139
|
+
* Returns all notes matching the given range with extended properties.
|
|
140
|
+
* Compared to getNotes, this method returns additional note information.
|
|
141
|
+
*/
|
|
142
|
+
async getNotesExtended(fromTime, fromPitch, timeSpan, pitchSpan) {
|
|
143
|
+
return this.sendCommand("get_notes_extended", {
|
|
144
|
+
from_pitch: fromPitch,
|
|
145
|
+
pitch_span: pitchSpan,
|
|
146
|
+
from_time: fromTime,
|
|
147
|
+
time_span: timeSpan,
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Available since Live 11.0. Replaces modifying notes with remove_notes followed by set_notes.
|
|
152
|
+
*/
|
|
153
|
+
applyNoteModifications(notes) {
|
|
154
|
+
return this.sendCommand("apply_note_modifications", { notes });
|
|
155
|
+
}
|
|
137
156
|
/**
|
|
138
157
|
* Jump forward or backward by the specified relative amount in beats.
|
|
139
158
|
* Will do nothing if the clip is not playing.
|
|
@@ -171,12 +190,19 @@ class Clip extends _1.Namespace {
|
|
|
171
190
|
*/
|
|
172
191
|
removeNotesExtended(fromTime, fromPitch, timeSpan, pitchSpan) {
|
|
173
192
|
return this.sendCommand("remove_notes_extended", [
|
|
174
|
-
fromTime,
|
|
175
193
|
fromPitch,
|
|
176
|
-
timeSpan,
|
|
177
194
|
pitchSpan,
|
|
195
|
+
fromTime,
|
|
196
|
+
timeSpan,
|
|
178
197
|
]);
|
|
179
198
|
}
|
|
199
|
+
/**
|
|
200
|
+
* Remove notes by given note ids.
|
|
201
|
+
* Available since Live 11.0.
|
|
202
|
+
*/
|
|
203
|
+
removeNotesById(ids) {
|
|
204
|
+
return this.sendCommand("remove_notes_by_id", [ids]);
|
|
205
|
+
}
|
|
180
206
|
/**
|
|
181
207
|
* Replaces selected notes with an array of new notes.
|
|
182
208
|
*/
|
package/ns/track.d.ts
CHANGED
|
@@ -158,5 +158,19 @@ export declare class Track extends Namespace<GettableProperties, TransformedProp
|
|
|
158
158
|
* Duplicates the given clip into the arrangement of this track at the provided destination time and returns it.
|
|
159
159
|
* When the type of the clip and the type of the track are incompatible, a runtime error is raised.
|
|
160
160
|
*/
|
|
161
|
-
duplicateClipToArrangement(clipOrId: Clip | string, time: number): Promise<
|
|
161
|
+
duplicateClipToArrangement(clipOrId: Clip | string, time: number): Promise<Clip>;
|
|
162
|
+
/**
|
|
163
|
+
* Deletes the given clip from the arrangement of this track.
|
|
164
|
+
* Raises a runtime error when the clip belongs to another track
|
|
165
|
+
*/
|
|
166
|
+
deleteClip(clipOrId: Clip | string): Promise<any>;
|
|
167
|
+
/**
|
|
168
|
+
* Delete a device identified by the index in the 'devices' list of current track
|
|
169
|
+
*/
|
|
170
|
+
deleteDevice(index: number): Promise<any>;
|
|
171
|
+
/**
|
|
172
|
+
* Given an absolute path to a valid audio file in a supported format, creates an audio clip that references the file in the clip slot.
|
|
173
|
+
* Throws an error if the clip slot doesn't belong to an audio track or if the track is frozen.
|
|
174
|
+
*/
|
|
175
|
+
createAudioClip(filePath: string, position: number): Promise<any>;
|
|
162
176
|
}
|
package/ns/track.js
CHANGED
|
@@ -48,11 +48,34 @@ class Track extends _1.Namespace {
|
|
|
48
48
|
* Duplicates the given clip into the arrangement of this track at the provided destination time and returns it.
|
|
49
49
|
* When the type of the clip and the type of the track are incompatible, a runtime error is raised.
|
|
50
50
|
*/
|
|
51
|
-
duplicateClipToArrangement(clipOrId, time) {
|
|
52
|
-
|
|
51
|
+
async duplicateClipToArrangement(clipOrId, time) {
|
|
52
|
+
const rawClip = await this.sendCommand("duplicate_clip_to_arrangement", {
|
|
53
53
|
clip_id: typeof clipOrId === "string" ? clipOrId : clipOrId.raw.id,
|
|
54
54
|
time: time,
|
|
55
55
|
});
|
|
56
|
+
return new clip_1.Clip(this.ableton, rawClip);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Deletes the given clip from the arrangement of this track.
|
|
60
|
+
* Raises a runtime error when the clip belongs to another track
|
|
61
|
+
*/
|
|
62
|
+
deleteClip(clipOrId) {
|
|
63
|
+
return this.sendCommand("delete_clip", {
|
|
64
|
+
clip_id: typeof clipOrId === "string" ? clipOrId : clipOrId.raw.id,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Delete a device identified by the index in the 'devices' list of current track
|
|
69
|
+
*/
|
|
70
|
+
deleteDevice(index) {
|
|
71
|
+
return this.sendCommand("delete_device", [index]);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Given an absolute path to a valid audio file in a supported format, creates an audio clip that references the file in the clip slot.
|
|
75
|
+
* Throws an error if the clip slot doesn't belong to an audio track or if the track is frozen.
|
|
76
|
+
*/
|
|
77
|
+
createAudioClip(filePath, position) {
|
|
78
|
+
return this.sendCommand("create_audio_clip", [filePath, position]);
|
|
56
79
|
}
|
|
57
80
|
}
|
|
58
81
|
exports.Track = Track;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ableton-js",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.7.0",
|
|
4
4
|
"description": "Control Ableton Live from Node",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"author": "Leo Bernard <admin@leolabs.org>",
|
|
@@ -19,10 +19,12 @@
|
|
|
19
19
|
"ableton:copy-script": "set -- ~/Music/Ableton/User\\ Library/Remote\\ Scripts && mkdir -p \"$1\" && rm -rf \"$1/AbletonJS\" && cp -r \"$(pwd)/midi-script\" \"$1/AbletonJS\" && rm -rf \"$1/AbletonJS/_Framework\"",
|
|
20
20
|
"ableton10:launch": "set -- /Applications/Ableton*10* && open \"$1\"",
|
|
21
21
|
"ableton11:launch": "set -- /Applications/Ableton*11* && open \"$1\"",
|
|
22
|
+
"ableton12:launch": "set -- /Applications/Ableton*12* && open \"$1\"",
|
|
22
23
|
"ableton:logs": "tail -n 50 -f ~/Library/Preferences/Ableton/*/Log.txt | grep --line-buffered -i -e AbletonJS",
|
|
23
24
|
"ableton:kill": "pkill -KILL -f \"Ableton Live\"",
|
|
24
25
|
"ableton10:start": "yarn ableton:kill; yarn ableton:clean && yarn ableton:copy-script && yarn ableton10:launch && yarn ableton:logs",
|
|
25
26
|
"ableton11:start": "yarn ableton:kill; yarn ableton:clean && yarn ableton:copy-script && yarn ableton11:launch && yarn ableton:logs",
|
|
27
|
+
"ableton12:start": "yarn ableton:kill; yarn ableton:clean && yarn ableton:copy-script && yarn ableton11:launch && yarn ableton:logs",
|
|
26
28
|
"prepublishOnly": "yarn build",
|
|
27
29
|
"build:doc": "jsdoc2md --files src/**/*.ts --configure ./jsdoc2md.json > ./API.md",
|
|
28
30
|
"version": "node hooks/prepublish.js && git add midi-script/version.py && auto-changelog -p -l 100 && git add CHANGELOG.md",
|
package/util/note.d.ts
CHANGED
|
@@ -12,5 +12,16 @@ export interface Note {
|
|
|
12
12
|
velocity: number;
|
|
13
13
|
muted: boolean;
|
|
14
14
|
}
|
|
15
|
+
export interface NoteExtended {
|
|
16
|
+
note_id: number;
|
|
17
|
+
duration: number;
|
|
18
|
+
mute: boolean;
|
|
19
|
+
pitch: number;
|
|
20
|
+
probability: number;
|
|
21
|
+
release_velocity: number;
|
|
22
|
+
start_time: number;
|
|
23
|
+
velocity: number;
|
|
24
|
+
velocity_deviation: number;
|
|
25
|
+
}
|
|
15
26
|
export declare const tupleToNote: (tuple: NoteTuple) => Note;
|
|
16
27
|
export declare const noteToTuple: (note: Note) => NoteTuple;
|