Just-In-Time (sort-of) (imperfect) (fun) Polyphonic Classifier

Dear all

After talking to @rodrigo.constanzo and thinking in this other super long thread, I came up with this idea, which is just showing how to do just-in-time processing of a short moment in a circular buffer. This is fast, and I decided to train an nmf~ on 3 potential classes (excuse the fat synth drums).

I think the patch is documented enough to understand what is happening, but here it goes again, just to make sure it is as clear as possible.

  1. the sound is recorded in a circular buffer.
  2. when an attack is detected, there is a snapshot of the index where it is situated
  3. that index is used to trigger the non-real-time bufnmf process. the process is done on 128 samples following the attack, with a fft of 128 and 64 overlap. We get 3 frames, and the middle one is centred on the audio.

There are 2 different branches of the nmf process: 1) a training one, and 2) a classifying one

  1. the training branch will make a single rank bufnmf, that is updating its filter with training material,
  1. it is then copied to a classifying filter at the right position (the patch has 3)

The classifying branch takes the 3 rank filter created by 3 iterations of the training above, one for each channel/rank. It does not update but tries to factorise the input with the 3 seeded filters, and give 3 activations. What I do then is to check the amplitude of each activation, and trigger the same synth sound on the right channel. It is late, but most of the time the same, so we have a classifier!

It is far from perfect, but loads of fun. There are better classifier out there, but this should allow you to find some sort of fun parameters to play with.


----------begin_max5_patcher----------
16505.3oc68s2bqiakm+c2eJPblY16MssZhWDjSmNa2IyjYxVSdTo6rSM0zS
4hVh1l8UlTEIku8MoFW6mk8i19IYAH.oHkHo.e.QZY0IWaYwG.3GN3fC.Nmy
u+1m+YWcWzO4mbE3eD7eB9rO6u84e1mk8Uhu3yT+8mc0Sd+zx0dIY21UKid5
I+vzqtVdsT+eJM66W4m5uLMH7AfWZp2xOj.Ri.owAO7feLH8QeP1qH39fkdo
AQg4OeR5mV6m8Bx+lMdoKej+dtMl+9j0Lni0BqqAHW6ET9uH3r+h+cf+K0CE
t8ofv09oY0Qn5KCVk8hit6Guw09pc2Yz1z7a0R7k+2e9mK9w0CDAt2aYZTbP
heVyMHby1T9Oy9i67SRA7m6tfvrVOH59ruGCV4eePn+JPrW3GR5DnffTAL3P
y9EV9qtAJTyCJowdAgI.O.LqIBBe59qAa2rxKSTQfA2GrNkKh36s7QPZvS9W
C9eD7zl3nm42v+ir6HCiBJiaxxUUVq4.3xnsgYEHtKPHywV.Z1VDwufrLHjv
5BDZYdHjiEK8SR.PjCHw6oMq84348oxgU+PnbfGWDRNtC7tjsa7iSdLJN8m8
9ZwHTWvHhU1XOJFVBiv3NfQNtlGiVFDub6ZuXvcau+d+3NMPBiYxllTJfZ04
ARNNm.sKAqWmOjYUvxTvGCReD7O8a.dhQWIodwYin1DEDltf+qD9.lm8AgQB
EReLZ65UfUQh6L3o.AP8iQ2M7APTHR.VLrqD5r67.HG73Acg9ej+JOb7CHhC
Zw2lJp7I2lFc6pnaEn2sbE1AOmoPtapdswVhIhbYxIhjJhQnlZ1jZZ1nFZ1k
KTtbrrwpZselPHv+Y9fawDn6vyO6JuMaJ80eVoGQ.Q+XT1KhccwWEDJ+JbwW
E6+bP9ySK9VuXdSWndYarDT9IaxU6dMQq7iC2FjUUjeIuy5yyegEnUlLhaFV
AgNNYyZgs2gV790GVGs7C9qJAAe1UQa7C4yhF6mvGOHMZn7k4yJ3scc5s2GE
llD7WypeYhi0bc9Ty9M9vgdOIabeabf257l2UODGrJJTTIp.0huNu33VlPkB
9kaLY2Qn2lZdXdWOGVZ3h7wvoaStyKVzSbmTJDkewznn0UuTwys1+9T0k2DD
FtGJlFso4KxMO6wVd16h3W7o1d2YWI41sgxqdKerX5sIdOWEsS8VuVM3r5q+
m7BCdxK0WLueVy0p3h9gd7F5iIKiiVutR6Udkmq4Jq3BwK8+XvpzGyJnxBC7
aOXStPzUE8xqBdfaaV0uK06gjpeyAZE3e016TCRuM0mOoLuUT8FpXYc4QjkU
iU46aclfp5zBR3p7iiBEUdv6DZ0CeX8Nar41Fb2m.odeHeFi0QaWIt0cZ7de
42akY.rKcgCa3MMS.JabssalYBrrIBbJMQPiSFbflQRkRpzn+xkFlHKsLUKV
pereYs+zIeV9TJJMU8reYKuWY6UGEjjkd5m1nTUbUfnuTbO7+UopVmUWLqRv
obd0xSvnMbxbq1wEyU1wMc7V4fnxCGydPtnrRl8Jg45PQk8ZwOD+EpxegupE
7FOh3cko0qNLfeeAOs8o92YH90Q6KPxUIHWgkM938EnF5KbtpQ.CMh.VaJNV
tNfuFAtVKew5yWGE8A95FxTQTxXHv8QpEjwm8mufh0QeD7idO6I0g1rlCbez
bXagjVFvJY9MoOpNXLcTc3lonBhbm.UGsHJuQr1s6E+udHMqsLLRa8I3FvX6
lkggmHYXtwqO4slutlUfXe9Duh047r25s9hsGHSrM68r.76D69BepxkdI9WK
2HF92eyp3sOcSHeI0xuiaNVru5u8BWk8cOF7nWZ12A9padO36h.Qg7oWyVF0
RtMibSO3qBSrTSdkDnVgNec4q74V0sRLqaDur4WbUR0JUiicn8YriSlxHJQt
jUbV2pXYrcenC8pSx.fznG31ozS80GeRyrQ1xMr.Qx+Y2ACTWlyrA8L4UFcs
PA9ZAksYxUvQGJJC6BJaNvpEcxOHLp2.ZikahFzISYrzT1dYPgsqFS3IsjDZ
6NABhIqCVUrab8GBuecjWJ+d1rMceAp5Ns.lDWcX4ajGu4S1uQWrkAKr5nfq
s8Hnd.J6Vvxcf9MQ2hzDDy0sPGitk7JoyaktEWKy1qPl8Z4+E7t3d.5Yv7QU
0qfW4omvWyAsmp5oNWcViS4JsGNPwNyAJkFpgCTVWc1ZekzlJ0VJL.CrHtSN
FsxmuHy0Qezj3Dwcf6xHY5Gzks+II9oxC.t7tYQLIzoNVKJp+xX3SC18iIaC
Fk1LBm0lwp0YaS0UfY+ixqIgowv9Z4BSITrP+HyVdvzD7dUUw4oVb7e2udav
pEb4mmC7+3heLYxEo8+oMwbSt.eI3c+c2CAeA3u6dT1Owu2DhzHoQuHhb0oD
bu2jPL8zfcYUDCa5lZ6jvE+rYzvpAzPmSzh.k5fI5ttiRWIeuR2ucGDtx+md
cg4HHYj.crNmEfTFmZaBPG8pAzwxYuFAPGoAnaK21KyHoehN2wMfvnvaVFE9
bP3Rwt8+iAoYNwHWicvSEyw0msz2EgKY6Jxxs2Fkgaw.eq8qD670npPRi9bT
S9czdOdc9eTC9fTy9gzw8Eol7GoJ9jzd9kDU5zZRm+zVdFJDm8DFq22jzv+j
zwGkNpeJoouJ0h+JomOKcD+V5n9tzQ8eoi3CSG2OlNpuLog+LoiOM0E+ZpEe
a5n92T693T694T695Tq96TS97T898TyZtNt+OUuOPsu1g80Eev0OxDgsTCOt
QvM6QBpsVowYCacFw80CCu5vGr942ZaNtFrnqxbcUmuanX8gGAesNei7n2SZ
tS4Q+0aDShvGDcm+5qNN9ynp8sQMSHbeGx9nSCteW.hzdef0b.N88BGerjhx
hYFEVJOsogAk3WAPYPnYjLQtvxRlVrgCmnoGN4qRHrhSz0YspWCt5NuvGzR6
pizq4wpE7pbckZfvJFMgWXcvkiexaeGVsSXOjcUMEYylXow1Q0lm8c9zCBcl
K8fNW5A6SOHylLW5AcuzC1qdP4FCLC5AQVmK8fGrgOUspfuXPwYLYsn3+OfN
a4NyccyePKg.UjmICOZHD2Wo.s6qgcuutZ+H4rajnMY1nK09htz9zCRUNoyL
PWJ8ROXu5Akt99bXLH4ROXe5AINn4xXP6K1yLQ1yPUtTxoydF1E6YNXjHbtn
KEcY088pGDaCmKyFZcoGrW8fxcVdFzCdY6Y5UGHhNWLmw4h0LSj0LHl6o0ZF
6WCFybjtweLHcAdnCSqMMazn8ND44KqxgUtTS2MQuzM0ito7LOm7rmnV0E2K
cy1D5zixBXbyGCBWUI9NZAwzRuiLU7fk4yNo1G6gbF0vibj+nWqHkJ0YNd.E
5p49zjBbTMUId.Ce4ula4FlDG7SBvts+pKcDxPaSFIfCarMb1qAMEnBQ292I
jGiuZsyJk7va5vAX1Q7osWqZDfDz3pR.+pPifLn4doonlaL0NzEwUoyWBQrA
KudDEy3V5Fp5jzhb1yQ7n0r1i39ZuOJIZa7xhgxR+DEbXKTj19TYM5R2KSdu
8R5ou0OVGpenIn9g5P8CVOXGEuRFHDvSZMG1ktd3TfsY0Pnl0P7TUAQ5BgSQ
MztCHn6DU+zUFzYhpeXcU+LUUPsk.slfJHsC8v1ST8SW.DAmnJntCgQSwTzn
tLQBxZppg5hgP2opFp83XmopFpqpP3jHG1IaEsmpZn1xgjopFps5P5TUC0VN
zdluj.Z6qHvp0kH94kZEkB5aum8WcqLvYu0KkuD361lJW9XMsf9EzlOrN5Nu
0pPwr3TDzIBN2Etme9gsqILoEbvgr1RtnghGXJK.d03j3AH0.b6nDhC10fcX
Ych1kPzCDowj8kSaZKBNvf9qdJXUF+vnpJtYIOLQlnj+KBlV7WUdnCGAzprQ
maO3tzdfs0dPnrr8CzFk0fjYXhr+5j1fPcoAgZqAIbjGQChl00PXnh+5T1fD
os98.9FZP6Yt13VKr0EVcLYsP2NWaihEPMqEDSVKzVSTFV.qWjEZjpVN5ezp
F9fY8M8nIsqZTmlqZlA0nV51gRMnXEkoasv1j0BGcqEDSNDSW0MTVyCwPlop
Q6RUyZVZRQl.+LE0rN0i90up4bpQMht5LILCNXrSS5BMTkfnq1QB1fPAQ2QX
DSpiV6w4X5o1.DsUbiOXSuaupsaMkYqltgEUVrO.7EjaKVsdwqOOahUe6P3T
.KiVGEeaPnHwtoZRVkSUeWKxB7UpvdKWxWab1yke+Nha0A6hf1hOwrbcrHG9
j28PomBpd2pejsNzO+vsUQ3dx7hqtMS3pm3srfxSrTWeYEvYuMonc3oRSjfv
TjqndhYHJI6SHFgBUMSiW0exOIw6Aey12d2CBhmsngW21Vku0MW8Pr2pf8xK
ORLCVHWXy+O1009I39IjtrGEk+nLGGNhecsep9GM+IQtVP2L4PrRNT7I9WAq
4I8DDoX1TYr8xoZahi1DEWjm+Vfcq7baSiJ.fJ6WX4MUqYQgCGo1cIB4lW0K
o4r9eBWL1Bk8INNwaeikjr5cj+BN1Fi925Cqc19FgVGEdt2FfJ6mFKBoNZym
.YjedP3CchbgYpjRqJGS0G5nFZd5nVQ134jO9OqSMQh6tjsYOahiHuqyE8RK
RVq0z.ZeCpqs8ISuNDIMndHGYczlGqABEGNh8f++9+7+UPAjYxnYbd2Nxi8G
BA7+SbCa1lBDWN6lD4WUAaQ9ywYDmW3taqfuHydGfOEskKYjDD6CdWFA7kgQ
fG8R.Xff6P+xr668xWP9KQT5ODB7xticUMQARpdmaV68I98cu+G4UtjTuvkY
T+WQiP7vbUeby0.uS73v8JI4fS9cmUB9qxHTctRFu3OI3MWQJcUPntfeNcWS
LRTH7WYPxi7GHej80YHzOGK.orZk.i3OzODpf2DeI6Zl9H+k9Xz5UIk.WwCT
TokjOXNibFjln3zPE8bJyaofEf+cevFe+BZ6Dwencts40B5fOf+3I.Uu5SAq
Vst.djN54hc0gCpehWffuO4+ZSTRVlZUzNBiRAOvu2kwQB70a8G.2GyqOhmM
id0W.9ddOlfigSBDy.3E5GsMQPfnYUETdM.m2ZE4P1ruQoxFbGWhgKf8yg6p
cBAokdbYf0IQfn6R7ie1+.xJk2iISEuOT408yY.tTo.pDWQgFkcv0bv.7GE0
e.ur8xHqwO9n.Z4RPQ.AKwm8bxLIHfOoG+Msb81UbYffJUeNlVzouxmOf0em
DVlfxpnsbrTx+p+7hw2U3.RnSWzhBsjIreW0wcHiuLhSWzyXa9YJpHoiABx2
TJB3K4YVdeLuaZMG72JzWvGrJFH7kQEb3gDHuym2qHt+62FxuKz6upOXkMKm
VH55LNEjBoAgpcRd+i8p0gcJwIIUlvoRnqYmaW6wazinkDhVY0oZeLn5IpVS
i8vEHV17eByh53TwH9lizrxbaYKIeBWFdGSn0IID6hA0GFPefeMW0ZwXd+G7
V9oh0iU90EyUErRlQpsKV9QaAjayTafp0X0PqoRwKVA.N21+8+PYzkOAcTrT
IV4p8ddS+9x01WcFJuXKiQeWY.I1G4E5LRdwUFo5HY1vehkWXmixKtX1Ncz8
QbAOmDWTMF2YfzhyYo1EWxBFU3fSt8UdAMijWrkYdb5tb49DJvPOGEXnNxTM
hiUOkWntyIyWjIZcpCdFHuPNGkWPxn.V3TY8TdYNYtaQqYNXtK9rT+hLxngj
9Jt.mUqNRxAR1y.oETejVpDS2k4krrCeYyZewFuI2NNwdlHXmm3ttC2Wu2ua
UahLcjKo1MnDcKGv105K10xfrM.W6QRY4mPTCjSVcDSV9IeUCgjUCYjUOQj0
NIjUGAjUblYkHdLG4NMbissaiTOVszN1QnbriQ2XsR0XZPyXMPwXGmdwZgZw
ZkVwZkRwZgNwZmJwZkFwNBEhcL5CSWpCqAZCqUJCqY5BqYpBqYZBqaGt5ATC
Vcmm5wnDrCoCrtFRIGR7O6z8kD9EO9XunbQE6MK23OBoNN8QOVvtE9VbDiql
1.g6V0WPvkMJX.dVfAI8i6MkJhGLFfNMXPEqEG8.rRQtUpTFzgmgs1nADdZH
CZCCGU3H2A.GtmCnQkzI0..C1oAL12un5fJAUK0gnabF1jdQG8Hi2SJWdO.b
IW8vfAFBZj.FzLAXTJJFNvPGIfAepBMUs8ReSF9P55e7XSFlfPsiU.Ti0hyW
elrgMuve0C9uz2MonU2wC6j4gLxcvRYXGpC6cElT+lSfFuF+xG4shN07ENKG
es45zvU4LWVma3Hx34GhMzvSA2Mltdo5XPrIrRllzklLw03M40QdqDNuOPro
IAgIdOsIArya.z.FZEBvRhs2V5DpPhS2w.GiiAYYfVQnE.rV.GqVNwNSdmY0
PdjsZCGUSCGOdM7w2shYPlLmW31S2JFaOqadxz+qsUuadXiK1dCnKBqG8P9k
cn1Jmtwc+bZ9QkWsgFuEGryOEGiVrCUpd1tmsXj4UMkrIl2LtGrINZoPKMWK
Upe7MhszjvsU6FHP9+r.+8qTWLgT7gwRWVNRwTrKY2mICwFOnZKeIFa6nbv9
Y2+VFAPYN4YZ4t1HQWoww.Fv67TKx4JQzEHpWWKhIT0uQpeiKWt6mefGGoq7
TsbEoptnTofIRNpBUribOckF9AQvNitTia268q2FrRj+oCe59W.eSVne.AeC
uCKV4d+PKKv27QtYRbik3MBGv27Xzlr+vl.9FILxe9p.p562tYkv+wgi4zTp
AlJQVJq6nJ5jqBKHTDlJb0Uvc5OGrYlLE2FYmmlk5LNPOAqtXLmuFZm0VcT9
LS2UICm0FfgfxzMkEE0SKvPyZ6mwCt8AclysOBVFxnVTm919XlegefG8RG2s
4.Sj48MK0dt1884.Z0zFcbF59IxLm3M1VRG0vQNZHahrKtexE2O4h6mz3wBc
.SprSs1W.fDXONt0xlbzrq5Zsf555xr4p0j6kKoVJ7o1UO2nUWF9PWaErvtV
VFBsfN1EnETtBnC2BT8QK7jiV70DsJ5IwHwSAhQk6cJs+HF5rveOvRNTlNPO
b.YM4xO6NgkwGkjq5yws90CouOB4L4nzunzAQzEb5P9fsNfxAh2oBWthYb+G
hwXy.U3Bds8zfWRCVIj9iWNm+JwKiXP4VyL.k3L2Yw.RKKyMjz1kkc5CPo22
61erhLCFMZs.abjRZzIt+FSwnm+iCUfEzYn1QwrmbvRwn5hC65FqEN.qrb0U
1mI8.9zVPSlkVfT1wAO65AO6oeL4xswOW3POcAlT6300ZZCVNn4px4XGGyvM
fYsL5Dchz4+BWbyt+X1wvJhq8BQ1ljZKbJS4ZCQ8dDJb5Umk778u.HPJTDtm
Dxfj1Z4SGEWkbsARZ2gqcukAgsnzibpjAMn7mxzeUXs6VGI1qmn2zqeKweMu
cEE+B.YP.ior1HyzClUuErld6Y4s3W.PyAUT0w7aKCeIb+WLt07.qtwjfkkS
Yvh0evBN4f0uhOoowGABkms3.1zBHZxQpvnfD+WLOVYIkpr6uTE9sg5cbN0t
OT06Nm8p2I49YyPUuyN+0tiqNUX+0taelqbWM9a3J2om851ygpAqamLSVznE
zRrXaa6oZQi4J+G7hFwml0LNjnHVlsDw3AFSnnYXPDaTZdUBbx7jyLfkWgys
PoEZR9URWJvyjLMESWjfYRp+h0I1.jXpZAaVPApZSDqljYDYz4.+LxzlLlmC
g7tijpwLCslpa+gXmKMF63YSlCLXpcG5OLERP6PcvXrDntDJoI4HvCnWuVDK
MUk.Q6xz4lRj.g6v74vSIgspcMCQO0rhJRWhbDYRqfP5xLyPilUSz0JnZLZy
vRP5W0rO0RPZW0pQTyv7pal5FszNZRUzvNY5fwpE5NaExjUBcUDBMZsPWcdt
ygTnjIYaYnUGpDnIl2oaQ2+atbI0FPR33FjgHJqRPFh6QPFReyEjgNxbQTQP
FBujiquDjgWBxv95RoBpEvfmwkL1BgNHcCwvlR1oSuqd7KdA.WPLGTwTwvCb
f9PJ1ZdbbfNYmFnEcpNLPVdBNJSypCt2GFHxc58fTiFJYDBaWf9H8sgAbv81
yfXWQjGoOMvkLbLFPjjMCb2OiGAKUPLI43vdU61elNRxvXYdkQMYP+ijrYfa
+IhjLlwQJoEFCHRxfuAhjrbvBwF5PP1bIRxbgbqxDwOFSDKYPYrjwLQnjo.O
EuTAss5cnjMChf+SUnjkCZR6IFPnjgfSenjYTiv3lrrKmr.wryg.5GhMnYXU
ALa5kH5uiPFz5RH8ezbffCIaFSB7bHj9gKLORwPmMgzO1boVCEXAYmagzOqT
H82KGAWary04RH8qscXJPSsYXu1CoeCtIrpMMTFmOPm9GO013y9.XQAV46te
+CfE6YxN5XtYGQDzBFsvv9Ar89ny8DalXk0zwXIPnYwRfnlbIPJnxFNvE+fd
Cr4W4fEDOzzQ4b3DNbVXdcU1NRhB4RpNUGzZ3xUj4gs7XjsfJZr.DnEfJLjm
lM3An1cUpIrpWd52PW4wzB0PUl6zlrXaOYDiflRdSATJU9C37NbmKiMgVFFq
vCcj4oJYxZZBm1tzVyL.5219bNADKkYrGb9GlLCbXIS6rRHGU71y5+Pq4xYg
AbrL+1vnfMrhx5LQxo4DsILK+zx09lW.SkuUl8oQjAjIGT982fY262bYxAlz
VQ5asL4fyLHHXujDEtjDEtjDEFoDXfM97OAFncjhaYxZg1gds6LHYNjGuhSZ
1b.Zx9CLZNHUfslAwoKxUy.m11nYE.mYQtIf0wj2fYpE5NNEwlCI5irX821T
0BsCkcSZhi9I0CAVvLUs.MCRDNHXWzeCm5jHBxjSkAc6X5vXZSJGPiliCzU0
IzjJvg1yh7ug1pNslCYAjIHE2Pluo3FcqZ3VRwMrINstzBpQm3pFo4pFYZqZ
0nGsnpYOwUMVyUM7DW0N8Y5IsSrPz4PhExdNjXgxlngL0YVHitXZ3vm4+MXp
E5tUiapEB5BkoVd0oJQ5QpEx9sVpEBKIXwKYVnKYVnKYVn4tC0CozxgKKcfd
U+rHbYMnO8VEtjdUw.br24SvxRLm+hWAxjr614PvxZxAkDrL17vYtOGk9ZmA
rsXlGqjbT1Phb8YSvaPM2fwbzRZMyq6Hl0vwOER5XgPjyPygDvYvfPWSlJuJ
vJoqQOjAgn2.QPUNZYAG5fP7LKr0ohvV2fg2Rg9KWImuoij1knVOG0PH7kvV
WmQlHYXA8JOt0krIHydhYSvBPUJ8M.5Drs3ambdjnbfVD2RFnMfLkC0cVX5u
i4gJh8.SUN1VuAr7WgVtC0lCa34dRlvkq8eW18xYfaIFcVjHeM3dhUAtF7XQ
J67eA.kQrAOdj5b9m83XnQZNQ7Y9bh4H0vGFRN+mRTAVCeDH8beFQli8NEVC
dBQqy7IDKiV7E+LzQhuARr8kQL1fGNhNy2YZlEduQiCXyoIygSrEYxr6UY3R
Mbb.aPM4MP9MtLhM3gij4v9PvLFVYKCb9bAq96K.Dx4ehDRAVtC0I.Hz4w4d
.W.DG7AxZg3bOVXjzzKEKIlCoXFD26C7fL8K9Q3.rmhrzqDyPRJxAa2e4LzY
8wcnFNpx6PC4zNHv4w.RF0JKk6IN.mrgkl5fHyU6KouDQ1Is2CKeSk4lxwMG
2Al5lvtS9PyL6VMEUeIyJOpMxY.lUfYm+lUn.qAuQNXmy8MxAKO807cRc.ri
4bXmTcLFAeofI01n1+UKheCrMpJvZ3i9nm+7QHzs7vO2WyjSqYOHibjZvGjA
F9FXDnDrF9HPzrYY0TwBqsxVWMtedtp1hXLmRY239QDgtm463LBwjImcDZnj
IwLwDKjACHA5hcP0PXnj4vNyyaLFGoFrN92DztgDrF7VmNKXcClAOtmBcUT7
PEqvm+LnWNZMb4pYBqajS5FPD2xAEqaP4FT3XxMCDVxPBjE60MoaXNcXJbZv
6o0aAN2PgUPmWIbtQarLgW3il7TLfRaRczUpBNsjwtgYmDEBfuvNIGUlgRtv
NIGGkPRpH9UN6jbhN5Y0lJnXdqAbzyS+wacJOUPkVaqW874RZbvK.WnUO2Nl
NFRcpiQkA6MhM86wfoY.mbmbPJbM.Jvw97GpjxQR1v6rlrfT1L55dgrf5igS
P3aMxBxcNjmvuvXQWXrnKLVz7mwhX5lSeYlLe9yzMm9ZzAp5lHaYljTAzcbp
M5BOVMu3wJHaNviUFkrfr0cHB0nrokto8ZQXD.nSLmdQLJmdoqIN1lLCfS01
ZOSlS1ortHVfMUsPW4BpIUWP0UAN0jpKnjtziXrZgtJvolzbOptJvoFcjptJ
vIlj2Bn5p.md1yGhDcUfSLo5BhSWDKLkpSh1JvM4ZTI5JWPLo5BBoK8HFqVn
qpShIWMBA0ESsL0pQHv4v5.HZS4KlzBbr6LfCdv5pzBaxNDLqKDLroVLBVWk
VXSZoElzErvTSif0l3oIm+DcLbNP+0ZS2xXno4aYcpEtWna4Kzs7E5V9nXwY
McKeghg6AECiN+YX3Kb6qQqZ3SNolp8gLAmsTAK0Y1xsu0rQzyEFQlhlszNL
wc1Rw0jV5PclXhAukgAtSbUqETCNwSGzFepCm34CZiP0gSrV21XTc3DOYUaT
pNzPSIXMG1ezKjQc2Ii5D+0.XGXi5Luu85RAaZsI5JDSQbXt0GdI05d1UBqD
m5oiZTOZ42uNh+R5Pa7f3Ao11njzKckQczgIVuqtOJ9IuzRoiiiRB2t4ASCu
7h4xEo9w2JoV3Rtn7H.HMHJ7q1kZP0AkJGcnsHD3JS6RGx9rGUFXWPqVmy4O
ODBj4MCWBdzDBfE40ooQJvHJDPxHXXHJDfycEBXYzFLpJDPmSJDTBA8WgfKd
tqO.CYis9.Wx4m5.ni0.UG3vl6pCftnwVcfi84j5.kPP+UG3Pm6pCftzwVcf
yzpNXiu+GdA3sLM34rUUkP.3NfZUSMR0a0nDxjITDHxpcwB7gHDaDEKzGEPi
JJfsPCEEHSAJ.GUTHWCw.PgQzhgznGdf2lFOEfTHRlmgpOEnbTUAEzAZGTEL
hc+7BLNB.gc15.MvDI0Oai67bBErXo4Z2Ki1FxgZQh+ztiRCWKm2P7OMENXY
hEGlRSpBDzZ.hFzBRFSfX85NNiYw+ZeJ.Y90folzj1VSulwEzFT8QTeqnde6
JuTu82Eurd1rWpcw92otsCiL6O3+opgA9UO6sdqpwtyOTqaeMUOJp1G0RmGE
W6ih04QI8uTo09nHcdT69Wpr92Vc5emia+qvPq9WrvFjmtVuFLb.xTPb+6dg
CPpBR6eGLz9nOaO2Qe+mtye0NmhXz2xcNth6wxp2+25nHUw4WzirJaRMZRwF
eRj.9TocYRDMZuxEThNxbl0MwAx71LKx8m2GrdMvZrZ0LV1TjNYsZ6tuLZh4
WoPJ3NPxXuIRp1sszH5isGR0zcSFwsTtgF9J+0de5E9HPGw+5.BrWlPp9Cfx
Qz9wtYlH51cakIi3wqTIYQNJqD.JyVXNvdt5nBhWZd15jTqQ+acr4bqixFVi
y76fy5HuUO4mj.RB9q9AgIdOsIAXS6zbx5ncRlVugTmNqcBeBlLB7nW53pTR
MpUIdi69bv3FTJCKWlReYor4Z7oT8e1ONQ4.F4VQek2lMk95JFQxgneLJtxJ
LthW2jeUgsvWE6+bP9yWXo5Udw7VdJuYuMVBZ+j8tbr5UOEsxONbaPImpM29
SwKrXW9xFZbiskhq4nxiJP.g6RNX28v5nkePZKZ9BKtJZieXP3lX+D+vzB2a
o3xq7u2a65zauOJLUHfKWZvhZu98dK8a7gK7NkuMNva8NOXINXUTnnRTArEe
cdwwEEjsJZ4FS1cD5solGVZQdCWLg2H2lbmWrnuPsAWnBuiIJZc0KU7bq8uO
Uc4MAgg6ghoQaZ9hwAO7XKO6cQ7K9Tau6rqjb61P4UukOZL8VwpOpdedqWqF
dV80+SdgAO4k5mFH6BPVEWTtIeOlrLVrCLkauxq7bMWYEWLdo+GCVk9XVAUV
XnC9tzNOQpE2UJY6cpgo2l5+zl07VQ0af25ZJg2MBIFdHAZJVHPraTJBmFAc
FX5geFPGHeA27QyQEH7kjTPn4NYSEPNGX4BzoAwjqWeHTcA5rHQwigk3xo9m
n3QVmyIJdnbYvx7r7PxT7Nm4TDlCDuSEtk8.oIL1bf6qPNFjlhpfWRCVI8mm
QYNm+JwKiXPl6.UhybO6YaTaWV1Y7AsFHaixHyB1FEabjRZz4.nLL1a.lnSA
VPmgZGEyddPYX7oEAPA4f4H3MLpjnvbHFgovTBZxyfGRY8lyQsm9wjRBB4Dv
NHJPStg7DVuI6Ba5jyOH+hW3ha1liBGHt1Kr4+G0VjY9YCjBRgSu5rjmu+E.
ARgbbiPHCRZqkOcTbUwUTR6Nbs6sLXa7pE4TICZP4Oko+NxiMycemLReQuoW
+Vh+Zd6JJ9E.xf.lh0HQRx61p2BVSu8r7V7K.Cx5QT4zkPo6KRv8ew3VyCr5
FSBVVNkAKV+AK3jCV+pW.VFeDnh.3GvlV.md1aMLJHwjLDUNVYIkpr6uTE9s
g5cbt6RMT06Nm8p2UlNLb06ryes63pSE1es61m4J2Ui+Ftxc5Yut8bnZv51I
yjEMZkQCm7ECOUKZLW4+fWzH9zrlwAPnhR8QX0vrKDpn1GvnD3rcuPnhMjSg
LY1NW6jc9EBU7BgJdgPEaEKny.96SHUflZ56KKKnclSeecn+.NwLMjQo0lY.
g7hkx7SaFbV678d1z4voNSqqHXySWZjV+b.O8TmFo0NwvaVxSvpiIgyoMyvO
AIhbm4ahH2oiY0+SXhH2VWsilTEMj9pJK6aTBGPah+0n0BzLf0ZfvNTIL0Tl
ZmfgcMno0vgq6+MW9EdCHIbjCwPUfkoBwPb2CwPq2bgXnC0sRHFBstDhgWBw
vKgXXOcnz0AK+fAOgKU9tyAoa.F1vgTfmdG83W7B.tfXNnhohfG3.8fTr073
v.cxNKPK5TcTfLU1HTlENcv89n.QtSu+iZz.IiPX6ByGomMLfis2dFD4JPKC
FGYUfKYvXLf3HaF3reFO9UpfXxLaE6UsS+Y53HCigYA7iZxf9GGYy.m9SDGY
LiiTRKLFPbjAeCDGY4fkzIYFxPP1bINxbgbqxDQOFSDIYPYjjwLQfjo.Ojkb
8m1V8NPxlAwu+oJPxxAMo8DCHPxPvoOPxLpQXbSV1kQVfX14P37CwFzLrp.l
M8R772QHCZcIf9OZFPvgjMiIAdNDP+vElGoXnyl.5GatDqgBrfrys.5mUJf9
6kafqM145bIf901NLEno1LrW6AzuA2DV0lFJixGnS+ilZa7Ye3qn.q7c2u+g
uh8LYGcL2riHBZAiVXX+.1dez4dZMSrxZ5XrDHzrXIPTStDHETISU9CXwOn2
.a9UNXAwCMYTNGNgCmElWWksS8zYn9H0afDcZAZMb4Jx7vVdLxFxsh2BPfV.
pvPdZ1fGfZ2Uolvpd4oeCUb+.TCUYtSaphs8TQLBZJ4MEPoT4Ofy6vctL1DZ
YXrBOzQlmpTIqgS+vT6RaMS+S+vP6y4zOrTlwdvYeXxLvgkLsyJgbTQaOq+C
slKmEFvwx7aCiB1jKpwlXhTSyIZSXV9okq8Mu.lJaqL6ShHCHONn76OGxk73
PG0TKsUj9VKON3LCBA1KoPgKoPgKoPgQJ8EXiO+SeAZGm3VlrVncfW6NCRkC
4Qq3jlKGflr+.ilCREXqYPT5hb0LrosMZNAvYVjYBXcL0MXlZgtiSQr4PZ9H
KR+sMUsP6.Y2jl3neJ8PfELSUKPyfzfCB1E82voNEhfL4TYP2NlLLl1TxAzn
Y3.cUcBMoBbn8rH6anspSq4PN.YBRvMj4aBtQ2pFtkDbCahSpKsfZzItpQZt
pQl1pVM5QKpZ1SbUi0bUCOwUsSeddR6zJDcNjVgrmCoUnrIZHScdExnKlFN7
Y9eClXgta03lXgTbUfJuBQ5bdEpHkG7lIuBgkbq3kzJzkzJzkzJzb2a5gTZ4
XkkNPWpeVDqrFzgdqBWRWpX.d067IRYIlyYwq.YRhc6bHRYM4fRBVFXd3Lem
iResS90VLyiUR5IaHgs9rIxMnlavXNZIsl40c3xZ3fmBI8pPHxYnIPB3LXPn
qIyiWEXkzunGxfPzafvmJGsrfCcPHdlEy5TQLqavXaoP+kqbY45HocIj0yQM
DBeIl00YjIRFSPuxCZcIQBxrmXhDr.TkReCfIAaK31ImGYIGnEwsjAZCHM4P
cmEl96XdnhXOv7jis0a.K+Unk6Ps4vFdtmgIb4Z+2kZubF3VhQmEYwWCtmXU
fqAOVjxN+W.PYDaviGoNm+oNNFZjlSDelOmXNRM7ggjy+oDUf0vGARO2mQj4
XuSg0fmPz5LeBwxnEewOCcj3afrZeYDiM3giny7cllYg2az3.1bZxb3DaQlL
0dUFtTCGGvFTSdCjbiKiXCd3HYNrODLigU1xnlOWvp+9B.gb9mEgTfk6PcB.
BcdbtGvE.wAefrVHN2iEFIG8RwRV4Pwug3defGjoewOBue8TjhdkXFRxONX6
9KmgNqOtC0vQURGZHm1AANOFPxnVY4aOwA3jMrzTGDYtZeI2kHRMo8dX4apz
1TNt43Nv71D1cxGZlY2po34KYJ4QsQNCvrBL672rBEXM3MxA6btuQNX4oulu
SpCfZLmC6jpiwX2KELo1F09uZQ7afsQUAVCezG87mLBgtkG949ZlYZM6AYji
TC9fLvv2.i.kf0vGAhlMKqlJVXsU15pw8yyU0VDi4TJ0F2OVHz8LeGmQHlLy
riPCkIIlIlXgLX.IPWrCpFB8jLG1Yddiw3H0f0w+lfyMjf0f25zYAkavL3w8
TnqhhGpXE97m97xQqgKWMSnbibF2.h3VNnnbCJ2fBGStYfvRFRfrXutYbCyo
CSgSCdOsdKP3FJrB57JgvMZihI7BezjmhATZSpitRUvokI1ML0jnP.7EpI4n
xLTxEpI43nDRxCwuxoljSzQOq1TAEsaMfidd5OdqS4oBpzZa8pmLWRiCdA3B
s541wzwPpScLpLXuQroeOFLM82j6jCRgqAv+M1m+PkTNRREdm0LEjxlQW2KL
ETeLbBBeqwTPtygjD9E5J5BcEcgthl+zUDS2D5KyjIyeltIzWiNPU2rXKyjL
JftiSsQWHwp4EIVAYyARrxnLEjstCQnFkJszMmWKBi..chIzKhQIzKcMww1j
o+ap1V6YxDxNk0EwBropE5JWPMo5BptJvolTcAkzkdDiUKzUAN0jl6Q0UAN0
niT0UANwjjV.UWE3zydxPjnqBbhIUWPb5hXgoTcRzVAtIWiJQW4BhIUWPHco
GwX0BcUcRL4pQHntXpkoVMBANGVG.Qa9dwjVficmADvCVWkVXS1gfYcgcgM0
hQv5pzBaRKsvjtfElZZDr1rNM47mkigyAtuVatVFCMMYKqSsv8BWKegqkuv0
xGEKNq4Z4K7KbO3WXz4O8BegXeMZUCexYzTsOjI3rkGXoNyVh8slMhdtPGxT
zrkygItyV9slzRGpyDyJ3sLLvchqZsfZvId5f1HSc3DOeParoNbh051FcpCm
3IqZiO0gFZJAq4v9idgIp6NSTuNxa0S9II.qNvG0sxD0HrJyamETILT2ohZX
CTQ830p+B.rCM2xwAYsASijZUyXPZda8fzSXsNidkVr030h29je31N13tVb8
i0sJyrmDYGpsUm6VKhFV9aOlK0m5Geqj3jK4.1WEj5+jxWnuZyZuOIpWWK9Q
ZrWP3UkKsR.Ed7DMdvK0Gf5xfgigbXY76Qk4XCxQ3l8ZDOfMHdfFuV8cau+d
+3W.2Grl2ujPDgxO.2ATPlzC1OPppMqMyrJwRFPTOjjLNbrAfBWcSbzV9Oit
+lMd2D7zl3nmEd4exMg9wOGsM4F97AdK+vMq7EDReGvp8BykZibJYrRggNYJ
Sbc6LH4zfJkxkozlfxSjw6+8elK.nlHqfGy81rozWWYlXNf9iQxUmbcwWEDJ
+phv45pXeASwKedZw25Eya4B3aarDz9oR7c3UOEwMaIbaPoMmHelYwKrfmZj
w.DSFjYxv8.ZQYkB3iqtiOq6xOrGawKH79fvMw9I790BqDJQQ626scc5s2Gw
60C9qRNtGsn1qeu2R+Fe3hI4+13.Q3FlaHPbvpnPQknBVK957hSvK0xL2Z4F
S1cD5solGVZpRCWLg2H2lbmWrnqPo3EUXjQTz5pWp34V6eep5xaBBC2CESi1
z7EiCd3wVd16h3W7o1d2YWI41sgxqdKena5sByxpdedqWqFKW80+SdgAOwUo
mFH6BPVEWTN4yibK2hVutR6Udkmq4Jq3RwK8+XvpzGyJnxBCcvDvcFz0hUeI
auSMJ8V9jh7ICS26F3stlhaHyFBV5F9mxQjTz.iBKjAiBqIHn9PRnvVQXy8O
p9fyvn5KuvpKtPs5EbAcvBZA01gIR+OrENXLlQDbq6AJFylAqjxZmEV5.ohJ
3OtkuRw6CVVLKPOXEHqSS305kFs5NCFdsJ4SLFsvkOaJEyMZ0Y1mtRZAvdvO
7Ev2rZabVmK2.TlwAOpi0B9JlbPN0Zhq1nmqdp91yZtp3TiV00jkc6830YgW
CV40rkdG2Zulr3qhUe6Y4GyAtyxOWnZcV6oKkOe9pfTQ2zcOrLZsrJ+exm61
85R+.t+CUmEiZX0nNVNdTqG0zBxVrhTOKIOh0jG0hxiZU4Qrr73VWdTKL0vJ
ScrzrKVa1hEmG0py1s7rcqOa2BzVsBsIKQq2Zzl0KdbqRq2xz8UoruV8Ct9A
lUrxW7DWW8dpuN9YGM63UXoPcC7ZzZVUNoWRID1xLWEd+gS6aCxdC6aSweaY
xih2aglfe4umOdLYCuAr5Wc0gkP8yTnLHbk7U7uFjjFE+IfbD763xRu+q9g3
eH7OI1fNP9DluiPDo3XdqkWs+Zn7VD+KHbYruvZOvWmo97KKdjc2x8f2Ie6f
e4WCr.+C+CfkO5E9f+6BBguG707G78+sraNUca7uQ9zo+2he4uNwGT5s7q.V
uGr+Sn9vMf2UTkde4WxOjJ9IGQf7aN+MkU1e0UkglByPpZJxPEdOvzjplmDD
BfipfcKBukVJ191iz5xwZaoGsYX2zgp7ZSWf0lwLhL2FhY5AZsLdlzNnY0Bn
UcF6CRXHGhk0c1Y0fnGOxVayc.pdLZcputu0OXGpe1Gs9U5h6thgWELrWqBV
tEmXjSwZxll0+1V9y0ZVuOBRDjPQSMBhNMHXxRt05uzuzNEY+M..p1U812mp
lZwUD4iES+muDLqCV3kAQj6WGwe4kqKO6s6.34W5N+3+S5+UeR8x5lAAUaOf
fFNcXtV1170qV+tCbeT7Sdo6ylCcOknV2gsBaN8CVtsm46CEN8PMt+v96yvy
dq25GceyajvtJCuq3g8gd3+U0MCX2cm7XTbZq8TUt87dFbCWOHLHkuL55Qj5
tSkAA16MySkar7xa+75lvYTmgQKYYhQkkwVN6KKaaO1xxzWqxx3tILSl.gYq
82nr4k.8nq60U5YNbEtTLkXCMgtW7wjWsl77kabTRxKh9+Akvb61Y.Bs45Jb
YNTdG.yp2YrSG3oIy4pk1UjY0tJ4EDhKagCwAgMgkBrJVJvQffm3s5r8qrhc
u72T9UpdgWSJjIcSgL5nJjsZ35OwAxCAwwPmMZAs7xYmTaKfl0NYWnPWsYk9
Iugj9ocS5GNCk9gmBY+V24Fz.13AJhs.Oottfs8j65BKWGr4EvM70QYad+Wf
QV.cgN1jFWWhNYdd6STVBuMAOxPj6bQSrKyXOC1xPmgffT2oFAwSOBBsGxtt
5RmZkenW26asMBO0HHbxm9H8wX+jG4qcUXIr48gKLGmsYVLmqAN8m5RnSOKv
EE5uIZs+KxM8w3.GxxcAFJ7YyqAt8mMlnNyBOGzfvkiLhf3ijIPKaBUP0GMr
HmlbnDsVoSUZXuU+I6hSFdfSFBkNvdtyraI+C2C8WvN3bgyCORDN0djnJTct
3QhW7HwKdjXm8HQpxO8KEt01BBRtc+QD1a+QjZZ+Q7K+E.o658DW+nWnJZTu
V8k24k3uBDEBR1twOlq2bc.WONnx8Bt6SfebA3okK8hSC8+j5QuQ7eJOAj+u
uS7B9M4ufXeu0.w3Bf21UAQfjOEl9neRPB+SIbIpeHDv+ueSzlOkMnF7tkuW
L7AA9ewa5Ife+xeirrV.910qAY2SBPnKN9Y+UKDkGWSvl+wu7K+3G+3hrhHq
DVvWp.+hYu7u+QdosIN5AgeWx+38w99fjn6S+nWr+WA9TzVvRdaLl2TST6TH
HHE3Et5Ki3HPzpf6+j7Mw+1sghVEuI.3.xSIfn6y9i+k+veA7u3G5Gyas+os
2sNXI3eiOtMLg2t4Et3aRdjCv2odShm42JpGempd.9sh3gU5em.+.90iApY0
An7RQ8JuFDEKeMuyKUT+iAQY5.dOuR+IfXLZwCunITXWicEHHL60+HWeO+C7
2Iug9w.NdemOXah+8aWes7kvucv+9u66+W+i+kuG7s+g+Cv+929m+ye6e36+
O9J9sm9nvq.4VoHeYAbkEA72MuwE6El9IdaP9N98+y+4ey+J+g91e8u6e628
8+G71B329699+v+728cfe6e7OC9Vve5a+ye+u627W9291+L3O8W9y+o+328O
u..9NeQUyW9JZAsuOqKiimq7S8BVmTz9+O3cyI7p35UfG4J34c2K8C3xP.Ov
Rtz2w6HkuFOwF.m0Z429ND8qDtQaXT50fOFysOBjFcXWr7Erqe9ZvuKb4BQp
MfeedgeXMua36R4OA+s7aCtmWB+10QQ7Qn+5njTws+6+VfEBBstAhsf.ve46
91eH7W7k4dC7+jWpG3Yu0uiZ89qAdO3K9Pli5l6IxO8tJtfrPo06bkNdLh+K
ue5qyeBw7fBW+keGfaT9L7lHg2.ei7O3FDsUbGAgvB2QV7uu7KAKWu8ojOAD
6t70Yxi2wULyEH+n2m9eptENVk8pkdqbB3i9x9DNpE6KdPQ0W5gyuK6F+YeM
3oBOSl2E+tO70VeE3C+xUAO8N9s9d9m+huFVbG+P5lnO3Ktx0fOv++U7W4re
7jp0UT4Euz.wKM3Wl88ffxuPQW829fO+g136+A4KNH+sxqjEW+qABnqREQfZ
AUcX5L+tt3Vxe3uXm2YWtAntboBbWyP7uO9HesAuCvKne1WaA1Uk8y5Bypub
ohqE2vMJ+KGjUok8g+Rf3N2G5xdBwExdt2WS0ZGPHewGbiIfaJ4t4.Ya9N97
Ae3qpqAHdfe1dvWcsgunRa.HaD+pwnQ7E01H9B8ZD6JvrZToWztRyp5qemWy
uqAlIt+kn2+9Jipdi3G8RStjQCo7mvAZuUWbx91W20Ypa3KgbFU5E9zQAz6h
S52UPeV3F+zyH23mNYtw+fcgZpEZ2t1ODWnlvZvEpuwZAT3dUmLmnV5f.s6b
HF0unPt66b5z9Ge0DZC9.BsAO.A8J0+Or6j+ezem+HPdDRKNl6gPGc2CIaCY
MuChHRVdbSkp83BxVHveGrOh+5J1WxoFHt89nUH3I+nUtw7YvBB0dgMxkfDN
cJr+fk0oArzxs6vl0oSskxTlzEowuZCOEV27gN7o1k9Ewo8Lxi9aYvehXmWe
gaUmnJa9yi1EtfQIHFR30DN89j7QVStVSu6RLudyxC+wr9m4ebmdOmKwOUtO
dQ2WbBA9oez2Wrk0dgq3p2.u6wfGx1Kag5gDPVJDvKwGrbyVvVwb8uu7qVrX
mkQak4SKReVZ.1gIiBeY9XwRl7XsZ4H+c67I9ivMdh++u8iW4E50Mm4YWtG7
fEs1+70rtrrhIIFJGEsApMOKXFhe2tKbqMxT0BRWpEvol+4qgNDMLUlncUqF
RO6ofUahBBSSxU0lELZDtR.rEDQIWWDyCEe0oj.YnyABRiNKX7H8IAV7bf9U
MJGBpMkiRO4Tdj1UsZnV3FFL53tv0ARDIQ3x+8oTECVadwyxfyDnMoMl0IXp
YBP5VKPPM6gwbCYcrw113793ceyorWF0U9x3zMrRa92CNKHfOq4.02YSmCbe
miIY.aHsK7QlwpE3tHW.afhWpjysaXsLEKWhuTS6J94WtWvVeUVrxyLW5Urc
K9wIkyzM69w947FukK4qfshq.6HtUGrKBZK9Dyx0whb3SVwAhgp2s5GVKpP4
zWWB1iEDYPMKX8pm3srfxZWpqaqB3rWRDuc3oRSjfvTTl2NiYbycy9DhQnPU
yz3U8C1KeSz2d2C2GrdcQCutMlLemZt5gXuUAU2KCElAKjKDwUA65Z+zAdLd
1ihxeTliCGwut1OU+il+jHWKnalbHVIGJ9D+qf07jdgOnb4Z1d9B7l3nMQwE
9m9BrakmaaZTA.T4fzKusjMKJb3H0tKQreZcuCRyY8+DtXrEJ6SbbB6NZRxu
4HlpjMwby2tW38hKE7SkzKp96WAfHmwhppvpX5vRlbLs6NWUY6ZbtpJmZd7V
lF7b17bB54wXjyi7bxrT9p.s6HBy3ryy8q2FrZAGWBe59W.eivwT4.x2Dj5K
y9rI.nkE3a9XPX1V+xEX.eyiQax9CaB3a7Cel+vUAzuQt6vhuufCjTe21Mq5
JmPcTbFJytKNRlCy1lzcb113RdEbCm.43fo2SaR.74Kr5D6ook7l7WvCOk1i
iCDiiChHMJ4wnzW57PNMT9jSnZ1clVvnVluk683KiKwVoZ0XY68vSW5nsZy2
cmc5N4GNYmD00n8SjwOHTlDrb6d6uHi3YP1Q7kxmK6H2vcsk4Tgt2vMeOuvO
neQZoQyM95DpU8iRwYFt81Ftl1Ft91l0LnsAGZaCY71VtIRRaDQ6hwciXbDV
dhsPKV2mrZ7rMx+utxa4KcqqTQfARdRIOeH2ggfERoqiV5UNPPGgt1pmhe4S
veMuA.7.xMCJ6P6EDCJ3cqh29Dva8CQYgV1SAhnCTbUt8fqhj+48wQOs6Qy9
quiOY9lf+ZVbDtDrNHg+tEQL9yEGyesGwudHrzYoj3KxpfoT0V9fxFuwJBDj
ulvT9J+TuyGCpxBX0zlNb6jJuYADlE0woxR9afOTu93rlqL9ITIVCq7epMTQ
JFKcnC5C90QqWUza5+f2xOUr2MkecYD7oLpqsK1phVom1xwXeYy4yy4TRNds
llSkxWrcA37MJX+OTFb4SqFwKk0AK+Pyi1v6OjAdUIwkr2UUu1PJ8r+dupjg
Nzq.prmqMs2yUN1f8NihCDb0tnI5VzvQuno5Vznwtncc0nngVk1g69WTN5TT
LSz2pWQaQpurgCqr0Qj1szAb0+RBoSIgGitRnN3oiQ5J0pnsnlnqzgoQYivl
nYqUQCsrMRy1VG0SzQPtxQKEgrQXrhNJDHlPWuNEL1D8hZMICzBNgksU8kMx
7yq6ZDU+5UzXizpw5NlchJZi.315YMyHnox1VWS1visFDsJZnQlIvVGAZ6QP
8rsNyxSbMRaTmhF4Xh4FrsznnoiA9R0QFhRGiRRGU+TxXTR5HbRQiQIgqrTr
FlD2crJI3wJI1XURG0vjQQhPmkoPwiQIoy3I6wnehnyDOjwnMQzw.xwnaJyS
lgZJjOt5AyJZzzUzVZNfaJZ0LSLmmdsZpwJZ3zTz5LgwXrwLD7oZLqVlMQFq
RBpG1otm87RdG44XByReN.liUweMzplNZ8QiBHnS2pkQDc0oe1xDZov5LSGd
LF0f0Roj0XTR15Zx+fKIcrFFMFVjf0QDgYjsnEOciKv5XaIYTjN0QUqiI1eE
sJ4F1TIr4KYnQ1+a8JZjQjorlrdZqIqm1Z55oslrdZj6T0SqUIajdZsJYyzS
qWQaldZcVEMZL1WEjNSFhGCqQQ5L2m8XL2GRKkwigULHKc2P+AWR5zMMFafC
TGodzXzjf5XVKiZhg15UzF4LfzqnMxgtAoZdpxieiVqCXkXjtZptZwgiNdSz
ctqgdbe66YEMOA8vKI5IqjHmrRRG03tiwBrgZsk+1iUIcrc.6vSaR5hj6wQU
hxXONoZOtn5PNnpYtmZeNmJKNN2K.zks05C778hC0+1m2u.RteAZtdAYtJzT
aHtVqFSqk6baJXxquI24.HeTpVUBT7wpunl.COOrcaLfv6Yvf2y.AueAAd8A
.dyA+cCA9cdvDWe2W0QG50KVN3t0P55XAzc2jr3Oy+8m++GjY7p..
-----------end_max5_patcher-----------

Hi PA,
I did not follow the entire description of all messages and trust that your ā€˜stepsā€™ provided in the patch get me going. But Iā€™m unlucky. I completed the training, but the patch is not playing anything on the right channel.
The output of the sprintf on the right side is not connected to anything.
What does the copy training do then?
Thanks for a quick hint.
Hans

Iā€™ve not tested it yet but based on the earlier version of the patch I was looking it, thereā€™s a fluid.bufcompose~ missing there.

Looking forward to playing with this to see how it performs, particularly the jitter-y stuff.

Ok, tested it finally.

I can see your confusion @tutschku. The numbers donā€™t correspond to the order at all. You have to read through the text on the right of the patch to get it going. Once you add the fluid.bufcompose~, the core patch should work.

I havenā€™t tested it with acoustic kick/snare/hat yet, but I tested it with much more subtle sounds. (I went to record some new sounds for this last week, but as you know, I canā€™t really use any USB2 audio interfaces with my new laptopā€¦)

First what the filter dicts look like for the synthetic kick/snare/hat:

This is what the dicts look like with my prepared snare/crotale training set:

The differences are significantly more subtle. I canā€™t get these to match consistently at all, though I havenā€™t spent too much time trying to optimize the thresholds or used the jitter part(s) of the patch yet.

Worse yet are the differences between different types of snare hits (center, edge, rimshot, etcā€¦):

Stuff like this is going to be a real problem to differentiate between given how the filters look.

@rodrigo.constanzo did you try it? It does look the same, and all in the low end, so maybe larger FFT size will help

@tutschku you indeed need the real install for it to work. Very few patches I do rely only on one of our objects.

@rodrigo.constanzo another idea is to try longer resonance with higher fft too. Try to make it workā€¦ although the idea of classifier is not what this is for really (there are better algo, you can try for instance the full MOOC on machine learning if you are interested on this before our second toolbox, although that would void the point of making you do something creative with the current toolset) - the fast descriptor approach you have done with my JIT code is another option. We have useful descriptors coming with cool stats tools as part of the 1st toolbox too, and Iā€™ll make sure I make such a patch for you :wink:

Iā€™ll play with the FFT size some to see if it looks any better. As well as some longer window times.

I suspect it will never perform as well as the basic kick/snare/hat comparison since those are quite different.

Iā€™ll also try it with the direct audio from the sensor to see if that makes any difference.

A combination of the onset descriptors and this might be interesting. Not sure how that would work, but worth exploring.

Also curious what the descriptor stuff you guys are bringing forward will be (and how it will differ from @a.harkerā€™s stuff).

What I discovered with @groma experience is that how to deal with them statistically changes everything. Weā€™ll have a bunch of examples to explain that I reckon.

1 Like

Ok, tested things further.

First I made new filter dicts using a bigger FFT size (512/64). That gave me these (obviously more detailed) filters:

Prepared snare/crotales:

Snare hits:

The bigger FFT size still didnā€™t work too well with the normal thresholding used in the top level patch.

BUT it worked pretty consistently with the jitter processing (jit.3m -> zl sort -> zl slice 2), on both sample sets. It also worked well with the normalised relative value maximum-ing.

So with that, I went back to the FFT size of 126/64 and was able to get usable results with the jitter means on both sample sets (even the similar snare samples!). With the smaller FFT size, the normalised relative value didnā€™t work too well though.

I guess itā€™s a matter of fine tuning the post-processing to work quickly and consistently even different sample sets.

In revisiting some of the posts the thread about pre-processing for NMF, I came across the filter comparisons between pre bug-fix @filterupdate 1.

These are the raw filter dicts that were created from training multiple hits:

And then these are the ones from when I ran the process again on a pre-seed dict with @filterupdate 1:

The difference is pretty huge.

Iā€™m wondering if something like this can be incorporated into how you are creating the initial dicts. Since you updating each hit as you update it, you never run it on a pre-seed bit of performance audio. I get really confused with this side of things as the averaging/normalising/pre-seeding gets very close to voodoo for me.

Do you think that would be useful?

With the code I provided, you can do it yourself. At this point, Iā€™ve chewed a lot for you, but you need to try a bit more how to update dicts. For instance, and without having tried, you could have a refining process, in which you train on one of each class in one passā€¦ like the seminal piano example I provided (but with smaller number of classes)ā€¦ but again, you are trying a lot to do something it is not meant to do, instead of trying to do stuff with it it can doā€¦ nmf as classifier will be slow, creative, and divergent, as it tries to combine the 3 dicts to make the sound you try to match. Think of it as a division.

Iā€™ll try adding a refining pass and see how that goes.

The results do seem more promising than what I was doing before, but I may abandon this line of inquiry altogether (for what I want to do with it) and focus more on ā€˜onset descriptorsā€™ approach since it doesnā€™t require having classes and such predefined.

Either way Iā€™ll test it more and make a patch that does all that.

I thought that was the whole point :wink:

indeed, so please continue and fight! It is fun to see where you will go. Abandoning nmf because it is not perfect is a bit sad though, since there are many other things you could try to map to that approximate polyphonic classification (which you would not get otherwise I think, but here I might not be rightā€¦ Iā€™m still learning myself!)

Iā€™ll definitely keep testing and will post my results.

Not in general, but in terms of what I was thinking specifically for the performance.

Ok, did some testing with acoustic kit sounds.

I recorded everything with a DPA 4060 magnetically clipped to the snare, kind of above the kick.

I hit each drum at a variety of dynamics and created sets with snares on and off.

Here is a ā€œhybridā€ of kick being trained with snares off, and snare being trained with snares on:

The differentiation between kick and snare being subtle came as a surprise. I imagine this is due to the FFT size (128/64). The hihat also came as a surprise. I initially recorded hihat hits that went from tightly closed to semi-open, and when I saw the dict for the hat, I used only from tight to closed, leaving out the semi-open hits for another set.

I then trained everything with the snares on. I donā€™t know if itā€™s because my playing was different, but the kick looks more differentiated here:

Next I tried training everything using a ā€œcompleteā€ set. As in, training the kick with snares off and on, then doing the same for the snare. I also included the complete set of hits for the hat:

Surprisingly the snare didnā€™t change much. And the kick is quite similar to the kick being trained with snares on only. The hat looks a bit better here, less ā€œbroadbandā€.

And finally I created a preseed-refined dict. I used the ā€œcompleteā€ set from above, and then ran @filterupdate 1 with a recording of me playing a beat with the same recording setup:

This looks the best, with clear differences between the hits, which makes sense.

In terms of how they track and sound. None of them worked super great (with the default ā€˜polyphonicā€™ patch). I didnā€™t spend a long time with each, as my focus/intent for today was just to create the dicts which I could then go back and more thoroughly test and compare. So that being said, I only really played back a bit of my recorded beat and messed with the thresholds at the bottom of the patch. It was difficult to find a setting that got minimal cross talk between kick and hat with the snare still working.

I also didnā€™t (thoroughly) check the the jitter (monophonic) activations to see if those performed better, which was definitely the case with the other acoustic sounds I tested the system with. Thereā€™s definitely something to be said for testing/trying it with acoustic sounds as the differentiation is much more subtle than when using the synthetic counterparts.

Iā€™m attaching the dicts I created along with a shorter section of the ā€œtest beatā€ if anyone else wants to give it a spin.

trained dicts.zip (5.2 KB)

beat for testing.wav.zip (758.1 KB)

my heart gave 2 turns when I read this: Iā€™m so proud :wink:

the way I approached that was to look at values I get when I use the other 2 classes separate and at the same time (values in BD for a hit on SN, on HH, and on SN+HH) as my crosstalk, and set just above that. Do the same for the other 2 classes, and it was quite good in polyphonic mode - but indeed artificial sounds are more consistentā€¦ I would make the filters larger (256 if you can spare the extra 2ms) :wink:

Hehe, learning.

Iā€™ll make some comparisons with everything, but here are what the 256 sized dicts look like.

The ā€œcompleteā€ set:

And the preseed-ed version (@iterations 5000 now since Iā€™m in no rushā€¦(took almost 8min)):

Not massively different, particularly at the low end. Thereā€™s no hipass or anything (on the recording/analysis side).

In setting the thresh-es, I can get ok responses out of kick and snare, but itā€™s hard to get a good bass drum (that doesnā€™t also trigger the snare).

I presume you get so much snare resonance (mechanical) in the micā€¦ have you tried on the snare, with the special captor, for different techniques?

I record everything on both mics. This is what the special sensor audio looks like for the snare (but normal audio for kick/hat, as the sensor doesnā€™t really pick those up at all):

A bit more resonance on the snare.

I actually recorded audio from a normal contact mic drum trigger on the kick drum too, so I can manually tell the difference between whatā€™s being played, but itā€™d be useful to figure out how to do it with purely audio analysis.

so the idea is to have 2 processes in parallel: BD and HH as 2 classes on air mic, and SN (many timbre) on the other input. That would be optimal, no?