| Author |
Topic  |
Twang
Posts: 126
|
Posted - Fri Jun 07, 2002 8:06 am |
|
|
Can this be done using the DirectX SDK?
Is there a CEP-specific API and, if so, where is it documented?
thanks,
- Twang
|
|
kblackwell
Location: USA
Posts: 37
|
Posted - Fri Jun 07, 2002 12:26 pm |
|
|
| Quote: | Can this be done using the DirectX SDK?
Is there a CEP-specific API and, if so, where is it documented? | I had similar wonderings, did a search, found some older discussion. I suppose you know about the Direct X files web site and the toolkit that Cakewalk provides for free? I have no idea whether it can work with CEP, or what operating system it requires, etc. I have, however, tried using the XFM SDK specifically for CEP, which you can get right here on this site (go to the download area). It works. I happen to have an old version of Visual C++ Developer Studio, and had no problems getting it to work.
Modifying one to make it do what I want has been more problematic, however, as there aren't enough examples for using various kinds of controls in the dialog box (sliders, etc.). Worse off, the SDK has not been updated for CEP 2, meaning it gives you no way to make the XFM show up in the Multitrack window for real-time effects, and no way to use the dynamic controls (automation) there. I asked Syntrillium for help with this a few days ago, and have not gotten any reply whatsoever yet. You have to pay close attention to what you're doing, as the ReadDataEx and WriteDataEx routines take arguments dealing with "samples" where "sample" is defined as both a left and right value when operating on a stereo waveform, and they return a number of bytes instead. Plenty of room there for mistakes even when you think you *are* paying attention.
Does anybody have any nice XFM example code to share besides that provided by the SDK?
_________________ -- Keith W Blackwell
|
|
|
|
Twang
Posts: 126
|
Posted - Fri Jun 07, 2002 1:19 pm |
|
|
Howdy KB
thanks for the reply. I'm guessing that the API updates, documenting them, or both are the last things on the CEP2 to-do list. (I have no way to know, just thinking like a programmer.)
"I had similar wonderings, did a search, found some older discussion. I suppose you know about the Direct X files web site and the toolkit that Cakewalk provides for free?"
No, I haven't done any hands on with this kind of stuff for a while. Can you post the link to that DX site?
"[...] the XFM SDK specifically for CEP [... in] the download area [...] works."
Oh cool! I missed that. Great I'll dig it up and muck around with it this weekend.
"Modifying one to make it do what I want has been more problematic, however, as there aren't enough examples [...]"
Time to hack and test sounds like...
" the [old] SDK has not been updated for CEP 2 [...] I asked Syntrillium for help with this a few days ago, and have not gotten any reply whatsoever yet."
Hmmm... I have no idea how their responses are to such queries, but I'm a bit baffled about my not getting an email response for a *sales* request. (Do you guys want to sell me something or not ? ;-)
"[... routines] take arguments dealing with 'samples' [...] and return a number of bytes instead. Plenty of room there for mistakes even when you think you *are* paying attention. "
I sure hope this is standardized across the API, as in the rtn val is the bytes sucessfully sent/received or an error code. Anything else, or a mix could get pretty goofy... well I shouldn't judge without seeing the code...
"Does anybody have any nice XFM example code to share besides that provided by the SDK?"
Ditto the request. Best way to learn is while you burn brain cells on other's code.
ciao
- T
|
|
|
|
|
Twang
Posts: 126
|
Posted - Fri Jun 07, 2002 2:08 pm |
|
|
BK:
Skimmed the APISPRO.doc. I see what you mean about the ReadDataEx() returning bytes read in terms of samples - whereas the WriteDataEx() returns the "units of samples, not bytes."
Same thing only different? ;-)
If the newer API is like this one, it seems like it would be pretty straightforward ... but the multiple wave and multiple file functions look kinda hairy.
I'll bet a cup of coffee and two 96kHz samples that the new API drops all the routines listed as 'obsolete' in the current doc, modifies the CI struct, and adds whatever new functions CEP 2 has that older versions don't, while maintaining the same approach. (Unless CEP 2 was a total rewrite ?? If so, we may have longer to wait!)
- T
|
|
kblackwell
Location: USA
Posts: 37
|
Posted - Sat Jun 08, 2002 1:45 pm |
|
|
| Quote: | | I'll bet a cup of coffee and two 96kHz samples that the new API drops all the routines listed as 'obsolete' in the current doc, modifies the CI struct, and adds whatever new functions CEP 2 has that older versions don't, while maintaining the same approach. (Unless CEP 2 was a total rewrite ?? If so, we may have longer to wait!) | The SDK as is works with CEP 2, as that is what I am using. But there is no indication how to access newer features.
I've been pulling my hair out over a series of problems, one thing after another. Most of it is because my plugin needs to always have some prior and successive data available when processing any given sample. Simple matter of programming, right? But I keep seeing really weird things. Like when then plugin finishes, the progress meter hangs there without ever going away (until I press "Cancel") because the last few samples never get read in. The ReadDataEx routine keeps telling me it read 0. Well, it's probably yet another thing I'll eventually figure out that I did wrong. Still, it sure would have helped if they had made some sample code available that does this. I can't tell for sure, but I don't think ReadDataEx works on negative offsets (I was hoping it would return 0's), or maybe even with offsets prior to the selection area, or if it does work, perhaps it needs a balancing WriteDataEx? Or maybe my code has still more undiscovered bugs (duh). Like I said, it's a confusing world to program in, where "sample" is really 2 samples in a stereo waveform, but you put them into an array of floats where each index is just 1 actual value. You really have to watch your steps. I've been trying to use a naming convention for all the variable and such that keeps it clear what their "units" are, and this has helped clear up some things.
I also haven't been able to get the dialog box control changes (made by the user during Preview) to actually show up within the running code. Thought I got everything in needed for that, but no dice. Oh, actually, Preview is generating some weird noisy modulation at the moment, so I'm having to just click "OK" and see what happens. Yet another bug to work out.
My intent was to work in the complex plane, but to get the imaginary component I figure I need the instantaneous derivative (slope) of the waveform at each sample. Sorry, I've only had one DSP class (an intro), so perhaps it is a well-known procedure how to go from a real waveform to a complex waveform, but I'm trying to make this up as I go (the theory/idea side of things can be a lot more fun and more of a learning experience that way). I'm using something like a sum of squares of the delta of samples before and after to get a better
approximation, though ultimately I was hoping to do some interpolation using the FFT features available in the SDK. Using the slope and actual sample value as points on a 2-D plane, you can then convert to polar coordinates and do interesting things to the angle, or whatever, before converting back to an instantanous rectangular value to output. But my "slope" ends up with a glitch in it every so often. I've been surprised to see that ReadDataEx is always returning less than what I'm asking for. Sounds like a logic error in my code to manage walking through the data in a loop. Or....
Hey, I think I better go back and re-read that ReadDataEx documentation. :-)
_________________ -- Keith W Blackwell
|
|
|
|
kblackwell
Location: USA
Posts: 37
|
Posted - Sun Jun 09, 2002 3:04 pm |
|
|
| Quote: | | Skimmed the APISPRO.doc. I see what you mean about the ReadDataEx() returning bytes read in terms of samples - whereas the WriteDataEx() returns the "units of samples, not bytes." | Your mention of this inconsistency made the light bulb come on for me. I checked the docs again, and indeed APISPRO.doc dos say that ReadDataEx returns the number of bytes read in. But it was showing me only a fraction of what I asked for. So, I tried removing the division by the number of bytes in a sample (potentially multi-channel sample). Guess what? Everything worked. No more glitches. Preview sounded the same as the result of pressing OK. About 90% of my problems just evaporated.
ARGH! I've spent many hours pulling my hair out over this one. And all because APISPRO.doc is WRONG.
I still can't figure out how to get changes made to the dialog box to take immediate effect during Preview (I have to push Stop/Preview a couple of times). But my plugin is working, letting me experiment to my heart's content. Yucky interface, but hey, I don't know my way around the Win32 world yet.
_________________ -- Keith W Blackwell
|
|
|
|
kblackwell
Location: USA
Posts: 37
|
|
Twang
Posts: 126
|
Posted - Mon Jun 10, 2002 8:28 am |
|
|
KB:
a very interesting discussion we've got going. Can see some good exchanges developing.
A couple of items, then a detailed reply...
| Quote: | | ARGH! I've spent many hours pulling my hair out over this one. And all because APISPRO.doc is WRONG. |
How wrong is wrong? I mean, are only the read/writeEx parameters labeled wrong, or is it worse? If the Synt programmers read this, it would be good for all of us to post anything we notice. I'm guessing that someone has been tasked with updating the API doc --- albeit giving it a much lower priority than a CEP 2 service release ;)
"The SDK as is works with CEP 2, as that is what I am using."
Thanks for posting TheDirectXFiles.com. They mention that Synt supports DX.
Do you know if a pure DX plug in works in CEP?
" But there is no indication how to access newer features."
Really no way to know how without the functions and parameters spelled out is there? Even with a TLB file, it would still take longer to figure it out than it would to merely wait for an updated API doc.
"I keep seeing really weird things. Like when then plugin finishes, the progress meter hangs there without ever going away (until I press "Cancel") because the last few samples never get read in."
Is there an undocumented "DismissProgessMeter()" ?
"Still, it sure would have helped if they had made some sample code available that does this."
YO SYNT! ARE YOU LISTENING ?
"I don't think ReadDataEx works on negative offsets (I was hoping it would return 0's), or maybe even with offsets prior to the selection area, or if it does work, perhaps it needs a balancing WriteDataEx?"
Assmuing the buffer's index is always positive, wouldn't wrapping your pointers for the prior chunks be farly easy to code? I'm not sure why you'd need a 'balancing' write... not that I understand the API yet - it just seems odd... unless the write after read is somekind of weird flush.
"Or maybe my code has still more undiscovered bugs (duh)."
You don't write bug-free code? <G>
"a confusing world to program in, where "sample" is really 2 samples in a stereo waveform, but you put them into an array of floats where each index is just 1 actual value. You really have to watch your steps."
Probably legacy from the first versions. It could be better implemented. (But it's easy for us to yack as arm-chair coders!)
"I've been trying to use a naming convention for all the variable and such that keeps it clear what their "units" are, and this has helped clear up some things."
Excellent idea.
"to work in the complex plane"
Oh now that's a complex subject! (Ouch... sorry, couldn't resist.) There's much to consider here. First, I've had enough math do work on this, but not enough reply cold. Ditto the DSP stuff. For example, I tried to figure out some years ago the indexing tricks (in C or asm) that do (or emulate) complex transforms in the old MOD players. Would love to learn how this simple thing is done!
"to get the imaginary component I figure I need the instantaneous derivative (slope) of the waveform at each sample."
Does this work? In trying to change the pitches of MOD player files, I had thought of this, but couldn't get it without introducing tons of artifacts. You're trying to get the first derivative to go from the time domain to the frequency domain, right? (Aside to anyone else reading this quickly-to-become-arcane thread: a spectrum analyzer, in essence, transforms time to frequency.)
"Sorry, I've only had one DSP class (an intro)"
Not a problem - I'm about in the same boat... so here we have two near-blind programmers trying to figure out the interface to an Elephant. If one more joins us, we should get it <G>.
"perhaps it is a well-known procedure how to go from a real waveform to a complex waveform"
Ah, so I had thought ! At least the formulas are well known. And implementing them directly in CPU intensive code is also out there. But doing it in fast, streamlined code is, I suspect, among the tricks of the trade. Sure, the engineers and audio programmers know it, but for most of the rest of us, it's a BigBlackBox. (Otherwise, we'd not need CEP cause we'd have done it ourselves!)
"I'm trying to make this up as I go (the theory/idea side of things can be a lot more fun and more of a learning experience that way)."
Indeed - that's the main reason --- getting a filter/plug in that really does something is only a side-effect :)
"using something like a sum of squares of the delta of samples before and after to get a better approximation"
Can you write the formula here? I'm not sure if you mean:
SUM ( ( sample[1] - sample[-1] ) ^2 )
or
SUM ( (d(sample[-1] )^2) + (d(sample[1]))^2) )
where sample[0] is the current sample and
where 'd' is the first derivative.
"though ultimately I was hoping to do some interpolation using the FFT features available in the SDK. Using the slope and actual sample value as points on a 2-D plane, you can then convert to polar coordinates and do interesting things to the angle, or whatever, before converting back to an instantanous rectangular value to output. But my "slope" ends up with a glitch in it every so often.
"I've been surprised to see that ReadDataEx is always returning less than what I'm asking for. "
Is CEP "sample accurate" as is, say, Sonar? There's room for a lot of sample-length slop in all this. I'm not sure if you resolved that particular problem when you said "[ReadDataEx]
was showing me only a fraction of what I asked for. So, I tried removing the division by the number of bytes in a sample (potentially multi-channel sample). Guess what? Everything worked. "
Maybe the Preview problem is related to proper buffer flushing? Here's a stab: try padding the buffer end with some near-silent value... say just a tick above the zero crossing. Although this would appear as a D.C. offset, it wouldn't sound but would be identifiable by code. This could help in two ways. 1) It might force CEP to flush the last of what you do want, and, 2) you could compair lengths in and out, changing your pad length in experiment to figure out what the real length is.
"Yucky interface, but hey, I don't know my way around the Win32 world yet."
I've yet to meet an interface that wasn't Yucky!"
- T
|
|
|
|
|
Syntrillium M.D.
Location: USA
Posts: 5124
|
Posted - Mon Jun 10, 2002 11:08 am |
|
|
Hello Twang. Unfortunately, I can't really help you with SDK/programming-related questions...but if you have questions about SDKs and future (potential) updates, I'd just email prosupport@syntrillium.com directly.
---Syntrillium, M.D.
_________________

|
|
|
|
kblackwell
Location: USA
Posts: 37
|
Posted - Mon Jun 10, 2002 9:33 pm |
|
|
| Quote: | | Is there an undocumented "DismissProgessMeter()" ? | Notice that once I figured out that ReadDataEx was *not* returning the number of bytes read (ie, the documentation was wrong), then I fixed that part of my code and this problem went away. So did many of the others you asked about.
Problems that remain include not being able to get updates to parameters during Preview (I probably just need a working example), and of course no way to access dynamic parameters (automation) within the MultiTrack window's FX Racks. Plus, of course, not knowing how to quickly put together sliders and other more-useful controls in the dialog box (text edit boxes get old quickly).
| Quote: | | Assmuing the buffer's index is always positive, wouldn't wrapping your pointers for the prior chunks be farly easy to code? | I think I got it to work. Actually, I haven't specifically tested to see whether the plugin is able to get samples prior to the selection, but I believe it probably can because my code tries to do it (still, it fills in with 0's if that fails, so maybe my error handling is too good :-). | Quote: | | I'm not sure why you'd need a 'balancing' write... not that I understand the API yet - it just seems odd... unless the write after read is somekind of weird flush. | I don't think I do, anymore. I don't get the hanging ProgessMeter anymore. All these problems were due to the mis-documented ReadDataEx return value.
| Quote: | "to get the imaginary component I figure I need the instantaneous derivative (slope) of the waveform at each sample."
Does this work? In trying to change the pitches of MOD player files, I had thought of this, but couldn't get it without introducing tons of artifacts. You're trying to get the first derivative to go from the time domain to the frequency domain, right? (Aside to anyone else reading this quickly-to-become-arcane thread: a spectrum analyzer, in essence, transforms time to frequency.) | I am not doing any FFT or moving to the frequency domain. I'm just moving to polar coordinates, then back. I think.
I'm just estimating the derivative, using that as my "y" value, using the sample value as my "x" value, using atan2 to get the angle, and of course using the sqrt(x*x + y*y) as the magnitude. From there, I've *mostly* just tried to multiply the angle by 2. I get lots of even harmonics without the odds. I assume that the reason I don't get a true octave-up is that I simply don't have enough accuracy in my method of estimating the derivative, and that by doing some interpolation I could get it better. Of course, I really should be doing a low-pass filter first to avoid aliasing, but the thing is that I was actually getting multiple even harmonics, not just an octave up, and that is *exactly* what I was wanting (not an octave-up effect). Now, admittedly, by switching to that formula that uses exp(), I imagine this becomes simpler or something, and indeed I have seen a nice little distortion formula that uses exp()'s which does produce both even and odd harmonics. I just haven't taken the time to play with the math rigorously enough; I'm still in the mode of doing what's on the top of my head for now.
| Quote: | "using something like a sum of squares of the delta of samples before and after to get a better approximation"
Can you write the formula here? I'm not sure if you mean: (examples deleted) |
Neither of those. What I'm doing is | Code: |
( (this - previous)^2 + (next - this)^2) / 2
| and the truth is, I doubt this is ultimately a very good idea. I just haven't taken the time to analyze it yet. It just seems to work a little better than (next - previous) / 2. Of course, I should take the sqrt of the sum of squared deltas, but I've played around with leaving it squared like that. It's one way to distort the imaginary component, if you know what I mean. You basically change the polar path in a way that when you convert back to rectangular (and I've just been using newoutput = cos( angle ) * magnitude), you get distortion. And the possibilities for how to do that are limitless. I've even thought about applying the various sample-modifying distortion formulas I've seen to this estimated derivative instead of the sample value, just to see what difference it makes (maybe none?).
Realize, everyone reading this, that I have absolutely no perspective on any of what I'm doing here. I'm a beginner at this stuff, ok? It's just for fun, ok? But if anybody really understands this stuff and wants to set the record straight and put it into perspective, then PLEASE DO!.
| Quote: | | I've yet to meet an interface that wasn't Yucky!" | I can imagine lots of things I would like to do in the interface. I just am too interested in doing the DSP stuff right now, rather than spending a few months trying to learn how to wrestle with Windows. That's precisely why example code would be so helpful.
By the way, I'm toying also with some alternate mixing method ideas. You see, each distortion method I'm using has it's own "wetness" parameter, such that I basically do something like this: | Code: |
dry = 1.0 - fabs(wet)
....
newvalue = original_value * dry + new_value * wet
|
Oh, and by the way, the fabs lets me specify negative wetness that ends up inverting the effect with respect to the original, but then if you specify -50% wetness, all you get is what is different between the original and the new, which is actually a good way to hear what each distortion method is actually doing.
But anyway, in some of the methods, the added harmonics are at a constant relative level so that I really need to scale them up according to the original level. In other words, I want the distortion to come up with the level of the original waveform. The first thing a person might think of is | Code: |
newvalue = original_value * dry + new_value * wet * fabs(original_value)
| and this is actually somewhat useful in cases. But there are other ways to skin this cat. I'm thinking of a matrix like this:
| Code: |
amplitude magnitude
raw ( ) ( )
sqrt ( ) ( )
squared ( ) ( )
|
Where each of the 6 boxes is like a radio button (mutually exclusive) and you also have 3 more orthogonal options that let you chose which value does the scaling come from: the original waveform, the new waveform, or a combination (average).
Sounds like a cool idea, but it's probably a recipe for disaster. Anyway, the more I get into this, the more I find I want all this stuff to be completely modular with the ability to route data from any output to any input arbitrarily. It's too bad that CEP doesn't yet have a "modular synthesizer" into which new such modules can be placed. Maybe in the near future.... Of course, I realize that other such things exist, and maybe it would even be cool for CEP to have a interface into C-Sound, but that's another topic. Back to modularity: you could even split your compressor up into separate modules for the envelope-follower and triggered dyanmic gain control, and then you could find uses for those modules in other situations besides just a classic compressor. Oh, anyway, I'm rambling. Back to work....
Wait, let me tickle your imagination a bit. The one distortion effect I'm liking the most is one that ultimately adds mostly (if not only) odd harmonics, but the point is that is maps a triangle wave to a sin wave. Surely you've heard of this. But what's so cool is that you can go past the range of [0..PI/2] and get some seriously nasty stuff going on. By allowing this to be fully adjustable, you can get only a slight lift, as in [0..PI/4], or you can go hogwild with something like [0..5PI]. And by doing it *twice* (as in sin(sin(x))), this effect becomes even more crazy. Send your drum track through that, and it's just absolutely incredible. Each impulsive noise becomes something like a Star Wars blaster sound (well, not quite, but whatever), and cymbal hits become explosions. Low level stuff just gets boosted without distortion. Man, I'm loving this.
Next I want to try mapping the triangle wave to something that looks like a sine wave with increasing frequency, scaled such that the peaks are monotonically increasing up to 0dbFS (or such that each + peak reaches 0dbFS and the -peaks rise up to meet it linearly or otherwise). Or maybe the peaks are left at + and - 0dbFS; dunno if it matters. The frequency increase should not be linear, though, because I would want to be able to set a threshold for the input at, say -6dbFS (+50%) or so where the mapping would put it at PI/2, then have maybe -3dbFS at 5PI/2, but the last few db of headroom wouldn't reach infinite frequency, but just some limit like 17PI/2 (that would give you 4 full cycles with most of concentrated at the top). This would theoretically give the more extreme version of this effect only for the loudest signals. But ultimately, it might be best to control the sin frequency scaling with an envelope follower rather than with the amplitude of the input samples.
Hope these ideas aren't patentable, or potential trade secrets or something, because if so I just spilled the beans big time. Then again, I'm always full of ideas that I rarely get to implement to see if they're really as good as they seem. Fortunately, with software it's usually not too hard to build your invention to see how well it works.
Come on everybody, let's share our homemade transforms! Or is everybody doing their custom plugins in something like VST or Direct X?
Edited by - kblackwell on 06/10/2002 9:46:47 PM
_________________ -- Keith W Blackwell
|
|
|
|
kblackwell
Location: USA
Posts: 37
|
Posted - Mon Jun 10, 2002 9:52 pm |
|
|
I wrote: | Quote: | | Code: |
( (this - previous)^2 + (next - this)^2) / 2
|
| Now I hope I'm not misleading anyone by simplifying things here. Obviously, actual coding is more complicated. For example, in this example, I actually have to retain the original sign of each of the squared expressions, so it isn't really a squaring that I do. It's more like | Code: |
sqrt( (this-previous)*fabs(this-previous) + (next-this)*fabs(next-this) ) /2
| So when reading any pseudo-code snippets, just remember than when you go to code it you will inevitably have to apply some common sense.
_________________ -- Keith W Blackwell
|
|
|
|
Twang
Posts: 126
|
Posted - Wed Jun 12, 2002 7:59 am |
|
|
KB:
just a quick note about the preview refresh problem you mentioned.
I don't know if this will help, but there is a section concerning preview and updates in the
file
XFMSPRO.H
It's in the "distort" and "dtmf" examples. Search for the define statement
PREVIEW_QUERY
and read the next few define's comments. Seem's like you have to tell it to refresh...
- Twang
(PS I am thinking about the formulas you posted and will respond with a longer reply soon.)
|
|
Twang
Posts: 126
|
Posted - Wed Jun 12, 2002 8:44 am |
|
|
| Quote: | | when then plugin finishes, the progress meter hangs there without ever going away (until I press "Cancel") because the last few samples never get read in. |
void ProgressDestroy( ci )
COOLINFO *ci //Cool Edit info structure pointer
/*
Close the progress meter box.
*** Always remember to close the progress meter if you created one when processing is finished. ***
*/
/* -T */
|
|
kblackwell
Location: USA
Posts: 37
|
Posted - Wed Jun 12, 2002 9:05 am |
|
|
| Quote: | | I don't know if this will help, but there is a section concerning preview and updates in the file XFMSPRO.H | I'll look again, but I have already added a default: section to the relevant callback's switch that does the call to Preview_Update. Perhaps the note you mention will give me more clues.
I have gotten a response from syntrillium, but it's just to say that they are still working on the 2.0 SDK and my comments would be forwarded to someone appropriate for that. I might hear from them with more help sometime in the near future.
Meanwhile, my thought about increasing the SIN frequency with amplitude was probably a bad idea due to the logarithmic nature of sound levels (it already does increase distortion with higher levels, at least at just PI/2, and doing what I suggested is not helpful). Rather, it is better to spread the sin wave's cycles into the lower amplitudes so as to get distortion even at lower levels. It's not something you always want, but it is helpful. Anyway, you can just squeeze the amplitude downward (as in squaring it, or something more appropriate such as the decibel scale, as CEP's distort effect does) before feeding it to the sin() function. So I made that a check-box option, and don't normally use it.
I also spent quite some time coming up with a formula to ramp the gain up to retain some dynamics even when using the crazy extreme distortion (as in mapping to multiple sin cycles). I wanted the positive peaks to follow a nice boosting curve, and the negative peaks to gradually stretch downward, with a hump into the positive side that arcs down to -0dbFS for input values at 0dbFS. This turned out to be a lot more complicated than I thought it should be, but I got it working. I'm sure someone could come up with a more efficient way to do it: | Code: |
if(abs(ALPHA)>0.5) scale=1.0;
else scale = abs(sin(APLHA * PI_OVER_2);
// ...
distorted = sin( ALPHA * PI_OVER_2 * input ) / scale;
// or instead of input, above, use (input<0? -sqrt(-input):sqrt(input))
ramped = (distored * input^2 + input ) * 0.75 +
input * (sin ((input^2 - 4/3) * 2.5 PI) - abs(input) ) / 4;
| But I'm not quoting actual code, just typing from some handwritten notes. So there could be some typos or something. The effect of using the ramp isn't necessarily what you want for smaller values of ALPHA. I think I need to use the actual "magnitude" (calculated using both derivative and the input sample, as discussed earlier) instead of the raw amplitude. I intend to make those changes next.
Anyway, I'll be away for a few days and might not reply to further postings for a week and a half or so. But post away, and I'll catch up.
_________________ -- Keith W Blackwell
|
|
|
|
Ben
Posts: 63
|
Posted - Tue Jul 02, 2002 11:12 am |
|
|
Hi guys,
Im not a programmer, but I was wondering about this.
I have a Digi96 (digital) card with the Digicheck software.
The checking include checking the amount of bits that is coming in.
But now, when I preview a 32 bit wav [with an effect or plugin] in Cool Edit
I see just 16 bits showing by Digicheck.
But when I preview in Wavelabdemo , I see 24 bits ; that's the max. you can see.
Is there something wrong within Cool Edit or so?
|
|
Twang
Posts: 126
|
Posted - Tue Jul 02, 2002 11:29 am |
|
|
Ben,
this might have something to do with the way CE aligns samples that are over 16bit, but I'm not sure... maybe Synt has an answer...
cheers,
Twang
|
|
kblackwell
Location: USA
Posts: 37
|
Posted - Wed Jul 03, 2002 9:11 am |
|
|
Just to update anyone interested, since I mentioned the idea of using the instantaneous slope as the imaginary component... it should be painfully obvious to anyone well versed in DSP that this was a garden path. There is no way to properly scale the slope since lower frequencies will have almost no slope at all but higher frequencies will have a larger slope (and it probably comes close to what is expected at f_s/4, just guessing). This is not the way to convert a real signal into a complex one. I suppose something like a Hilbert transform is needed, but I haven't gotten that far yet.
And by the way, any non-linear messing around with the waveform (as with the Distort plugin) will create harmonics that can exceed Nyquist, resulting in aliasing that may or may not be an audible problem depending on the source material. Getting around this requires oversampling first and good low-pass filtering (polyphase is useful) afterward, then decimating. Again, I haven't gotten that far. I know lots of other people have already done this sort of thing, but it sure has been a learning experience for me to try to reinvent this wheel. And this is just the distortion side of things; getting into speaker and cabinet (or miking thereof) simulation is a whole 'nother ballgame.
For anyone interested, I recommend searching the "music-dsp" archives (use Google, just include "music-dsp" as one of the search words). Very good stuff there.
_________________ -- Keith W Blackwell
|
|
|
|
Ben
Posts: 63
|
Posted - Thu Jul 04, 2002 5:39 am |
|
|
Thanks for reply Twang.
Forgot to say that after the processing in CEP,
Digicheck shows 24 bits though [that's the max. it can display],
when playing the processed wav file.
|
|
Twang
Posts: 126
|
Posted - Mon Jul 08, 2002 9:10 am |
|
|
Hey KB:
what compiler settings are you using? Til now, I was just reading the docs etc. Tried to compile the sample stuff on visual studio 6 - and got a bunch of errors... look's like mostly unresolved externals... which probably means my libraries or header references are in the wrong order.
And it likely doesn't matter that you're using an older version as you mentioned - I assume the compiler/linker directives would be about the same.
any ideas?
thanks
- T
|
|
kblackwell
Location: USA
Posts: 37
|
Posted - Mon Jul 08, 2002 1:20 pm |
|
|
| Quote: | | what compiler settings are you using |
I dunno. I'm totally new to using the Developer Studio stuff myself. The CEP SDK stuff compiled the first time I brought up one of the demos into it. I don't remember having to change anything. Sorry. Since I still don't know my Debug from my Release yet (don't really know my way around), I suggest you ask Syntrillium directly for help. It might take them a week or two, but they'll get around to it. Or maybe I could mail a file to you if you can tell me what file to send. Honestly, I'm clueless about that stuff. Give me Unix anyday. I was just really surprised that this stuff worked without any tweaking.
Meanwhile, I've gotten past most of my original problems. Preview wasn't updating because I need to add a case for every widget on the dialog box into a switch statement in the DialogMsgProc() so that any change to any one of them would call PreviewUpdate(). Duh. I shudda figured that. I haven't added oversampling (to eliminate aliasing of the harmonics added), and my simple state-variable LPF is producing some noise I think, and the Hilbert transform I put in (2/nPI style, n being odd offsets, to get the imaginary signal) with a Hanning (cosine) window is producing some strange noise as well. But I've also discovered that my crazy little idea of warping the signal toward the positive or negative side relative to magnitude works especially nicely when I apply it to the imaginary signal instead of the real (and then convert back from polar coordinates to rectangular). It gives me more even harmonics than odd, and seems to work pretty well. Hooda Thunkit? The octave-up function still produces lots of other even harmonics, but it is where I most here those glitchy errors that I'm assuming is from the Hilbert transform. Anyway, I'm learning a lot with this little experiment.
--
Keith W Blackwell
_________________ -- Keith W Blackwell
|
|
|
|
ozpeter
Location: Australia
Posts: 3200
|
|
Twang
Posts: 126
|
Posted - Tue Jul 09, 2002 7:55 am |
|
|
OK OK OZ!! You got my attention ... I'll take a look ...
Gads, someone called me a "guru" ... how scary (and geeky)!
- T
|
|
ozpeter
Location: Australia
Posts: 3200
|
Posted - Tue Jul 09, 2002 8:01 am |
|
|
|
Someone called me something stranger than that on this forum the other day, but I see Synt has edited it out!
|
|
Twang
Posts: 126
|
Posted - Tue Jul 09, 2002 8:44 am |
|
|
>> what compiler settings are you using ? - T
> I dunno. I'm totally new to using the Developer Studio stuff myself. - KB
Keith:
yes, I'm putting in a shout to the support folks... in the mean time, which version of Dev Studio / VC++ are you using? (Help->About) And are you serious about the difference between release and debug??
Aside from assuming the "Hilbert transform" comes from the reknown mathematician, Hilbert, I'm uncertain if I've used this alogorythm or not --- "2/nPI" looks like a factor from standard Fourier transforms. What did Hilbert do specifically? (don't fret the details... maybe I'll find it on the web... any hints where to look?)
> Someone called me something stranger than that on this forum the other day,
> but I see Synt has edited it out! - OZ
LOL !! Well Oz, Synt's here to support us in more ways than one :]
Edited by - twang on 07/09/2002 08:45:25 AM
|
|
Twang
Posts: 126
|
Posted - Thu Jul 11, 2002 7:05 am |
|
|
[keywords] Compile, Visual Studio 4, VC4, VC6, Plugin, CE filter, SDK
GOT IT! As I had surmised, it was something trivial related to the VS/VC++ versions involved. The short answer: let the version of VC you are using convert the example's project file [ExampleName].MDP file into a VC 'project workspace file' [ExampleName].DSW. This is obvious to old-hat VC++ coders --- except that the file type MDP is ancient, so it's easy to forget!
NOTE: at some future date, the following will be moot as Syntrillium will release an updated SDK for CEP2 (at least that's what we users have been told The existing SDK's files are rather old, dating from 97. And therein lies the problem - if you are using VC 5, or more likely, VC 6, you'll get hundreds of errors during compile --- errors that look goofy because they are mainly syntax related, in otherwords, they shouldn't happen.
Caveat: although I was able to compile ALL of the samples, as of this writing, I haven't actually tested them in CE - I assume, perhaps naively, that they will work - my concern was just to get them to compile at all.
Procedure:
No matter which version of VisualStudio/VC++ you're using, initially open the [Example].MDP file (not the MAK file).
VC++ versions 5 and 6 will ask to backup and convert the project to the more recent version, creating the standard DSW file instead.
Compile and grin.
(I'd suggest going this route first before considering using the templates for cutting and pasting the sample code.)
Good Luck!
-Twang
|
|
|
|
|
kblackwell
Location: USA
Posts: 37
|
Posted - Sat Jul 13, 2002 9:29 pm |
|
|
Twang, sorry you're having trouble, wish I could help. I think I've got Visual C++ version 4, or 4.something. It was being thrown out at my old workplace because it was old, so I snagged it. As for Hilbert, I don't know the man. All I know is the few things I've read. You can do it in the frequency domain (take the FFT, zero out the stuff beyond the range of 0 to fs/2, and then inverse FFT, and use the imaginary half of the result) or in the time domain (that's replacing each sample at position n with the sum of the series 2/(n+i)PI where i is odd, though in practice you have to choose your window size and use a windowing function). Somebody correct me if I'm wrong. No time to talk now, really, just trying to keep the conversation alive while I'm too busy to look things up.... Maybe later....
_________________ -- Keith W Blackwell
|
|
|
|
Twang
Posts: 126
|
|
Twang
Posts: 126
|
|
| |
Topic
|