Отладка языков программирования потока данных, в частности исправления Pure Data - PullRequest
0 голосов
/ 08 февраля 2020

Я изучаю Pure Data, в частности, я использую puredata vanilla 0.46.7. У меня все хорошо с основами: создание и управление звуковыми сигналами, управление и обмен сообщениями, использование абстракций и т. Д. c.

У меня была идея иметь вертикальный слайдер внутри основного патча, который идет от От 0 до 1000, чтобы я мог настроить его, не нажимая Shift. Тем не менее, я хотел бы задать ему определенный c диапазон, например, от -10 до 10, и я мог бы сделать это, просто установив диапазон ползунка.

Я не сразу подумал об этом, поэтому я попробовал этот подход: у меня будет выходное отверстие ползунка, подключенное к входному отверстию range arg1 arg2, что будет абстракцией, так что, например, путем создания range -10 10 диапазона ползунка (0..1000 ) будет сопоставлен диапазону, указанному в качестве аргументов объекта (-10..10).

Итак, я создал этот патч ( здесь - это ссылка на его вставку): range patch

Я думал, что это было довольно легко, и я ожидал успеха, но безрезультатно. Вместо того, что входит в диапазон -10..10, вместо этого я получаю -10..0. Как я уже говорил ранее, я мог бы просто установить диапазон непосредственно на слайдере, но тот факт, что это не работает, означает, что я что-то упустил, поэтому я хотел бы знать, в чем заключается ошибка в моих рассуждениях, чтобы лучше понять, как работает уровень контроля чистых данных.

Основываясь на том, что я узнал о горячих и холодных входах, подключив [loadbang] к [t b b], [f $2], а затем [f $1], произойдет следующее: что когда я создаю новый [range] (например, range -10 10), [f $2] равен banged, что заставляет объект выводить второй аргумент, переданный в [range] ($2). Поскольку выход объекта подключен к холодным входам двух [expr], он просто находится там, и объекты [expr] должны вывести свое значение по умолчанию (равное 0).

Затем, [t b b] should bang [f $1]: это заставляет объект выводить первый аргумент. Поскольку его выход подключен к горячим входам объектов 2 [expr], это должно привести к тому, что два объекта выведут результат своих выражений.

Они проверяют, равны ли $1 и $2 0, что означает, что для [range] не было предоставлено никаких аргументов. В этом случае первый [expr] выводит 0 (минимальное значение по умолчанию), второй выводит 1 (максимальное значение по умолчанию). В противном случае они просто выводят все, что нужно: первые [expr] выводят $f1 (что является минимальным значением, хранящимся в [f $1]); вторые [expr] выходы $f2 (максимальное значение, сохраненное в [f $2].

Выходы объекта [expr] подключены к входам [swap], затем его выходы подключены к [- ]. Итак, я передал -10 и 10 в качестве аргументов, минимальное значение -10, максимальное значение 10, их поменяли местами и затем вычли, что означает, что [- ] теперь должно вывести 20 (10 - (-10)): это диапазон, в котором я хочу отобразить 0..1000.

[inlet] из range - это значение, полученное от ползунка: я делю его на 1000, чтобы он находится в диапазоне 0..1. Давайте назовем это число n. Теперь я хочу сопоставить n с -10..10, поэтому я придумал эту формулу: x = R * n + m, где R это ранее вычисленный диапазон, а m - это минимальное значение, которое действует как смещение. Таким образом, если 500 - это значение ползунка, n = 0.5. Для R = 20 и m = -10 это означает, что x = 0.0, что ожидается: 500 находится в середине 0..1000, а 0.0 - в середине -10..10.

Это именно то, что последний [expr] объект делает: $f1 - это значение из ползунка, $f2 - это R (диапазон), а $f3 - m (минимум, или смещение).

На данный момент, учитывая, как предыдущие объекты связаны, я должен иметь правильные значения для $f2 и $f3. Если значение ползунка изменяется, я должен увидеть соответствующий вывод, но это неправильно: вместо отображения на -10..10 он отображается на -10..0.

Поскольку я не могу отлаживать, как на языке программирования "classi c" (то есть go шаг за шагом при выполнении кода), я подключил [print] объекты к соответствующим выходам, чтобы проверить порядок операций. Затем я создал [range -10 10] на основном патче и прочитал консоль, чтобы увидеть отпечатки. Я получил этот «след»:

arg2: 10
swap-dx: -10
range: 10
swap-sx: 0
check-min: -10
check-max: 10
arg1: -10

Это сбивает с толку, учитывая приведенные выше рассуждения о входах горячей / холодной воды и о том, как я соединял различные объекты, я ожидал что-то вроде:

arg2
arg1
check-min
check-max
swap-sx
swap-dx
range

Я не могу понять смысл полученного следа: как это возможно, что swap-dx сразу после arg2? И как это возможно, что arg1 находится в самом низу? Я понимаю, что сообщения передаются "справа налево" относительно входов и "сначала глубины" относительно расположения объектов, но в этом случае, мне кажется, что нет пути от arg2 до swap, поскольку выходы [f $2] подключены к холодным входам, и соответствующие объекты не должны ничего выводить, пока что-то не изменится на их горячих входах.

Если я увидел что-то вроде arg2 -> check-min -> swap-dx -> range, а затем все остальные, то было бы четким указанием на правило "глубина в первую очередь". Вместо этого я получил все вышеперечисленное.

Однако результат (тот факт, что диапазон изменяется от -10 до 0) согласуется с тем, что я вижу на графике: swap-sx: 0, swap-dx: -10, range: 10, и это дает подсказку о проблеме. По какой-то причине горячий вход [swap] никогда не обновляется и остается равным 0, поэтому [- ] делает вычитание 0 - (-10), равное 10. Следовательно, значение должно быть отображено на -10..0.

Я проверил каждую «стадию» индивидуально, убедившись, что все объекты ведут себя так, как я ожидал, и они делают: выражения кажутся правильными, есть нет причуда с [- ]: если я передам -10 к его холодному входу и 10 к его горячему входу, выход будет 20, что правильно.

Итак, ясно, что все это .. неясно мне: что я делаю не так? Что я мог бы сделать для более эффективной отладки патча, кроме размещения объектов [print] везде? Должен ли я использовать [float] объекты для хранения значений на каждом этапе, используя тот факт, что они выводятся только тогда, когда они стучат по горячему входу, а затем использовать триггер, чтобы стучать по ним в нужном порядке? Мне это кажется излишним и головной болью.

Ответы [ 2 ]

1 голос
/ 12 февраля 2020

Это все еще выглядит слишком сложным и не очень похоже на собственный синтаксис Pd. Разве это не то, что вы ищете?

Pure Data abstraction to scale a range

0 голосов
/ 09 февраля 2020

Благодаря gilbertohasnofb и Max N я нашел решение: range patch fixed

Добавив [t f f f] после [f $1], я могу обеспечить правильный порядок: сначала значение переходит ко второму [expr], затем к первому, что приводит к выводу [swap], и, наконец, к последнему [expr].

Теперь патч работает, как и ожидалось, без проблем! Я полностью забыл, что [trigger] может распространять сообщения любого типа, не только bang. Извлеченный урок: всегда используйте триггер при подключении выхода к нескольким горячим входам.

...