STFTs to Jitter matrixes and back - two issues

Hello,

I want to export an STFT analysis into a Jitter matrix then do the inverse operation.

I have tried with regular Max objects but I’ve met several issues, especially to resynthesize a sound from a matrix containing STFT data, so I’m having a try with fluid.bufstft~.

I want a 512x512 pixels image. Magnitudes will be coded into the red component/plane and phases into the green component/plane.

My first issue is to have the FFT settings right to get the correct amount of data. To match the matrix size, I need 512 frames of 512 bands. So I start with a buffer of 512 frames of 1024 samples (supposing that only the positive half of the spectrum will be returned), that is 524288 samples. Therefore, in fluid.bufstft~, I use the @fftsettings 1024 1024 512 (I know that with the Hanning window it might not be the best thing to have hop size = window size, but this allows me to get a longer sound).

However, the resulting output buffers have dimensions which appear weird to me:

  1. They have 513 channels instead of 512. What it this 513rd channel? What is it used for?
  2. The length is 525312, which corresponds to 513 * 1024. 513, you again! :interrobang:

The second issue is related to the way the data are organized in the output buffers for magnitudes and phases : if I am correct, each channel matches a channel in the FFT. And the duration matches the number of frames. So, each frame is split into all the channels, linked by the position - however with the aforementioned numbers, I am not so sure. Can someone confirm that I am correct?

Thank you in advance.

Another issue: with so many layers, it’s not possible to use jit.buffer~ for a translation into Jitter matrixes. The object is limited to 32 channels.

So I am planning to do some JS to convert each output buffer into a single-channel buffer with all the frames in series (that’s some kind of time multiplexing like inside pfft~). But if there’s some obscure external which can do that, please let me know!

Hello!

So, a bit of STFT/FFT explanation. If you know any of this, please skip it and do not feel patronized - it might help others with similar questions.

First, I presume you have read the fantastic resource prepared by @tedmoore here so you know about windowing and STFT being a lot of FFTs windowed in time.

Second, why 513 values? It comes down to the conversion post-FFT: once we convert what FFT gives back, we have a lot of redundancy. In effect, we have 3 types of values: for a 1024 FFT frame size, we have 1024 frames of 2d (real-imaginary, cartesian values)

  1. Frame 0 - the DC component
  2. Frames 1 to 511, and 513 to 1024 - the real-imaginary components
  3. frame 512 - the Nyquist component

The type 2 above, are redundant - the 1 to 511 is the same as 513 to 1023 (just flipped).

So most software, when converting from real-imaginary to magnitude and phase, will just take frame 0’s mag, append 1 to 511 converted (cartesian to polar), and this gives you 512 values of magnitudes and 512 values of phases (with DC phase always 0). They just scrap the Nyquist value.

That made us sad. so we give it to you. It is more rigorous and in certain processes changes how the algorithm will behave and such things.

The good news is that you can just scrap it: just ignore it if you don’t need it. Which leads me to your 2nd question:

indeed, each channel is a ‘bin’ in time. Channel 0 is the DC magnitude, channel 1 is bin 1, etc… up to channel 512 being bin 512, the one you want to ignore if you don’t care about the Nyquist magnitude.

I hope this helps!

p

you can also do that with the fantastic fluid.bufcompose - or you can spit out one frame at a time with fluid.bufflatten @numframes 1 and iterated with @startframe… again, some fantastic resources designed, this time, by @jamesbradbury

https://learn.flucoma.org/reference/bufcompose/

https://learn.flucoma.org/reference/bufflatten/

They help visualize what these powerful objects do. You could also scrap the 513th bin (512th zero counting) at the same time with these buffer manipulation tools.

Hello PA and thank you!

This Nyquist component seems a bit weird to me. I thought the last band in FFT was ending at the Nyquist frequency, not being occupied by the Nyquist frequency specifically. But as there’s usually nothing of importance in the very upper end of the spectrum, I’ll happily remove the last band to go down to the required 512.

Now, let’s dive into fluid.bufcompose and fluid.bufflatten…

1 Like

There is a mathy explanation here I find approachable:

http://paulbourke.net/miscellaneous/dft/

but not as approachable than the appendix of a book I cannot remember the name but I’ll post it when I’m back in my office.

This is fun too:

http://www.dspguide.com/ch8.htm

1 Like

Because I had the pleasure of going on a plane, here is a quick dash to make something which converts the contents of a buffer int a jitter matrix.

jitbufadventures.zip (5.3 KB)

2 Likes

Thanks a lot, James. This will be quite helpful!

As I was already in the process of building a patch without any JS code, I went on with the attached patcher.

I still got a puzzling number of samples after having flattened the buffers coming from the analysis.

Also, I am not a Jitter specialist but going 100% with regular objects seems to be quite slow. Moreover, I cannot fill my matrix completely, I got only something like 20% filled.

Any comment would be highly appreciated!


----------begin_max5_patcher----------
5685.3oc6cs1jaZjt9ySpJ+G5Re3T6lLVG5aPy9gM1NY7FukSbJGmjxUpTSg
DHMDi.U.xyLYqS9se5KfDf3RKF.MdclDOiDHT2uO868t629+74e1EyVDcmWx
Lv+.7qfKt3+vuxExqItxE4W3hYabtaYfSh7CNaYzlMdgoytL6lod2kJuwyBc
BtOwOAv+eu615sL0yEjFAh8R2EGBnPDXUryFuDPzJ469fSvN963ejMNoKuA3
.R3Ok+J+kf+seZpWr35w92AR7+Cu46avvca7CC7RkcGXgqFsKM+xF4W12U12
hV76OAhf6+N1JZP+v0WGy6lJ5GhwyoWBrLlabIfXaK9Ch+FvuIel+uO+yD+k
+mK0FpB8tk2vGiTAQNtKbBWeRjz9KqtV58a8Tc7YxuJvuUGICsaijsIPAISr
PBhkxjjL5gQx61rvKtCBaqifOfO.esWnyh.uRiXkoZTiT8rKamxsZixYPKII
Sjzr0fP4MLX+EBd85ADzoNR6yk6Zfbo5PtHIyM1ZDI2+WN4hGexknA4RrIRx
kN.jaiZ8dSjSfK34N6bi1cG3I.WukdBQ..DldCWAB5vX+1XuD92gSpeT30A9
gdKi1ElVEY5mtsBXdy51HXIR.MF.caMBHOe2pUbxmqU+Eu3sh+TRW9CWKdAg
oloTnT8MjZMlT5uby8.2Hvsdf0dofza318Tp+.NgtfvHw07.Qgh+IeYr+5aR
+p8eQC.KvhcK35OS7ckhL3ZwKi1vKSCl.un3L6cJIFl.vJ2FxdSuwPAlsXWZ
ZT39NyM9JBe19qrX8xnfn3rARQGwXtEigvTwqHVFTF6RwMJnSXcXDmXB7W99
pvUMfXf2Zmk2K5K6aH8rIsJJLMjeakeNw9NAfmGE3Nq9QG7QbJGzVUqYLw+Z
VWmwAa3wbtEWO48LEBwMOtRYlxwUkANTAI9hctB3swbLw1.cYMu.NNhO+nmG
3lnakRFb+EihSKnsfKKkDvuoPRJwyaixMQ+D9ki13k4H4CWYhQqdIfnRwARt
TgRaBYnENZDgh15EJ7J1Yy1.OveKgaPIv+8d.nAGSVFE5l.bRADxb36+1+3u
2AZn5oaixD637BrSR4BpV7qU2NfDjfIz1ThaLoWlBEM+ktkAT2B9AoaA2CcK
PtH.cuXw4T2xm3C8nGzPOp+C8Hrw4dnuxv9CNPydEdsATivPvV3b6F4VO9nO
7ZlNQWSLUQWiGwvMSicBSBbR8.bWDTFJSFnzpz.kqSf1DhTOCDgFQR2ObUze
B7C2tK85MNqudM5jHb6FI7UAQNohw+.+D4e2eAcdQqZcXZE2tgjigGj+.fdO
FzSvZO3bhLDLrJKbCiZhFXY1BVHiN+IoQOYfhGmA0f1xbU.ZXbXDszS4EmQN
4zC23nef2G7hS74idE5RWLyY61BW+hhOj.F9ckombmaEWyOTcM5gqE68A+7u
BiCW1IlSAo7t+tXkU46L2ywJ9lhb8hC24evgU0.SdWSNBHrnmr0Yo5KPLRs+
9G.FhbvlISMEzTkQFFqXb2BGWBhV9dkc488QYPAbg9B4Rp78c8V4rKH8ZgyE
hDmK6qn40+AVk0Mq+tk8M4.YrN12MJTzQJOxHtddSxG6UDGsDMI+HgNaq6w4
rSb7oo6lvI1cIKbhECbYxnn82MMJJn78N7jAdqRyt+V+vvp.ZZz1VtqLmMsb
+EQ76to0ud4sRtdWn51WyYRRuNw4CUP9TmffLA2JsvcNg9bwUuTe03Ax3vcU
JrtIYYbTPPY5VcqOT2sb4r+K8t02M8lrfAKbK9C3uMmwZ1ggcW+0dIoUtXpy
5jJWJI8d0PPwqsaQlf90odbqzbpoxmfK4vM2jbSzsIYexb1uRPwgoqpjfeQU
hkuQ6AaWV+3a+1q.eyUu5Yu6GAO6MWA3uU76WC9g2b0Oe02+Vvq+4qdyKd0q
+EvK+dwMA+6W912d0a.+xqeyq9FvS.O66eG36dM+Qt5Eu3ke8KEOwydE+C78
O6su7muB75e5s+3K+F9S8ieUoluTd.oEuiJ7XQ2aiS7ZekDgQwOQspsqLJjI
RO63u4hYCnx2ZMp8aIo.UsJfPzRMWMlFvT3bHkYSLI1xenlB6dp3KfY1KJlq
kZSXvEGrPlqLdbXMd4J.WRFrhK6pRA0tv8SxY1DY5DG6+AO.my0q4wWbIXow
YD.q2f7QCiV8ZXznwgQXWCiDt07iFFoFr4PFhwMrk8CVXIPZkyz5QyXpHA9N
wdhLPx+chXdnCuGvUOkdOfGC6tMgIe0W0hrJRuAoVFFJg0Fcg01LoXgkgoxx
pwQIq+7hmWcGObrko0LU+beicS.+M23nsIxD9Rg3zajW9uOaPQQHqKTDYq71
RN22XipSQzjgV6R7.+te5bkK4.GtBjPd3b7nPDdkAV3kdqmmZhib145Gk46d
BvKzUd0rTkeaTbPx.ChVcAhPnsZZUopYVz.dtfQt0MtLoHg3BsnBFtbbJMBv
IVd3wCL3f6FbflEh2AxLOWfiiqKvIX6MN.tKWbT5VetTG2bE.NeldFhFVcbv
NsmXZJ4qvpLLBojyIzsfaWuJxYLefYm5TsODggyILBkxTFSgFlhk0fZNtIjy
rjGOfgT+PIqSlUStVrJS2+jxjcXBSaV.kiZGgnTnUMdsXiOW3q.hDJwx.0+G
PrLgHdCK+mQmFLYbU8VBk7JVMHdLMYVN0UUR1KXAvuWTeIFr5ybW0zVdLPY1
o+YTS0pJShO1xHYPiBJII5lQhVBlC1MRzBDzYTcHNAadTTcRMUJM5XiptqlK
CTJc.xVNz06twwMVtqoINq8pmMSsXD72T8CT6hY6jg31fWRWvK0tlfloVVyM
ssMIlGTaYUcQuMjnW4bp2gfXa4Vev4OQZ5dQlpriR19mFnjQujhMkt3e32Sr
xeQnRab1Bdp3WOAOGRfTaLX+KLlW0o1gw3.ucuN2Yl1jdgrtiKv.qblfYorM
XLhBocgkQbnj+uu.7TkWsFvdoran.uNkbYHqBXGDwNiXmq+l8rhPfA3o9gbO
yR4upLH1zbvzN2YKS8x3g+cFXVVVmxcBjYMh3eqlm6Jl9QvxLzpSe+XYykWV
9PPeRgNc5VnkYVTTROAOenSgshwwBn3VDPQ8V.s2npYmgwJ1kRG4MHgI4.MU
4bBO8Xrbkff+3Ams5zcHBOnkGe3L4iGDtSiKXhYiHrEYDQ31rzGyowrz+IyT
EPPs.ts+9A7jdC7j1A9KK7uVFDPcOir0wlq1PMHJ5LMJn76W3BiXAu0KG76O
iKtWyhMwfJYbwmIWTSA9h+qWXEtUrRjgrKK8mVre08jHYnVyaYySBYLCGxIM
Mdm+PEMt3aqf6VhUzyn3BfY2yMfxsbT1LNYZ+wJFtxOdj.Qp1wkOEf3i0zBA
M6L6ilJMZ3rcJ9Xl7r1Tu45E3bOnx7lMLA4TCDc7lGI+WvpYxtDZpaBMxT9Q
IeRxyA6WFuUynvYiCTjomEiPtFyrq1AnQY8J+sPrDtLomIuRThszG2hsztcZ
wzZtswQdICmisMrw4ybLxbjEoaMzvkAdNwWBJViQllLAQ6d8c.sOl0LSd1bL
yonHNhs25G5Fc6CWxM49vkcCT5l8UhglIe0zvZNG3rXHE1wrYb7xjM2tvOLl
bgzxuH1xFYlcUBcLD2KsczFV6JkvaNFlrzI6Yla2Y7vcnAs607.zPstOHb0k
GIXSrOSpP257dfaRpq+FwZ.z.PgsLoM3QP9VikViABq6RqAd9wwjTG471XLs
3HrauCYpByQ8.G7LN4WYEkqU9gNAWuJhKNqJdCDPVlekq3Ww+dZR7xhXb9E1
y7Bd5tDO0.Af+lzah201HQC6uAUG9cdAAQ29D33LWYk1RyTCnMWULia0Gagj
aibctTqNdfHZZCntU6A0D8o3x8nSHCYRpwWM6Z1bBpPZorIWh5KaWIducRq8
0xFR27JAsrx2jAmEENeQwxI1jAOPsgGhYsUTs+6FdLzMgZYE.lQEdZeWa81q
dyyd6KesX658lW+S+quE7h27ru6pe7brtjIj9E1tp74.Y1eJtpagn9EPtX2z
SG4Egaqbde8q+g2AdwO8pW8NvW+5u6Gd0Uu8puQycR1XxOJ5e+9tjTQUVc+l
GG1napjdA90t8+TKXH7HkrtoJPzdDsIpWXnXeGH7+eLmSrzn0qC7NGN10pLu
MsWHFho16vmqjB+kfI2ONb+zMBIittw1.p0hx0CZDVsocjks9AVDUAEUM0fm
Az5edNBPvVmHqHGIAx0VQOiAKj16U8.R2U8PKozoeJsPYrWzyjvnz2BuXY5Y
pt5HKgdz9t9jxPuZqMTG6tW+LVZJWT31nyFiW.HXDX7ZWglMT23vx1MsmMM9
mI7wPyofeJfmGaKZaFS20mvDrh16Jkyd2sMF7T4u8C+Uie6KZaSXO5aVEV29
mJVTGTiC+fPV6W2LPD9QET9kvyJXpaduyQuyVt1jSfryx2CHyzaM9NJvEVW3
RM+QDH9XFwyD3opKG4krxUN+QgRV4.tFUKCkZCrZmTyrRdBDeN28dkwxxk+y
yNVZYq6l4KGJs9qUsZ0UFWmPHU4txG8K72wZwS2chiwL3ItreKTIKEIlsoZQ
nrwDefF.2jncwKyIg8o4FTY5gKTXUJ9QoYeT8GkO4tCQ6NCZ76Lp1.pS2QVi
Np1y236JKPdYCVhct5wyIb1Yhi5XPo76vVps7t5bDp76TE3YaydE89IiDJxS
KjPt6K.SQ2QO9Dwxgdz6NTc6NxRfvn2cNAoHRmrsl7HJpojLnJohLrpnLT7c
TKoVMKUlkjuabESo5qBC0sTpk0w4WjnVlKhEx7IcuL+Kp86TduwkQXP4CPV0
PfT0djb+XMYzUDYnu4J1nKpIBJRWA+ZX8hhcU0eb3XJdTGSe+YCX1pErjvAZ
SjgU95SkROvFb78FYE.vSlBGytiXspNb.NO5Ozb6iVWqlvlw+iu23RvlOtve
806QFeqwxBbxiHvIWqnlFKwSPuQO+JyExeTnNu1Q08pyMFUgMs4tyImQr2Xo
upNFZBj0z1Tm8TH4qM6j8DvaquiSS.eirx8nW2ImEaTkozlugwNWtwoeeTVz
nNOJmrzNvb13K.xXOh3wNAaKV3VF9Pi5v2IviAO1xcEOWEEJ5ixb.wxTM8PF
MbuQVuCRaGNDkmoNnPBOFdLh6uMFZJ+gfDTgbMgPXl0QgVSBEhzK2X1cRgTH
YtsMBYYyvxePLAUn1hXTZcTHazovSPTZBb5vzR+j.LQ8F8xYMbh5M5wLZvlf
ti4iHKBH8U1ZZd175f9HxfNReeXqqeOMt.Yne.1vZLFMMCqmPmzvtkNowHOW
f5oHi7nhy6LIpdBpSrNSxFHsSEFZJra+XJBTqGSpY0WA1DjLWsYYF+9BTWMR
1SSeQubbq5ziXeQ6b.ZSGcbAeJvx31Ur010owOearGSIMlQOoNy3NED1F5JT
K6LvwuynGxnwL0hkYZASka5tr4FT9twkFfmznKpiI+Lai7aZKOInrEYW3nk2
t7liOQoGWBUiYzklUNKIpsfkX4yb7Z1usApBKGPY4noo0C3gJ8r3fbbSoyEs
8GOu0iAKVuxOHXe4m4hi+HWLyIbc14gsU4Cx2J0sFjsnjzHpMMXCalAQ8J9k
fGWbZxdTX9yhsLIVP4SHpnMxmkz3ig5WStMNRdzKkcllOGaW514q6yYqicb8
Ea89C2sv.Swijc05Qk+Qq4PoVvRvAd+R9aWOm59AP05x94A67JUog5XPzY4R
dWnzXAFJ.TAbXRI1FHwqryv3iNbcFWpolJmzoSOLDEJIGKFjI4SLn1TRck8n
hUL8eUdtnPsMLXSCIu0IzK3eEE3dJz6CTHzYWZzdV1JqF5JhnBN.Co7B0FAo
RDElIuvklnsJi11CedDTUz1jKkJ1pDdt9ohw4SYT9DFJLYkYpEMo7wuVdV.k
3k+0bbsGcnPf7uoCeMyRb9fm60bYZukoWKVm89K1kpLKUjZEFMWF6uMe.7Pa
My0eM2fZkKtNHZgSfzbsW7dT9v8ScVq1n.y12ijuH6uYiVpVuvdNHq6zZUU4
v1dotsMT8aCgFJ.Jk1hJG9Jpcq9Xp1rYD4p7Vcz9fJdxEdX7tiw49.A2xGEW
EEu4O22GqvZppnbD6rJL2kZdohxw0u4tKTU8h8bC8R1evRuuSUpiPPXJxl.g
EDVpoUOtoKL7Xtus8BTGhykZB6Ce+TFSYm73KUravulbX3PC9g+HJZib2NoN
s3P1V1bmXfz7Mk2warDYsLTrMmZ4EA9Iok2ITkXw1uOA49q36VV2RdUAjrWs
qNWpDJ1Feq5OXnh8sDVn14X6EhKIUM7BsbtncpCl6zH.5IKuwIja+M+H59gK
FazlXLRUV.vpxkIzr54V6Hndp7NwqkR4D9gR5TbajtEw7uTf8egJvTmV.imR
K5zqzJmU8T0YkIp0alzxk0zFjCaayL1vFUrqxXZoZRjYaBwTCYlIvFV0dZG7
wJQiaUyEjvTDMYvH5xal5hmTc67ckak5.tuxdg+I3opTNcXKpCdZwi29d6BZ
y9YTQTrbL0J0CYpFj5DXETafo3ZNRCpszy0F2k5XWBiqt6W6CRWoJmT4DInd
HCcpbV0yUcnZ.W+YXuYAWAvzOxo01kfLfYDq4fQr8UDhqjtNQnJtI8XVDxPG
kUYxPGcheLjPcakOiGHBt24fJJsGVnDZpiDpBJ4MvjAkCJy3z.k5I+mAknQU
aGEQPGJlTih5tCmRT0QtbHTtLXUg5T7LjogPcx8mePB0oIVLYEVRbHH7EhiD
CxIwccp3ygCDp1vGkCU13wjYH1ywcTYEnTMTGCUEqL7PPpMFue1jS9PCimzJ
uMlYVffHroML9Fo8mE5Dbeh+CO+MjVcZCZoJTspJsjkwgPANDX3hr3SfiuQB
tqMNa1l.fEK59Sg4h9kjhhRM1sAyl1pxWh5zcDZaL.hMBTrRrl23GVddEJmT
nLExVR6exYWNKQHkIp0gQ7ddf+x2WEuqYTHvasyx6KIhnWPtGe7LCddg4Rpg
Zn0AdmCB0MdbMWpNn1voSk3HnNz0SdOyBI9o9SjhBZJPFZno.mOuyUewek7u
GUI+aDRyWA8WSUZ9vlDUZ9HmTZ993N+dPjFtqjYeaZR0UR5pzJAoCdJ23Vne
5N2RQsu8FmjRYBa0pzDNcyogDoOspeUnnQqksPRmZFaKd9GroPacFPTVBoXy
oLb9Ohcu.1df8pPxxbufglJPMGPUQnd3zY3iCLUGMG7u84DLh+8le1eJVRdr
lcfS0TkqcgYHd0EiYNtWyZdu7JMugUfYo59TsiwmPKR0oEgPqArII50jzAqI
YV50hjAqEqrcpZbqmUdoDez5nUUXlwpLuvPpbOYZUxElx6qoG3XS0NT6qM6g
XnQK9O1vw9I66lc1fCHyGVKJDNw7dU6VU1BeOrtfVpwHlZw7KmVd41zO+ciD
yuVcZ7XBaUQjt2GXOr1CqEqYoM0+CqAqTatZnAMgE1GJOvFTK0KzgCRQ5Yby
b3ZPsFCwCm4ajNsmsNh1HJUcLXb3cM4Vky1shk9aVin5cb+V+ckagrKUu2OT
8dUVKlE68A+7GQE44LmXt+dobm81EqhD9Nyr7jNaSDWRNbmetvb1Z+clz0XQ
jyIacTHgzE5O+y3ef+evrHCyS
-----------end_max5_patcher-----------

Hi,

There were two main issues causing you problems

  • all our buffer analysis objects apply padding by default. This is to do with making sure the first and last hopsize worth samples get analysed fully (due to the windowing). Just turn it off with @padding 0 and you get the number of frames you expect
  • your translation to jit.matrix was slow primarily because of using counter and a feedback loop to iterate. This is almost never a better idea than using uzi. Because you were using delay to try and stablize things, not only did this add considerable time to each iteration of the loop, but also accounts for the missing frames due to thread swaps (delay always executes on the scheduler thread if overdrive is on, but jitter always executes on the main thread)

Below is a version that seems to work as you hope. There’s room to make it simpler, I think, using fluid.bufselect rather than bufflatten.

Couple of queries:

  1. Your fft settings are, in effect, without overlap (window and hop of 1024), because they’re in the box as 1024 1024 512. The last number is the fft size, and this will automatically be bumped up to the minimum need to support the entered window size (i.e. 1024)
  2. Presumably putting the mags into one image channel and phases another is for export, rather than display? I can’t imagine that the phases will ever look especially suggestive

----------begin_max5_patcher----------
5999.3oc6cs0ajaik9Y2+JHpG1IcF2d4UQp7R5IylL6LHClY2MKVDDLvPtJU
1JsJoB5R61Yvje66gjRpjJIUkJYIY2.wIscU5JOe7bmGR9OeyUqtK9S9oqPe
E5mPWc0+7MWck4P5CbUw2uZ0NuOsNzK0bYqVGuameT1pqsmKy+SYliKHTzC9
I9kmHJeWPTnel4tHEGbuW15GBht+1D+0Y12pxUdi3ZDb65+PD7avWinvuQ+i
COo37rxGEt3n2ke2cg90e35lx53v3D6ClneP3peQp8DC1XZxw28yuiKKavai
ix15s19H0G5e8l2n+00OSf4GdHHEA+eRv8OjgxdHN+9GtF8je5WWdogAQ9qi
yiLWOsDpR7SgGmWVPbzscdECEgcwNZ.f6fMHriANXxECgEyMB+GBSiuF8mAr
MH5Cn7Tf7QaCyC1byc4aS8CAj.EDk5m4sAEuEAGbanWVleDBvzvM.aa3dTZv
t8gAaex7TtOEsMOIC3mWn9Hpz0zGobz8QLG2EtOh0YeTiWx93.KsAOnQz4s2
KxOr7sj9f29luh3jM9Isa2Lt.6pvLWJQ3nbzGhV66TonIMMT7VhUZflJb0+w
0fMb2yC2llY8N35fHsj71Euwu9s4EcusShJ0uohm080HWfrttwuNzR1mDuON
QyhYAewH.+c9ood262RxA2o1Z5IvMloiQ3ZXPoFziR6E2J6ArGJ6Iam9OgVs
pStP7pITqv2Dm8.5QvhDZStOJKFDr8Qod67Qq8xS8+pBEEdHiPqeB5w.3F15
6u4Nu0e.4EsAtiDePmQ5id62quVyUrwOz6oaP+k7zL3Q3ix+k.zW8t2hVXME
LqJhkVSASM6ZJ5iYUP4Tk5R4X4f+E.4nHB8ebHSJGKSNFN1H+GgatE88kHBl
xuT5SfMzmjWvVXjKGA8Y5x5hDESoP4WPeK5+J2O4oRow8g9VAPskY8w9h0wI
Zp6qeqwPMHWtIP+8vmtF48w3fMFg1nmP6iSSC.tMvTeLHWAG0v2g7SRhSR6T
ZTbVoQmKTZzQZPeGGkQlQXfeoZwjF4ysuUeA4sn+p2Gf9p7DiVTvMJz626sw
zO.eGi1FmX547h7BeJMnanmcoFnkFmVERKvZcZUPVLfkNU.6c4YYfo6Kj7ED
Cc6vDkgCcxfh5Up9Nv0iNEqIUw8r2KALJBF.u0Oxq.6lT01D5H0YKsAtHviU
mV2TtZB0YeODTQVVhQSV5X6jsJOTjyPlrdIyqK9WWjKkLgjqUi7uBQSsOO61
cd2ewjr0LUQOKAKNCMS6ilMJ80Dcub3T5TZ35OTnbSGIu+m1CDj+Fs5uD+r7
jHc5KPa0xQoZ6X5u8Quvb3avkrSCCfelovcErMXM5uDjo82DNdRvmf.O+E+a
tTbjvXZGYjEAtX8FGeVsi0EClTFCn2Xiom3R4GTl3vjbpQRWMVI890yQbGEY
lu6tCA+O3bYQL5sDbUoa.ii49j70joW0cuNjJHrKU2cIFPqRyzz5OJgHlP91
+czHLOUPhbWiYYlX5IQ9Tp55+N1KbC5a7x2Dm+Iz6f.XW6q4tQDBDNKESoiT
6SQvFD7Hz9.LVSYr91HE.kse228C5+zPE6HIOhq0md4XHuI03y+2COg1Didz
GA9anSPYJxpfxjkhn3Li+2wQ5+Y9nIWymN+xCNBGalxDrBaL7V4av5xcZfMm
WrKz87Fn1nR.jFlZ5k8CE4eX0kaNxj+0BE3zywXWRqI.3tw2PHN8jfuhvNjJ
EkIzehKwfwuiB.49nXnwDFr9Cm1u1BG9Zn.QGnRDXNv5tRRfWH5ahC2rp6vf
zoV0ESutiOzSHQDr6Is6Txr4eu25mZ71HGyOOop29e78QOD+nguG7LKNIqlB
.PRIMDNoVNI02em0grfT3vw67KbY6R4Rn1AohWHKnjidHqZ.uxoDUh26Go84
zlgkuHEzzGF.gwSv.NrNNZSJxKCw42P9v+4u71KVCI2LZctFu3oJiyaL2d0I
PeNvR0vG0N4hpWVsEDnOWTwG7aZKZ1uwlJsErUuJ5loL7u0M2talNUcyixio
wkcsBG3YR1bkcMLYxiQ64DQJ2lhIIaVhHUsTAjlk3EkF5k4i.C4VSaoiEQ3F
gOBkNoIWTMkAmFDsM9YjqsRJEyr4Z6bc9tmMWagAol+Vcfg7gV5jpCW7kSnm
vMAxvjzYRnWwVHwf8EiL16xhe2Hiv0hEEdtPvmKC6cDhqplFN34aqJhqpHDv
zSPn+G8SRKJbghVyUq71uu1gup1sno9e1ZcPcc0gBhrGhUcnD+OFTd+3pi5k
.TYFPh4IVycexobzwJJIijn7fpgwwzOTzjLHt1LY59hQ5wzwTd5C3FyfW1Qf
mvTFkpt0GUJsA9v30evZ2urwY7FGjiqMriMN8F+sd4gY2psVqSGroQRuoyyW
NVTcdxll5qHf6SB1DGoaDM5IzGt70A7DBa5NpSLlqHxaeG2LvC.vROmLEHx7
z67RzcTEB.zxSlEGG17TU2Wn+1rhSuOHJ5HTLKde+mzjxi9O8cwvI2cpms4L
o2lGYO6s.OQ1soderIZm4EFVHV17w+Iun.PXzOKv1EPwUmzpD3gz0IwggMnW
6Y9XGmYCviu1+wfMYOTDrygy.Wdv9RlnUU8xaBt2OMq4wx7tOs4QRydxB50N
T9cExv2l4CFUApn4E.RGfl+THJ6zhKrjQqN.bnNRqKSWWGWiiex.Yapv6v.P
+n+uKoJKW67BhJpQm52VWJA6OUeja3tvObpT5J3DsutJ1MJF7ifpvbhh45nc
3uke+8qmrk6fVuBtpzBPg1mQhTMrJzDn.cAU9HdwXAnNyA9QnjBWBQRnNcCE
LmisVzu4yy35TKfhMk.0oXo9y.+jd.4JRm5ilBAEjsQ24aKETcgmnynpspvN
pZRKX.iAkNAQPLUEUpxWDbi8F.J1bAE0Y5auFkFidJNGs1KBkja3Z00ALZ8C
dfxF3A7T0Gq2b6p5Ut39UoTbCWwEBpTvktDlioSDei.C+33R3foLoKWmwaiS
wtri5ZalMG7fX+akUmi6qcWptZcA5Acwdnc4qe.sCBlFkDemt78dz6Ic9.Au
FRzAULVAGF23nMg6XDfjTEUnHLpKSKlveF5MnKm3.vr+6xP5TVjrISmtzGe3
ICK6lXiHx0.SdFR6BS9Nvn0SlgcPW5OaBRASFO808x2xqid8V4UrwB9JmanZ
U3bK2sVqEW6daKlapnz4sSvbSmFl6hQxX903qYt0ka.tWl25TTGEXcUkTapz
51UE0kXsnaI.NsvFhfnTLGWo3rVOXmx5gsNCN725AW1peXoDf91Okk3AVFZW
HHPybSJ5K1jDuO0XTPPXfIE8ge6ncaAvOW2lL8PXHrVlpwxwq8gVToTKgJ5T
ezOGjcSgcTOPacDJPWU15vc.axYO56as45kuIHtvfaJx2Tk19kC2yiwIgoiE
TcThVfJ2A.vi0jvwjmCpJWJT03YyNH1vf8gAlQCeiegiy2mBvqMBrmPo6.Ge
5U8McJ4Q0HWKEy1gSiwFGbtXh3da1ftKL2GAl6JcL7ifye3aFOGGtsmYPPHc
X7hyeNrb3kBif.P.dGDDiZF3Xr1JOBr4juSKM2rZLtb9ILXHwsEZIo23nnJG
YIZI09wxdFnEdw7LUKmoc.s.h92PIlLl4OVHhyvMD4.6wVDpM+D64XX.qVHu
axP2gBFsa4DZ6X6IPvPFuQb0lJYbJmn0x2ZZgz+fibZmRNkyHTryThaFfnWv
Ae4tu41kCDFUy3wGqeizk2FQDqZ3dpUVodxmL2ADUxmpk41IA9ZVu5M46r0Q
RvtiNeu9U2UoDoY9nTIyQBfI.0Lc8s1QP2RwrkNEJlOkLbMF2kKW+sns6UNB
Ya.o8PyLw7bzUMZo8LVMuJ.stDSgfaaImRs4jyY1vL7RhYmvhfNJgcd6QuW+
q2wtAXaDtLT0Gv2.AuNVzFrGz19Im3z1mUJEO.o1SZw.njaK8H5ToDUwVsbP
aLfrv+9Rz60d1dBj7LZ+XT0.QRBQrXHIcAQxMA6p3SIHL58P7V9IYvmHik8D
7UYnt2ojcBp8L.iSHd2+nP1p2XRCb6TVyABXed1nYkk31tQRocDjFmNeCLhz
4yCz5XdTsAqkGrDKV7IA5+arBz.DU.V0Ysvr1nEiW34HlKcTLIQnddIQUGmx
0M9SunoyjlvJ8zkLeXHl9RqwRpGP9UmAPoM8wjqj.1Q5ZntrKbByC+miyR5s
z3QzsAImEREB5qBHU74iS6DGV6LeJIKdjNjZE.0qePanwKO6fF4URnN5jesN
z2aRKnCs61shdTQsgTJb.GcbjDWlyzjMLayuWnVLo4QT6089GCh1D+3nYBcc
ZmiBWvHsCWpbsLgNtZizNEw2T7iRu1TQgHycYRWpSwQ4hYNjFdivxSeJZ8Tm
krFkc9HxYuzov44ZioFSbixECLYV.UQsq8VWDKG.Moq8JjGuw8jFUt9bh7X0
qDQ98de.sIMChcTOvlXjfzevhrSC8tJRGiVBvg1dzRHync6ocvTFDzkl4Yhy
FOVnSwaqEnGjiLeHGYIyVQwZQwVc0rc61Xf02NSJ41UWIF0TJC5+89zj00A4
xCTwvhdedpusm.AeI6gj7SzUP5t5Tz18AkwXohyHLvs9qG3gNtxUNTtqVD3G
8CCie7cjUivPPWIqV3PWpzWQeEkLeM7fUtbB0BODmdBb0tjdHTyUho4uRzb+
6Oot5yjzDWvoLooF1DPrCRv4Bh1ECd6rkxTOWENmb.JWJUN0WYQlHzRW9HsP
K4rhVjOGPqtywzK.ZsX0fxe7u82+Qz28+98e+Oh9i+s+5e+6+1e3a+Ol7pax
Q1gBPmNT.ZyD+3JtI8BAyQT3OmmloWDoplDQjkJXzPT3zNtZhNJR21qnrWp0
zSZC0kr5y.3p6AO6k.tvelLDMcUoOK8nNnTKn+5f64In2a9cPzOg+GeIdzCU
qCl1HDcljUrPj2tB5YKjutJwKJV96G+.e28Xz1YYuNH6sSBZxWPzbudwyl2K
7wGC7w5vSX3CEiHl8GJUtLf4RVNFMWuM258K2dOcRMByzqcOs4LGRwsvFNXN
TnE+hAs67t+Y.scZvtGnU9h.sR2Ue1LhiLoaCCRuTi33mGig6.FUbWL90vP3
JGCfdXsHPG1VOyvbCMqOe2HcZbdx5x1WU4LhZRh0lxB0tRcb25KbPc0WZyn7
ge9VgPMmMCySmLj1gNcaG0h2ErwrjrkVxqYSRJQPEJoxE6nK5dGpYjHc3XLm
AmvQZ7lTpOpDiYNLhvkntjqzgULIrZO.SlSMqf0f5zlytrA1g0Q+U0NXCYVZ
YfglABOJ5bBPkO8y1NbwyXyvkLvVgdsCBQOkfkfyavnaSJfq5Fp33TtS3sGy
01W3bRxCg2Dhw6L5RDhtRajpiTW5PZF1PQLrstxYTbjNDwQryq.kBjSoU.OK
MsJB+7bEpkVi0vaa5hvcgAN2g5nh5rVlYLUGJP5RZhJHC5JmKMH3gpAgYuvY
oUzg5oSzJXyUqfeIshYSyhbnsh4zXJYnxok9fLOpKFpIc5b5eCkNXcVKut9g
1zbVZU8lB8ZXsM8hc9QJglYb6BZb5srh9ZbjW5NUwRyv00q7EP8zvEIcVdFe
mWE5N0Skjg4obkvvL1NFT.zjYuYLHaIyIiqR8pf2P57pvICo30.ZnFr9140w
O0PSQo67Jn7pvM3ACF5415RaDTMT+RqB+edZGzg1Uwm2XEdk.GX2Kscbhbq6
RZubQ4nWIBfeIKldJJtaOYEu8ENWDMgNcDsRzAofcGHM29Beo0MXV9QV5Lbw
mt9CGclVOZd54Po58IDEsDlw8xC15BmKuwwhA2gLqQEXxt3fRKao2fmbTPMy
mgdFFzCq6B50Hwc0Wp0JWk36tUe28aCBCql9EW05JtZkWz8EKi6Rb80Mhil0
FTW8DxvrvhhcUXt8SvgHslZFE2IoZqmQ5vkDyMnmNGlak22cQG0KbeRrYccp
X42+Fla8yVNH1qtOwaSft5hqNYUWwgMM.6XXCWU6ETcsPidUWrt09t3kp5ur
kpx2Dl6Wehob59Lu0qgWdyMuGhFB0Hfinb66ws.UOZDQmMhn87q4hICEUPj1
8EIhxvPfEtBdGStm5KmIlYPLbgXrZlIz8dQ9g+o3vMCmJeVBXd4YwUrjMKV7
ij9z80XivfPur9Z.QRgv.HpHNk32ot2W.YPKcsTBf5JCyeSP1e5vdi0.5Su.
r2Q0fwsZmv5VypBTpe4So8dS+ymtKdFkOfU58zhM2Z2+NtUWMQA2kmYsoTiD
ur8Yh6CiuyK7nMGht1FJdygdyIZmNriZib36CNX6lWKwtaPoDCbqds09lV69
s16XNxQsCm8HzasMNY2u1IsIJ6Sq3ER72D4mltZ.Dsicc20t.bopS0e7Whi2
YpDQ65pF0U5B1jIht2IGcp1gF00TYU2eW8LGI0Xm1lb2how40C7P0QX8dTSS
IwxYCJuRuzPNT8mY+aAVm3Ck6NVG1bnJ66Zz73Tlf5xIjZZL5f9Z1fr66Dfn
XiGk6gmivLM567P0eclcWPbO7mS51xJvGlaZw5E3V56p1nKrKb2W7Vtpizr4
cYmv0DmQrmLKwqlbsNMJa3gukJa23nVDkNB1qCkNkz7.z4X2NxtX8LM6K9M8
LuZ0yHVvM8OA1r2sVtOHL8a5ebmodS+64s6Fh4yDgxVpc2vp8ZohMOoeE8da
VUNLKXPuu9BL+fc.rYTlVF2BlVC2ppFCMSv5Pw5I3v31UJal6yYKVsSjeTtM
1bxVd.cqufR04DaqyEDEWmZVeYhIcKSkxewoOvi3BBzYNHP1pkS5.rB1kzw.
bTYVjNJUKUHcX2oOlVoC7DhtmX91sffVo3lEzfmzXAsJWF5eip1Y1PuWLVtR
g4B3iJlO3iMkptDTNUotTcW.1noVk0iZG4yW00QwYT5i3oiyvgLgLRl4hsdw
l5Kgdypk3mg6zmERjRd4tY3DpMuXMKbh5y06conuIIO8gd1IyomU2JwtlFnv
SKYJlxnkKFVrKreTu09cf.4p4LNYNYJo2+PjW3SoAWbZNHRiyjT6DvVhOiW7
3p3gOZ6HrAkwmSU7f6Gd61mhH0VihFfx9QEbZWlJYLCfIs6w8t34SWuvcL3n
F4ZFQ2CAM2gaFNyAv6ePbfhOi3PwjHeURrdS8zPGNGRrRi7iTncWZLyZF20h
H3aHrbeTLzXBCV+gSqN4Z6+puXP0w1B.5aNLVKsEYYkie4wenGw2CKgmcGdZ
w4B8u2a8SMdajiYwIuNRXFylorSjvrgmareKoXu5SJFgsZoyUTgUlYHWQD5R
mqnzrsYGEJrdqW49nfr7MMhMd+CdoMRkz1sYo.YAPTpwaS6uLK0o681rANd0
xW5BZXqrOxZXyo85V0QcR7yoNtovQW93Chk5gu+vNBrYHrqu7ppKytdT.6tp
lld8l1ZU4rMSQl+B63AAWjknBOOTzYzyCxb4AWIHZC8rZmIZ44yI50IbFEd.
kKn5lcwn4zctQkV0FqSKcCSUqOKEZONgMdtdua5Zjv0lzXLYRCgiLTkvlat4
5qhEKNtXGKPjNJ32FkMZuSaMwgBbrEtO72kXPuK4D7tTxA8p3Svqxc.uIdiY
HywElKwtTKyLidpYQfn7aG7rpwbPXVaqrF0C8QU37367oC3U6N.ThJLZuq+s
mKe4yskwslPj1pBPZSgU8uPsK03ksYG5ytMywCg+9TMZI2DSZwhwC30vMz1e
UXG6+BBz7smYCmMDc.L4gkGfw2spFxaZJTrQGBGzQMmIRrZ3uZxTqKg1XUKY
.Sk9w2ShGBUplBk4lGhy4dSSh0vgXgp9jXc7cTrgHHLEunA4KgyD7lDCQKhX
J38DCQKhCYBzWwFR2T8oS73Md3Lj2zTvPLDqTpYweC0PPS0THdoFBunRtTv4
wJK6wWS6vMpn1AbU+so19.gLDuMqu9H1HnFu8600WewUadKP.c+rMNV00luF
DY+pIg4qR7+XP40aRa7JuDHtsLHns7DaNU+Tw9p2pcw.MFkGTvnYpv9UlfE0
4eMceQZPLwT9l+0a9+kB+W8B
-----------end_max5_patcher-----------

Thanks for making this patcher working as expected! It’s great to know that it can be done without JS.
I am quite surprised about uzi doing the job because usually I use counter+delay precisely because uzi is not compatible with complex patches. I wished C74 provided more examples on how to deal with threads, scheduler, etc because despite having read the main paper on the topic, the subject sometimes remains obscure to me (especially in a patcher like this one where you both have MSP and Jitter objects). But I had never thought about avoiding thread swapping. Will remember that!

Indeed, putting magnitudes and phases in different channels is for export purposes.

In between, I have checked the JS code from James Bradbury and have improved it. Also, it made me programming the reverse operation (picture to buffers) in JS too. It’s almost done!

I thought I grasped the fluid.stft~ output but now I realize I still don’t. Numbers don’t add up.

If my buffer has a length of 524288 samples and I perform an FFT of 1024 samples with a full-window hop-size and without padding, why do I have 513 times 524 288 samples at the output, that is 268 959 744 data whereas I was expecting only 513 * 1024, that is 525 312.
I understand the 513 channels, that’s because of the Nyquist band. But why do we keep the same length on the output buffers as on the input buffer??? It’s as if there were no windowing, which is supposed to reduce the number of samples to a -smaller- amount of windows.

Here are two tables summarizing what is puzzling me:

Amen to there being better information about this: it’s the bit of the Max / PD abstraction that’s most consistently leaky, insofar as people run into problems with it all the time. IMO, uzi is almost always the right choice, but – as with any iteration in Max – it requires some care about threading in order to keep the order of execution unsurprising:

  • uzi will always execute on the thread that it’s triggered from, so a leading defer can be needed if you know that all the work needs to happen on the main thread (as with jitter)
  • correspondingly, you need to make sure that there aren’t accidental thread changes in the ‘loop body’ (so, avoiding objects that ‘promote’ off the main thread or vice versa), otherwise using the middle outlet to signal that work is complete will be unreliable
  • none of which means that it’s still not possible to overflow the Max scheduler with really complex workloads. Sometimes, in that case, the only option really is to use a counter + feedback set up, but this will always be slower, and all the same caveats apply. Although, I’d generally try and avoid that by refactoring the workload and staying with uzi where possible
1 Like

I don’t quite follow. Which of your output buffers in that patch are you looking at?

input_mag, which is what fluid.bufstft~ writes to has 512 frames and 513 channels (with @padding 0). Is that not what is expected?

Here’s a version that uses the @numchans, @numframes, @startframe attributes of bufflatten in the matrix filling subpatch, instead of doing one big flatten and then having to unravel it (so, essentially, it does the annoying counting for you, and cuts down on data copying). Turned out that using fluid.bufflatten this way was ergonomically better than fluid.bufselect in this instance


----------begin_max5_patcher----------
4120.3oc4cs0iiaaE94Y+UPXTzqyZvqRj8ooaaRJJRQKJZeHnHXfrkrGkUVx
PW1Y1Tz7auGRJIKYcwxNirmlLXWOdnnjH+34FO7vC+Ou6tEqRdIHaA52i92n
6t6+7t6tyTjtf6J+66Vry6k0QdYlps36ByWt+4vX+jmWbu85wE6RJxiBxM0f
VVpsn7OuOv93024i67xSCeYw8nEKPeaYE26ku9ov3sOlFrN2VWBWtTbOhIwK
ELBl4Hvlent2iHL1RUiejRGnPJaI2QpbXbaotr5me1miWqerjx+Nz2zQRV8c
umpZzGBiq5BDcY+228N8G2OQbYcxtcAw4UOu7fWL8kE+gXunOmElgf+E7xdn
KF3ixSPoA4EowHAgh1j5sKHCkrw7WexKp.9KnJ6z.CxCkA2U3lv0n+RXddPJ
xBhnrvuOXY+iA3QfV.9.n0EuDeOB.K8unveTCWMfGBkL63y+HwKxG8AuB+jh
WPuG4GrNX2JnWRH4OAsLJ8R6hblouQvi1EIrYuK9ghMafNDLh9ke4+T+qVii
WZ2iXF5HB2w6dzYu6krOHVSk5saeT.5WmACaQgeL.Qvnrf0Iw9YHubDmuj7w
+72+aFu6tpX0pnf8IgwlmMzqjiIkfpABkiAAjT8uXpF.g8okE5GzTvTS3AK5
GdZ8.tT.SiPqJxyShqdIOU1uVzOJvpZgaiSftYT35O1p0rccRTRZYmW2awKc
kRJSn+F2EKjx60WnF.hB15s9y51Q8cV8v1jDmGCxcrBoRC8hPeHIxewPRuMx
rg+a5AiI5lvMhtK495x7US2Ty3klTD6GXFUbz0+P8ZzewKAQ6X5887Ex.z93
52vdOsHVfm6wfXuxQT7qEewOOGlolgYJCepgY5rOLSuJCysGhaOhRFBNW4Eu
cRV5fEFDjW8Ye8T40gdNN3Y3s0QL+dzJidr2mm79wzbQlf8eSAQrBPHXKoEc
.HgLp7ayiOHsryV1aAlhvnfOEjlEBimGp8cK71uuQw203VzPz2YoQKUHoKJL
1VDqtnzfOEVc+35R8RgNYNzCKRsLhu3vWb3wj3GjFWDVOdYFrJaRlgEMCb1d
u01aVO5Uc4CvFyP53ZMJfIk5eq3M3H0BVhRV+QKGXUiyn8NLdeZPFna2K+n1
9B+fMdEQ4OpkinM3zzHoK685aJag8dw1Bgp6.aSC8Sh0MhViD5hqdc.IgvZp
SyNioFwd664lABC.VF3hYPmrHakWpdfpj0gVcw7jjn1Wp99hB1jWd48gwwGg
h4I6G9hogaeZj6cUBbwci8rMWI6whX6UeDnIxeLy6SsQ6bunnRd21O9W7hCA
Fuf7P6P.EWeQq3imxVmlDE0p+Zuxm54J9.M95fmC8yepzFsCWApd39JhnE0i
x9gaCxxaWVt21r1kjk+YKn2nnhUk7vOlG.1WB8h1U.3NByxydJ44rxJVQn0D
.NLE2l7zMED1p7iDHZkjUyvNjwqCIPqTGoK1vSZ+CVSFyiUnIO5U0QtlUxPo
43MgCySBTx9RCYIkx+KEqbgP.H+IyaaPy2yA6+Kx2WLB7zrQ20diVnPOnm.6
tjywJlj3xcobtiV4fCaIUnjblC2kKwXBAluG8XMEcmMzfHK8mDfEkSr9FQPY
DGpjnHWLXIuJXUKiMZCUVyM9ADncp.zg388OtkNLvQGC31Dk3kqMqsk8XCgh
NBqYXJ1R2iwMBQdJfyYX12aAvsya60F3.BNiC6bTDNXKhqhq8Pm3T.m3VCba
hJB8WpgOPQSdP7OfdHKoHccvAZPzCPCa8SdwYFm0o+qR22QPO.5+xCiMFQMH
UaTXbvZXlPl2nykMpzx+omkfy9GZXFOnHUCOzvuJCMiI3DraKM2.0neAvGZn
GulRQo.8KiRkLgvg6PXLtdJoD1oHpohasbzSQUCBHNSp5thTtZT00iMbWA2U
QHbGMUsaWMbDl5TT0zqBUca+l1dr4u58w.TFLsPzyA+J3S.hyeJ.syKT+kz.
O+K1rSBirzrXHbpqqRvIZenHYKkL3GAUh4DISoQObGu2zwvoatnYXpjv73mI
FdX1xNvOBIntmPbITm9QJqbxQsvjcyIoJ99P8ZM4g1Ur9IztDfpJMYUQVN5Y
uOqW8gv7fTXdTnKlxhwMq4.v5YfMWpjJjDFXujFb3mjXhdqIlzPjVNGdXHfM
FAkU4yge2zYomCMV+HHXZtkxSPjRlixUzCMWWWDyTThvQ5Pc4BrRduYh4McZ
ZmwgqhhowHU+hWxS8Vm2yhfBHqeF5W6mlrOyHQTPX4OYJ92b4RDATrotC8Pf
frj0gMG6dJZX5XSR+ZwnmEfzqFu0bejGvyqUPCb2ZGwgVEj+bPfUehWgeXRo
+ayPAw9lRKWFxmSRixtXPU3n5.pfZ3dlwIlbZT08lipd99nUQEAn8QdwfZ4P
fr6SdQ.2zOBHhsjK4BA0BQLGMgm.lHYGKw47SiQ3aNFAJiA68PMMLDjGUrSS
90dUsOevxUgWpNFrf4wrTpf4xTBVRss2J1IwJr5liUZKi0ZcKAneIJ0rzCAW
L.wY3tV.Kbo8MutSKGCKu0JiyQf8JWn6IzJdmn92dm3fgFRwHRpRRvDNUP0b
ll3qXzI0guNN4w7TuPqdmjGa5ypDUeZDOkSqo3gmh.9snWqCdYeRZd3tit9q
pqqovDvnTWliK.j.LCV2Izgz1wLptmz0XTL+pXsVqE49pQwwkcI4n14Z4LFl
zRS3HqI9MS1l17rcd6QOn+38rkvPtPwP0eAuDLP+Bk8MP3TdVtCjqcJ6wTiT
J9jSyUxV7F.ZS.jE9+uE8f1BsqER1qljdQRBQbZjjdq8OnFI8C2USmRPXzCg
wfUJ4v2HSCTGdI9mMHueadjtmFxISZAVONjG9+Jwrjop6oaHG0AubHu0kyli
VgVGE3kdgR.pbji8YbQtxAX06nCSRsJ1DNbkxwEr1z4Djlhqi43cCh+YVlIQ
4zwKAtfw2JGtqTYIGcTTsBeY2n6mBFHnXtJpSYobQqW3QQ3emEu55LiY3AuJ
3Ro.m7Zr555T5V+lZebncleLW0qfPXHKasWIa6R0.zgsmV3aQV98deD4mkCJ
tztyBiDDxrs7.ZxuN9uAJzAXvcbqDlp2aJD0I09LhOIXWanyrnp.3gmKnyEl
yXGp0AfNxoCeG5sF5rFza19MaBi8hdbSBvTXlJIhiLQKAiZ7fsYcTyRW2Dkq
JnlhE8PQVfcnPuRq4OkVL1XQSIHGBVNay8aBhhRdtsS8mCo1NB2tFQHb5Obh
ZEX2BL77vtRNivbolfYeJEM1JXPuNwkv7atlFnwREmPs.Mwrtr8DqFBS3Go+
bvoEyeSH5dLeh9G+a+8uA8k+qu9q+Fze7u8W+6e8W7O+h+zfQS.8nmv2Ujkq
2Mb0wpL4R8jpiaOfdeAHicNEL1Xhl32d+nFghVbsCnHN.hc8ff5TNPUQ9IOb
0uaB.N2tyYUTNurxefpdBzC+Vv6KfZuTzClOCi+23u82huRNfwg01DXlqdxs
Xm9B5vSFeVRwaA+uzEK+c2T2YIzKV6PqmzXnI+s.Zt2a8GQ7aI7o2MNGCevW
ZwlS06l8QAygcxJ+5Al8EF1nGrwwtdinL9LuXSGpeMbnMSpLQoImxcktBJw5
wkS5Pa4aBIp8E31uEf5dowG.pOoHB2yaM4OriuzVENv93wzl0Wu+w.a3tVhD
0Sb.0tI1HZFZVSYmJlj5a2RgSyivmaayr1xSpsoCsXcEmwlAYJPDVNisCffG
QmBXTAaySqfLwwDsfjYqULYhVxL1HjSrQn4ymOpyoNbLm.AdxxPXyXynBmmP
yfNmiHhI1L5RDuKz2jwOJEtSEkAtdqsegvcoiKnuQgURFELexUG7lNKUc1hK
cq4UU78TwA5vJVHyjD8I2zv3YUyxjkiQOIwhi1xjiVmSGv7CFWIokKrjDqzd
Sq8jFM9xraEmM8GzWu9rKS00bLGrZI1ghcq5K7g5zcq3b0owpWuNsTH6FDsN
ZK6mTmtaEmqNsC4b6zyS6Xxl3xwWaIQlHv30hvnVcQatgdbia+bCcp3bYt.a
x5omSy2HStcnl0lAVNYiYoclHxbSeN8FmQDG4ZZfgbp70ypUmRw4zJXyTqP6
H7IMGUSqfLmshIgEWlvLtj0yZrLwZNiSKmbgBvmYFD0Taa8PCezvAXrQOK4k
NgCd7vgCWzxlLyZRzSMmKRPx4vNRGsO22jp.ijWREGuVzDdG8o8TwYSQ1TMo
VgmY+SMEhsw3ClIsXhIqEaNwGSqf75XqmBaC9DhfJjtREXRO7rcnl3wzgiwb
FbAG26QJkYq05hwLGFQnHxynhNrxsgWO1KxLQJ67.US1BQgbVme9jcr0vVXb
vs8l.UZ.+1eHhw0aP0cM21fUIOt9azq1tILJpN7htqSMtagW71xr6l6gTTV2
nRhpzAbjYCTiURL29MnHRmPOp7NI0YpRWGtKwbC5vUxbq7gtK5E8B2mlX1lR
kYkukLUyqVs9NK1l54Gpi1l5KVOTbHWBZiFHnVcyyZZNM.qCapTtORo5wK6B
Y8gnhflQb13iYdqWCu7145ShFB0HfinJaepJQURa9rYqSzMv4N6tgDLFy0ll
VgIuY148Bkf2Svq0bOEXBRenhXrbl6n68hCh9pjH+o2K+Qwf4UjmTSR1NNrN
h6SOViMLCBc5Kv.hjRlAfUQLF62X26MfGz1utVLf50MNvOL+qNjLemvX5Yf8
Nx1gMdUZ58QyNCJKn5ofuuwGuR7rkOipGvBcptz+QaZ87Qu77zvUE4VcJM5h
mW5mbaTxJunixYj8kcJe2gQyyLQ51d6mdXo90o0GzGRKxdJH6LygtSIy4Rr4
1O4nINWQ+I9b5qXdguzvhyM81yjNM5EbYuYV5VDxcIA61e4jq1I8v4mP+cal
KssmLCCkCn47YLg0OPletSXofdPmr+0IGLQqiOgobJfzeFEr2scg8bNf5ZSD
zptzysnB3Tlfp3DRC4ZlPHmqJCo76soJmAnPDudmEH+LMiviav2NVFgmL6YD
d4UIQo+LnVZSR5ten+AUm9F8z17dDQ4zJpYeUm6qaqJuZ6RvqMrYJE07YdP2
bZfeLn4ZwI4fG4KQgY4m7T9oRRuiY11L6lkV1jjoBgeUYzG3DeQTADAQPKDr
gn0KUc3MJLautdKpYCyvShacZjnEiVy5Yjlt3s1AQP0A5vnGDAD5s7fHnNeV
lkuI+njYodGruMNLuvuU1sb+SdYsRhqa1jmA3C.AfVLLka+3g8d99PY06Aqi
PW9ojQN0C1pRcZNc2tfKZlH8IuZ54NRlZkND8jeNj23LS.n4luRuZ5CvD85o
rbRFcXFztNFc31373fHoyrQGjqJNVggBJmJkHxrAiUSEQuYkYT.Pp1N2lTzv
baI2oOyqL2V6HJ1hwG6rzRjtmvqnoORGZgGZUmi7kMwtU9nhxC2hC+kc5ucF
9mZSSMgVVy0F9heQsihigV2C0qwahMk9D4U3MIDS3MIncdSVBpiN.YzujiN3
XN5Pio6AFyvGVLGePwXbOxPGPLu6+9t+GLLq0x.
-----------end_max5_patcher-----------

This is the size of the buffers containing the magnitudes and phases of the STFT.

image

I’m still confused :smile_cat:

The literal size of input_mag – the number of total samples it contains – is

channels * samps 
 => 513  * 512 = 262656. 

This is a little over 524588 / 2 because of the nyquist bin.

What I don’t understand is why you multiply the product of the number of windows with the hop size (which gets you, reassuringly back to the duration of the source) by the number of channels. All this tells you is that if you had a 513 channel file at the same sample rate as the source, then it would be <whatever that large number is>.

I try to make sense of the contradiction between the data sources :

  • indeed gettatr reports a duration of 512 samples but I’ve never used this type of query so…
  • when info~, which I use quite often, reports a duration of 524588 for the same buffer, I am more inclinated to believe it
  • also : if you double click on the input_mag or input_faz buffer~, the timeline (in ms) duration matches the duration of the input buffer~, so it supports the idea that these buffers have all the same duration (it’s very hard to see it so I’ve duplicated the timeline of the input_mag in my picture editor and have increased the contrast to make it readable).

image

The value returned by the @samps attribute is the ground truth: i.e. the literal number of frames in the buffer, and this is what max stores. When you use info~ or look at the ruler in waveform~ then the figure you see in milliseconds is calculated using the samps attribute value and the sample rate of the buffer~.

All our descriptor objects adjust the sample rate of output buffer~s so that they’re accurate: generally source sample rate / hop size. As such, if you then look at one of those buffers in waveform~ or whatever, the duration you see should indeed match the source’s.

I’d send a demo patch, but I’ve currently got Max paused in a debugger :smile: Try checking the sample rate outlet of info~ for one of the output buffers: it should be a lowish number (like 40-something if your source is 44k and your hop is 1024)…

2 Likes

Jeez! What a mess! Thank you for this huge clarification, @weefuzzy ! :pray:

1 Like

and to add to this: that sample rate is right: it is the rate at which that sample needs to be played at to be at the right speed, one hop at a time. I think that @jamesbradbury has a demo patch of that somewhere…

1 Like