Statistics

38478 registered users
17886635 pageviews

You're not Logged in.
 
Home
Login
Sign up (free)
News archive
Search profiles
Info
What is Buzz?
Buzz on Video
Buzz FAQ
Download Buzz
New Buzz Beta (2008)
Developer section
Messageboard
Machines / Plugins
Buzz Generators
Buzz Effects
VST Instruments
VST Effects
Machines Top-25
Presets
Latest presets
All presets
Misc downloads
Drumkits
Index.txt
Utilities
Tips archive
Ad
scottyp recommends:
 
Never overuse an effect, unless it sounds good. - scottyp
 
Last updated profiles:
 
lnktech - United States
admins - India
frankedukes - Guatemala
yoshisato - Japan
lnkklog - United States
annafranklin - India
rami - United States
hotcat91 - Brazil
denniferro - Germany
ionisaattor - Finland

  FREQUENT MISTAKES OF MACHINE PROGRAMMING

These are some of the biggest mistakes that I see being made over and over again. If you are new to machine making (or even if you have already released machines), please read over this.

1. Wavetable access

If your machine access the wavetable, you MUST get the pointer to the wavelevel structure IN THE WORK FUNCTION, not in the Tick function. If the user loads a new wave into the wavetable over the one you are playing, your pointer will no longer be valid. This means your machine will crash buzz and the user will probably lose the song they are working on. This is not good. New waves are not loaded until after the Work functions are finished, so it is safe to get the pointer here.

2. WM Errors

When your machine is not producing output, your work function MUST RETURN FALSE. If it doesn't, it wastes lots of CPU, and can also lead to floating point errors which will bring the system to a halt. Think about it - if you have a generator at the begining of a chain which is returning true, even though it is not giving any output, all the effects after it in the chain are on, and thus taking up CPU. If you have a Raverb at the end, then this is a big waste. Here is a quick rundown of what the WM_ functions do:

WM_NOIO - No input / output WM_READ - This means the machine (probably an effect) has an input connected to it, but no outputs (or maybe the outputs are muted). WM_WRITE - This means the machine has no input waiting for it, but output will be sent (if your effect is a delay, you may want to finish sending any echoes during this phase). WM_READWRITE - the normal machine state, input and output

If you are not sure if your machine is returning the proper value, you can check the leds on the machines to see if they stay on after the machine should be off, and also thru the debug option on the CPU usage menu.

3. Pops and Clicks

A pop occurs whenever you have a large, quick change in amplitude. This change is usually too fast for the speaker to handle, and causes an audible click. In order to avoid pops, you must put a slight ramp in the volume whenever you play a sample or a wave (ie, fade it in). Even if you don't have an envelope, it is a good idea, to do a quick fade over 50 samples or whatever seems like a good idea. These ramps should occur at both the begining and end of a sound, since the amplitude will be changing from zero to some value, or some value to zero, once the sound starts or stops. Also, if one note interrupts another, you may get a pop if your amplitude goes right back to zero for the new wave. An easy thing to do would be to keep the volume for the new wave, and not fade in. This still may allow some pops though. The idea solution would be to fade out the old wave while the new wave is fading in. This provides the smoothest transitions.

4. Optimize

I can't emphasize this enough. The early buzz machines were VERY fast. These days people don't seem to care how much CPU it takes up, as long as it sounds ok. This is not a very good attitude, since the slower the machines are, the less you will be able to use in a song. To make sure your machine is as fast as possible, be sure to optimize your loops. Any values that stay constant for the duration of the loop can be precalculated before the loop. Any other values that can be precalculated and possibly put in a table will save time also (please, lets avoid massive tables though). Some operations that are really slow are Pow(), Cos(), Sin(), %, and converting from Float to Int. A trick to avoid doing % with binary numbers (2, 4, 8, 16), is to do this:

x % 16 becomes x & 15 or in other words x % a = x & (a - 1)

This will yield the same result and is much faster. Also, multiply is faster than divide, so * 0.5, is faster than / 2.0 if you are using floating point numbers. For integers, you can multiply by binary numbers very fast using shift operations. A shift left is the same as multiplying by 2 and a shift right is the same as dividing by two. Most people are already aware of this trick. If you must use Pow, Cos or any other math function in your loop, try to put this info in a table. If it's a waveform you need, you can access any of the default oscillators using the GetOscillatorTable function. Finally, there are often special cases in audio (ie, a delay with no feedback can be done with one less multiply). Try to figure out what these cases are, and optimize for them if they occur frequently. Finally, if you have a small function which is used often, declare it as inline. Remember that it takes time to call a function, so it may just be faster to put your code in the same routine if it is not a lot of code. Always pay attention to how often each part of your code is done, and optimize the parts that get run most often, as much as you can. Floating point is fairly fast on today's computers, but fixed point math is still faster in most cases. Look elsewhere for more info on fixed point math if you are unsure what it is.

5. Aliasing

Almost every new synth gen that comes out has this problem. Aliasing occurs when you try to play frequencies that are higher than Nyquist frequency (which is half the sample rate). So, for 44100hz audio, the highest frequency you can play without aliasing is 22050 hz. When you play a waveform at a specific note, you get frequencies at that note, and harmonic frequencies which are higher than that note. So, say you have a wave sampled at C-4 which contains all the harmonics up to the highest frequency which can be represented. If you try to play that wave at C-5, some of those frequencies will be above the highest frequency (the aforementioned Nyquist value), and will alias, causing lower, disharmonic frequencies to emerge. Aliasing usually sounds pretty bad. This is especially annoying, since with any of the default oscillator waveforms, aliasing tends to become noticable around the 5th and above octaves. Oskari has provided a way around this problem though most people either don't understand or are too lazy to do it. The answer is to keep band-limited versions of the waveforms which don't have as many harmonics and won't alias when used in the upper octaves. When you use GetOscillatorTable function, it returns the address of the lowest bandlimited wave, which is size 2048. Next to it in the table is the next wave, sized 1024, then another at 512, ect. The highest level you can use is level 10, which is size 4. To decide what level to use, pick the wave size so that your step (rate) per sample is one. This is the algorithm I use to do it - There is probably a faster way. As you can see, this could be optimized by precalculating Frequency/SamplesPerSec. You wouldn't want to use this in your main loop.

  LevelShift1 = 0;

    while(Frequency*((float)(2048>>LevelShift1)/(float)pmi->pMasterInfo->SamplesPerSec) > 1.0)
      LevelShift1++;

      if(LevelShift1 > 10)
        LevelShift1 = 10;

You will also need to do some interpolation of your points (since the higher waveforms contain very few points). Linear is the minimum.. Cubic spline is good, if you can get it fast enough.

6. Notes

The way notes work in buzz is a little wierd, compared to midi. Instead of every 12 notes being an octave, it's 16. So, to find out what octave a note is in, you must divide by 16. The notes themselves are still 0-11 in each octave, so to find what note it is, modulus by 16. The last four numbers are ignored. The numbers were picked this way so they could easily be done with logical operations. If you don't do this properly, your machine will be out of key and unusable.

7. Inertia

It's always annoying when you try to tweak a parameter only to find that there is no smooth interpolation between values. Without inertia, tweaking sounds mechanical and quantized. Not exactly what you want for your smooth filter sweeps. So, please add some glide time for your parameters whenever a value is changed. Slowly go from one value to the next over each sample that is produced. Inertia is only needed where it makes sense that a person would want to change a parameter in real time. Otherwise, the extra overhead needed to do inertia on all the parameters would be very slow.

8. Midi

This isn't a mistake so much as something most people overlook. Adding midi to generators is VERY easy. Here is some code originally by oskari with some additions by me.

void mi::MidiNote(int const channel, int const value, int const velocity)
{
    int v2;
    if(aval.MIDIChannel != 0) 
        if(channel != aval.MIDIChannel-1)
            return;

        v2 = value + aval.MIDITranspose-24;

          if (v2 / 12 > 9)
            return;
          byte n = ((v2 / 12) << 4) | ((v2 % 12) + 1);
          if (velocity > 0)
          {
                    for (int c = 0; c < numTracks; c++)
                    {
                             if (Tracks[c].Note == NOTE_NO) 
                            {
                                        Tracks[c].Note = n;
                            if(aval.MIDIVelocity == 1) // 0 = ignore velocity
                                        Tracks[c].Volume = velocity<<20;
                                            Tracks[c].NoteOn();
                                            return;
                            }
                     }
          }
          else
          {
                for (int c = 0; c < numTracks; c++)
                {
                    if (Tracks[c].Note == n)
                    {
                        Tracks[c].NoteOff();
                        return;
                    }
                }
            }
}

This will allow you to take midi input from keyboards and such and play as many notes at once as you have tracks for in the machine. It also checks an attribute called MIDIChannel if it's set to 1-16. This will allow different generators to be controlled from different midi sources if you desire. If your sound card has low enough latency, you set up your driver right, and you actually have a keyboard, this is a pretty cool feature. Some things I'd like to see with midi control - samplers, drum machines, ect.


That's all for this week, stay tuned for future editions.

WhiteNoise (LowPass) - admin@whitenoiseaudio.com - www.whitenoiseaudio.com


Search



Reviews
Latest reviews
All Articles
All Tutorials
All Sound Examples
Contribute
Add a link
Add a preset
Add a review
Add a quick tip
Submit machine
Links
Buzz links
Developer links
Music links
Contact
Contact (mail)
About buzzmachines.com
Hosting by: Mijndomein.nl
Partnersite(s)
Shotsbyme.com
Poll
 
Do you access the links section? / Are you sick of the spam links?
 
Yes, and this page would be more useful withouth the spam please do something about it.

Yes, I not only use the links section but have posted my Buzz related links there.

Yes, But have not used them recently because of the spam.

No, I am a weekend warrior and never really visit Buzzmachines.

No, It took me a week just to figure out how to open my internet browser.

 

Show results
Ad
   
Copyright © 1999-2010 By Buzzmachines.com   -   Buzz Copyright © 1997 - 2010 By Oskari Tammelin