SynthMaker

High-resolution oscilloscope

Archive · 2012 79 old posts

From the original SynthMaker forum (2004–2014), with its members’ names and dates.

vinxz ·

Hi everybody, I'm working on a synthmaker design which purpose is to create a high-resolution oscilloscope to observe waveforms, and especially slow-evoluting waveforms (such as modulated by a LFO, etc.) I'd like as well, to have the trace writing in quasi-realtime from left to right. I tried to sample the signal with a tick 100, but it's not precise enough... I attached my design. It's nearly working, but I'm losing some buffers and some buffers are repeated... Can someone explain me what's happening ? Thanks..

trogluddite ·

Hi there vinxz, welcome to the forum.

I wasn't able to look too far into your schematic - my internet machine only has an Atom CPU and couldn't handle it - but the problems you are having are not uncommon with SM... Basically it is down to the way that streams (blue/white 'audio' links) and triggered data (the green/yellow bits) work - although they do obviously 'speak' to each other, there is no timing synchronisation between them, so it's not possible to create a 'chain' of data blocks that will join end to end properly.

The stream parts are easy to understand - everything happens once over for every sample, and the timing is as accurate as the sample clock in your soundcard. Green parts, however, rely on discrete 'triggered' events - and in order not to interrupt the audio too much, have a relatively low CPU priority.. For example, a tick100 never (as far as I have seen) generates 100 triggers per second - and the rate will drop as your CPU works harder. The interval between triggers cannot be guaranteed, except for incoming MIDI events. For a better explanation of triggers, take a look at the Triggers Tutorial HERE.

Added to this is the problem that manipulating the buffered samples (float arrays and graph drawing) tends to hog the processor a while (SM tries to calculate the entire array during the time period of one sample) - so each screen drawing event makes a big spike in CPU power - further reducing the timing accuracy.

However, all is not lost - I too wanted a nice 'CRT style' scope for just this kind of long term audio monitoring - you can find the schematic HERE It can manage multiple traces, fitted to the display any way you like - but the waveform scaling is arbitrary, so (as yet) not useful for taking absolute readings. The timing problems I mentioned above are got around by having two overlapping buffers, and some code that keeps track of the buffer pointers when switching between them - it also uses the trick of storing previously sampled values as a bitmap 'snapshot' of the screen, which helps with the CPU hungry graphics calculations. The wiring is probably a little bit too chaotic to understand easily, and there is much that is written in code and assembly - but I'd be happy to try and answer any questions you post.

Happy SM'ing The Luddite

PS) One other little tip - your file opens with the audio in/out turned on - which made for screaming howlround between the crappy speakers and mic on my netbook. In some cases, it can also crash user's machines if they happen to have lousy DirectSound drivers. So it's a good idea to post files with the audio turned off to save any nasty surprises.

tester ·

So - there is no "wave display" in a way that you get in any DAW? I'm asking, because I work with slow LFOs too, and to make adjustment right - I need a few secods view of wave window, like EKG or somegthong like that.

Partial solution would be to use cool edit or something like that, because it can display "on the fly" what is being recorded (and it can record what is on playback from other app).

infuzion ·

Heartbeat with about 20FPS should work fine.

aliasant ·

Try this as an idea. Something I made a long time ago but I had a quick look at it and its not that bad. It has glitches though.

basicly it divides the incoming signal into 8 chunks using delays. Then do FArray on all 8 and finally chain them back again. It finishes with a resample down to get a smaller array to the draws. That last part saves a lot of cycles redrawing.

Would be interesting to see if anyone can fix this?

vinxz ·

Hi, And first thank you very much trogluddite for your precious explanations & osm designs...Your work on Synthmaker is really impressive ! Actually, for some reason I really need to be able to do that in synthmaker, otherwise I would have done that in wavelab... aliasant, I'll have a look at your design this afternoon, seems promising as well !

trogluddite ·

aliasant wrote: Would be interesting to see if anyone can fix this?

Buffering the 'old' samples is a great idea - but, sadly, also part of the problem 🙁 ...

First an experiment... When loaded, the gaps in the wave have a very definite pattern of alternate up and down steps. Now try this... Delete all of the trigger connections to the eight "mono to graph" primitives - remake those links in proper sequence from bottom to top (the trigger order was different to this in the original)

You should see that the waveform is now smoother, and all the gaps go in the same direction.

What is happening, is that each "Mono to Graph" takes quite a while to do its stuff - while this happens, the other ones have to wait before they can 'see' the trigger - so there is a delay of a few samples in between each M2Graph doing it's stuff. Hence the gaps - and why changing the trigger order changes the look of the graph, by putting those delays in a different order too.

Sadly, I don't think there is an easy way around this - it's the reason why the scope I made uses a complex "overlapping buffers" system. I've even had problems just getting two simple "mono2float" prim's to trigger simultaneously - the interface between green and stream works in a very odd way that is never truly synchronised. It's also important to remember that when you send a green trigger to lots of destinations, they are also not seen simultaneously - in particular, they can be delayed for many samples by large arrays calculations and loops.

Very annoying 😠 - it has put a stop to many nice graphics I'd like to do; making that 'scope was very tricky, and some more interesting things were too hard for my brain to find a work-around.

tester ·

Maybe someone knows how to make a code/ASM addon for making long-time wave display? I saw some talented users here, who could be able to make a really working piece.

One idea came to my mind. For certain needs - why to not delay a little bit the whole playback in order to make the display right?

cyto ·

tester wrote: Maybe someone knows how to make a code/ASM addon for making long-time wave display? I saw some talented users here, who could be able to make a really working piece.

One idea came to my mind. For certain needs - why to not delay a little bit the whole playback in order to make the display right?

Here's a quick little sketch that may put you in the right direction for a "long" wave display. Basically, it has two (positive/negative) peak detectors in it from which "snapshots' are taken at appropriate intervals. The response of the peak detectors is dependent on the interval between the snapshots. Those snapshots are then sent to a m2f primitive and take advantage of the fact that the m2f only sends a trigger when the value changes. These values are then pushed onto a float queue (actually two) that feeds the peak graph. It's a long way from being a fully fleshed out solution and I'm sure there are many things that could be improved. But it might get you going in the right direction.

BTW - if you open up the properties panel, you can set the length of the display as well as the resolution of the graph (Right now i think it's 10 seconds with a 256 sample graph).

-cyto

trogluddite ·

That's excellent stuff, Cyto - the use of the M2F "Automatic trigger reduction" particularly. (I've yet to completely fathom the peak detector code - but it seems to be very effective also).

I was just working on a version using bitmap scrolling rather than array storage - and the peak detection/M2F combo of your design happens to drop into mine rather well - solves problems I was having with making the scrolling smooth at a stroke!

Anyway, here's my version - it takes the output of your peak detector, and draws only a single line representing the current data point at the right of the display (no arrays needed), then scrolls using a bitmap buffer and transform.

This may not be so useful in some cases, I'm sure, as the wave data itself is not stored in an accessible way, and the window scaling is likely less accurate - but on my little Atom CPU mashine, it offers a useful reduction in CPU usage (about 25% compared to 40% for your design). Quite why plotting 256 data points is more CPU intensive than encoding a bitmap still baffles me - and I'd be interested to know of those CPU savings translate well to other systems.

aliasant ·

trogluddite wrote: That's excellent stuff, Cyto - the use of the M2F "Automatic trigger reduction" particularly. (I've yet to completely fathom the peak detector code - but it seems to be very effective also).

I was just working on a version using bitmap scrolling rather than array storage - and the peak detection/M2F combo of your design happens to drop into mine rather well - solves problems I was having with making the scrolling smooth at a stroke!

Anyway, here's my version - it takes the output of your peak detector, and draws only a single line representing the current data point at the right of the display (no arrays needed), then scrolls using a bitmap buffer and transform.

This may not be so useful in some cases, I'm sure, as the wave data itself is not stored in an accessible way, and the window scaling is likely less accurate - but on my little Atom CPU mashine, it offers a useful reduction in CPU usage (about 25% compared to 40% for your design). Quite why plotting 256 data points is more CPU intensive than encoding a bitmap still baffles me - and I'd be interested to know of those CPU savings translate well to other systems.

I have been looking at scrolling bitmap too and had something that worked so and so. It got the peaks and looked ok but the resolution was far from precise... to say the least.

Looking at your mod of Cytos i noticed that your using the trigger from the Mono to float as trigger for the draws and that means that it wont redraw if theres no change in the float after the mono to float... Set a 25 tick or similar directly to the draw part works better..

Nice work!

trogluddite ·

aliasant wrote: Looking at your mod of Cytos i noticed that your using the trigger from the Mono to float as trigger for the draws and that means that it wont redraw if theres no change in the float after the mono to float... Set a 25 tick or similar directly to the draw part works better..

Yes - I copied that pretty much from Cyto's original. If I understand the idea correctly, using the output of the M2F keeps the scrolling nice and even - e.g. so that each pixel always represents the same number of samples, because it only updates once the peak detector has analysed a complete block of samples. But you are quite right - an unchanging value will not scroll, and maybe I have misunderstood the logic. Possibly adding an 'update now' output from the code could fix this, while also keeping the accurate resolution? Cyto?

aliasant ·

I pursued my 8split farray version and this one actually works glitch free and smooth.

I havnt figured out the zoom function but at least it draws smooth and consitent even at high frequencies. Im pleased but feel free to correct me 🙂

cyto ·

trogluddite wrote: But you are quite right - an unchanging value will not scroll, and maybe I have misunderstood the logic. Possibly adding an 'update now' output from the code could fix this, while also keeping the accurate resolution? Cyto?

I haven't had a chance to look at the new versions yet (but I'm sure they quite put mine to shame), but I just wanted to pop in and say that in the code I wrote there is a little routine that prevents duplicate outputs. You should get a new value every time. Basically, it just tests the last value sent and if it's the same, it adds a very small amount (1e-036) to it.

-cyto

trogluddite ·

aliasant wrote: I pursued my 8split farray version and this one actually works glitch free and smooth.

Sure does! 🙂

Mono to Graph * 8 😮 !- where did that spring from? - he he, been in my toolbox all along and I never saw him! 😊 Guess it was added for FlowStone - for synchronised data logging etc. - and solves all the timing "bugs" I posted before so easy; will be useful in many other displays I wanted to make.

cyto wrote: You should get a new value every time... ...very small amount (1e-036) to it

Aha, the mystery of "scrolling silence" is solved! 😉

aliasant ·

Been working on the zoom but Im banshing my head severly now. Got it working in steps by changing the divide factor that goes into the MinMax

Also changed it from 8 strems to 16 to get a bigger window.

if someone can fix the zooming that would be wonderful 🙂 It needs stepless transitions so that the zooming is stepless.

LOL Didnt realise that you MISSED the 2, 4 and 8 mono-graph prims! 🙂 You of all m8 !

cyto ·

Okay. After looking over trog's wonderful bitmap rendering thingy, I made a few (I hope) positive changes to this thing. I redid the peak detector. I was certainly over-thinking it in the earlier version. This new one doesn't have all the unnecessary "smoothing" filters in it. It simply just captures the max and min of the given range. I also rethought the "scrolling silence" mechanism (as it could potentially start to accumulate after long bouts of silence). So basically there is a little "switch" in there that alternates between +1 and -1 each time the values are captured. This switch gets sent to its own m2f which triggers the updates on the capture m2fs. I didn't dare go in and touch the bitmap generator, but I did make it so the whole module is scale-able and the capture timer should only trigger when a new pixel is actually needed. I'm sure there is plenty more to do, but this may be a more usable solution than the previous versions.

-cyto

aliasant ·

Not sure about yours Cyto. It doesnt behave as expected or? Timing seems quite off.

Check this out just to see what it could look like but use a test osc instead. Then you can really see if it draws the waveform ok.

I fixed a "bug" with the whole zoom function. Seemed the Hop value in the first piece of code needs to correspond with the Div Factor ( 8, 16, 32 and so on).

cyto ·

aliasant wrote: Not sure about yours Cyto. It doesnt behave as expected or? Timing seems quite off.

Yeah, you're right. I didn't notice it when working on my 3GHz quad-core machine, but after testing on the old netbook, there certainly is a timing issue. The timing discrepancies are definitely apparent with smaller window sizes (ie. less than 10sec - I'm sure this is a trigger issue). It seems our two version compliment each other: Yours is significantly more precise (both in display and timing) but is limited to shorter windows (?) whereas mine seems better at handling longer windows (potentially several minutes or more) at the expense of precision. Perhaps there is a happy medium to be reached?

-cyto

aliasant ·

cyto wrote: aliasant wrote: Not sure about yours Cyto. It doesnt behave as expected or? Timing seems quite off.

Yeah, you're right. I didn't notice it when working on my 3GHz quad-core machine, but after testing on the old netbook, there certainly is a timing issue. The timing discrepancies are definitely apparent with smaller window sizes (ie. less than 10sec - I'm sure this is a trigger issue). It seems our two version compliment each other: Yours is significantly more precise (both in display and timing) but is limited to shorter windows (?) whereas mine seems better at handling longer windows (potentially several minutes or more) at the expense of precision. Perhaps there is a happy medium to be reached?

-cyto

I wish 🙂

There might be a way to get as big a window as you like but with no delay and that is to pursue Trogluddites idea of a scrolling bitmap perhaps combined with my way.

You would need a small window, maybe just 1-4 ( mine currently has 16) streams and after the window has rendered the array, take a snapshot of that and save to a bitmap that you then start scrolling 1 pixel to the left / trigger and at the same time you scroll in the newly rendered window from the right at 1 pixel / trig.

I think you could just keep adding bitmaps til your entire frame is covered.

Trogg PLEASE Help us with this 🙂 ( Maybe your already cooking for us? Smooking and puffing like the mad scientist... in the dark basement far from any distracting affections like long necked guitars and what nots...)

tester ·

@cyto - on my C2D 2GHz it shows less than 4% usage on your longviews (both versions), so is the timing on second attempt/code - a matter of CPU?

I'm curious how your version evolves into properly working long waveview, because your approach produces small and efficient (not complicated) schematics. Could you take some time on that? Stereo/dual synced version would be nice. I noticed some display-related bugs in first version, but I'm sure you noticed them too.

trogluddite ·

cyto wrote: there certainly is a timing issue... ...ie. less than 10sec - I'm sure this is a trigger issue)

I've had a quick look, and I'm pretty sure that you are right about the triggers. For a 10s window, the sample block size is just over 1000 samples - so the output values are changing at around 40Hz. Even on a powerful system, a Tick100 rarely manages more than about 60Hz, and this drops dramatically when the CPU is stressed - eventually to the point where you can't guarantee that there will be a trigger during the ~25ms window between value updates. On my 'baby' Atom powered machine, the 'jerky' movement of the display is obvious without even needing to use a 'test signal'. A larger window size (as you point out) reduces this problem - but the limit of resolution is rather arbitrary as we can't predict what machine the end-user might have. So a system is needed to cater for the possibility of more than one data point per trigger - kind of like a 'low resolution' version of aliasant's system.... (see below)

aliasant wrote: Trogg PLEASE Help us with this

He he, thanks for the vote of confidence! Have a lot of boring chores to do today, but for the problem above, I think there may be a solution similar to what I use in my older 'CRT scope' schematic. It works something like this...

1) Write the detector output value into a 'mem' using a Wave Write and pointer. 2) When a trigger does make it through the M2F, convert mem->array.. 3) Also read the array index (M2F), use this to truncate the array and to know how many pixels to scroll. 4) Draw the truncated graph and scroll. 5) Send a flag to the detector code to tell it to reset to index zero of the mem.

But this still leaves a problem... some samples may pass before the 'reset' flag is seen by the code (it can't be sent until the mem to array operation is done, and green->stream is not sample synchronised). This is why my earlier 'CRT scope' schematic uses two alternating (and slightly overlapping IIRC) buffers. TBH, it's so long since I made that, that I can't quite remember the logic that I used, but I will try to take a look and see if it can be adapted (and hopefully improved).

I think that by juggling the detector block size and the mem array size, this might make a good start for a "dynamic" system. You would be able to juggle between the Draw Graph doing most of the work (to show detail), and the 'scroller' taking over when 'zoomed out' to the the long term 'envelope' - and using Cyto's "block" method should mean that scrolling is always in whole pixels, getting around the 'anti-aliasing' fuzziness problem that I had when I tried this before.

trogluddite ·

OK - Here's a first rough attempt at bringing together everyone's ideas so far...

After some thinking, I realised that the stitching together could be done using a single circular buffer. Here's a quick description of what's happening...

1) Min, Max detector similar to Cyto's - finds the min-max for a block of samples; each block to be represented by one pixel width in the display. 2) Mins and Maxes are stored to a psuedo-circular buffer (mem) 3) Ticks can come in at any arbitrary rate - if there is no new block since the last trigger (i.e. index not changed), there's no change at the M2F that reads the buffer index, and that trigger will be skipped because there is no new information to display. If there is new information... 4) Convert buffer into a float array 5) Extract from the array only the new data (between the last index read and the current one) 6) Scroll the bitmap buffer by the number of new data points since the last animation frame 7( Draw the new data at the right hand side 8) Capture a new bitmap buffer for the next frame.

There are a few "fiddle factors" here and there - these were added to make 'slices' overlap by one pixel - there are two reasons why the overlap is needed. - To avoid weird vertical lines in the display - the graph draw does not seem to quite fill the given area. - Draw Graph must be given at least two data points - a single point draws nothing as the graph module draws lines, and a line must have two ends!

CPU seems reasonable - at the uploaded size, I get about 3-4% CPU on my Q6700. The animation is still a little 'lumpy' - the size on screen seems consistent (1px per sample block), so I think it is just due to the need for scrolling in whole pixels that makes the movement a little uneven.

EDIT) Tested on my Atom netbook also - works just as effectively for about 25-30% CPU.

aliasant ·

Nice work Trog! I knew you could do it!

On my new machine cpu usage is around 0 🙂

One anoying thing is the need for drawing the Min and Max seperatly getting that line at zero In mine I convert the -1 to +1 range to 0-1 and then back again before the Draw. Tried to do this with yours but I couldnt get that to work.

Its also a bit choppy if you use say 10000 Samples per Pixel. Thats probably something that needs a fix if possible at least for those who wants to use it for long big fancy windows.

Its perfect for me though, not needing them long times.

trogluddite ·

aliasant wrote: Its also a bit choppy if you use say 10000 Samples per Pixel

Damned nit-pickers! 😉

Re: Min and Max graphs I think there are two different approaches here depending on the time scale...

-For the long-time - the max and min are essential to be able to see the upper and lower limits over a period of time (sound envelope) -For short-time (i.e. looking at wave shapes) you just want to see the value of the samples (likeyour method with the mono to graphs) - so min/max is probably not so useful. A better way might be to find the average (or max absolute amplitude) for the block of samples - then have only mono mem - one array - one Draw Graph; so that there is only a single line.

NB) the little 'seam' at the centre line is another effect of the Draw Graph not filling the area completely that I mentioned in the other post - maybe another of SM's strange anti-aliasing artefacts (or maybe anti-aliasant?! 😉 )

aliasant ·

trogluddite wrote: aliasant wrote: Its also a bit choppy if you use say 10000 Samples per Pixel

Damned nit-pickers! 😉

hehehe

Thats my speciality! and you know what?

It works.

You fixed it!. I didnt think it was possible even but you did it in what? An hour? Amazing. This works GREAT!!! Thanx m8

aliasant ·

Heres a PIMPED version with a Zoom control 🙂

trogluddite ·

My turn to nit-pick! 😈

Can you re-up your pimped scope with audio disabled - I can only download onto my Atom machine (big machine is not online) - CPU freezes when SM tries to load the toolbox while audio is running on your schematic.

PS) Crossed lines! - see my previous post for edits I did while you were posting.

aliasant wrote: You fixed it!. I didnt think it was possible even but you did it in what? An hour?

See posting times! Boy am I quick today 😈 - think I deserve a beer or two...

aliasant ·

You deserve a full box of Obans! That is if you do the single malts..

Heres a pimped version with no audio in or out. The last one had only a ASIO out but it was not active. Odd.

Edit:

Reread your post now. Would be nice to have a switch to go between Min/Max and Average perhaps? Im still amazed at the speed you did this in.

When you were working on the goniometer I was trying to achieve this but failed since I simply dont understand the whole buffer thing but i did get something that looked like it could have worked. I, as many here, do SM in periods and I think I started that at an end of a period. Typical... And again. You did it in the same time it takes me to boot my pc and get some coffe.. 🙂

philter5 ·

...i bet trog´s brain is equipped with the newest-high-tech 64core processors 😀

tester ·

Thanks, nice designs. Yet in multichannel (tested on stereo) mode those fellows still don't sync best; is not bad, but not refresh irregularity is not "as one".

I would see another solution here, which should solve a display/refresh problem. Switching between "live srolling" and just "redrawing" the time window (when the wave reaches it's end). Thus - there should be no motion related flickering.

I don't know whether redrawing the scope is designed for the whole scope screen (this schematic is still beyond my comprehension), but in redrawing mode - redrawed could be only one vertical line at the time (plus some vdrtical separator), and not the whole scope screen, thus there would be no flickering at all. What do you think about such direction?

cyto ·

Ha! Awesome work trog and aliasant! While you two were having at it, I was coming up with my own take on the issue. I post it here for completeness. It certainly doesn't have all the advanced bitmap trickery as yours. I went back to just a plotted array like SMs scope. I, too, went the circular buffer route but instead of having all those complex write/read things, I kept mine inside the asm box. Oh well, here it is for those interested, though it looks like it was obsolete before it was made 🙁

(though, I think mine is more lightweight and the zoom might be smoother 😉 )

-cyto

trogluddite ·

philter5 wrote: ...i bet trog´s brain is equipped with the newest-high-tech 64core processors 😀

trogluddite wrote: See posting times! Boy am I quick today 😈 - think I deserve a beer or two..

...not after this many beers! 😠

aliasant ·

cyto wrote: Ha! Awesome work trog and aliasant! While you two were having at it, I was coming up with my own take on the issue. I post it here for completeness. It certainly doesn't have all the advanced bitmap trickery as yours. I went back to just a plotted array like SMs scope. I, too, went the circular buffer route but instead of having all those complex write/read things, I kept mine inside the asm box. Oh well, here it is for those interested, though it looks like it was obsolete before it was made 🙁

(though, I think mine is more lightweight and the zoom might be smoother 😉 )

-cyto

Thats pretty nice. Very simple and effective design.

I just placed yours, Trogs and mine ( clearly inferior ) versions next to eachother and set their zooms so that the sync with eachother.

Mine is very limited by fixed times even though Im sure i could make the max window at least twice the sice without loosing to much performance but it does render a detailed wave. I could probably fix the zoom so that it works smooth as yours too but why waste time on something you guys already fixed in such genious ways?

Edit: Forgot to mention that mine has serious redraw problems were it cancels out the waveform at certain frequencies... Not very good eh?

Cytos seems to have a redraw glitch though. Might be fixed by finetuning the buffer size or similar or maybe use a dirty fix by extracting only a section from the final farray. Simply skip the first say 16 samples from the array? ( I had to try that and it seems to work perfect)

Heres that .osm if anyone is curious. I included that small glitchfix on Cytos.

cyto ·

aliasant wrote: Cytos seems to have a redraw glitch though. Might be fixed by finetuning the buffer size or similar or maybe use a dirty fix by extracting only a section from the final farray. Simply skip the first say 16 samples from the array? ( I had to try that and it seems to work perfect)

I'm afraid it might be a little more complicated than that. I know because I've been working on stretching this thing a little further (why? I have no idea). When you get to very short window sizes, the glitch becomes even more apparent. Arrrgh!

-cyto

EDIT: I'm convinced now more than ever that this is a trigger issue. I think the glitch is an old (or a new) "shift" factor finding its way into the graph (if that makes sense). In one of my little "splinter" projects from this, I had the trigger line going to the redraw in between (in connection order) some graphs and said glitch was even more pronounced (and misaligned graph-to-graph). Fixing the connection order at least lined up the "glitch" but didn't remove it. If there were a way when dealing with the tick primitives to only allow a new tick trigger once the previous trigger has completely propagated the schematic (or definitely gotten to a certain point, say the redraw primitive), I think this could be worked out. Perhaps a certain Trigger Master might chime in 😉

trogluddite ·

Hmmm, without understanding the assembly block, it is hard to be certain, but I'm not yet convinced that this is trigger related...

cyto wrote: only allow a new tick trigger once the previous trigger has completely propagated the schematic (or definitely gotten to a certain point,

AFAIK, there is no way around the default behaviour - "pending" triggers are held in a queue until the schematic is free to service them. So using a trigger blocker etc. as a 'gate' would serve no purpose as (from the gate's point of view), the waiting triggers haven't arrived yet and there is nothing to block. The gate would then be opened for new triggers at precisely the time that the schematic becomes free to take the next trigger off the queue anyway. So the system already works the way that you suggest with one critical difference - new triggers are queued while the schematic is busy rather than being dropped. OutSim have obviously made the decision (correct IMHO), that this is the right behaviour most of the time - otherwise MIDI input could go missing, and sequential logic would be highly unpredictable. Which makes me think now - is this the purpose of the "ReDraw Limiter" primitive? It has often mystified people that, although it does prevent triggers when the plugin window is closed etc., it doesn't actually seem to reduce the trigger rate very much (certainly not to a sensible animation frame rate). But maybe its purpose it to do as you describe - to ensure that any currently pending ReDraws are complete before allowing a new one to be intiated - thus avoiding the build-up of a large trigger queue (maybe through some sort of feedback from the GDI graphics engine) - might have to contact Malc about that one.

Anyway, back on topic - we can easily test if "queuing triggers" are the problem with your schematic - remove the ticker, and replace with a manual trigger button. This ensures that we are only seeing the effect of a single trigger free from any "trigger queuing". The 'glitch' still remains. All of the array primitives used are discretely triggered - they are all ones I have tested quite thoroughly, so I am quite certain that... - Changes at the primitives' array/integer inputs do not cause a recalculation of any arrays. - They do not respond to or propagate "reverse triggers" Checking with a trigger counter also does not show any unexpected duplicate triggers - and the trigger order seems to be right. I experimented with other orders too, but apart from putting the redraw between the two graphs (with the expected "offset" between them), the results were always the same - a slightly random offset to the wrap-around of the wave. So my suspicion is that somehow the code/mono2graph combo is not generating the correct index for the 'wrapping' of the waveform - though I dont understand the code block well enough yet to say that with any certainty.

cyto ·

Thank you, trog, for replying. Your insight is always very much appreciated. In hindsight, my (false) Eureka moment was definitely premature. Unfortunately, my obsessive/compulsive tendencies are keeping me down in this rabbit hole much longer than I probably should be. While the rest of the world moves on, I'll be fine-tuning shift factors.

-cyto

cyto ·

I had a chance to revisit this little guy tonight and and happy to report that I have solved my "glitch" problem. Instead of shifting whole blocks of data in the external arrays, I added a couple lines into the code that manipulates when the sampled values are being assigned to the exported arrays. While in there, I added a few functions to the module that don't really add any overhead but might be nice to have for analysis...

1. Ability to morph in between "envelope" graphs and "signal average" graphs (so it is equally effective at 5ms windows as it is at 15 minute windows). 2. Pause. While paused the graph is still accumulating data so that when you un-pause, there is no interruption in the display. Additionally, while paused you can export a graphic file of the scope readout (in fact, that attached png was generated by doing just that). 3. Readouts of peak values in the display (dBFS) as well as dc offset of the graphed signal. 4. Oh yeah, this is a dual-scope version, too.

Let me know what you all think. If anybody wants me to expound on how to access the asm memory buffers without having to rely on those read/write modules, I'd be happy to do so (this scope relies heavily on that little trick).

WARNING: this current version ONLY works in environments that have an ASIO buffer size of at least 256 and a whole number multiple of 256 (ie 256, 512, 768, 1024, etc.) Has NOT been tested with the Direct Sound output. See the rest of the thread for discussion of why this is.

-cyto

nix ·

mighty work, I'll remember u guys have developed this, ty!

aliasant ·

Cyto. Thats quite nice!

I have a request.

Could you change it to use 1024 instead of 256? I tried and failed but the code is not that easy to read 😉

cyto ·

aliasant wrote: I have a request. Could you change it to use 1024 instead of 256?

Yeah, the code is a bit cryptic. I didn't want to bore everyone with the inner workings. Lots of inter-dependent incrementors (like the gears of a clock). I'll see what I can do about expanding it to 1024. I can't make any promises. 256 is kind of the "magic number" to sync the internal arrays with the mono to graph captures. I might be able to use some of the delay techniques from your examples to accomplish it, though. Let me see what I can do.

-cyto

aliasant ·

cyto wrote: aliasant wrote: I have a request. Could you change it to use 1024 instead of 256?

Yeah, the code is a bit cryptic. I didn't want to bore everyone with the inner workings. Lots of inter-dependent incrementors (like the gears of a clock). I'll see what I can do about expanding it to 1024. I can't make any promises. 256 is kind of the "magic number" to sync the internal arrays with the mono to graph captures. I might be able to use some of the delay techniques from your examples to accomplish it, though. Let me see what I can do.

-cyto

Cryptic but brilliant 🙂

I was under the impression that 1024 was the magic number for stream to float stuff. That 1024 is somehow the "native" size that works faster and it would also give a higher resolution especially if you upsize the window to see better? Maybe a bigger chunk means a chunkier zoom as well and that might not be so good?

tester ·

Impressive!

cyto ·

aliasant wrote: I was under the impression that 1024 was the magic number for stream to float stuff. That 1024 is somehow the "native" size that works faster and it would also give a higher resolution especially if you upsize the window to see better? Maybe a bigger chunk means a chunkier zoom as well and that might not be so good?

You had me second guessing myself! But after doing a few more experiments, I think I can confidently say that 256 is the magic number. Here is a quick demonstration...

Read the little notes in there about what's going on and what to look for. Unless I'm missing something (which I very well could be), you can only be 100% certain of the mono to graph captures when the data is exported in cycles of 256 samples. Now, you could very well send multiple (parallel) blocks of 256 samples out, somehow "tagging" them as to their position and reconstruct the data blocks in green (which is probably what would need to be done to expand this scope to 1024).

Let me know if that demo makes sense and if you can shed anymore light on this (as I'm just beginning my experiments in this type of data manipulation).

-cyto

aliasant ·

Cyto.

That was a very interesting experiment! That it locks to the right side is indeed quite unexpected as well.

This is perhaps related, like a distant cousin, to my own little "trick" of setting my test oscillator to 187.5hz when Im viewing signals. At that frequency (or multiples of that like 375Hz, 562.5Hz, 750Hz...using a samplerate of 48kHz) the oscilloscopes signal is frozen perfectly, just as your experiment shows. That trick is samperate related. If I change my samplerate from 48kHz to 44.1kHz I loose the "sync"

That is not true with your signal test BUT. Im betting your using a samplecard buffer of 256 ? If you change it to some odd buffer like 192 you will loose the sync and again, if you change it to 1024 you will have perfect sync on the 1024 ramp and the 256 ramp.

It seems that you need bigger buffers to get less flickering....

cyto ·

aliasant wrote: This is perhaps related, like a distant cousin, to my own little "trick" of setting my test oscillator to 187.5hz when Im viewing signals. At that frequency (or multiples of that like 375Hz, 562.5Hz, 750Hz...using a samplerate of 48kHz) the oscilloscopes signal is frozen perfectly, just as your experiment shows. That trick is samperate related. If I change my samplerate from 48kHz to 44.1kHz I loose the "sync"

Not too distant a cousin! 48000 / 187.5 = 256 😉

I bet the "lock frequency" at 44.1kHz is 172.265625Hz

Interesting thought about the soundcard buffer. I hadn't even considered that it would have an effect. When I have time later tonight, I'll do some tests.

-cyto

aliasant ·

cyto wrote: aliasant wrote: This is perhaps related, like a distant cousin, to my own little "trick" of setting my test oscillator to 187.5hz when Im viewing signals. At that frequency (or multiples of that like 375Hz, 562.5Hz, 750Hz...using a samplerate of 48kHz) the oscilloscopes signal is frozen perfectly, just as your experiment shows. That trick is samperate related. If I change my samplerate from 48kHz to 44.1kHz I loose the "sync"

Not too distant a cousin! 48000 / 187.5 = 256 😉

I bet the "lock frequency" at 44.1kHz is 172.265625Hz

Interesting thought about the soundcard buffer. I hadn't even considered that it would have an effect. When I have time later tonight, I'll do some tests.

-cyto

There are definetly things to learn here but right now Im way to tired to even try 🙂

trogluddite ·

Great work, Cytp - the addition of the peak and DC readouts is a masterstroke.

cyto wrote: I added a couple lines into the code that manipulates when the sampled values are being assigned to the exported arrays

This is looking like a very interesting technique - though there are still some mysteries that I haven't quite got my head around yet! I'll stick my neck out and see how I'm doing so far...

44100/256 = 172.5Hz - so blocks of 256 samples can be generated much faster than ticks. There is no explicit "signalling" between the code and the mono to graph - the code does not know when a tick has happened, nor a frame drawn - and the ticker does not know any of the code's variable values. From which I deduce... There is an implicit "frame size" for the receipt of triggers from the windows timer (ticker) - triggers to the 8*Graph can only occur at 256 sample boundaries. Indeed if count1 is loaded with a non-zero value in stage(0), the whole graph is "rotated" - but never drifts. Effectively the routine that reads the windows timer, and generates triggers from it is using a hop(256), synchronised to the sample sample counter (ecx) used for all other hops. Your buffer is filled at the desired rate (appropriate to the zoom) - and the reading out is a continuous loop at sample rate, but (here I am completely guessing!) the clock for this is advacned/retarded based on the write index.

This is a real revelation to me - not only is your scope fantastic (the "analytical" complement to my "low CPU, but sketchy" version) - but I think that you have discovered something really fundamental about the inner workings of SM that I have never seen before.

cyto ·

trogluddite wrote: This is a real revelation to me.

You and me both 😉 I'm still exploring/testing/debunking this little "trick". Any further insight would be definitely encouraged. Getting back to the scope: FWIW, the code block always has a 256-sample copy of the "readouts" of the scope in its internal memory. The output to the graphs is generated by simply continually cycling through those arrays (as I said earlier, the trick was figuring out how to internally update that array). No matter when the graph is captured, it should output a perfectly synced version of the internal array. You'll notice that there is a stage 0 routine that resets all of the counters to 0. This is there because I noticed that sometimes, SM will retain values in its memory even when the stream is reinitialized. In order for this to work, those counters must be reset.

I am certainly interested in any discoveries made on the 256 "magic number". 🙂 I can already imagine some very cool things that could be done with this little bit of knowledge.

EDIT: I see you already figured out about the counter reset. I should have read your post more carefully 😊

-cyto

cyto ·

HOLD THE PHONE!!!

Aliasant was right! The ASIO buffer definitely makes a difference in the capturing of the graphs. Back to the drawing board. 😊

-cyto

cyto ·

Did I mention my obsessive/compulsive tendencies? 🙂

You can extract the current ASIO buffer size from the ebp register!!! (you need to copy it to the eax register first (for some reason) or else SM will crash) 😕

Scope update coming soon!

-cyto

trogluddite ·

This gets more and more interesting with every post! 😮 By complete fluke, my ASIO buffer was set to 512 (crappy netbook!) - so your scope had worked perfectly!. And, as expected, when changed to a non-multiple of 256, the display went bonkers.

cyto wrote: You can extract the current ASIO buffer size from the ebp register!!!

He he, and to think I posted this mere hours ago... Trogluddite wrote: I think some other registers are also used internally by SM - I guess that is why the assembler only recognises 'eax' for most of the x86 opcodes, and why 'ecx' must be copied into 'eax' before calculating hops

I have done a little fiddling with the other registers before - but gave up when I found that SM will often highlight the syntax as though valid despite the opcodes not working (or crashing, as you have already found!) Even pushing/popping the values doesn't seem to always fix that either, so I guess the assembler simply doesn't compile the opcodes properly.

BTW) You can also get the buffer size from the string output of the ASIO Out primitive (with a little parsing) - maybe useful if needed in "green".

aliasant ·

cyto wrote: HOLD THE PHONE!!!

Aliasant was right! The ASIO buffer definitely makes a difference in the capturing of the graphs. Back to the drawing board. 😊

-cyto

😀 Glad I did something right for a change :=)

DigitalWhiteByte ·

Interesting 😀 nice to see so many minds at work

cyto ·

Okay. I have discovered a few things. My previous revelation about the ebp register should be interpreted with a healthy amount of skepticism. First of all, it does not simply contain the array size (-1) of the asio buffer, but rather continuously "ramps" an integer value from zero to the buffer size (-1). The reason the m2f only outputs the buffer size can actually be found in the demonstration from a few posts back. Like the "mono to graph"s, the mono to float orients itself to the right of the buffer size, so I was only seeing the last value of the increment. Secondly, the ebp register is simply a copy of the edi register, which I would argue may be a better choice for accessing this type of information. This makes sense if you analyze the code compilation of the schematic. The edi appears to be the cyclical index of the code. The data in this register is passed to the ebp register in order to locate the necessary data to access (for output).

I will say that the more I burrow down this rabbit hole, the more I am convinced we are treading in dangerous waters (sorry to mix metaphors, and even sorrier to the non-native English speakers 😉 ). I do believe that there are many new "tricks" waiting for the adventurous, but after countless crashes and one BSOD, I think I might put this on the back burner for awhile. I do intend to try to fix the scope that I posted earlier (wasn't that what we were talking about?).

-cyto

trogluddite ·

cyto wrote: My previous revelation about the ebp register should be interpreted with a healthy amount of skepticism

For sure - on my netbook, I don't even seem to be able to read ebp, just trying to use "mov eax,ebp" causes a crash! 😠 That's a real shame - this was all starting to look interesting - but a reliable way to get the buffer size will be needed to get the "frame sync" right. It can be got at as a string from the ASIO out code - but that's not much use for VST exports or DS users.

DigitalWhiteByte ·

Found solution to extract the current audio buffer size. 😈 tell me if it works for everyone.

nix ·

It's working here 😮

aliasant ·

nix wrote: It's working here 😮

Works here too but this reminded me of an odd behaviour when changing buffersizes.

If I change from one buffer to a larger buffer all is well but if I change from a large to a smaller buffer I need to clear the audio before it works. Can anyone confirm that ?

I guess were all waiting for Trogs fabulous laptop now? 😀

trogluddite ·

aliasant wrote: I guess were all waiting for Trogs fabulous laptop now?

Yup, that seems to be working just fine here - nice work DWB! 🙂

DigitalWhiteByte ·

aliasant wrote: If I change from one buffer to a larger buffer all is well but if I change from a large to a smaller buffer I need to clear the audio before it works. Can anyone confirm that ?

Sorry, my sample hold value, not working properly. Ok now after you change the buffer size and retrig it refresh the new value size.

tektoog ·

Works for me too...*-* good job !

tester ·

Ehm, so... This "Get_Audio_Buffer_Size_DWB~2012.osm" should be connected inside cyto's "superScope.osm" somewhere?

By the way (superScope.osm) - direct sound output seems to work fine here, my ASIO - not (view changes into this strange stretching flickering mode).

When we are at the graphs, I have another question. Is it possible to make using SM and ASM - an efficient FFT frequency viewer (and/or accurate freq peak finder)? Let say an equivalent of the resolution 0.336 to 0.084Hz at 44.1kHz and at some acceptable refresh rate?

trogluddite ·

tester wrote: Ehm, so... This "Get_Audio_Buffer_Size_DWB~2012.osm" should be connected inside cyto's "superScope.osm" somewhere?

At the moment, the size is hard-coded into Cyto's asm, so it needs a fair chunk of the code re-writing so that it can handle the different buffer sizes read by DWB's little gadget. I imagine that also explains the difference when you switch to ASIO - your buffer size is probably different to the one that the code is made for (128 samples).

tester wrote: When we are at the graphs, I have another question. Is it possible to make using SM and ASM - an efficient FFT frequency viewer (and/or accurate freq peak finder)? Let say an equivalent of the resolution 0.336 to 0.084Hz at 44.1kHz and at some acceptable refresh rate?

A stream FFT is not impossible, I think, but very difficult - assembly in SM only supports a limited set of instructions, making nested arbitrary size loops tricky to code. For a really efficient FFT you would probably need to "unroll" a lot of the loops, making for a very large block of code (very easy to make a mistake, and very hard to de-bug).

High accuracy of frequency measurement and fast refresh (i.e. high accuracy of timing measurement) are, unfortunately, mutually contradictory due to the uncertainty principle. For greater frequency resolution it is always necessary to analyse a larger sample window containing more cycles of the waveform - this is also true of other frequency analysis techniques such as auto-correlation etc. As an example, take a look at my "Funky Mountains" schematic. Try playing some pitched sounds into it while changing the "Speed vs. Accuracy" parameter - as you raise the value, a greater number of samples are used in the analysis, and you will see the frequency peaks become much more defined. At low values, the display is less sluggish, but the frequency plot becomes almost meaningless. (NB. the schematic has a fixed semi-tone resolution). The optimisations that make FFT (relatively) fast also rely on the window having a power-of-two number of samples - so there is little room for maneouvre when choosing a compromise of window size. The window size also determines the lowest frequency that can be reliably measured - the wavelength must fit inside the window (several times for a good analysis). For peak frequency/pitch measurement, you can get around these limitations to a degree by using interpolation etc. when there are certain known conditions - e.g. the pitch is known to be within a particular frequency range etc. For a good example of this, take a look at Martin's Pitch Extraction schematic. This uses auto-correlation to look for the discrete pitches of "concert tuned" semitones, folllowed by interpolation of adjacent frequency bands to find the degree of "pitch bend".

tester ·

Thanks Trog, I understand these issues. I just feel so encouraged by previous resuts achieved in long-time scoping/viewing (impossible became real).

I have an idea (I think). Since the peak detection is semi-sensoric (you hear the sound, you look at the screen), resolution can be dynamically changed, depending on actual zoom. The more you zoom to certain frequency spectra (left/right border limits or center point), the greater accuracy can there be. Magnification levels could be connected to resolution progression? I see no reason to display high resolution FFT on a small window/screen, but magnified area could show some more details (sometimes two or three peaks that produce very slow differential beating). I also think, that displaying the spectra below maybe 20-30 Hz is useless via FFT, maybe through some other algos for slow changes (wavelet or something like that as far I remember is used there?) - because there is nothing "musical/melodic" going on (most audible vibrations are harmonic, differential or physiological/phase-dependent in nature), only "bass pumping" and quasi/semi DC added to the signal. So maybe there are some ways to overcome some habits? Probably there some "overlap" routines can be used (repeating blocks?) or seeing the 44kHz as 22kHz and lower (which extends the time of samples). I don't know which one for offline and which one for "real time" view are used however. Just some thoughts.

Generally I'm interested in two directions. Visual observations of how the sound (and it's changes) looks like, and spectral peak detection over surrounding "background area" (peak frequencies, which in my case - are 2-4 per band in c.a. 10 bands, and these per band are very close to each other, let say 0.2 to 30Hz difference) per audio sample (batch processing on multiple files. These are for further projects, but I'm writting here while I remember about them. 😉

trogluddite ·

Maybe something like the correlator system used in the "Funky Mountains" example (from my previous post) is more suitable then. Compared to FFT it is inherently more scalable - the centre frequency and integration time of each bin are independently adjustable to any arbitrary value, there is no reliance on discrete "blocks" of samples, and extra bins are easily added by copying and pasting modules. In that schematic the integration times are already scaled according to the frequency of each bin, as shown by the faster decay time for high frequency peaks (just a low pass filter on the correlator outputs, in fact). So the update speed vs. accuracy compromise is also very easy to tweak. Should be quite simple to derive the frequency centres from the zoom scale, and also to scale up the integration times as the zoom increases in order to reveal the extra detail. There have been some nice quadrature oscillators posted since I made that too, which could potentially save a lot of CPU in the correlator code.

cyto ·

trogluddite wrote: At the moment, the size is hard-coded into Cyto's asm, so it needs a fair chunk of the code re-writing so that it can handle the different buffer sizes read by DWB's little gadget. I imagine that also explains the difference when you switch to ASIO - your buffer size is probably different to the one that the code is made for (128 samples).

I just looked over the code again, and I don't think it would be too hard to integrate. It would only involve adjusting 2 of the counters in there in addition to 2 "green" calculations. I think the most difficult part would be ensuring that we get an accurate buffer value before any of the accumulation routines start to run. Without knowing exactly how DWB's wonderful little sensor works, I can't be too sure how to implement it. I would imagine there is a significant time lapse (in terms of samples) between when the stream is initialized and when the final buffer size is returned. I promise I'll get back to this when my attention can be a little more focused (too many pots on the stove right now).

-cyto

PS. not to split hairs, but it's actually 256 samples 😉

DigitalWhiteByte ·

cyto wrote: Without knowing exactly how DWB's wonderful little sensor works, I can't be too sure how to implement it. I would imagine there is a significant time lapse (in terms of samples) between when the stream is initialized and when the final buffer size is returned.

I try to explain, as I think it works. each time it fires a polyphonic voice, it respects the size of the buffer of the soundcard. then the smallest execution of a note will have the size of the buffer. if you try to increase the duration of the note in milliseconds, you will notice that the read buffer will be increased by a size equal to cover the period. for example if my buffer is 1024 samples, each time will be increased will be equal to the size of the buffer, then 1024 +1024 +1024 and so on.

Then measuring the shortest note that the polyphonic voice can make you get the size of the buffer set to the sound card.

tester ·

Knock, knock!:-) Any chances to finalize the cytoscope with this buffer tiny thing?

cyto ·

tester wrote: Knock, knock!:-) Any chances to finalize the cytoscope with this buffer tiny thing?

Soon 😉 I had a chance to work on it a little tonight. I have the buffer-size issue sorted out. It works well even at "strange" buffer sizes. There still is one tiny little issue with the internal timing that causes a very slow "drift" in the readout at certain zoom settings. I want to get that worked out before I post it. Sorry it has taken so long... I have a lot on my plate right now!

-cyto

aliasant ·

Keep on perfecting Cyto! Well all be here waiting patiently in an unorganized line/mess 🙂

Interesting that you figured out how to get it to work with odd buffers.

cyto ·

Okay. I think I have everything sorted out. 🙂

I was able to integrate DWB's "buffer get" method into the scope (I was actually able to simplify it even more, but the essence is still the same). This version should work for all buffer sizes, but there are a few caveats...

First, the resolution of the scope display (data points) is always equal to the buffer size. This may be problematic if you are using either very small (ie <64 sample) or very large (>1024) buffers. There is a way to adjust the resolution based on integer factors of the buffer, but I don't think it would be worth it to add that functionality. I'm sure most people will be using around 128-512 sample buffers, which should translate pretty well to the scope display.

Second, you have to manually reset the scope if your current ASIO setup is not compatible with the scope. For instance, when you download this osm, it is configured to "my" buffer size of 256. If yours is something like 384, you have to hit the little "reset" button that I added. This will grab your value and re-initialize the scope. Adding an "automatic" detect would just be too much trouble, I'm afraid, since there is a lot green-to-poly-to-mono-to-green-to-mono stuff going on during initialization. So obviously, this is not really something that can go into a finished vst. But for metering during a build, this should be acceptable.

Anyway, it tested pretty well in my setup. If anybody runs into any problems, let me know and I'll try to address them. 😉

-cyto

tester ·

Can the reset not be done simple and automatically? Something like "after load" trigger plus trigger on changing soundcard? But manual reset/cleanup is desirable option too 😉 Thanks!

adamszabo ·

Very nice stuff guys! Cyto, I have added a new zoom control and changed the old zoom into an amp knob. I guess it can be done in a nicer way, I just did it for fun 🙂

cyto ·

tester wrote: Can the reset not be done simple and automatically? Something like "after load" trigger plus trigger on changing soundcard?

Absolutely! If you go this route, though, you need to find some way to get a "green" trigger from the soundcard change. The only way I can think to do this is via the "audio select" module. I'm pretty sure that sends a trigger out. Just route that trigger into the "reset" node and it should work okay. I'd be interested in any better suggestions for "auto-detect" though.

Adam, that zoom is awesome! Though, may I suggest that the "amp" multiply the incoming audio signal and not the arrays. The reason this might be better is that the code section has a "clipping" routine to keep the graphs [-1 to 1]. So if you have a loud signal going in and you "amp" it down to see its peaks, they won't be there because they will have already been clipped. If you multiply the incoming signal, though, they will be kept intact. A cool feature, though!

-cyto

tester ·

AudioDevice primitive + AfterLoad primitive should do. The first one probably detects changes in default windows sound settings, and the seconds resets the scope each time when schematic/app is loaded. Can it be simpler? I guess not.

cyto ·

tester wrote: AudioDevice primitive + AfterLoad primitive should do. The first one probably detects changes in default windows sound settings, and the seconds resets the scope each time when schematic/app is loaded. Can it be simpler? I guess not.

For an exported .exe that should be perfectly fine. I would worry about using that in a VST, though. How many people make changes to their audio setting from within a plugin? Not many, I'm afraid. They would make the changes in their DAW settings. Unfortunately, the only ways I can think to detect those types of changes would be via code/asm. The routine currently in place involves a "clear audio" as the final step in the reset, so I'm afraid we would run the risk of getting into an infinite loop of audio refresh if we went that route.

-cyto

tester ·

Ah, I see - I just checked. I thought, that this one shows also which one is in use. Hmm... When dealing with VST - what the host is sending to a plugin? Is this buffer thing not host dependent?

tester ·

Just a quick question. If nothing is conneted to the scope inputs, but the scope is present in the schematic - is the scope taking CPU too or get's offline?

Wrote something here? To have a post removed or your name hidden, write to [email protected].

Before your first post

A few rules keep this a friendly place. You agree to them once.

Shown next to what you post, here and in the app. It doesn’t have to be your real name: 3–24 lower-case letters, digits or _ (capitals become lower case, spaces become _).

    Then your post goes up straight away.

    Delete this reply?

    Open it in SynthMaker?

    It goes on the track you’re editing there, in place of that track’s sound, and into My sounds. Your other tracks stay as they are.

    Want to keep that track’s sound? Start a new song in SynthMaker first (Song › New song), then open this.

    Report this reply?

    Only the developer reads reports. The person isn’t told who reported them.

    What’s wrong with it?

    Block this person?

    You won’t see their posts and replies here any more. They aren’t told, and you can unblock them at any time.

    People you’ve blocked

    Their posts and replies are hidden from you. Unblock someone to see them again.

    The community rules

    A few rules keep this a friendly place. Everyone agrees to them once, before their first post.