Old BuzzDev Answers

From Jeskola Buzz Wiki
Jump to: navigation, search


Answers by Oskari:

Fri, 12 Jun 1998 20:12

From: Oskari Tammelin Subject: Re: wavetable

At 11:31 AM 6/11/98 -0500, you wrote:

>is it possible for a plug-in to access the samples in the wavetable?

Yep, Jeskola Tracker wouldn't work otherwise (it's just like any other machine). You can also write to the wavetable if you want to write a nonrealtime samplegenerator or something like that.

virtual CWaveInfo const *GetWave(int const i);
virtual CWaveLevel const *GetWaveLevel(int const i, int const level);
virtual int GetFreeWave();
virtual bool AllocateWave(int const i, int const size, char const *name);
virtual CWaveLevel const *GetNearestWaveLevel(int const i, int const note);

In tracker you just need to do this:

CWaveInfo const *pWave = pCB->GetWave(pstate->iWave);
CWaveLevel const *pLevel = pCB->GetNearestWaveLevel(pstate->iWave,

See the attached file for example of writing to wavetable. It's the MOD importer code of the Tracker.

-- Oskari Tammelin .oOo. http://www.twilight3d.com

Tue, 16 Jun 1998 03:18

From: Oskari Tammelin Subject: Re: importing .IT file samples

At 04:32 PM 6/14/98 -0500, you wrote:

>Currently it is messy - you add the machine, and the mi::Init() method pops open a file dialog to select the .IT file to load samples from. In the meantime a mutex lock error message box pops up.

You shouldn't show any dialogs in Init().

>What would be the correct way to implement something like this which isn't really a generator or effect? I was thinking the context menu of the machine should have an "Import..." command, just like the Tracker machine does. How do I do that, if possible?

Yep, just implement the Command() method:

void mi::Command(int const i)
        case 0: ImportModule(); break;
        case 1: AnotherCommand(); break;

And change last line of MacInfo to "Import Module...\nAnother command"

Note that you must lock the machines if you are changing something that the player thread is using at the same time. The easiest and safest way to do is to use the MACHINE_LOCK macro like this:

    MACHINE_LOCK   // this constructs a C++ object

    // do something..

} // <- unlock happens here

-- Oskari Tammelin .oOo. http://www.twilight3d.com

Wed, 17 Jun 1998 07:03

From: Oskari Tammelin Subject: Re: simple buzz tracker question

At 04:55 PM 6/16/98 +0200, you wrote:

>im trying to code a simple buzz tracker. for now it plays samples nicely at their default rate. How do i calculate the playback rate according to the entered notes and resample the samples to this rate in the generator code ?? Are there some build-in functions to do this ?

Rate = 2.0 ^ (N / 12.0)

Where N is the note relative to the root note. For example if root note is C-4 then N=1 would be C#4 and N=-12 would be C-3.

dsplib provides a resampler function, so you should use it (see resample.h for help). The resampler has separate inner loops for all special cases so it's very efficient.

-- Oskari Tammelin .oOo. http://www.twilight3d.com

Fri, 26 Mar 1999 03:36

From: Oskari Tammelin Subject: Re: New machine released: JoyPlug 1

At 06:35 PM 3/25/99 -0600, you wrote:

>JoyPlug 1 has been released! >JoyPlug 1 is a joystick-controlled lowpass resonant filter with distortion. Instead of preprogramming in your filter data, just control it with the joystick, live. The source code is included as a slightly more complicated example of how to write something in Buzz. The plugin works with Buzz 1.x and a Win95 compatable joystick (3 axis joystick preffered)

Sounds like a cool machine. I wish I had Win95 and a joystick. :) The documentation was very nice too but there were some wrong information. Here are some corrections so that people don't get confused.

If there are functions that you don't need (like SetnumTracks and Tick in your machine) you don't need to implement them either.

The range of the signal is -32768..32767 inclusive if you want full dynamic range without lowering the master volume. It's not limited to that however. Machines can use much larger values if they need to but the user must manually lower the amps to avoid clipping.

Those were both just minor things but this one is quite important: The 'mode' parameter in Work() tells you what you can do to the samples for effect machines, generators can ignore it.

WM_READWRITE is the normal mode. WM_READ means you should only read but not write to the buffer. This happens when machine is in <thru> mode (set in seq editor). WM_WRITE is the opposite. it happens when machine has no input (in other words when all input samples are 0). Machines that generate output even if there's no input should support this mode. That includes reverbs, delays and even filters. WM_NOIO means there's no input and you shouldn't write to the buffer.

In all cases, you should run your machine normally, but not read or write to the buffer depending on the mode. If your machine's output doesn't depend on past inputs you should "turn it off" to save cpu time when mode is WM_READ or WM_NOIO. Reverbs and delays should turn themselves off after they haven't had any input for a while (reverb/delay time).

Otherwise the code was fine. Nice work. :)

-- Oskari Tammelin .oOo. http://www.twilight3d.com

Fri, 26 Mar 1999 16:55

From: Oskari Tammelin Subject: Re: New machine released: JoyPlug 1

At 09:31 AM 3/26/99 +0100, you wrote:

>Why? >This is something I've never quite understood. Isn't it better to have the same load on the computer all the time, instead of load changing? I guess not =)

Why the hell would it better? Low CPU usage is always better. We are not talking about a game like quake where constant FPS rate is usually more important. For example if part A of your song uses a machine connected to reverb1 and part B uses machine connected to reverb2 you think it would be better to run both reverbs all the time? :)

There's another reason too. When a feedback delay line runs for too long without input it starts to generate floating point exceptions (too small numbers). This makes it run around five times slower.

[Yes, the interrupt is masked but it's still very slow. anyone know the exact number of cycles wasted here?]

The machines are turned off when their output is so low that it can't be heard so no-one can notice when it's turned off.

-- Oskari Tammelin .oOo. http://www.twilight3d.com

Fri, 09 Apr 1999 07:52

From: Oskari Tammelin Subject: Re: resampling with dsplib

>At 03:37 AM 6/19/98 -0500, you wrote:

>I'm having some trouble figuring out how to use the resampler in dsplib.

>If you want to resample some data to a given Rate, what do you set StepInt and StepFrac to? (or what do you pass to SetStep()?) Also, what is the difference between the two step modes?

I was going thru old buzz-dev mails and found this.. Maybe I should have replied it earlier. :) Anyway:

Step is the value to add to the sample read pointer for each sample. So Step=2 would play the sample at double speed and Step=2^(1/12) would play C#3 if the sample is sampled at C3.

RSS_ONE means the resampler assumes Step=1 (happens often with percussive samples) and doesn't do any resampling which is of course much faster.

RSS_CONSTANT means Step can be anything but stays constant. The resampler doesn't support pitch sliding so there's no RSS_INTERPOLATE mode. SetStep is just a helper function so you don't have to set StepInt and StepFrac manually. You can use it or not.

-- Oskari Tammelin .oOo. http://www.twilight3d.com