physicsLab 1.4.8__tar.gz → 1.4.9__tar.gz
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.
- {physicslab-1.4.8 → physicslab-1.4.9}/PKG-INFO +1 -1
- {physicslab-1.4.8 → physicslab-1.4.9}/physicsLab/music/music.py +36 -24
- {physicslab-1.4.8 → physicslab-1.4.9}/physicsLab.egg-info/PKG-INFO +1 -1
- {physicslab-1.4.8 → physicslab-1.4.9}/setup.py +1 -1
- {physicslab-1.4.8 → physicslab-1.4.9}/LICENSE +0 -0
- {physicslab-1.4.8 → physicslab-1.4.9}/README.md +0 -0
- {physicslab-1.4.8 → physicslab-1.4.9}/physicsLab/__init__.py +0 -0
- {physicslab-1.4.8 → physicslab-1.4.9}/physicsLab/_colorUtils.py +0 -0
- {physicslab-1.4.8 → physicslab-1.4.9}/physicsLab/_tools.py +0 -0
- {physicslab-1.4.8 → physicslab-1.4.9}/physicsLab/celestial/__init__.py +0 -0
- {physicslab-1.4.8 → physicslab-1.4.9}/physicsLab/celestial/elementsClass.py +0 -0
- {physicslab-1.4.8 → physicslab-1.4.9}/physicsLab/circuit/__init__.py +0 -0
- {physicslab-1.4.8 → physicslab-1.4.9}/physicsLab/circuit/elementXYZ.py +0 -0
- {physicslab-1.4.8 → physicslab-1.4.9}/physicsLab/circuit/elements/__init__.py +0 -0
- {physicslab-1.4.8 → physicslab-1.4.9}/physicsLab/circuit/elements/_elementBase.py +0 -0
- {physicslab-1.4.8 → physicslab-1.4.9}/physicsLab/circuit/elements/artificialCircuit.py +0 -0
- {physicslab-1.4.8 → physicslab-1.4.9}/physicsLab/circuit/elements/basicCircuit.py +0 -0
- {physicslab-1.4.8 → physicslab-1.4.9}/physicsLab/circuit/elements/logicCircuit.py +0 -0
- {physicslab-1.4.8 → physicslab-1.4.9}/physicsLab/circuit/elements/otherCircuit.py +0 -0
- {physicslab-1.4.8 → physicslab-1.4.9}/physicsLab/circuit/wire.py +0 -0
- {physicslab-1.4.8 → physicslab-1.4.9}/physicsLab/electromagnetism/__init__.py +0 -0
- {physicslab-1.4.8 → physicslab-1.4.9}/physicsLab/electromagnetism/elements.py +0 -0
- {physicslab-1.4.8 → physicslab-1.4.9}/physicsLab/element.py +0 -0
- {physicslab-1.4.8 → physicslab-1.4.9}/physicsLab/elementBase.py +0 -0
- {physicslab-1.4.8 → physicslab-1.4.9}/physicsLab/errors.py +0 -0
- {physicslab-1.4.8 → physicslab-1.4.9}/physicsLab/experiment.py +0 -0
- {physicslab-1.4.8 → physicslab-1.4.9}/physicsLab/experimentType.py +0 -0
- {physicslab-1.4.8 → physicslab-1.4.9}/physicsLab/lib/__init__.py +0 -0
- {physicslab-1.4.8 → physicslab-1.4.9}/physicsLab/lib/_unionClassHead.py +0 -0
- {physicslab-1.4.8 → physicslab-1.4.9}/physicsLab/lib/logic.py +0 -0
- {physicslab-1.4.8 → physicslab-1.4.9}/physicsLab/lib/wires.py +0 -0
- {physicslab-1.4.8 → physicslab-1.4.9}/physicsLab/music/__init__.py +0 -0
- {physicslab-1.4.8 → physicslab-1.4.9}/physicsLab/savTemplate.py +0 -0
- {physicslab-1.4.8 → physicslab-1.4.9}/physicsLab/typehint.py +0 -0
- {physicslab-1.4.8 → physicslab-1.4.9}/physicsLab.egg-info/SOURCES.txt +0 -0
- {physicslab-1.4.8 → physicslab-1.4.9}/physicsLab.egg-info/dependency_links.txt +0 -0
- {physicslab-1.4.8 → physicslab-1.4.9}/physicsLab.egg-info/requires.txt +0 -0
- {physicslab-1.4.8 → physicslab-1.4.9}/physicsLab.egg-info/top_level.txt +0 -0
- {physicslab-1.4.8 → physicslab-1.4.9}/setup.cfg +0 -0
|
@@ -76,12 +76,10 @@ class Midi:
|
|
|
76
76
|
else:
|
|
77
77
|
self.midifile: str = midifile
|
|
78
78
|
|
|
79
|
-
self.channels: List[int] = [0] * 16
|
|
80
|
-
self.tempo: int = 500_000
|
|
81
79
|
self.messages: mido.MidiTrack = self.__get_midi_messages()
|
|
82
80
|
|
|
83
|
-
# 使用mido打开一个midi文件并获取其tracks
|
|
84
81
|
def __get_midi_messages(self) -> mido.MidiTrack:
|
|
82
|
+
''' 使用mido打开一个midi文件并获取其messages '''
|
|
85
83
|
self._midifile = mido.MidiFile(self.midifile, clip=True)
|
|
86
84
|
wait_time: numType = 0
|
|
87
85
|
res = mido.MidiTrack()
|
|
@@ -93,10 +91,6 @@ class Midi:
|
|
|
93
91
|
elif msg.time != 0:
|
|
94
92
|
wait_time += msg.time
|
|
95
93
|
|
|
96
|
-
if msg.type == "program_change":
|
|
97
|
-
self.channels[msg.channel] = msg.program
|
|
98
|
-
if msg.type == "set_tempo":
|
|
99
|
-
self.tempo = msg.tempo
|
|
100
94
|
return res
|
|
101
95
|
|
|
102
96
|
# 播放midi类存储的信息
|
|
@@ -176,8 +170,8 @@ class Midi:
|
|
|
176
170
|
|
|
177
171
|
return self
|
|
178
172
|
|
|
179
|
-
# 将time重设为原来的num倍
|
|
180
173
|
def set_tempo(self, num: numType = 1) -> Self:
|
|
174
|
+
''' 将time重设为原来的num倍 '''
|
|
181
175
|
if not isinstance(num, (int, float)):
|
|
182
176
|
raise TypeError
|
|
183
177
|
|
|
@@ -188,26 +182,39 @@ class Midi:
|
|
|
188
182
|
|
|
189
183
|
# 返回 [Note(...), Chord(...), ...]
|
|
190
184
|
def _get_notes_list(self,
|
|
191
|
-
div_time:
|
|
192
|
-
|
|
185
|
+
div_time: Optional[numType],
|
|
186
|
+
max_notes: Optional[int],
|
|
187
|
+
fix_strange_note: bool = False,
|
|
193
188
|
) -> List[Union["Note", "Chord"]]:
|
|
194
189
|
|
|
195
190
|
res: List[Union[Note, Chord]] = []
|
|
196
191
|
wait_time: int = 0
|
|
197
192
|
len_res: int = 0
|
|
193
|
+
channels: List[int] = [0] * 16
|
|
194
|
+
tempo: int = 500_000
|
|
195
|
+
_div_time = div_time
|
|
198
196
|
|
|
199
197
|
for msg in self.messages:
|
|
198
|
+
if msg.type == "program_change":
|
|
199
|
+
channels[msg.channel] = msg.program
|
|
200
|
+
if msg.type == "set_tempo":
|
|
201
|
+
tempo = msg.tempo
|
|
202
|
+
if div_time is None:
|
|
203
|
+
_div_time = mido.second2tick(0.11, self._midifile.ticks_per_beat, tempo)
|
|
204
|
+
|
|
200
205
|
if msg.type == "note_on":
|
|
201
206
|
velocity: float = _format_velocity(msg.velocity / 127) # 音符的响度
|
|
202
|
-
ins: int =
|
|
207
|
+
ins: int = channels[msg.channel]
|
|
203
208
|
|
|
204
|
-
if velocity == 0 or (
|
|
209
|
+
if velocity == 0 or (fix_strange_note and ins == 0 and velocity >= 0.85):
|
|
205
210
|
if msg.time != 0:
|
|
206
211
|
wait_time += msg.time
|
|
207
212
|
continue
|
|
208
213
|
|
|
209
214
|
len_res += 1
|
|
210
|
-
|
|
215
|
+
if _div_time is None:
|
|
216
|
+
raise RuntimeError("find some error in midifile, please manually pass in the div_time parameter")
|
|
217
|
+
note_time = round((msg.time + wait_time) / _div_time)
|
|
211
218
|
|
|
212
219
|
if note_time != 0 or len(res) == 0:
|
|
213
220
|
if note_time == 0:
|
|
@@ -226,13 +233,14 @@ class Midi:
|
|
|
226
233
|
return res
|
|
227
234
|
|
|
228
235
|
def to_piece(self,
|
|
229
|
-
div_time: numType =
|
|
236
|
+
div_time: Optional[numType] = None,
|
|
230
237
|
max_notes: Optional[int] = 800,
|
|
231
238
|
is_optimize: bool = True, # 是否将多个音符优化为和弦
|
|
232
|
-
|
|
239
|
+
fix_strange_note: bool = False, # 是否修正一些奇怪的音符
|
|
233
240
|
) -> "Piece":
|
|
234
241
|
''' 转换为Piece类 '''
|
|
235
|
-
|
|
242
|
+
|
|
243
|
+
return Piece(self._get_notes_list(div_time, max_notes, fix_strange_note),
|
|
236
244
|
is_optimize=is_optimize)
|
|
237
245
|
|
|
238
246
|
''' *.pl.py文件:
|
|
@@ -256,8 +264,11 @@ class Midi:
|
|
|
256
264
|
f.write(f"import os\n"
|
|
257
265
|
f"os.environ['PYGAME_HIDE_SUPPORT_PROMPT'] = '1'\n"
|
|
258
266
|
f"from mido import MidiFile, MidiTrack, MetaMessage, Message\n"
|
|
259
|
-
f"mid = MidiFile(
|
|
260
|
-
f"
|
|
267
|
+
f"mid = MidiFile(type={self._midifile.type}, "
|
|
268
|
+
f"ticks_per_beat={self._midifile.ticks_per_beat}, "
|
|
269
|
+
f"charset='{self._midifile.charset}', "
|
|
270
|
+
f"clip={self._midifile.clip})\n"
|
|
271
|
+
f"track = {self.messages}\n"
|
|
261
272
|
f"mid.tracks.append(track)\n"
|
|
262
273
|
f"mid.save(\"temp.mid\")\n"
|
|
263
274
|
f"from physicsLab.music import Midi\n"
|
|
@@ -265,27 +276,28 @@ class Midi:
|
|
|
265
276
|
|
|
266
277
|
return self
|
|
267
278
|
|
|
268
|
-
# 以 .mid 的形式导出, read_midi已经在Midi的__init__中实现
|
|
269
279
|
def write_midi(self, midipath: str = "temp.mid") -> Self:
|
|
280
|
+
""" 导出一个 .mid 文件 """
|
|
270
281
|
if not isinstance(midipath, str):
|
|
271
282
|
raise TypeError
|
|
272
283
|
if not midipath.endswith(".mid"):
|
|
273
284
|
midipath += ".mid"
|
|
274
285
|
|
|
275
|
-
mid = mido.MidiFile(
|
|
286
|
+
mid = mido.MidiFile(ticks_per_beat=self._midifile.ticks_per_beat,
|
|
287
|
+
type=self._midifile.type,
|
|
288
|
+
charset=self._midifile.charset)
|
|
276
289
|
mid.tracks.append(self.messages)
|
|
277
290
|
mid.save(midipath)
|
|
278
291
|
|
|
279
292
|
return self
|
|
280
293
|
|
|
281
|
-
# 以.pl.py的格式导出, div_time: midi的time的单位长度与Note的time的单位长度不同,支持用户手动调整
|
|
282
|
-
# max_notes: 最大的音符数,因为物实没法承受过多的元件
|
|
283
294
|
def write_plpy(self,
|
|
284
295
|
filepath: str = "temp.pl.py",
|
|
285
|
-
div_time: numType = 100,
|
|
286
|
-
max_notes: Optional[int] = 800,
|
|
296
|
+
div_time: numType = 100, # midi的time的单位长度与Note的time的单位长度不同,支持用户手动调整
|
|
297
|
+
max_notes: Optional[int] = 800, # 最大的音符数,因为物实没法承受过多的元件
|
|
287
298
|
sav_name: str = "temp" # 产生的存档的名字, 也可直接在生成.pl.py中修改
|
|
288
299
|
) -> Self:
|
|
300
|
+
''' 以.pl.py的格式导出 '''
|
|
289
301
|
if not (isinstance(div_time, (int, float)) or
|
|
290
302
|
isinstance(max_notes, int)) and max_notes is not None:
|
|
291
303
|
raise TypeError
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|