Page 3 of 3

Re: The Design Thread

Posted: Thu Feb 28, 2008 4:27 pm
by lowkey
Ok Delia co-composed it because the sounds are just as important as the time and pitch. :)

Im with you Darren. Using samples to make new sounds is where Im at. That's why I love music by Art of Noise, Autechre, Aphex Twin, Boards of Canada, Future Sound of London and Amon Tobin.

I recon resampling would have to be part of the architecture if sonic exploration is an aim.

Re: The Design Thread

Posted: Thu Feb 28, 2008 4:53 pm
by Consul
Actually, Ron Grainer did want to give her co-composer credit, according to that wikipedia article you linked to. :)

I'm going to see if I can find a tech or user's manual for the Synclavier, to find some inspiration.

Re: The Design Thread

Posted: Thu Feb 28, 2008 5:25 pm
by lowkey
If Im not mistaken Alex used a Fairlight so he may be able to help. I'll see if I can find a manual for the Synclavier for you.

Re: The Design Thread

Posted: Thu Feb 28, 2008 5:28 pm
by Consul
Already found them, thanks!

To be honest, the basic capabilities don't seem to be beyond what any modern software sampler is capable of. In fact, my feature requests involving modulating loop points and the like appear to go beyond the Synclav's capabilities. Only the resynthesis capabilities seem to be unique. I'll keep reading and see if I can find anything interesting.

Re: The Design Thread

Posted: Thu Feb 28, 2008 9:30 pm
by dahnielson
Here's a rather simple example of a mapper implemented in Python just for fun. It lacks round robin and key switches, but that is easily added.

Code: Select all

#!/usr/bin/env python

"""Simple mapper example."""

class Any(object):
    """A wildcard type."""
    def __lt__(self, other): return True
    def __le__(self, other): return True
    def __eq__(self, other): return True
    def __ne__(self, other): return True
    def __gt__(self, other): return True
    def __ge__(self, other): return True


def note_event(key=None, vel=None, ch=None, trigger='attack'):
    """Note event factory."""
    type = "note"
    return locals()

def control_event(control=None, value=None):
    """Control event factory."""
    type = "control"
    return locals()

def region(out,
           keylo = Any(), keyhi = Any(),
           vello = Any(), velhi = Any(),
           chlo = Any(), chhi = Any(),
           bendlo = Any(), bendhi = Any(),
           chaftlo = Any(), chafthi = Any(),
           polyaftlo = Any(), polyafthi = Any(),
           bmplo = Any(), bmphi = Any(),
           trigger = 'attack'
           ):
    """Region factory."""
    return locals()

def status(key=None,
           vel=None,
           ch=None,
           bend=None,
           chaft=None,
           polyaft=None,
           bmp=None,
           trigger='attack'):
    """Status matching closure factory."""
    def _match(r):
        return key >= r['keylo'] and key <= r['keyhi'] and \
               vel >= r['vello'] and vel <= r['velhi'] and \
               ch >= r['chlo'] and ch <= r['chhi'] and \
               bend >= r['bendlo'] and bend <= r['bendhi'] and \
               chaft >= r['chaftlo'] and chaft <= r['chafthi'] and \
               polyaft >= r['polyaftlo'] and polyaft <= r['polyafthi'] and \
               bmp >= r['bmplo'] and bmp <= r['bmphi'] and \
               trigger == r['trigger']
    return _match


class Mapper(object):

    def __init__(self, regions):
        self.regions = regions
        self.bend = 0
        self.chaft = 0
        self.polyaft = 0
        self.bmp = 0

    def map(self, event):
        return getattr(self, event['type']+'_event')(event)

    def note_event(self, event):
        match = status(key=event['key'], vel=event['vel'], ch=event['ch'],
                       bend=self.bend, chaft=self.chaft, polyaft=self.polyaft, 
                       bmp=self.bmp, trigger=event['trigger'])
        return [note_event(event['key'], event['vel'], event['ch'], event['trigger'], r['out'])
                for r in self.regions if match(r)]

    def control_event(self, event):
        getattr(self, 'update_'+event['control'])()
        return [event]

    def update_bend(self, event):
        self.bend = event['value']

    def update_chaft(self, event):
        self.chaft = event['value']

    def update_polyaft(self, event):
        self.polyaft = event['value']

    def update_bmp(self, event):
        self.bmp = event['value']


if __name__ == '__main__':
    mapper = Mapper([
        region(out=0, keylo=20, keyhi=25),
        region(out=1, keylo=26, keyhi=27)
        ])
    print mapper.map(note_event(key=23))
    print mapper.map(note_event(key=26))

Re: The Design Thread

Posted: Thu Feb 28, 2008 9:34 pm
by dahnielson
Consul wrote:To be honest, the basic capabilities don't seem to be beyond what any modern software sampler is capable of. In fact, my feature requests involving modulating loop points and the like appear to go beyond the Synclav's capabilities. Only the resynthesis capabilities seem to be unique. I'll keep reading and see if I can find anything interesting.
Loop points would be parameters to the sample player (which I should have called "synthesis/resynthesis" to begin with as samples are just a subset of that field and new synthesis/resynthesis modules could be added going beyond sample playback) so hooking up a modulator to them should be an expected task when creating a instrument.

Re: The Design Thread

Posted: Thu Feb 28, 2008 11:50 pm
by dahnielson
I haven't drawn the block diagram yet, but what I'm working on turns out to be actually simple:

0. Events arrive from the "outside world" (via MIDI and GUI).

1. The events pass a series of event processors. The processors are either pre-build (like the mapper) or scripts.

2. The processed events are then sent to the bank of voices. Each voice consist of synthesis, filters, amplifier and modulators (the modulators are connected to parameters of the synthesis, filters and amplifier). All of them have parameters that is modified by one or several events. E.g. the amplifier has a volume parameter that is modified by (listens to) the velocity value in note events while a filter has a LFO modulator connected to one of its parameters and the modulator is also modified by (listens to) the velocity value in note events. The voices generates an audio signal.

3. The audio signal is sent to the "outside world" (for further processing).

Things I ignored in the description above: The "outside world" can actually be inside the sampler but is outside the scope of what I'm working on. Voice groups or voice layers so that each instrument can have multiple voice signal paths and exclusive voice groups and voice stealing per group/layer.