creating a hanning window
i've been trying to make a hanning window the hard way, without using an expression and without simply loading an existing hanning-array into a buffer...
i thought i could record one period of a sine wave, with the frequency of 44100/512 into a buffer of 12 ms using count~ & poke~. before the sine wave is sent to the buffer it's multiplied with 0.5 and then 0.5 is added to the signal. that would prevent any value from being below zero.
the buffer seems to receive the signal fine from poke and records it perfectly BUT it is for some reason delayed by approximately 12 ms. the buffer has to have the size of 24 ms to see the hann window...
why isn't it recorded instantly? any thoughts? i need a perfect hanning window preferably of 12 ms!
here's the patch
check out this: http://www.fredrikolofsson.com/pages/code-max.html
and search "hanning" here: www.maxobjects.com
cheers,
Carey
On Thu, Jan 22, 2009 at 6:56 PM, klive wrote:
>
> i've been trying to make a hanning window the hard way, without using an
> expression and without simply loading an existing hanning-array into a
> buffer...
>
> i thought i could record one period of a sine wave, with the frequency of
> 44100/512 into a buffer of 12 ms using count~ & poke~. before the sine wave
> is sent to the buffer it's multiplied with 0.5 and then 0.5 is added to the
> signal. that would prevent any value from being below zero.
>
> the buffer seems to receive the signal fine from poke and records it
> perfectly BUT it is for some reason delayed by approximately 12 ms. the
> buffer has to have the size of 24 ms to see the hann window...
>
> why isn't it recorded instantly? any thoughts? i need a perfect hanning
> window preferably of 12 ms!
>
> here's the patch
>
> max v2;
> #N vpatcher 175 146 713 706;
> #P window setfont "Sans Serif" 9.;
> #P window linecount 1;
> #P newex 241 296 49 196617 vectral~;
> #P newex 58 47 48 196617 loadbang;
> #P number 225 112 44 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
> #P message 177 65 26 196617 512;
> #P newex 178 85 66 196617 mstosamps~;
> #P window linecount 2;
> #P message 396 172 51 196617 ; dsp set 0;
> #P message 330 167 51 196617 ; dsp set 1;
> #P user number~ 141 238 231 253 9 3 3 2 0. 0. 0 0. 20 0. 0 0 0 221 221 221
> 222 222 222 0 0 0;
> #P window linecount 1;
> #P newex 54 194 61 196617 count~ 512;
> #P newex 42 269 59 196617 poke~ hann;
> #P newex 85 173 40 196617 +~ 0.5;
> #P newex 85 151 46 196617 *~ -0.5;
> #P message 136 92 14 196617 0;
> #P newex 85 130 49 196617 cycle~;
> #P newex 85 110 37 196617 / 512;
> #P button 74 67 15 0;
> #P message 85 91 40 196617 44100;
> #P newex 401 88 82 196617 buffer~ hann 24;
> #P connect 7 0 8 0;
> #P connect 2 0 9 0;
> #P connect 9 0 8 1;
> #P connect 16 0 2 0;
> #P connect 2 0 1 0;
> #P connect 1 0 3 0;
> #P connect 3 0 4 0;
> #P connect 4 0 6 0;
> #P connect 6 0 7 0;
> #P connect 5 0 4 1;
> #P connect 2 0 5 0;
> #P connect 9 0 10 0;
> #P connect 14 0 13 0;
> #P connect 13 1 15 0;
> #P pop;
>
>
thanks!
but i really want to make this method work, as i'm pretty close to getting there and i want to understand what i'm doing wrong... if i'd download an external i'd never understand the workings behind them!
i'm sure i'm simply making a simple mistake somewhere...
1:
cycle~ outputs a cosine wave not a sine wave. cosine waves start at 1 not zero. so that's why it's half the buffer out. set the phase to 0.5 instead of 0. [whoops, that's not true! sorry, didn't notice you'd multiplied it by -0.5, that clears it up too. ahem]
2:
when you do that it's still not perfect because you always get some processing delay when you do things in Max rather than in MSP (scheduler rate rather than sample rate - slower).
3: is there a reason you need to record it to a buffer? you can use a phasor~ or similar to read through a cycle~ by connecting it to the phase inlet - so whatever you'll eventually be using to read your recorded buffer you could just link to a cycle~, scaling the output accordingly as you have done. Here's the patch for that solution plus a fix of your original...
thank you so much, i understand a lot better now .
awesome!
Hi,
I wrote a helpful abstraction to generate a whole host of different
famous windows into buffer~ data, because these formulae aren't so
easy to roll off the tips of fingers. This has turned out to be quite
useful...
You can create a window buffer~ like this: [window win 512 kaiser].
'window' is the name of the abstraction, 'win' is the name of the
buffer~ it will create, 512 is the length (in samples), and 'kaiser'
is the window function. There are a bunch of functions possible,
including: rect/dirichlet, inc, dec, expodec, rexpodec, cosine,
bartlett/triangle, blackman, hamming, hann, gauss, sinc, lanczos,
nutall, blackman-harris, blackman-nutall, flattop, kaiser-bessel,
kaiser and tukey. Or, you can specifiy the window function as an expr
(valid for jit.expr). An extra numeric argument is used for some of
these, e.g. for expodec it specifies the curvature power.
I should put this on a website soon, but in the meantime... save this
as window.maxpat (a help patcher follows after):
Save this as window.maxhelp:
Very useful patch Graham, thanks a lot. I especially like the hanning setting ;) You missed a great opportunity to call it "the windowmaker" though!
lh
really really useful!!!
thanks a mega lot!
I've got a window-making abstraction on my website, help yourself if it's useful.
Best,
Steven
there is also an abstraction by Les Stuck within the example patches that come with max, it is in the granular example, hanning window is used to create the grain envelope.
Dear Klive,
Probably a useless answer coming one month later. The basic answer to your original question is: 512 as an argument for count~ doesn't set the max count, but its minimum. Make a "count~ 0 512" is what you're looking for - although it doesn't solve the whole problem... Zoe
thank you!
you guys really cleared things out for me, and i'm sure the other windows will prove useful in the future :)