On Wed, Jul 23, 2008 at 16:41, Darren Landrum <[EMAIL PROTECTED]> wrote:
> [EMAIL PROTECTED] wrote: > > It's not XML, it's a sort of flat-text-ish thing with various keywords > > for setting keys, keygroups, mutegroups and so on. > > > > Having briefly skimmed the spec over lunch, I'm not in much of a > > position to say how good it is, but it "looks right". > > > > Essentially an SFZ file is a text file describing what to do with a > > bunch of .wav or .ogg files. It's almost worryingly clueful. > > It wasn't actually created by Cakewalk, but by a small company that > Cakewalk had bought, and rather than closing up or quelching SFZ, they > decided to keep it open. That's the story best as I was able to divine > it, anyway. And now with the news that Tascam is discontinuing all > Gigastudio-related development (http://www.filmmusicmag.com/?p=1738 and > confirmed on the "Legacy" section of Tascam's web site: > http://www.tascam.com/legacy;37,7.html) it's possible that SFZ might > become a new standard for sample libraries to use. Garritan is > apparently releasing, or getting set to release, their libraries in SFZ > now. > Hi Darren! :-) Note that Garritan/Plogue are using a later version of the SFZ format with additional and sometimes custom opcodes in their ARIA player. (See e.g. http://www.northernsounds.com/forum/showthread.php?t=60929 ) Here's a simple tokenizer for SFZ I wrote once upon a time in Python. Not sure if I got it completely right. [BEGIN PYTHON] import sys def find_delimiter(string, delimiter): """Find all occurences of delimiter.""" start, i, ndx = 0, 0, [] while True: i = string.find(delimiter, start) if i != -1: start = i + 1 ndx.append((i, delimiter)) else: break return ndx def find_all_delimiters(string, delimiters): """Find all delimiters.""" ndx = [] for delimiter in delimiters: ndx.extend(find_delimiter(string, delimiter)) return ndx def tokenize_sfz(string): """Tokenize SFZ string.""" delimiters = [ # comments '\n', '//', # headers '<region>', '<group>', # sample definition 'sample=', # input controls 'lochan=', 'hichan=', 'lokey=', 'hikey=', 'key=', 'lovel=', 'hivel=', 'lobend=', 'hibend=', 'locahnaft=', 'hichanaft=', 'lopolyaft=', 'hiplyaft=', 'lorand=', 'hirand=', 'lobpm=', 'hibmp=', 'seq_length=', 'seq_position=', 'sw_lokey=', 'sw_hikey=', 'sw_last=', 'sw_down=', 'sw_up=', 'sw_previous=', 'sw_vel=', 'trigger=', 'group=', 'off_by=', 'off_mode=', ] + [ 'on_locc%d=' % cc for cc in range(128) ] + [ 'on_locc%d=' % cc for cc in range(128) ] + [ # performance parameters 'delay=', 'delay_random=', ] + [ 'delay_cc%d=' % cc for cc in range(128) ] + [ 'offset=', 'offset_random=', ] + [ 'offset_cc%d=' % cc for cc in range(128) ] + [ 'end=', 'count=', 'loop_mode=', 'loop_start=', 'loop_end=', 'sync_beats=', 'sync_offset=', # pitch 'transpose=', 'tune=', 'pitch_keycenter=', 'pitch_keytrack=', 'pitch_veltrack=', 'pitch_random=', 'bend_up=', 'bend_down=', 'bend_step=', # pitch eg 'pitcheg_delay=', 'pitcheg_start=', 'pitcheg_attack=', 'pitcheg_hold=', 'pitcheg_decay=', 'pitcheg_sustain=', 'pitcheg_release=', 'pitcheg_depth=', 'pitcheg_vel2delay=', 'pitcheg_vel2attack=', 'pitcheg_vel2hold=', 'pitcheg_vel2decay=', 'pitcheg_vel2sustain=', 'pitcheg_vel2realease=', 'pitcheg_vel2depth=', # pitch lfo 'pitchlfo_delay=', 'pitchlfo_fade=', 'pitchlfo_freq=', 'pitchlfo_depth=', ] + [ 'pitchlfo_depthcc%d=' % cc for cc in range(128) ] + [ 'pitchlfo_depthchanaft=', 'pitchlfo_depthpolyaft=', ] + [ 'pitchlfo_freqcc%d=' % cc for cc in range(128) ] + [ 'pitchlfo_freqchanaft=', 'pitchlfo_freqpolyaft=', # filter 'fil_type=', 'cutoff=', ] + [ 'cutoff_cc%d=' % cc for cc in range(128) ] + [ 'cutoff_chanaft=', 'cutoff_polyaft=', 'resonance=', 'fil_keytrack=', 'fil_keycenter=', 'fil_veltrack=', 'fil_random=', # filter eg 'fileg_delay=', 'fileg_start=', 'fileg_attack=', 'fileg_hold=', 'fileg_decay=', 'fileg_sustain=', 'fileg_release=', 'fileg_depth=', 'fileg_vel2delay=', 'fileg_vel2attack=', 'fileg_vel2hold=', 'fileg_vel2decay=', 'fileg_vel2sustain=', 'fileg_vel2realease=', 'fileg_vel2depth=', # filter lfo 'fillfo_delay=', 'fillfo_fade=', 'fillfo_freq=', 'fillfo_depth=', ] + [ 'fillfo_depthcc%d=' % cc for cc in range(128) ] + [ 'fillfo_depthchanaft=', 'fillfo_depthpolyaft=', ] + [ 'fillfo_freqcc%d=' % cc for cc in range(128) ] + [ 'fillfo_freqchanaft=', 'fillfo_freqpolyaft=', # amplifier 'volume=', 'pan=', 'width=', 'position=', 'amp_keytrack=', 'amp_keycenter=', 'amp_veltrack=', ] + [ 'amp_velcurve_%d=' % c for c in range(128) ] + [ 'amp_random=', 'rt_decay=', 'output=', ] + [ 'gain_cc%d=' % cc for cc in range(128) ] + [ 'xfin_lokey=', 'xfin_hikey=', 'xfout_lokey=', 'xfout_hikey=', 'xf_keycurve=', 'xfin_lovel=', 'xfin_hilev=', 'xfout_lovel=', 'xfout_hilev=', 'xf_velcurve=', ] + [ 'xfin_locc%d=' % cc for cc in range(128) ] + [ 'xfin_hicc%d=' % cc for cc in range(128) ] + [ 'xfout_locc%d=' % cc for cc in range(128) ] + [ 'xfout_hicc%d=' % cc for cc in range(128) ] + [ 'xf_cccurve=', # amplifier eg 'ampeg_delay=', 'ampeg_start=', 'ampeg_attack=', 'ampeg_hold=', 'ampeg_decay=', 'ampeg_sustain=', 'ampeg_release=', 'ampeg_vel2delay=', 'ampeg_vel2attack=', 'ampeg_vel2hold=', 'ampeg_vel2decay=', 'ampeg_vel2sustain=', 'ampeg_vel2release=', ] + [ 'ampeg_delaycc%d=' % cc for cc in range(128) ] + [ 'ampeg_startcc%d=' % cc for cc in range(128) ] + [ 'ampeg_attackcc%d=' % cc for cc in range(128) ] + [ 'ampeg_holdcc%d=' % cc for cc in range(128) ] + [ 'ampeg_decaycc%d=' % cc for cc in range(128) ] + [ 'ampeg_sustaincc%d=' % cc for cc in range(128) ] + [ 'ampeg_releasecc%d=' % cc for cc in range(128) ] + [ # amplifier lfo 'amplfo_delay=', 'amplfo_fade=', 'amplfo_freq=', 'amplfo_depth=', ] + [ 'amplfo_depthcc%d=' % cc for cc in range(128) ] + [ 'amplfo_depthchanaft=', 'amplfo_depthpolyaft=', ] + [ 'amplfo_freqcc%d=' % cc for cc in range(128) ] + [ 'amplfo_freqchanaft=', 'amplfo_freqpolyaft=', # equalizer 'eq1_freq=', 'eq2_freq=', 'eq3_freq=', ] + [ 'eq1_freqcc%d=' % cc for cc in range(128) ] + [ 'eq2_freqcc%d=' % cc for cc in range(128) ] + [ 'eq3_freqcc%d=' % cc for cc in range(128) ] + [ 'eq1_vel2freq', 'eq2_vel2freq', 'eq3_vel2freq', 'eq1_bw', 'eq2_bw', 'eq3_bw', ] + [ 'eq1_bwcc%d=' % cc for cc in range(128) ] + [ 'eq2_bwcc%d=' % cc for cc in range(128) ] + [ 'eq3_bwcc%d=' % cc for cc in range(128) ] + [ 'eq1_gain=', 'eq2_gain=', 'eq3_gain=', ] + [ 'eq1_gaincc%d=' % cc for cc in range(128) ] + [ 'eq2_gaincc%d=' % cc for cc in range(128) ] + [ 'eq3_gaincc%d=' % cc for cc in range(128) ] + [ 'eq1_vel2gain=', 'eq2_vel2gain=', 'eq3_vel2gain=', # effects 'effect1=', 'effect2=', ] stack = find_all_delimiters(string, delimiters) stack.sort() stack.reverse() comment = False tokens = [] while True: try: start = stack.pop() end = stack.pop() stack.append(end) except IndexError: break if start[1] == '//': comment = True elif start[1] == '\n': comment = False continue if not comment: tokens.append(sfz[start[0]:end[0]].rstrip().split('=', 1)) return tokens sfzf = open(sys.argv[1], 'r') sfz = sfzf.read() sfzf.close() print tokenize_sfz(sfz) [END PYTHON] -- Anders Dahnielson <[EMAIL PROTECTED]>
_______________________________________________ Linux-audio-dev mailing list Linux-audio-dev@lists.linuxaudio.org http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev