Skip to content

Commit aa9d896

Browse files
committed
add from_numpy to stub
1 parent a9f530b commit aa9d896

File tree

5 files changed

+245
-11
lines changed

5 files changed

+245
-11
lines changed

generate_stub.sh

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1-
pip install . --user
2-
pybind11-stubgen symusic.core --numpy-array-remove-parameters -o .
3-
pip uninstall symusic
1+
#pip install . --user
2+
nanobind-stubgen symusic.core --out .
3+
rm symusic/core.pyi
4+
mv symusic.core.pyi symusic/core.pyi
5+
#pip uninstall symusic

py_src/core.cpp

+87-8
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ py::object py_filter (vec<T> & self, py::callable & func, const bool inplace) {
9494
}
9595

9696

97+
#define NDARR(DTYPE, DIM) py::ndarray<DTYPE, py::ndim<DIM>, py::c_contig, py::device::cpu>
98+
9799
template<typename T>
98100
std::tuple<py::class_<T>, py::class_<vec<T>>> time_stamp_base(py::module_ &m, const std::string &name) {
99101
typedef typename T::unit unit;
@@ -129,6 +131,10 @@ std::tuple<py::class_<T>, py::class_<vec<T>>> time_stamp_base(py::module_ &m, co
129131
return std::make_tuple(event, vec_T);
130132
}
131133

134+
void show(NDARR(float, 1) arg) {
135+
136+
}
137+
132138
// a template functions for binding all specializations of Note, and return it
133139
template<typename T>
134140
py::class_<Note<T>> bind_note_class(py::module_ &m, const std::string & name_) {
@@ -167,7 +173,17 @@ py::class_<Note<T>> bind_note_class(py::module_ &m, const std::string & name_) {
167173
.def("shift_velocity", [](Note<T> &self, const int8_t offset, const bool inplace) {
168174
if (inplace) return py::cast(self.shift_velocity_inplace(offset), py::rv_policy::reference);
169175
else return py::cast(self.shift_velocity(offset), py::rv_policy::move);
170-
}, py::arg("offset"), py::arg("inplace")=false, "Shift the velocity by offset");
176+
}, py::arg("offset"), py::arg("inplace")=false, "Shift the velocity by offset")
177+
.def("from_numpy", [](NDARR(unit, 1) time, NDARR(unit, 1) duration, NDARR(i8, 1) pitch, NDARR(i8, 1) velocity) {
178+
if(time.size() != duration.size() || time.size() != pitch.size() || time.size() != velocity.size()) {
179+
throw std::invalid_argument("time, duration, pitch, velocity must have the same size");
180+
}
181+
auto size = time.size();
182+
vec<Note<T>> ans; ans.reserve(size);
183+
for(size_t i = 0; i < size; ++i) {
184+
ans.emplace_back(time(i), duration(i), pitch(i), velocity(i));
185+
} return ans;
186+
});
171187
}
172188

173189
// bind symusic::KeySignature<T>
@@ -195,7 +211,17 @@ py::class_<symusic::KeySignature<T>> bind_key_signature_class(py::module_ &m, co
195211
.def(py::init<unit, i8, i8>(), py::arg("time"), py::arg("key"), py::arg("tonality"))
196212
.def_rw("key", &symusic::KeySignature<T>::key)
197213
.def_rw("tonality", &symusic::KeySignature<T>::tonality)
198-
.def_prop_ro("degree", &symusic::KeySignature<T>::degree);
214+
.def_prop_ro("degree", &symusic::KeySignature<T>::degree)
215+
.def("from_numpy", [](NDARR(unit, 1) time, NDARR(i8, 1) key, NDARR(i8, 1) tonality) {
216+
if(time.size() != key.size() || time.size() != tonality.size()) {
217+
throw std::invalid_argument("time, key, tonality must have the same size");
218+
}
219+
auto size = time.size();
220+
vec<symusic::KeySignature<T>> ans; ans.reserve(size);
221+
for(size_t i = 0; i < size; ++i) {
222+
ans.emplace_back(time(i), key(i), tonality(i));
223+
} return ans;
224+
});
199225
}
200226

201227
// bind symusic::TimeSignature<T>
@@ -221,7 +247,17 @@ py::class_<symusic::TimeSignature<T>> bind_time_signature_class(py::module_ &m,
221247
return time_sig
222248
.def(py::init<unit, u8, u8>())
223249
.def_rw("numerator", &symusic::TimeSignature<T>::numerator)
224-
.def_rw("denominator", &symusic::TimeSignature<T>::denominator);
250+
.def_rw("denominator", &symusic::TimeSignature<T>::denominator)
251+
.def("from_numpy", [](NDARR(unit, 1) time, NDARR(u8, 1) numerator, NDARR(u8, 1) denominator) {
252+
if(time.size() != numerator.size() || time.size() != denominator.size()) {
253+
throw std::invalid_argument("time, numerator, denominator must have the same size");
254+
}
255+
auto size = time.size();
256+
vec<symusic::TimeSignature<T>> ans; ans.reserve(size);
257+
for(size_t i = 0; i < size; ++i) {
258+
ans.emplace_back(time(i), numerator(i), denominator(i));
259+
} return ans;
260+
});
225261
}
226262

227263
// bind symusic::ControlChange<T>
@@ -248,7 +284,17 @@ py::class_<symusic::ControlChange<T>> bind_control_change_class(py::module_ &m,
248284
return control_change
249285
.def(py::init<unit, u8, u8>(), py::arg("time"), py::arg("number"), py::arg("value"))
250286
.def_rw("value", &symusic::ControlChange<T>::value)
251-
.def_rw("number", &symusic::ControlChange<T>::number);
287+
.def_rw("number", &symusic::ControlChange<T>::number)
288+
.def("from_numpy", [](NDARR(unit, 1) time, NDARR(u8, 1) number, NDARR(u8, 1) value) {
289+
if(time.size() != number.size() || time.size() != value.size()) {
290+
throw std::invalid_argument("time, number, value must have the same size");
291+
}
292+
auto size = time.size();
293+
vec<symusic::ControlChange<T>> ans; ans.reserve(size);
294+
for(size_t i = 0; i < size; ++i) {
295+
ans.emplace_back(time(i), number(i), value(i));
296+
} return ans;
297+
});
252298
}
253299

254300
// bind Pedal<T>
@@ -277,7 +323,17 @@ py::class_<symusic::Pedal<T>> bind_pedal_class(py::module_ &m, const std::string
277323
return pedal
278324
.def(py::init<unit, unit>(), py::arg("time"), py::arg("duration"))
279325
.def_rw("duration", &symusic::Pedal<T>::duration)
280-
.def_prop_ro("end", &symusic::Pedal<T>::end);
326+
.def_prop_ro("end", &symusic::Pedal<T>::end)
327+
.def("from_numpy", [](NDARR(unit, 1) time, NDARR(unit, 1) duration) {
328+
if(time.size() != duration.size()) {
329+
throw std::invalid_argument("time, duration must have the same size");
330+
}
331+
auto size = time.size();
332+
vec<symusic::Pedal<T>> ans; ans.reserve(size);
333+
for(size_t i = 0; i < size; ++i) {
334+
ans.emplace_back(time(i), duration(i));
335+
} return ans;
336+
});
281337
}
282338

283339
// bind symusic::Tempo<T>
@@ -308,7 +364,17 @@ py::class_<symusic::Tempo<T>> bind_tempo_class(py::module_ &m, const std::string
308364
}, py::arg("time"), py::arg("qpm")=py::none(), py::arg("mspq")=py::none())
309365
.def_rw("mspq", &symusic::Tempo<T>::mspq, "Microseconds per quarter note")
310366
.def_prop_rw("tempo", &Tempo<T>::qpm, &Tempo<T>::set_qpm, "The same as qpm")
311-
.def_prop_rw("qpm", &Tempo<T>::qpm, &Tempo<T>::set_qpm, "Quarter per minute, the same as tempo");
367+
.def_prop_rw("qpm", &Tempo<T>::qpm, &Tempo<T>::set_qpm, "Quarter per minute, the same as tempo")
368+
.def("from_numpy", [](NDARR(unit, 1) time, NDARR(i32, 1) mspq) {
369+
if(time.size() != mspq.size()) {
370+
throw std::invalid_argument("time, mspq must have the same size");
371+
}
372+
auto size = time.size();
373+
vec<symusic::Tempo<T>> ans; ans.reserve(size);
374+
for(size_t i = 0; i < size; ++i) {
375+
ans.emplace_back(time(i), mspq(i));
376+
} return ans;
377+
});
312378
}
313379

314380
// bind symusic::PitchBend<T>
@@ -333,7 +399,17 @@ py::class_<symusic::PitchBend<T>> bind_pitch_bend_class(py::module_ &m, const st
333399

334400
return pitch_bend
335401
.def(py::init<unit, i32>(), py::arg("time"), py::arg("value"))
336-
.def_rw("value", &symusic::PitchBend<T>::value);
402+
.def_rw("value", &symusic::PitchBend<T>::value)
403+
.def("from_numpy", [](NDARR(unit, 1) time, NDARR(i32, 1) value) {
404+
if(time.size() != value.size()) {
405+
throw std::invalid_argument("time, value must have the same size");
406+
}
407+
auto size = time.size();
408+
vec<symusic::PitchBend<T>> ans; ans.reserve(size);
409+
for(size_t i = 0; i < size; ++i) {
410+
ans.emplace_back(time(i), value(i));
411+
} return ans;
412+
});
337413
}
338414

339415
// bind symusic::TextMeta<T>
@@ -351,7 +427,10 @@ py::class_<symusic::TextMeta<T>> bind_text_meta_class(py::module_ &m, const std:
351427

352428
return text_meta
353429
.def(py::init<unit, std::string &>(), py::arg("time"), py::arg("text"))
354-
.def_rw("text", &symusic::TextMeta<T>::text);
430+
.def_rw("text", &symusic::TextMeta<T>::text)
431+
.def("from_numpy", [](NDARR(unit, 1) time, NDARR(std::string, 1) text) {
432+
throw std::runtime_error("TextMeta does not support numpy");
433+
});
355434
}
356435

357436
template<typename T>

pyproject.toml

+5
Original file line numberDiff line numberDiff line change
@@ -116,3 +116,8 @@ extend-select = [
116116
"S101", # allow assertions in tests
117117
"T201", # print allowed
118118
]
119+
"symusic/core.pyi" = [
120+
"UP007", # `X | Y` for type annotations
121+
"A003", # allow using filter as method name
122+
"F811", # the first overloaded function generated by nanobind has no @overload decorator
123+
]

0 commit comments

Comments
 (0)