Re: [linux-audio-dev] Re: EVO-Linux Physical Modeling HD Sampler

New Message Reply About this list Date view Thread view Subject view Author view Other groups

Subject: Re: [linux-audio-dev] Re: EVO-Linux Physical Modeling HD Sampler
From: David Olofson (david_AT_gardena.net)
Date: Wed Jul 19 2000 - 02:36:27 EEST


On Tue, 18 Jul 2000, Benno Senoner wrote:
> On Tue, 18 Jul 2000, David Olofson wrote:
> > > - loop point begin , loop point end
> > > - oneshot / looped
> >
> > Although you can do most things you want with this, multiloops (ie a
> > list of regions, rather than a single loop) may be worth
> > investigating...
>
> yeah, I thought about this , but it may be quite tricky to implement,
> because the audio thread has to instruct the disk thread where to
> preload.

I did it in 68k asm right in the mixer code of my old Amiga engine -
it wasn't much more complicated than handling a single loop. (That,
OTOH, is quite messy enough to get right in asm. The fraction part
mustn't be reset when switching, and then there's interpolation...)

I used a 16:16 signed fixpoint sample offset, which was set up as a
*negative* offset from the fragment pointer, which pointed at the end
of the current fragment. Whenever the offset got >0, a special case
(the only one in the inner loop) invoked a code section that checked
what was going on and dealt with it; namely 1) stop the voice or 2)
calculate the next fragment to play. 2) could mean either a) set up
the next fragment (up to 32k) for playback, or b) check the playlist
for the starting point of the next section.

This allowed quite transparently working around the 64k or 128k
sample/loop length limitation that most player routines had (most
because of a hardware restriction at 128k, but >4 ch players imposed
a similar limitation due to the need for a fixpoint playback offset),
and provided multilooping practically for free.

> In theory the disk thread could work it's own and just follow the "playlist"
> His goal is to keep the ringbuffer full and he can do this by following
> the loop points described in the voice structure.

Yep, works for static playlists/multiloops, and simplifies things, as
it basically allows you to move one feature out of the mixing loop.

However, it won't work for multiloops that are controlled by RT
events, such as the loop/release switch that even SoundFonts support.
(You can set a waveform up to play from the start to the loop, play
the loop section until a NoteOff is received, and then continue with
the section after the end of the loop at the next turn, instead of
skipping to the start of the loop.)

> The problem arises when let's say the starting point of the loop is in the
> initial preloaded RAM area (which is mlocked), and the end point
> resides after this area.
> But I think the simplest solution to this is simply letting check the diskthread
> the requested playback offset, and if it resides in RAM , then instead of
> filling the ringbuffer using read()s , just memcpy() from the RAM are into the
> ringbuffer, and the audio thread will not notice that we cheated.
> Simple solution and alway faster than reading from disk :-)

Basic caching logic. :-)

> > > - base volume
> > > - base pitch
> > > - base panorama (balance)
> > > - base filter cutoff
> > > - base filter resonance
> >
> > Filter types?
>
> the ones where source code is available :-)
> any good pointers ?
> I have a 24dB resonant lowpass I found on comp.dsp
> long time ago (sounds quite ok),
> and a guy on music-dsp just posted another one a few
> days ago
> (12dB LP with resonance)

Well, some basic IIR filters would be nice. Easy to implement, fast,
and no nasty FIR style side effects. They basically emulate simple RC
filters, and thereby seem to avoid sounding digital without any
special tricks or tweaking. (See softsynth for a simple example. I use
two in series for 12 dB, IIRC - just a quick hack.)

As for more filters, there's not really a limit to how many different
kinds of filters you may find a need for, but the essentials are low
pass, high pass and band pass. Notch (band reject) can be handy as
well. 12 dB covers most things, but 18 and 24 should be supported as
well, for greater control when *constructing sounds* rather than
tweaking sampled audio.

Resonance is of course essential (not only for acid, if anyone
thought that!), and there should be lots of it, preferably with
various distortion methods for the TB-303 fans.

Another thing that I find pretty useful on the JV-1080 is to use two
filters in series, for more control. It's nice to be able to cut or
boost some with a second filter after building the "real" filter
effect with the first one. (I sometimes miss the support for more
than two filters in series!)

Besides, using for example one LP and one HP filter is more flexible
than using a BP filter with fixed band width and the same attenuation
on both sides of the pass band. That's more a matter of UI and filter
features than final result, though. A BP filter may actually *be* an
optimized pair of filters, and could then just have some extra
parameters to provide the same functionality using sligtly less CPU
power.

> > With quadratic splines:
> >
> > validity in number of samples
> > starting value
> > delta per sample
> > delta change per sample
>
> yea I forgot that we can aproximate any polinomial
> with the finite differences.
> I think we should support two types:
> - linear slopes
> - cubic splines

Actually, since linear functions is a very simple special case of
quadratic and cubic functions, and we're only fighting for one or two
additions, one has to consider the overhead (run time and code
complexity) of providing more than the highest degree needed.

> with cubic splines you can aproximate arbitrary curves
> VERY accurately.
> And considering that is needs only two more additions
> compared to the linear case, then it is really CHEAP.
> :-)

Yep. This is what approximates the perspective 1/z component in most
texturizing software 3D rasterizers and hardware 3D accelerators,
it's used for smoothing movements in network games ("dead
reckoning"), movement precalculation and estimation in control
engineering and all kinds of other things, so it's not exatly hard to
find the formulae you need to set the coefficients up to approximate
various types of functions.

> > There's another problem here, though; envelope timing may need to be
> > scaled along with pitch and other things.
>
> this IS a problem: the validity is given in num of samples so it has to be an
> integer.
> But in theory you could use a float value, and decrement in non integer steps.

Disadvantage: FP<->integer conversions, as pointers and offsets are
integers... At least internally, I think integers/fixed point should
be used, as these conversions cannot be avoided otherwise.

> As soon numsamples gets <= 0 load the new dataset,
> check the fractional part and apply linear/cubic interpolation between the two
> points.(this happens only between two envelope segments)
> Should produce quite smooth curves.

Should work, and it's also another reason to support higher degree
functions for the segments.

> > > Another thing we could do is to map a MIDI controller
> > > to different envelope structures, so that
> > > differen controller values (the modwheel or breath-controller)
> > > could for example change the attack behaviour of the sample
> > > at the next note trigger.
> > > (would this feature be useful ?)
> >
> > This could be a way to solve the issue mentioned above. No big
> > problem with data size, and editors can generate the timestretched
> > envelopes when saving the files. How to load them back into something
> > editable, though...?
>
> Yes this mapping is quite easy to implement, but would my proposed
> real-time envelope stretching make sense ?
> eg. stretching and expanding pitch envelopes using LFOs ,
> are we in the FM domain now .... ?
> :-)))

Depends on the frequency anh amplitude of the modulation. If LFOs are
to truly FM envelopes, the envelope generation will be a lot heavier,
as you have to consider the modulation a part of the signal WRT
interpolation. For "normal" modulation (like the modulation
LFO->wave), just updating the scaling factor/frequency at regular
intervals should be enough. (FM is not nearly as sensitive as AM to
that kind of cheating.)

For anything like a normal envelope, you'll even get away with
scaling the section times to the nearest integer value, and then just
run the standard algo. Only envelopes with very short sections will
need interpolation.

> > > Obviously the voices will be routable through a FX section
> > > (the FXes should be loadable plugins) , with dry/wet parameter.
> >
> > Better do this real. There are at least 4 standard MIDI CCs for
> > effect send levels, two of which are supported by most synths and
> > samplers with built-in FX. Two is pretty restrictive for a full
> > arangement, considering that a really good sampler should be able to
> > handle *all* sounds in many kinds of arrangements, so at the very
> > least, the 4 standard sends should be implemented. Preferably
> > something more powerful and more generic.
>
> How about using LADSPA to load plugins, and let the sampler map
> MIDI CCs to LADSPA controls ?

Yep. Actually, I have dreamt about a machine that could use a
separate MID port, separate channels or some CCs to control the FX of
the playing channels, rather than resorting to machine-specific and
totally messy SysEx for anything beyond the FX send levels. Most
machines hardly support any CCs beyond Volume, Pan, Reverb, Chorus
etc, RPNs are rarely supported at all and NRPN (when supported) is
about as standard as SysEx. What were the rest of the "standardized"
CCs meant for!?

> My voice structure is already prepared for flexible routing because the
> audiovoice class has its own output pointers.
> So you can basicallly send your data where you want.

Cool. :-)

The only problem; can we come up with a sensible and *usable* MIDI
implementation that allows this to be set up via MIDI without
dedicated editors?

How about something like:

The "normal" MIDI ports support the usual 4 FX send levels, and add 4
CCs that allow chosing which FX bus to connect each of the 4 sends
to. There should also be an option to make the volume CC a send
level to the dry output, rather than a master level control before
the sends, so that you can route through FX only if desired.

There could be up to 128 FX units (perhaps 0 should be "none"?), and
their parameters could be set via CCs in two different ways,
depending on the MIDI setup:

* Using the normal MIDI ports:

  Using a CC on any MIDI channel on any port to select an FX unit
  for that port/channel and then set it's parameters using other
  CCs on the same port/channel. You can control one FX unit with
  each MIDI channel on each port, and as long as the normally
  unused CCs are many enough, any parameter of one of the selected
  FX units can be set directly with a single CC.

* Using separate MIDI ports:

  Using a similar scheme to the above, but treating it more like
  the FX units where separated from the sampler, by using dedicated
  MIDI ports for the FX control. That is, the "Select FX Unit" and
  the array of "Set FX Parameten #n" CCs don't get in the way of the
  patches, but stay entirely on their own MIDI ports, as if the FX
  units had been running in a big, external, MIDI controlled
  multi-FX box.

> > Finally, don't regard MIDI as the True Model to design the sampler
> > around! MIDI has too low controller resolution, no timestamps, only
> > 16 channels/port, only pitch + velocity data inside NoteOn events etc
> > etc... Not that I'm expecting MIDI to be replaced any time soon, but
> > at least, accepting the *figures* defined by MIDI as the measures for
> > how many Fx sends there should be and that kind of stuff might result
> > in somewhat illogical restrictions. Adopt the MIDI implementation
> > (CC, BC and PC mapping for example) to the sampler rather than the
> > other way around, within sensible limits. Just something to consider
> > before hardcoding MIDI into the engine core forever, perhaps.
>
> BTW: CC is continuous controller , but what is BC and PC ?

CC = MIDI Control Change
BC = Bank Change (should have been Bank _Select_ actually!)
PC = Program Change

Sorry about the confuson.

> I agree MIDI is not the best in the world, but for now we have to live with it.
> My code does not depend heavily on MIDI:
> the only part which depends on MIDI is the midithread which sends events
> to the audio engine and the note-on , note-off receive parts.
> Internally I use my own structures for instruments , voices, samples,
> patches (not ready yet).
> For example there is no concept of MIDI channel yet.

Good. That single thing is probably the biggest source of trouble, as
a program that assumes that there are 16 MIDI channels, and builds
everything statically around that (array of 16 structs) may need
serious hacking even to support more than one MIDI port...

> When it will be added, it will simply map one or more MIDI channel to an
> instrument.

Insert abstraction layer here, perhaps. Any serious machine with more
than 32 voices should definitely have more than one MIDI port, so
something like real_channel = MIDI_port + MIDI_channel may make
sense. Also, simply throwing in both port and channel fields
everywhere makes no sense at all when interfacing directly with
something like a tracker or "next generation sequencer" which tries
to avoid throwing that MIDI stuff in the face of the user all the
time. Ports make sense for separate, different machines; not as a
hack to get more parts/channels, unless you can't avoid it. (As is
the case with MIDI.)

Speaking of "next generation", how about a *real* API? Logically
similar to MIDI, but with timestamps and without the range and
precision limitations. There are a few protocols, but most of them
are really *protocols* just like MIDI, and none of them are standars
that more than one (if any!) company builds equipment for. The MuCoS
event system in it's current form (not yet running, though) could be
used for this as well as for plugins (ie give EVO a MuCoS client
interface), but it's quite a bit more involved than MIDI.
Unfortunately it seem like it has to be in order to be useful.

Anyway, I'll release that prototype before speculating more about
this. Some "vacation" starting next week should do the trick. :-)

//David

.- M u C o S --------------------------------. .- David Olofson ------.
| A Free/Open Multimedia | | Audio Hacker |
| Plugin and Integration Standard | | Linux Advocate |
`------------> http://www.linuxdj.com/mucos -' | Open Source Advocate |
.- A u d i a l i t y ------------------------. | Singer |
| Rock Solid Low Latency Signal Processing | | Songwriter |
`---> http://www.angelfire.com/or/audiality -' `-> david_AT_linuxdj.com -'


New Message Reply About this list Date view Thread view Subject view Author view Other groups

This archive was generated by hypermail 2b28 : Wed Jul 19 2000 - 09:23:58 EEST