Since some users complained about the lack of a way to play MIDI files on all platforms (most solutions are windows-only), here is a solution.
Modern sound cards does not have midi-capable hardware, so a software synthesizer is needed; most software MIDI synthesizer produce sounds by playing pre-recorded samples: this solution is easy to implement, produce a realistic sound, but is really heavy in terms of memory and download size. So, a common solution is to replace MIDI files with MP3 (they are bigger, but they require no soundfonts so download size will still be small).
FM synthesis is an alternative, used on older sound cards, but also on synthesizers like the Yamaha DX 7; it can produce almost any sound, by using almost no memory and very little resources. The sound is a bit "electronic", but it's more than enough for most computer applications.
Some time ago, I used an OPL emulator written in C by Ken Silverman; anyway, it emulates perfectly most advantages of the old hardware... but also its limits: only one note per channel, only nine channels, only two operators.
I found a better solution here (http://milkpot.sakura.ne.jp/fmmidi/), and finally I managed to port it to FreeBasic: it is not an emulator of a specific hardware, so it has not the limitation of an OPL chip, although the algorithm used is similar (phase modulation of sine waves, lookup tables to speed up the process, an output buffer with PCM data).
It supports all 128 MIDI instruments, and percussions. Also, it's possible to change values in the array "programs", to define different instruments (defining a sound using FM parameters is much harder than defining it, i.e., with subtractive synthesis; fortunately, default instruments have already been defined)
You can turn on and off any note, on any channel; there is no limit to polyphony, and every instruments can use an algorithm based on 4 parameter FM synthesis.
But the synthesizer can just replace the MIDI driver: to be able to play MIDI files, a sequencer is needed, too; instead of porting the sequencer from C++ version of FMMIDI, I ported the sequencer written by Sebastian Mate for RealMidi: it's simpler, and easier to understand. It's more limited (it can't play multi-track files), but its main purpose is just to test the synthesizer.
Anyway, here is the files:
http://www27.zippyshare.com/v/9457100/file.html
Cross-platform MIDI in pure FreeBasic!
Re: Cross-platform MIDI in pure FreeBasic!
Here is the source code (if zippyshare does not work)
MIDISYNTH.BAS
MIDISYNTH.BAS
Code: Select all
'
' Copyright(c)2007 yuno --- Port to FreeBasic by Angelo Rosina
'
' This software is provided 'as-is', without any express or implied warranty.
' In no event will the authors be held liable for any damages arising from the
' use of this software.
'
' Permission is granted to anyone to use this software for any purpose,
' including commercial applications, and to alter it and redistribute it
' freely, subject to the following restrictions:
'
' 1. The origin of this software must not be misrepresented; you must not claim
' that you wrote the original software. If you use this software in a product,
' an acknowledgment in the product documentation would be appreciated but is
' not required.
'
' 2. Altered source versions must be plainly marked as such, and must not be
' misrepresented as being the original software.
'
' 3. This notice may not be removed or altered from any source distribution.
'
const LOG10_32767=4.5154366811416989472479934140484
const LOGTABLE_FACTOR=(4096 / LOG10_32767)
dim shared as short sine_table(4095)
dim shared as unsigned short log_table(4095)
type _envelope_table
TL(127) as unsigned long
SL(15,127) as unsigned long
AR(63,127) as double
RR(63,127) as double
end type
dim shared envelope_table as _envelope_table
dim shared as long vibrato_table(16383)
#include "midisynth.bi"
#include "instruments.bi"
sub InitTables() constructor
for i as integer= 0 to 4095
sine_table(i) = cast(short, sin(i * 2 * M_PI / 4096)*32767)
log_table(i) = 10^ (cast(double,i) / LOGTABLE_FACTOR)
next
for t as integer=0 to 127
dim as double fTL = 32767 * 10^(t * -0.75 / 10)
envelope_table.TL(t) = fTL
if envelope_table.TL(t) = 0 then
envelope_table.TL(t) = 1
end if
for s as integer = 0 to 15
dim as double x = fTL * 10^(s * -3.0 / 10)
if x <= 1 then
envelope_table.SL(s,t) = 0
else
envelope_table.SL(s,t) = 65536 * LOGTABLE_FACTOR * (log(x)/log(10))
end if
next
next
for x as integer = 0 to 63
dim as double attack_time = 15.3262 * 10^(x * -0.75 / 10)
dim as double release_time = 211.84 * 10^(x * -0.75 / 10)
for t as integer = 0 to 127
envelope_table.AR(x,t) = envelope_table.TL(t) / attack_time
envelope_table.RR(x,t) = 65536 * LOGTABLE_FACTOR * 48.0 / 10 * envelope_table.TL(t) / 32767 / release_time
next
next
for i as integer= 0 to 16383
dim x as double = (cast(double,i) / 16384 - 0.5) * 256.0 / 12.0
vibrato_table(i) = cast(long,(2^x - 1) * 65536.0)
next
end sub
function channel.synthesize(out as long ptr, samples as uinteger, rate as single, master_volume as long, master_balance as integer) as integer
dim volume as double
if mute=0 then volume = (cast(double,master_volume) * this.volume * expression / (16383.0 * 16383.0 * 16383.0))^ 2 * 16383.0
dim num_notes as integer
dim i as _NOTES ptr= _firstnote
while(i <> 0)
dim as fm_note ptr note = i->note
dim as ulong panpot = note->panpot
if this.panpot <= 8192 then
panpot = panpot * this.panpot / 8192
else
panpot = panpot * (16384 - this.panpot) / 8192 + (this.panpot - 8192) * 2
end if
if master_balance <= 8192 then
panpot = panpot * master_balance / 8192
else
panpot = panpot * (16384 - master_balance) / 8192 + (master_balance - 8192) * 2
end if
if panpot<1 then panpot=0 else panpot-=1
dim as long _left = cast(long,volume * cos(panpot * (M_PI / 2 / 16382)))
dim as long _right = cast(long,volume * sin(panpot * (M_PI / 2 / 16382)))
dim as integer ret = note->synthesize(out, samples, rate, _left, _right)
if ret then
i=i->_next
else
if i=this._firstnote then this._firstnote=i->_next
if i=this._lastnote then this._lastnote=i->_prev
if i->_next<>0 then i->_next->_prev=i->_prev
if i->_prev<>0 then i->_prev->_next=i->_next
delete note
dim old as _NOTES ptr= i->_next
delete i
i=old
end if
num_notes+=1
wend
return num_notes
end function
sub channel.reset_all_parameters()
program = default_bank * 128
bank = default_bank
panpot = 8192
volume = 12800
fine_tuning = 8192
coarse_tuning = 8192
tremolo_frequency = 3
vibrato_frequency = 3
master_frequency_multiplier = 1
mono = 0
mute = 0
system_mode = 0'system_mode_default
reset_all_controller()
end sub
sub channel.reset_all_controller()
expression = 16383
channel_pressure(0)
pitch_bend = 8192
pitch_bend_sensitivity = 256
update_frequency_multiplier()
modulation_depth = 0
modulation_depth_range = 64
update_modulation()
set_damper(0)
set_sostenute(0)
set_freeze(0)
RPN = &H3FFF
NRPN = &H3FFF
end sub
sub channel.all_note_off()
dim as _NOTES ptr i=this._firstnote
do until i=0
if i->status = 1 then
i->status = 0
i->note->fm.key_off()
end if
i=i->_next
loop
end sub
sub channel.all_sound_off()
dim as _NOTES ptr i=this._firstnote
do until i=0
if i->status <> -1 then
i->status = -1
i->note->fm.sound_off()
end if
i=i->_next
loop
end sub
sub channel.all_sound_off_immediately()
dim as _NOTES ptr i=this._firstnote
do until i=0
delete i->note
i=i->_next
if i->_prev<>0 then delete i->_prev
loop
this._firstnote=0
this._lastnote=0
end sub
sub channel.note_on(note as integer, velocity as integer)
note_off(note, 64)
if velocity then
if mono then
all_sound_off()
end if
dim as fm_note ptr p = factory->note_on(program, note, velocity, frequency_multiplier)
if p<>0 then
dim as integer assign = p->assign
if assign<>0 then
dim as _NOTES ptr i=this._firstnote
do until i=0
if i->note->assign = assign then
i->note->fm.sound_off()
end if
i=i->_next
loop
end if
if freeze then
p->fm.set_freeze(freeze)
end if
if damper then
p->fm.set_damper(damper)
end if
if modulation_depth then
dim as single depth = cast(double,modulation_depth) * modulation_depth_range / (16383.0 * 128.0)
p->fm.set_vibrato(depth, vibrato_frequency)
end if
if pressure then
p->fm.set_tremolo(pressure, tremolo_frequency)
end if
dim as _NOTES ptr pp=new _NOTES:
pp->note=p: pp->key=note: pp->status=1
if this._firstnote=0 then this._firstnote=pp:this._lastnote=pp else pp->_prev=this._lastnote:this._lastnote->_next=pp
this._lastnote=pp
end if
end if
end sub
sub channel.note_off(note as integer, velocity as integer)
dim as _NOTES ptr i=this._firstnote
do until i=0
if i->key = note andalso i->status = 1 then
i->status = 0
i->note->fm.key_off()
end if
i=i->_next
loop
end sub
sub channel.polyphonic_key_pressure(note as integer, value as integer)
dim as _NOTES ptr i=this._firstnote
do until i=0
if i->key = note andalso i->status = 1 then
i->note->fm.set_tremolo(value, tremolo_frequency)
end if
i=i->_next
loop
end sub
sub channel.channel_pressure(value as integer)
if pressure <> value then
pressure = value
dim as _NOTES ptr i=this._firstnote
do until i=0
if i->status = 1 then
i->note->fm.set_tremolo(value, tremolo_frequency)
end if
i=i->_next
loop
end if
end sub
sub channel.control_change(control as integer, value as integer)
select case control
case &H00
bank_select((bank and &H7F) or (value shl 7))
case &H01
modulation_depth=(modulation_depth and &H7F) or (value shl 7)
update_modulation()
case &H06
set_registered_parameter((get_registered_parameter() and &H7F) or (value shl 7))
case &H07
volume = (volume and &H7F) or (value shl 7)
case &H0A
panpot = (panpot and &H7F) or (value shl 7)
case &H0B
expression = (expression and &H7F) or (value shl 7)
case &H20
bank_select((bank and &H7F) or (value shl 7))
case &H21
modulation_depth=(modulation_depth and not &H7F) or value
update_modulation()
case &H26
set_registered_parameter((get_registered_parameter() and not &H7F) or value)
case &H27
volume = (volume and not &H7F) or value
case &H2A
panpot = (panpot and not &H7F) or value
case &H2B
expression = (expression and not &H7F) or value
case &H40
set_damper(value)
case &H42
set_sostenute(value)
case &H45
set_freeze(value)
case &H60
if get_registered_parameter() + 1>&H3FFF then
set_registered_parameter(get_registered_parameter() + 1)
else
set_registered_parameter(&H3FFF)
end if
case &H61
if get_registered_parameter() - 1<0 then
set_registered_parameter(get_registered_parameter() - 1)
else
set_registered_parameter(0)
end if
case &H62
NRPN=(NRPN and not &H7F) or value
RPN = &H3FFF
case &H63
NRPN=(NRPN and &H7F) or (value shl 7)
RPN = &H3FFF
case &H64
RPN=(RPN and not &H7F) or value
NRPN = &H3FFF
case &H65
RPN=(RPN and &H7F) or (value shl 7)
NRPN = &H3FFF
case &H78
all_sound_off()
case &H79
reset_all_controller()
case &H7B, &H7C, &H7D
all_note_off()
case &H7E
all_note_off(): mono = 1
case &H7F
all_note_off(): mono = 0
end select
end sub
sub channel.bank_select(value as integer)
select case system_mode
case 1
case 3
if ((bank and &H3F80) = &H3C00) = ((value and &H3F80) = &H3C00) then
bank=value
end if
case 4
if default_bank = &H3C00 then
bank=&H3C00 or (value and &H7F)
elseif (value and &H3F80) = &H3F80 then
bank=&H3C00 or (value and &H7F)
else
bank=value
end if
case else
if default_bank = &H3C00 then
bank=&H3C00 or (value and &H7F)
else
bank=value
end if
end select
end sub
sub channel.set_damper(value as integer)
if damper <> value then
damper = value
dim as _NOTES ptr i=this._firstnote
do until i=0
i->note->fm.set_damper(value)
i=i->_next
loop
end if
end sub
sub channel.set_sostenute(value as integer)
sostenute = value
dim as _NOTES ptr i=this._firstnote
do until i=0
i->note->fm.set_sostenute(value)
i=i->_next
loop
end sub
sub channel.set_freeze(value as integer)
if freeze <> value then
freeze = value
dim as _NOTES ptr i=this._firstnote
do until i=0
i->note->fm.set_freeze(value)
i=i->_next
loop
end if
end sub
function channel.get_registered_parameter() as integer
select case RPN
case &H0000
return pitch_bend_sensitivity
case &H0001
return fine_tuning
case &H0002
return coarse_tuning
case &H0005
return modulation_depth_range
case else
return 0
end select
end function
sub channel.set_registered_parameter(value as integer)
select case RPN
case &H0000
pitch_bend_sensitivity=value
update_frequency_multiplier()
case &H0001
fine_tuning=value
update_frequency_multiplier()
case &H0002
coarse_tuning=value
update_frequency_multiplier()
case &H0005
modulation_depth_range=value
update_modulation()
case else
end select
end sub
sub channel.update_frequency_multiplier()
dim as single value = master_frequency_multiplier * _
2^ ((coarse_tuning - 8192) / (128.0 * 100.0 * 12.0) _
+ (fine_tuning - 8192) / (8192.0 * 100.0 * 12.0) _
+ cast(double,pitch_bend - 8192) * pitch_bend_sensitivity / (8192.0 * 128.0 * 12.0))
if frequency_multiplier <> value then
frequency_multiplier = value
dim as _NOTES ptr i=this._firstnote
do until i=0
i->note->fm.set_damper(value)
i->note->fm.set_frequency_multiplier(value)
i=i->_next
loop
end if
end sub
sub channel.update_modulation()
dim as single depth = cast(double,modulation_depth) * modulation_depth_range / (16383.0 * 128.0)
dim as _NOTES ptr i=this._firstnote
do until i=0
i->note->fm.set_vibrato(depth, vibrato_frequency)
i=i->_next
loop
end sub
function synthesizer.synthesize(_output as short ptr, samples as uinteger, rate as single) as integer
dim as uinteger n = samples * 2
dim as long buf(n+1)
dim as integer num_notes = synthesize_mixing(@buf(0), samples, rate)
if num_notes then
for i as uinteger = 0 to n
dim as long x = buf(i)
if x < -32767 then
_output[i] = -32767
elseif x > 32767 then
_output[i] = 32767
else
_output[i] = x
end if
next
else
clear _output[0], 0, len(short) * n
end if
return num_notes
end function
function synthesizer.synthesize_mixing(_output as long ptr, samples as uinteger, rate as single) as integer
if active_sensing = 0 then
all_sound_off()
active_sensing = -1
elseif active_sensing > 0 then
active_sensing -= samples / rate
if active_sensing < 0 then active_sensing=0
end if
dim as long volume = cast(long,main_volume) * master_volume / 16384
dim as integer num_notes = 0
for i as integer = 0 to 15
num_notes += channels(i).synthesize(_output, samples, rate, volume, master_balance)
next
return num_notes
end function
sub synthesizer.reset()
for i as integer=0 to 15
if channels(i).factory=0 then channels(i).factory= new fm_note_factory
for a as integer=0 to 128
channels(i).factory->programs(a)=@programs(a)
next
for a as integer=35 to 81
channels(i).factory->drums(a)=@drums(a)
next
next
all_sound_off_immediately()
reset_all_parameters()
end sub
sub synthesizer.reset_all_parameters()
active_sensing = -1
main_volume = 8192
master_volume = 16383
master_balance = 8192
master_fine_tuning = 8192
master_coarse_tuning = 8192
master_frequency_multiplier = 1
system_mode = 0
for i as integer = 0 to 15
channels(i).reset_all_parameters()
next
end sub
sub synthesizer.reset_all_controller()
for i as integer = 0 to 15
channels(i).reset_all_controller()
next
end sub
sub synthesizer.all_note_off()
for i as integer = 0 to 15
channels(i).all_note_off()
next
end sub
sub synthesizer.all_sound_off()
for i as integer = 0 to 15
channels(i).all_sound_off()
next
end sub
sub synthesizer.all_sound_off_immediately()
for i as integer = 0 to 15
channels(i).all_sound_off_immediately()
next
end sub
sub synthesizer.sysex_message(pvdata as string)
if left(pvdata,6)= !"\xF0\x7E\x7F\x09\x01\xF7" then
' GM system on
set_system_mode(1)
elseif left(pvdata,6) =!"\xF0\x7E\x7F\x09\x02\xF7" then
' GM system off
set_system_mode(2)
elseif left(pvdata,6)=!"\xF0\x7E\x7F\x09\x03\xF7" then
' GM2 system on
set_system_mode(2)
elseif left(pvdata,2)= !"\xF0\x41" andalso mid(pvdata,4,8)= !"\x42\x12\x40\x00\x7F\x00\x41\xF7" then
' GS reset
set_system_mode(3)
elseif left(pvdata,2)= !"\xF0\x43" andalso (asc(pvdata,3) and &HF0) = &H10 andalso mid(pvdata, 4, 6)= !"\x4C\x00\x00\x7E\x00\xF7" then
' XG system on
set_system_mode(4)
elseif left(pvdata, 5) =!"\xF0\x7F\x7F\x04\x01" andalso asc(pvdata,8) = &HF7 then
' master volume
master_volume=(asc(pvdata,6) and &H7F) or ((asc(pvdata,7) and &H7F) shl 7)
elseif left(pvdata,5) = !"\xF0\x7F\x7F\x04\x02" andalso asc(pvdata,8) = &HF7 then
' master balance
master_balance=(asc(pvdata,6) and &H7F) or ((asc(pvdata,7) and &H7F) shl 7)
elseif left(pvdata,5) = !"\xF0\x7F\x7F\x04\x03" andalso asc(pvdata,8) = &HF7 then
' master fine tuning
master_fine_tuning=(asc(pvdata,6) and &H7F) or ((asc(pvdata,7) and &H7F) shl 7)
update_master_frequency_multiplier()
elseif left(pvdata,5) = !"\xF0\x7F\x7F\x04\x04" andalso asc(pvdata,8) = &HF7 then
' master coarse tuning
master_coarse_tuning=(asc(pvdata,6) and &H7F) or ((asc(pvdata,7) and &H7F) shl 7)
update_master_frequency_multiplier()
elseif left(pvdata, 2) = !"\xF0\x41" andalso (asc(pvdata,3) and &HF0) = &H10 andalso mid(pvdata, 4, 3) = !"\x42\x12\x40"andalso (asc(pvdata,7) and &HF0) = &H10 andalso asc(pvdata,8) = &H15 andalso asc(pvdata,11) = &HF7 then
' use for rhythm part
dim as integer _channel = asc(pvdata,7) and &H0F
if asc(pvdata,9) = 0 then
channels(_channel).bank=&H3C80
else
channels(_channel).bank=&H3C00
end if
channels(_channel).program=128*channels(_channel).bank
end if
end sub
sub synthesizer.midi_event(event as integer, param1 as integer, param2 as integer)
select case (event and &HF0)
case &H80
channels(event and &H0F).note_off(param1 and &H7F, param2 and &H7F)
case &H90
channels(event and &H0F).note_on(param1 and &H7F, param2 and &H7F)
case &HA0
channels(event and &H0F).polyphonic_key_pressure(param1 and &H7F, param2 and &H7F)
case &HB0
channels(event and &H0F).control_change(param1 and &H7F, param2 and &H7F)
case &HC0
channels(event and &H0F).program=(param1 and &H7F)+128*channels(event and &H0F).bank
case &HD0
channels(event and &H0F).channel_pressure(param1 and &H7F)
case &HE0
channels(event and &H0F).pitch_bend=((param2 and &H7F) shl 7) or (param1 and &H7F)
channels(event and &H0F).update_frequency_multiplier()
case &HFE
active_sensing = 0.33
case &HFF
all_sound_off()
reset_all_parameters()
case else
end select
end sub
sub synthesizer.set_system_mode(mode as integer)
all_sound_off()
reset_all_parameters()
system_mode = mode
for i as integer=0 to 15
channels(i).system_mode=mode
next
end sub
sub synthesizer.update_master_frequency_multiplier()
dim as single value = 2^( (master_coarse_tuning - 8192) / (128.0 * 100.0 * 12.0)_
+ (master_fine_tuning - 8192) / (8192.0 * 100.0 * 12.0))
if master_frequency_multiplier <> value then
master_frequency_multiplier = value
for i as integer=0 to 15
channels(i).master_frequency_multiplier=value
channels(i).update_frequency_multiplier
next
end if
end sub
sub sine_wave_generator.set_cycle(cycle as single)
if cycle<>0 then
_step = cast(unsigned long, 4096.0 * 32768.0 / cycle)
else
_step = 0
end if
end sub
sub sine_wave_generator.add_modulation(x as long)
position += cast(long, cast(longint, _step) * x shr 16)
end sub
function sine_wave_generator.get_next() as integer
position += _step
return sine_table((position / 32768) mod 4096)
end function
function sine_wave_generator.get_next(modulation as long) as integer
position += _step
dim as long m = modulation * 4096 / 65536
dim as ulong p = cast(ulong,(position / 32768 + m)) mod 4096
return sine_table(p)
end function
sub envelope_generator.set_rate(rate as single)
if rate<>0 then this.rate = rate else this.rate=1
update_parameters()
end sub
sub envelope_generator.set_hold(hold as single)
if this.hold > hold orelse state <= SUSTAIN orelse current >= fSL then
this.hold = hold
update_parameters()
end if
end sub
sub envelope_generator.set_freeze(freeze as single)
if this.freeze > freeze orelse state <= SUSTAIN orelse current >= fSL then
this.freeze = freeze
update_parameters()
end if
end sub
sub envelope_generator.update_parameters()
dim as double fAR = envelope_table.AR(AR,TL) / rate
dim as double fDR = envelope_table.RR(DR,TL) / rate
dim as double fSR = envelope_table.RR(SR,TL) / rate
dim as double fRR = envelope_table.RR(RR,TL) / rate
if fRR < 1 then
fRR = 1
end if
if hold > 0 then
fRR = fSR * hold + fRR * (1 - hold)
end if
if freeze > 0 then
fDR *= 1 - freeze
fSR *= 1 - freeze
fRR *= 1 - freeze
end if
if fAR < 1 then
fAR = 1
end if
this.fAR = cast(unsigned long,fAR)
this.fDR = cast(unsigned long,fDR)
this.fSR = cast(unsigned long,fSR)
this.fRR = cast(unsigned long,fRR)
this._fOR = cast(unsigned long,envelope_table.RR(63,0) / rate)
if this.fDR>fSL then this.fSS = this.fDR else this.fSS = fSL
if this.fDR>this.fRR then this.fDRR = this.fDR else this.fDRR = this.fRR
if this.fDRR>this.fSS then this.fDSS = this.fDRR else this.fDSS = this.fSS
end sub
sub envelope_generator.key_off()
select case state
case ATTACK
state = ATTACK_RELEASE
case DECAY
state = DECAY_RELEASE
case SUSTAIN
state = RELEASE
case else
end select
end sub
sub envelope_generator.sound_off()
select case state
case ATTACK, ATTACK_RELEASE
if current<>0 then
current = 65536 * LOGTABLE_FACTOR * log(cast(double,current))/log(10)
end if
case else
end select
state = SOUNDOFF
end sub
function envelope_generator.get_next() as integer
dim as unsigned long current = this.current
select case state
case ATTACK
if current < fTL then
this.current = current + fAR
return this.current
end if
this.current = 65536 * LOGTABLE_FACTOR * log(cast(double,fTL))/log(10)
state = DECAY
return fTL
case DECAY
if current > fSS then
current -= fDR
this.current = current
return log_table(current / 65536)
end if
current = fSL
this.current = current
state = SUSTAIN
return log_table(current / 65536)
case SUSTAIN
if current > fSR then
current -= fSR
this.current = current
dim n as integer = log_table(current / 65536)
if n > 1 then
return n
end if
end if
state = FINISHED
return 0
case ATTACK_RELEASE
if current < fTL then
this.current = current + fAR
return this.current
end if
this.current = 65536 * LOGTABLE_FACTOR * log(cast(double,fTL))/log(10)
state = DECAY_RELEASE
return fTL
case DECAY_RELEASE
if current > fDSS then
current -= fDRR
this.current = current
return log_table(current / 65536)
end if
current = fSL
this.current = current
state = RELEASE
return log_table(current / 65536)
case RELEASE
if current > fRR then
current -= fRR
this.current = current
dim n as integer = log_table(current / 65536)
if n > 1024 then
return n
end if
state = SOUNDOFF
return n
end if
state = FINISHED
return 0
case SOUNDOFF
if current > _fOR then
current -= _fOR
this.current = current
dim n as integer = log_table(current / 65536)
if n > 1 then
return n
end if
end if
state = FINISHED
return 0
case else
return 0
end select
end function
dim shared as integer keyscale_table(3,127) = {_
{_
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,_
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,_
0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,_
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2,_
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,_
2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,_
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,_
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3_
}, {_
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,_
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,_
1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,_
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4,_
4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5,_
5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,_
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,_
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7_
}, {_
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,_
0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2,_
2, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5,_
6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 8, 8, 8, 8,_
8, 8, 8, 8, 8, 9, 9, 9,10,10,10,10,10,10,10,10,_
10,11,11,11,12,12,12,12,12,12,12,12,12,13,13,13,_
14,14,14,14,14,14,14,14,14,15,15,15,15,15,15,15,_
15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15_
}, {_
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,_
0, 0, 0, 1, 1, 2, 2, 3, 4, 4, 4, 4, 4, 4, 4, 5,_
5, 6, 6, 7, 8, 8, 8, 8, 8, 8, 8, 9, 9,10,10,11,_
12,12,12,12,12,12,12,13,13,14,14,15,16,16,16,16,_
16,16,16,17,17,18,18,19,20,20,20,20,20,20,20,21,_
21,22,22,23,24,24,24,24,24,24,24,25,25,26,26,27,_
28,28,28,28,28,28,28,29,29,30,30,31,31,31,31,31,_
31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31_
}}
dim shared as single detune_table(3,127) = {_
{ 0 },_
{_
0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,_
0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,_
0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,_
0.053, 0.053, 0.053, 0.053, 0.053, 0.053, 0.053, 0.053,_
0.053, 0.053, 0.053, 0.053, 0.053, 0.053, 0.053, 0.053,_
0.053, 0.053, 0.053, 0.053, 0.053, 0.053, 0.053, 0.053,_
0.106, 0.106, 0.106, 0.106, 0.106, 0.106, 0.106, 0.106,_
0.106, 0.106, 0.106, 0.106, 0.106, 0.106, 0.106, 0.106,_
0.106, 0.106, 0.106, 0.159, 0.159, 0.159, 0.159, 0.159,_
0.212, 0.212, 0.212, 0.212, 0.212, 0.212, 0.212, 0.212,_
0.212, 0.212, 0.212, 0.264, 0.264, 0.264, 0.264, 0.264,_
0.264, 0.264, 0.264, 0.317, 0.317, 0.317, 0.317, 0.370,_
0.423, 0.423, 0.423, 0.423, 0.423, 0.423, 0.423, 0.423,_
0.423, 0.423, 0.423, 0.423, 0.423, 0.423, 0.423, 0.423,_
0.423, 0.423, 0.423, 0.423, 0.423, 0.423, 0.423, 0.423,_
0.423, 0.423, 0.423, 0.423, 0.423, 0.423, 0.423, 0.423_
}, {_
0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,_
0.000, 0.000, 0.000, 0.000, 0.000, 0.053, 0.053, 0.053,_
0.053, 0.053, 0.053, 0.053, 0.053, 0.053, 0.053, 0.053,_
0.106, 0.106, 0.106, 0.106, 0.106, 0.106, 0.106, 0.106,_
0.106, 0.106, 0.106, 0.106, 0.106, 0.106, 0.106, 0.106,_
0.106, 0.106, 0.106, 0.106 ,0.106, 0.159, 0.159, 0.159,_
0.212, 0.212, 0.212, 0.212, 0.212, 0.212, 0.212 ,0.212,_
0.212, 0.212, 0.212, 0.264, 0.264, 0.264, 0.264, 0.264,_
0.264, 0.264, 0.264, 0.317, 0.317, 0.317, 0.317, 0.370,_
0.423, 0.423, 0.423, 0.423, 0.423, 0.423, 0.423, 0.423,_
0.423, 0.476, 0.476, 0.529, 0.582, 0.582, 0.582, 0.582,_
0.582, 0.582 ,0.582, 0.635, 0.635, 0.688, 0.688, 0.741,_
0.846, 0.846, 0.846, 0.846, 0.846, 0.846, 0.846 ,0.846,_
0.846, 0.846, 0.846, 0.846, 0.846, 0.846, 0.846, 0.846,_
0.846, 0.846, 0.846, 0.846, 0.846, 0.846, 0.846, 0.846_
}, {_
0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,_
0.000, 0.000, 0.000, 0.000, 0.000, 0.106, 0.106, 0.106,_
0.106, 0.106, 0.106, 0.106, 0.106, 0.106, 0.106, 0.106,_
0.106, 0.106, 0.106, 0.106, 0.106, 0.106, 0.106, 0.159,_
0.159, 0.159, 0.159, 0.159, 0.212, 0.212, 0.212, 0.212,_
0.212, 0.212, 0.212, 0.212, 0.212, 0.212, 0.212, 0.264,_
0.264, 0.264, 0.264, 0.264, 0.264, 0.264, 0.264, 0.317,_
0.317, 0.317, 0.317, 0.370, 0.423, 0.423, 0.423, 0.423,_
0.423, 0.423, 0.423, 0.423, 0.423, 0.476, 0.476, 0.529,_
0.582, 0.582, 0.582, 0.582, 0.582, 0.582, 0.582, 0.635,_
0.635, 0.688, 0.688, 0.741, 0.846, 0.846, 0.846, 0.846,_
0.846, 0.846, 0.846, 0.899, 0.899, 1.005, 1.005, 1.058,_
1.164, 1.164, 1.164, 1.164, 1.164, 1.164, 1.164, 1.164,_
1.164, 1.164, 1.164, 1.164, 1.164, 1.164, 1.164, 1.164,_
1.164, 1.164, 1.164, 1.164, 1.164, 1.164, 1.164, 1.164,_
1.164, 1.164, 1.164, 1.164, 1.164, 1.164, 1.164, 1.164_
}}
dim shared as unsigned long ams_table(3) = {_
0,_
128 - 128 * 10^(-1.44 / 10),_
128 - 128 * 10^(-5.9 / 10),_
128 - 128 * 10^(-11.8 / 10)_
}
sub fm_operator.set_freq_rate(freq as single, rate as single)
freq += DT
freq *= ML
swg.set_cycle(rate / freq)
eg.set_rate(rate)
end sub
function fm_operator.get_next() as integer
return cast(long,swg.get_next()) * eg.get_next() shr 15
end function
function fm_operator.get_next(modulate as integer) as integer
return cast(long,swg.get_next(modulate)) * eg.get_next() shr 15
end function
function fm_operator.get_next(ams as integer, modulate as integer) as integer
return (cast(long,swg.get_next(modulate)) * eg.get_next() shr 15) * (ams * ams_factor + ams_bias) shr 15
end function
sub fm_sound_generator.set_rate(rate as single)
if this.rate <> rate then
this.rate = rate
ams_lfo.set_cycle(rate / ams_freq)
vibrato_lfo.set_cycle(rate / vibrato_freq)
tremolo_lfo.set_cycle(rate / tremolo_freq)
dim as single f = freq * freq_mul
op1.set_freq_rate(f, rate)
op2.set_freq_rate(f, rate)
op3.set_freq_rate(f, rate)
op4.set_freq_rate(f, rate)
end if
end sub
sub fm_sound_generator.set_frequency_multiplier(value as single)
freq_mul = value
dim as single f = freq * freq_mul
op1.set_freq_rate(f, rate)
op2.set_freq_rate(f, rate)
op3.set_freq_rate(f, rate)
op4.set_freq_rate(f, rate)
end sub
sub fm_sound_generator.set_damper(damper as integer)
this.damper = damper
dim as single value = 1.0 - (1.0 - damper / 127.0) * (1.0 - sostenute / 127.0)
op1.eg.set_hold(value)
op2.eg.set_hold(value)
op3.eg.set_hold(value)
op4.eg.set_hold(value)
end sub
sub fm_sound_generator.set_sostenute(sostenute as integer)
this.sostenute = sostenute
dim as single value = 1.0 - (1.0 - damper / 127.0) * (1.0 - sostenute / 127.0)
op1.eg.set_hold(value)
op2.eg.set_hold(value)
op3.eg.set_hold(value)
op4.eg.set_hold(value)
end sub
sub fm_sound_generator.set_freeze(freeze as integer)
dim as single value = freeze / 127.0
op1.eg.set_freeze(value)
op2.eg.set_freeze(value)
op3.eg.set_freeze(value)
op4.eg.set_freeze(value)
end sub
sub fm_sound_generator.set_tremolo(depth as integer, frequency as single)
tremolo_depth = depth
tremolo_freq = frequency
tremolo_lfo.set_cycle(rate / frequency)
end sub
sub fm_sound_generator.set_vibrato(depth as single, frequency as single)
vibrato_depth = depth * (16384 / 256.0)
vibrato_freq = frequency
vibrato_lfo.set_cycle(rate / frequency)
end sub
sub fm_sound_generator.key_off()
op1.eg.key_off()
op2.eg.key_off()
op3.eg.key_off()
op4.eg.key_off()
end sub
sub fm_sound_generator.sound_off()
op1.eg.sound_off()
op2.eg.sound_off()
op3.eg.sound_off()
op4.eg.sound_off()
end sub
function fm_sound_generator.is_finished() as integer
select case ALG
case 0 to 3
return op4.eg.state=FINISHED
case 4
return op2.eg.state=FINISHED andalso op4.eg.state=FINISHED
case 5,6
return op2.eg.state=FINISHED andalso op3.eg.state=FINISHED andalso op4.eg.state=FINISHED
case 7
return op1.eg.state=FINISHED andalso op2.eg.state=FINISHED andalso op3.eg.state=FINISHED andalso op4.eg.state=FINISHED
case else
return -1
end select
end function
function fm_sound_generator.get_next() as integer
if vibrato_depth<>0 then
dim as integer x = cast(long,vibrato_lfo.get_next()) * vibrato_depth shr 15
dim as long modulation = vibrato_table(x+16384/2)
op1.swg.add_modulation(modulation)
op2.swg.add_modulation(modulation)
op3.swg.add_modulation(modulation)
op4.swg.add_modulation(modulation)
end if
dim as integer feedback = (this.feedback shl 1) shr FB
dim as integer ret
if ams_enable then
dim as integer ams = ams_lfo.get_next() shr 7
select case ALG
case 0
this.feedback = op1.get_next(ams, feedback)
ret = op4.get_next(ams, op3.get_next(ams, op2.get_next(ams, this.feedback)))
case 1
this.feedback = op1.get_next(ams, feedback)
ret = op4.get_next(ams, op3.get_next(ams, op2.get_next(ams, 0) + this.feedback))
case 2
this.feedback = op1.get_next(ams, feedback)
ret = op4.get_next(ams, op3.get_next(ams, op2.get_next(ams, 0)) + this.feedback)
case 3
this.feedback = op1.get_next(ams, feedback)
ret = op4.get_next(ams, op3.get_next(ams, 0) + op2.get_next(ams, this.feedback))
case 4
this.feedback = op1.get_next(ams, feedback)
ret = op4.get_next(ams, op3.get_next(ams, 0)) + op2.get_next(ams, this.feedback)
case 5
feedback = op1.get_next(ams, feedback)
this.feedback = feedback
ret = op4.get_next(ams, feedback) + op3.get_next(ams, feedback) + op2.get_next(ams, feedback)
case 6:
this.feedback = op1.get_next(ams, feedback)
ret = op4.get_next(ams, 0) + op3.get_next(ams, 0) + op2.get_next(ams, this.feedback)
case 7
this.feedback = op1.get_next(ams, feedback)
ret = op4.get_next(ams, 0) + op3.get_next(ams, 0) + op2.get_next(ams, 0) + this.feedback
case else
return 0
end select
else
select case ALG
case 0
this.feedback = op1.get_next(feedback)
ret = op4.get_next(op3.get_next(op2.get_next(this.feedback)))
case 1
this.feedback = op1.get_next(feedback)
ret = op4.get_next(op3.get_next(op2.get_next() + this.feedback))
case 2
this.feedback = op1.get_next(feedback)
ret = op4.get_next(op3.get_next(op2.get_next()) + this.feedback)
case 3:
this.feedback = op1.get_next(feedback)
ret = op4.get_next(op3.get_next() + op2.get_next(this.feedback))
case 4
this.feedback = op1.get_next(feedback)
ret = op4.get_next(op3.get_next()) + op2.get_next(this.feedback)
case 5
feedback = op1.get_next(feedback)
this.feedback = feedback
ret = op4.get_next(feedback) + op3.get_next(feedback) + op2.get_next(feedback)
case 6
this.feedback = op1.get_next(feedback)
ret = op4.get_next() + op3.get_next() + op2.get_next(this.feedback)
case 7
this.feedback = op1.get_next(feedback)
ret = op4.get_next() + op3.get_next() + op2.get_next() + this.feedback
case else
return 0
end select
end if
if tremolo_depth then
dim as long x = 4096 - (((cast(long,tremolo_lfo.get_next()) + 32768) * tremolo_depth) shr 11)
ret = ret * x shr 12
end if
return ret
end function
function fm_note.synthesize(buf as long ptr, samples as uinteger, rate as single, _left as long, _right as long) as integer
_left = (_left * velocity) shr 7
_right = (_right * velocity) shr 7
fm.set_rate(rate)
for i as uinteger = 0 to samples
dim as long sample = fm.get_next()
buf[i * 2 + 0] += (sample * _left) shr 14
buf[i * 2 + 1] += (sample * _right) shr 14
next
return not fm.is_finished()
end function
sub fm_note_factory.clear_
static as FMPARAMETER param = (_
7, 0, 0,_ ' ALG FB LFO
_'AR DR SR RR SL TL KS ML DT AMS
( 31, 0, 0,15, 0, 0, 0, 0, 0, 0 ),_
( 0, 0, 0,15, 0,127, 0, 0, 0, 0 ),_
( 0, 0, 0,15, 0,127, 0, 0, 0, 0 ),_
( 0, 0, 0,15, 0,127, 0, 0, 0, 0 ))
erase drums
erase programs
programs(128) = @param
end sub
function fm_note_factory.note_on(program as long, note as integer, velocity as integer, frequency_multiplier as single) as fm_note ptr
dim as integer drum = (program shr 14) = 120
dim as fm_note ptr new_note= new fm_note
dim as integer feedbacks(7) = {31, 6, 5, 4, 3, 2, 1, 0}
dim as single _ams_table(7) = {3.98, 5.56, 6.02, 6.37, 6.88, 9.63, 48.1, 72.2}
if drum then
dim as DRUMPARAMETER ptr p=drums(note)
new_note->assign=p->assign
new_note->panpot=p->panpot
new_note->velocity=velocity
new_note->fm.freq_mul=1
new_note->fm.freq=440 * 2.0^ ((p->key - 69) / 12.0)
new_note->fm.tremolo_freq=1
new_note->fm.vibrato_freq=1
new_note->fm.ALG=p->ALG
new_note->fm.FB = feedbacks(p->FB)
new_note->fm.ams_freq = _ams_table(p->LFO)
new_note->fm.ams_enable = (p->op1.AMS + p->op2.AMS + p->op3.AMS + p->op4.AMS) <> 0
if p->op1.DT >= 4 then
new_note->fm.OP1.DT = -detune_table(p->op1.DT - 4,p->key)
else
new_note->fm.OP1.DT = detune_table(p->op1.DT,p->key)
end if
if p->op1.ML = 0 then
new_note->fm.OP1.ML = 0.5
else
new_note->fm.OP1.ML = p->op1.ML
end if
new_note->fm.OP1.ams_factor = ams_table(p->OP1.AMS) / 2
new_note->fm.OP1.ams_bias = 32768 - new_note->fm.OP1.ams_factor * 256
new_note->fm.OP1.eg.state=ATTACK
new_note->fm.OP1.eg.rate=1
new_note->fm.OP1.eg.AR=p->OP1.AR * 2 + keyscale_table(p->OP1.KS,p->key)
new_note->fm.OP1.eg.DR=p->OP1.DR * 2 + keyscale_table(p->OP1.KS,p->key)
new_note->fm.OP1.eg.SR=p->OP1.SR * 2 + keyscale_table(p->OP1.KS,p->key)
new_note->fm.OP1.eg.RR=p->OP1.RR * 4 + keyscale_table(p->OP1.KS,p->key) + 2
new_note->fm.OP1.eg.TL=p->OP1.TL
new_note->fm.OP1.eg.fTL = envelope_table.TL(p->OP1.TL)
if new_note->fm.OP1.eg.AR > 63 then new_note->fm.OP1.eg.AR = 63
if new_note->fm.OP1.eg.DR > 63 then new_note->fm.OP1.eg.DR = 63
if new_note->fm.OP1.eg.SR > 63 then new_note->fm.OP1.eg.SR = 63
if new_note->fm.OP1.eg.RR > 63 then new_note->fm.OP1.eg.RR = 63
new_note->fm.OP1.eg.fSL = envelope_table.SL(p->OP1.SL,p->OP1.TL)
new_note->fm.OP1.eg.fSS = envelope_table.SL(p->OP1.SL,p->OP1.TL)
if p->op2.DT >= 4 then
new_note->fm.OP2.DT = -detune_table(p->op2.DT - 4,p->key)
else
new_note->fm.OP2.DT = detune_table(p->op2.DT,p->key)
end if
if p->op2.ML = 0 then
new_note->fm.OP2.ML = 0.5
else
new_note->fm.OP2.ML = p->op2.ML
end if
new_note->fm.OP2.ams_factor = ams_table(p->OP2.AMS) / 2
new_note->fm.OP2.ams_bias = 32768 - new_note->fm.OP2.ams_factor * 256
new_note->fm.OP2.eg.state=ATTACK
new_note->fm.OP2.eg.rate=1
new_note->fm.OP2.eg.AR=p->OP2.AR * 2 + keyscale_table(p->OP2.KS,p->key)
new_note->fm.OP2.eg.DR=p->OP2.DR * 2 + keyscale_table(p->OP2.KS,p->key)
new_note->fm.OP2.eg.SR=p->OP2.SR * 2 + keyscale_table(p->OP2.KS,p->key)
new_note->fm.OP2.eg.RR=p->OP2.RR * 4 + keyscale_table(p->OP2.KS,p->key) + 2
new_note->fm.OP2.eg.TL=p->OP2.TL
new_note->fm.OP2.eg.fTL = envelope_table.TL(p->OP2.TL)
if new_note->fm.OP2.eg.AR > 63 then new_note->fm.OP2.eg.AR = 63
if new_note->fm.OP2.eg.DR > 63 then new_note->fm.OP2.eg.DR = 63
if new_note->fm.OP2.eg.SR > 63 then new_note->fm.OP2.eg.SR = 63
if new_note->fm.OP2.eg.RR > 63 then new_note->fm.OP2.eg.RR = 63
new_note->fm.OP2.eg.fSL = envelope_table.SL(p->OP2.SL,p->OP2.TL)
new_note->fm.OP2.eg.fSS = envelope_table.SL(p->OP2.SL,p->OP2.TL)
if p->op3.DT >= 4 then
new_note->fm.OP3.DT = -detune_table(p->op3.DT - 4,p->key)
else
new_note->fm.OP3.DT = detune_table(p->op3.DT,p->key)
end if
if p->op3.ML = 0 then
new_note->fm.OP3.ML = 0.5
else
new_note->fm.OP3.ML = p->op3.ML
end if
new_note->fm.OP3.ams_factor = ams_table(p->OP3.AMS) / 2
new_note->fm.OP3.ams_bias = 32768 - new_note->fm.OP3.ams_factor * 256
new_note->fm.OP3.eg.state=ATTACK
new_note->fm.OP3.eg.rate=1
new_note->fm.OP3.eg.AR=p->OP3.AR * 2 + keyscale_table(p->OP3.KS,p->key)
new_note->fm.OP3.eg.DR=p->OP3.DR * 2 + keyscale_table(p->OP3.KS,p->key)
new_note->fm.OP3.eg.SR=p->OP3.SR * 2 + keyscale_table(p->OP3.KS,p->key)
new_note->fm.OP3.eg.RR=p->OP3.RR * 4 + keyscale_table(p->OP3.KS,p->key) + 2
new_note->fm.OP3.eg.TL=p->OP3.TL
new_note->fm.OP3.eg.fTL = envelope_table.TL(p->OP3.TL)
if new_note->fm.OP3.eg.AR > 63 then new_note->fm.OP3.eg.AR = 63
if new_note->fm.OP3.eg.DR > 63 then new_note->fm.OP3.eg.DR = 63
if new_note->fm.OP3.eg.SR > 63 then new_note->fm.OP3.eg.SR = 63
if new_note->fm.OP3.eg.RR > 63 then new_note->fm.OP3.eg.RR = 63
new_note->fm.OP3.eg.fSL = envelope_table.SL(p->OP3.SL,p->OP3.TL)
new_note->fm.OP3.eg.fSS = envelope_table.SL(p->OP3.SL,p->OP3.TL)
if p->op4.DT >= 4 then
new_note->fm.OP4.DT = -detune_table(p->op4.DT - 4,p->key)
else
new_note->fm.OP4.DT = detune_table(p->op4.DT,p->key)
end if
if p->op4.ML = 0 then
new_note->fm.OP4.ML = 0.5
else
new_note->fm.OP4.ML = p->op4.ML
end if
new_note->fm.OP4.ams_factor = ams_table(p->OP4.AMS) / 2
new_note->fm.OP4.ams_bias = 32768 - new_note->fm.OP4.ams_factor * 256
new_note->fm.OP4.eg.state=ATTACK
new_note->fm.OP4.eg.rate=1
new_note->fm.OP4.eg.AR=p->OP4.AR * 2 + keyscale_table(p->OP4.KS,p->key)
new_note->fm.OP4.eg.DR=p->OP4.DR * 2 + keyscale_table(p->OP4.KS,p->key)
new_note->fm.OP4.eg.SR=p->OP4.SR * 2 + keyscale_table(p->OP4.KS,p->key)
new_note->fm.OP4.eg.RR=p->OP4.RR * 4 + keyscale_table(p->OP4.KS,p->key) + 2
new_note->fm.OP4.eg.TL=p->OP4.TL
new_note->fm.OP4.eg.fTL = envelope_table.TL(p->OP4.TL)
if new_note->fm.OP4.eg.AR > 63 then new_note->fm.OP4.eg.AR = 63
if new_note->fm.OP4.eg.DR > 63 then new_note->fm.OP4.eg.DR = 63
if new_note->fm.OP4.eg.SR > 63 then new_note->fm.OP4.eg.SR = 63
if new_note->fm.OP4.eg.RR > 63 then new_note->fm.OP4.eg.RR = 63
new_note->fm.OP4.eg.fSL = envelope_table.SL(p->OP4.SL,p->OP4.TL)
new_note->fm.OP4.eg.fSS = envelope_table.SL(p->OP4.SL,p->OP4.TL)
return new_note
else
dim as FMPARAMETER ptr p=programs(program)
new_note->assign=0
new_note->panpot=8192
new_note->velocity=velocity
new_note->fm.freq_mul=frequency_multiplier
new_note->fm.freq=440 * 2.0^ ((note - 69) / 12.0)
new_note->fm.tremolo_freq=1
new_note->fm.vibrato_freq=1
new_note->fm.ALG=p->ALG
new_note->fm.FB = feedbacks(p->FB)
new_note->fm.ams_freq = _ams_table(p->LFO)
new_note->fm.ams_enable = (p->op1.AMS + p->op2.AMS + p->op3.AMS + p->op4.AMS) <> 0
if p->op1.DT >= 4 then
new_note->fm.OP1.DT = -detune_table(p->op1.DT - 4,note)
else
new_note->fm.OP1.DT = detune_table(p->op1.DT,note)
end if
if p->op1.ML = 0 then
new_note->fm.OP1.ML = 0.5
else
new_note->fm.OP1.ML = p->op1.ML
end if
new_note->fm.OP1.ams_factor = ams_table(p->OP1.AMS) / 2
new_note->fm.OP1.ams_bias = 32768 - new_note->fm.OP1.ams_factor * 256
new_note->fm.OP1.eg.state=ATTACK
new_note->fm.OP1.eg.rate=1
new_note->fm.OP1.eg.AR=p->OP1.AR * 2 + keyscale_table(p->OP1.KS,note)
new_note->fm.OP1.eg.DR=p->OP1.DR * 2 + keyscale_table(p->OP1.KS,note)
new_note->fm.OP1.eg.SR=p->OP1.SR * 2 + keyscale_table(p->OP1.KS,note)
new_note->fm.OP1.eg.RR=p->OP1.RR * 4 + keyscale_table(p->OP1.KS,note) + 2
new_note->fm.OP1.eg.TL=p->OP1.TL
new_note->fm.OP1.eg.fTL = envelope_table.TL(p->OP1.TL)
if new_note->fm.OP1.eg.AR > 63 then new_note->fm.OP1.eg.AR = 63
if new_note->fm.OP1.eg.DR > 63 then new_note->fm.OP1.eg.DR = 63
if new_note->fm.OP1.eg.SR > 63 then new_note->fm.OP1.eg.SR = 63
if new_note->fm.OP1.eg.RR > 63 then new_note->fm.OP1.eg.RR = 63
new_note->fm.OP1.eg.fSL = envelope_table.SL(p->OP1.SL,p->OP1.TL)
new_note->fm.OP1.eg.fSS = envelope_table.SL(p->OP1.SL,p->OP1.TL)
if p->op2.DT >= 4 then
new_note->fm.OP2.DT = -detune_table(p->op2.DT - 4,note)
else
new_note->fm.OP2.DT = detune_table(p->op2.DT,note)
end if
if p->op2.ML = 0 then
new_note->fm.OP2.ML = 0.5
else
new_note->fm.OP2.ML = p->op2.ML
end if
new_note->fm.OP2.ams_factor = ams_table(p->OP2.AMS) / 2
new_note->fm.OP2.ams_bias = 32768 - new_note->fm.OP2.ams_factor * 256
new_note->fm.OP2.eg.state=ATTACK
new_note->fm.OP2.eg.rate=1
new_note->fm.OP2.eg.AR=p->OP2.AR * 2 + keyscale_table(p->OP2.KS,note)
new_note->fm.OP2.eg.DR=p->OP2.DR * 2 + keyscale_table(p->OP2.KS,note)
new_note->fm.OP2.eg.SR=p->OP2.SR * 2 + keyscale_table(p->OP2.KS,note)
new_note->fm.OP2.eg.RR=p->OP2.RR * 4 + keyscale_table(p->OP2.KS,note) + 2
new_note->fm.OP2.eg.TL=p->OP2.TL
new_note->fm.OP2.eg.fTL = envelope_table.TL(p->OP2.TL)
if new_note->fm.OP2.eg.AR > 63 then new_note->fm.OP2.eg.AR = 63
if new_note->fm.OP2.eg.DR > 63 then new_note->fm.OP2.eg.DR = 63
if new_note->fm.OP2.eg.SR > 63 then new_note->fm.OP2.eg.SR = 63
if new_note->fm.OP2.eg.RR > 63 then new_note->fm.OP2.eg.RR = 63
new_note->fm.OP2.eg.fSL = envelope_table.SL(p->OP2.SL,p->OP2.TL)
new_note->fm.OP2.eg.fSS = envelope_table.SL(p->OP2.SL,p->OP2.TL)
if p->op3.DT >= 4 then
new_note->fm.OP3.DT = -detune_table(p->op3.DT - 4,note)
else
new_note->fm.OP3.DT = detune_table(p->op3.DT,note)
end if
if p->op3.ML = 0 then
new_note->fm.OP3.ML = 0.5
else
new_note->fm.OP3.ML = p->op3.ML
end if
new_note->fm.OP3.ams_factor = ams_table(p->OP3.AMS) / 2
new_note->fm.OP3.ams_bias = 32768 - new_note->fm.OP3.ams_factor * 256
new_note->fm.OP3.eg.state=ATTACK
new_note->fm.OP3.eg.rate=1
new_note->fm.OP3.eg.AR=p->OP3.AR * 2 + keyscale_table(p->OP3.KS,note)
new_note->fm.OP3.eg.DR=p->OP3.DR * 2 + keyscale_table(p->OP3.KS,note)
new_note->fm.OP3.eg.SR=p->OP3.SR * 2 + keyscale_table(p->OP3.KS,note)
new_note->fm.OP3.eg.RR=p->OP3.RR * 4 + keyscale_table(p->OP3.KS,note) + 2
new_note->fm.OP3.eg.TL=p->OP3.TL
new_note->fm.OP3.eg.fTL = envelope_table.TL(p->OP3.TL)
if new_note->fm.OP3.eg.AR > 63 then new_note->fm.OP3.eg.AR = 63
if new_note->fm.OP3.eg.DR > 63 then new_note->fm.OP3.eg.DR = 63
if new_note->fm.OP3.eg.SR > 63 then new_note->fm.OP3.eg.SR = 63
if new_note->fm.OP3.eg.RR > 63 then new_note->fm.OP3.eg.RR = 63
new_note->fm.OP3.eg.fSL = envelope_table.SL(p->OP3.SL,p->OP3.TL)
new_note->fm.OP3.eg.fSS = envelope_table.SL(p->OP3.SL,p->OP3.TL)
if p->op4.DT >= 4 then
new_note->fm.OP4.DT = -detune_table(p->op4.DT - 4,note)
else
new_note->fm.OP4.DT = detune_table(p->op4.DT,note)
end if
if p->op4.ML = 0 then
new_note->fm.OP4.ML = 0.5
else
new_note->fm.OP4.ML = p->op4.ML
end if
new_note->fm.OP4.ams_factor = ams_table(p->OP4.AMS) / 2
new_note->fm.OP4.ams_bias = 32768 - new_note->fm.OP4.ams_factor * 256
new_note->fm.OP4.eg.state=ATTACK
new_note->fm.OP4.eg.rate=1
new_note->fm.OP4.eg.AR=p->OP4.AR * 2 + keyscale_table(p->OP4.KS,note)
new_note->fm.OP4.eg.DR=p->OP4.DR * 2 + keyscale_table(p->OP4.KS,note)
new_note->fm.OP4.eg.SR=p->OP4.SR * 2 + keyscale_table(p->OP4.KS,note)
new_note->fm.OP4.eg.RR=p->OP4.RR * 4 + keyscale_table(p->OP4.KS,note) + 2
new_note->fm.OP4.eg.TL=p->OP4.TL
new_note->fm.OP4.eg.fTL = envelope_table.TL(p->OP4.TL)
if new_note->fm.OP4.eg.AR > 63 then new_note->fm.OP4.eg.AR = 63
if new_note->fm.OP4.eg.DR > 63 then new_note->fm.OP4.eg.DR = 63
if new_note->fm.OP4.eg.SR > 63 then new_note->fm.OP4.eg.SR = 63
if new_note->fm.OP4.eg.RR > 63 then new_note->fm.OP4.eg.RR = 63
new_note->fm.OP4.eg.fSL = envelope_table.SL(p->OP4.SL,p->OP4.TL)
new_note->fm.OP4.eg.fSS = envelope_table.SL(p->OP4.SL,p->OP4.TL)
return new_note
end if
end function
Last edited by angros47 on Dec 20, 2013 10:41, edited 1 time in total.
Re: Cross-platform MIDI in pure FreeBasic!
Here are the included files:
instruments.bi
midisynth.bi
instruments.bi
Code: Select all
dim shared as FMPARAMETER programs(128) = {_
( 4, 3, 0,_
( 26, 10, 1, 0, 0, 2, 0, 1, 3, 0),_
( 26, 10, 2, 7, 2, 0, 0, 2, 3, 0),_
( 26, 10, 2, 0, 0, 4, 0, 1, 7, 0),_
( 18, 6, 1, 6, 4, 2, 1, 1, 7, 0)_
),_
( 4, 5, 0,_
( 26, 10, 1, 0, 0, 5, 0, 2, 3, 0),_
( 26, 10, 3, 7, 1, 0, 0, 2, 3, 0),_
( 26, 10, 2, 0, 0, 20, 0, 1, 7, 0),_
( 18, 6, 2, 6, 4, 2, 0, 1, 7, 0)_
),_
( 4, 5, 0,_
( 26, 10, 1, 0, 0, 2, 0, 2, 3, 0),_
( 26, 10, 2, 7, 2, 0, 0, 1, 3, 0),_
( 26, 10, 2, 0, 0, 4, 0, 1, 7, 0),_
( 18, 6, 1, 6, 4, 2, 1, 1, 7, 0)_
),_
( 5, 7, 0,_
( 26, 10, 1, 0, 0, 10, 3, 6, 0, 0),_
( 26, 10, 4, 7, 1, 1, 0, 1, 7, 0),_
( 15, 20, 5, 8, 1, 2, 1, 2, 0, 0),_
( 8, 15, 3, 11, 2, 3, 3, 3, 3, 0)_
),_
( 4, 3, 0,_
( 28, 10, 0, 0, 0, 2, 0, 2, 0, 0),_
( 31, 16, 0, 12, 1, 0, 0, 1, 0, 0),_
( 28, 10, 0, 0, 0, 20, 0, 1, 0, 0),_
( 22, 9, 0, 10, 4, 2, 0, 2, 0, 0)_
),_
( 6, 4, 0,_
( 31, 12, 0, 0, 0, 0, 0, 1, 3, 0),_
( 29, 12, 1, 7, 1, 1, 0, 1, 0, 0),_
( 26, 12, 2, 6, 2, 4, 0, 2, 3, 0),_
( 26, 12, 2, 6, 2, 5, 0, 0, 7, 0)_
),_
( 2, 4, 0,_
( 28, 16, 1, 0, 0, 2, 0, 2, 7, 0),_
( 28, 16, 2, 8, 1, 0, 0, 1, 3, 0),_
( 28, 14, 2, 8, 0, 4, 0, 3, 3, 0),_
( 28, 12, 1, 7, 2, 0, 1, 1, 0, 0)_
),_
( 2, 4, 0,_
( 28, 16, 1, 0, 0, 2, 0, 2, 7, 0),_
( 28, 16, 2, 7, 1, 4, 0, 1, 3, 0),_
( 28, 14, 2, 7, 0, 4, 0, 4, 3, 0),_
( 28, 14, 1, 7, 2, 0, 1, 1, 0, 0)_
),_
( 7, 6, 0,_
( 31, 18, 9, 6, 1, 1, 0, 4, 0, 0),_
( 28, 14, 8, 5, 3, 2, 0, 2, 3, 0),_
( 28, 14, 9, 6, 1, 0, 0, 1, 0, 0),_
( 28, 14, 10, 6, 2, 2, 0, 0, 7, 0)_
),_
( 7, 6, 0,_
( 31, 26, 21, 10, 2, 2, 0, 7, 0, 0),_
( 20, 0, 11, 5, 0, 7, 0, 4, 1, 0),_
( 31, 0, 11, 5, 0, 3, 0, 4, 0, 0),_
( 31, 28, 15, 7, 3, 0, 0, 2, 0, 0)_
),_
( 6, 2, 0,_
( 31, 0, 0, 0, 0, 2, 0, 4, 0, 0),_
( 31, 0, 13, 6, 0, 2, 0, 2, 0, 0),_
( 31, 0, 25, 12, 0, 0, 0, 1, 0, 0),_
( 31, 0, 13, 6, 0, 0, 3, 4, 0, 0)_
),_
( 6, 4, 0,_
( 31, 16, 0, 0, 2, 1, 0, 7, 7, 0),_
( 31, 0, 10, 7, 0, 4, 0, 1, 3, 0),_
( 24, 10, 9, 7, 1, 2, 1, 1, 7, 0),_
( 31, 24, 13, 9, 4, 0, 0, 1, 0, 0)_
),_
( 7, 1, 0,_
( 27, 20, 25, 12, 1, 2, 0, 1, 0, 0),_
( 16, 0, 13, 6, 0, 12, 0, 4, 0, 0),_
( 16, 0, 15, 7, 0, 2, 0, 1, 0, 0),_
( 27, 0, 19, 9, 0, 4, 0, 4, 0, 0)_
),_
( 7, 0, 0,_
( 31, 0, 11, 5, 0, 0, 2, 1, 0, 0),_
( 31, 0, 15, 7, 0, 4, 1, 3, 0, 0),_
( 31, 0, 19, 9, 0, 8, 0, 6, 0, 0),_
( 31, 31, 31, 15, 0, 127, 0, 1, 0, 0)_
),_
( 6, 3, 0,_
( 31, 0, 0, 0, 0, 2, 0, 5, 0, 0),_
( 31, 16, 11, 5, 2, 0, 0, 1, 3, 0),_
( 24, 0, 13, 6, 0, 6, 0, 2, 7, 0),_
( 31, 0, 19, 9, 0, 1, 0, 3, 0, 0)_
),_
( 4, 4, 0,_
( 31, 0, 0, 0, 0, 7, 0, 3, 0, 0),_
( 28, 24, 9, 6, 1, 1, 1, 1, 7, 0),_
( 28, 0, 9, 6, 0, 0, 0, 7, 3, 0),_
( 28, 24, 9, 6, 2, 3, 1, 1, 3, 0)_
),_
( 7, 5, 0,_
( 28, 0, 0, 12, 0, 4, 0, 0, 0, 0),_
( 28, 0, 0, 12, 0, 6, 0, 4, 0, 0),_
( 28, 0, 0, 12, 0, 4, 0, 2, 0, 0),_
( 28, 0, 0, 12, 0, 3, 0, 1, 0, 0)_
),_
( 7, 3, 0,_
( 31, 22, 0, 12, 10, 0, 0, 4, 0, 0),_
( 31, 20, 0, 12, 2, 0, 0, 2, 0, 0),_
( 31, 18, 0, 12, 1, 0, 0, 1, 0, 0),_
( 31, 18, 0, 12, 1, 0, 0, 0, 0, 0)_
),_
( 7, 5, 0,_
( 28, 0, 0, 12, 0, 4, 0, 0, 0, 3),_
( 28, 0, 0, 12, 0, 6, 0, 4, 0, 0),_
( 28, 0, 0, 12, 0, 4, 0, 2, 0, 0),_
( 28, 0, 0, 12, 0, 3, 0, 1, 0, 2)_
),_
( 6, 5, 0,_
( 18, 0, 0, 9, 0, 2, 0, 6, 0, 0),_
( 20, 0, 0, 9, 0, 2, 0, 2, 0, 0),_
( 18, 0, 0, 10, 0, 3, 0, 4, 3, 0),_
( 28, 0, 0, 12, 0, 5, 0, 1, 7, 0)_
),_
( 6, 2, 0,_
( 14, 0, 0, 10, 0, 0, 0, 6, 0, 0),_
( 20, 0, 0, 12, 0, 2, 1, 2, 0, 0),_
( 14, 0, 0, 8, 0, 1, 0, 1, 0, 0),_
( 17, 0, 0, 8, 0, 8, 1, 0, 0, 0)_
),_
( 3, 3, 0,_
( 16, 0, 0, 0, 0, 4, 0, 4, 0, 0),_
( 12, 3, 0, 0, 4, 6, 0, 1, 0, 0),_
( 14, 7, 0, 8, 4, 3, 0, 3, 0, 0),_
( 22, 0, 0, 8, 0, 0, 0, 1, 0, 0)_
),_
( 4, 5, 0,_
( 16, 0, 1, 11, 0, 3, 0, 5, 3, 0),_
( 20, 0, 3, 9, 0, 2, 0, 2, 3, 0),_
( 18, 0, 1, 11, 0, 0, 0, 4, 7, 0),_
( 24, 0, 2, 10, 0, 2, 0, 1, 7, 0)_
),_
( 3, 3, 0,_
( 20, 0, 0, 0, 0, 2, 0, 4, 0, 0),_
( 16, 3, 0, 0, 4, 4, 0, 1, 0, 0),_
( 18, 7, 0, 8, 4, 3, 0, 3, 0, 0),_
( 24, 0, 0, 9, 0, 0, 0, 1, 0, 0)_
),_
( 0, 0, 0,_
( 31, 31, 31, 15, 0, 127, 0, 1, 0, 0),_
( 31, 0, 0, 0, 0, 0, 0, 2, 0, 0),_
( 31, 0, 4, 10, 0, 2, 0, 1, 0, 0),_
( 29, 14, 8, 9, 2, 0, 0, 1, 0, 0)_
),_
( 1, 4, 0,_
( 31, 0, 0, 0, 0, 1, 0, 2, 0, 0),_
( 31, 0, 0, 0, 0, 2, 0, 1, 0, 0),_
( 31, 0, 4, 10, 0, 2, 0, 1, 0, 0),_
( 31, 20, 8, 9, 2, 0, 0, 1, 0, 0)_
),_
( 1, 4, 0,_
( 31, 31, 31, 15, 0, 127, 0, 1, 0, 0),_
( 31, 0, 0, 0, 0, 4, 0, 3, 0, 0),_
( 31, 0, 4, 10, 0, 4, 0, 2, 0, 0),_
( 28, 12, 8, 9, 1, 3, 0, 1, 0, 0)_
),_
( 0, 0, 0,_
( 20, 0, 2, 9, 0, 10, 0, 12, 0, 0),_
( 26, 0, 2, 10, 0, 2, 0, 4, 0, 0),_
( 28, 0, 4, 10, 0, 2, 0, 1, 0, 0),_
( 31, 14, 8, 9, 2, 4, 0, 1, 0, 0)_
),_
( 0, 0, 0,_
( 20, 0, 2, 15, 0, 10, 0, 4, 0, 0),_
( 26, 0, 2, 15, 0, 4, 0, 2, 0, 0),_
( 28, 0, 6, 15, 0, 8, 0, 1, 0, 0),_
( 31, 16, 10, 15, 2, 5, 0, 1, 0, 0)_
),_
( 1, 0, 0,_
( 16, 0, 0, 12, 0, 4, 0, 4, 0, 0),_
( 18, 0, 0, 12, 0, 2, 0, 3, 0, 0),_
( 20, 0, 0, 12, 0, 1, 0, 1, 0, 0),_
( 29, 4, 2, 12, 1, 2, 0, 1, 0, 0)_
),_
( 5, 0, 0,_
( 20, 0, 1, 9, 0, 4, 0, 5, 0, 0),_
( 28, 14, 1, 9, 1, 4, 0, 5, 7, 0),_
( 28, 14, 1, 9, 1, 4, 0, 2, 0, 0),_
( 28, 14, 1, 9, 1, 4, 0, 1, 3, 0)_
),_
( 4, 3, 0,_
( 31, 0, 0, 9, 0, 2, 0, 8, 0, 0),_
( 31, 12, 2, 9, 2, 4, 0, 2, 0, 0),_
( 31, 18, 0, 9, 5, 1, 0, 10, 0, 0),_
( 31, 18, 0, 9, 3, 2, 0, 1, 0, 0)_
),_
( 4, 5, 0,_
( 24, 0, 0, 0, 0, 4, 2, 0, 0, 0),_
( 24, 18, 4, 8, 1, 0, 2, 2, 0, 0),_
( 18, 18, 3, 7, 1, 6, 0, 1, 0, 0),_
( 22, 18, 3, 7, 1, 2, 0, 2, 0, 0)_
),_
( 2, 3, 0,_
( 28, 10, 0, 15, 1, 2, 0, 2, 0, 0),_
( 26, 22, 0, 6, 1, 1, 0, 2, 0, 0),_
( 28, 8, 8, 8, 1, 1, 0, 1, 0, 0),_
( 22, 14, 0, 7, 1, 0, 0, 1, 0, 0)_
),_
( 2, 3, 0,_
( 28, 10, 5, 15, 1, 2, 0, 2, 0, 0),_
( 26, 22, 10, 6, 1, 1, 0, 2, 0, 0),_
( 28, 8, 8, 8, 1, 1, 0, 1, 0, 0),_
( 28, 14, 6, 7, 1, 0, 0, 1, 0, 0)_
),_
( 4, 0, 0,_
( 24, 8, 3, 13, 0, 2, 0, 1, 0, 0),_
( 28, 9, 1, 13, 2, 0, 0, 1, 0, 0),_
( 31, 31, 31, 15, 0, 127, 0, 1, 0, 0),_
( 31, 31, 31, 15, 0, 127, 0, 1, 0, 0)_
),_
( 2, 0, 0,_
( 28, 10, 5, 15, 1, 2, 0, 2, 0, 0),_
( 26, 18, 8, 6, 1, 1, 0, 2, 0, 0),_
( 28, 6, 6, 10, 1, 1, 0, 1, 0, 0),_
( 28, 4, 6, 10, 1, 2, 0, 1, 0, 0)_
),_
( 2, 0, 0,_
( 28, 10, 2, 15, 1, 2, 0, 2, 0, 0),_
( 26, 18, 0, 6, 1, 1, 0, 2, 0, 0),_
( 28, 6, 2, 10, 1, 1, 0, 1, 0, 0),_
( 28, 4, 4, 10, 1, 2, 0, 1, 0, 0)_
),_
( 2, 4, 0,_
( 28, 16, 12, 15, 1, 2, 0, 2, 7, 0),_
( 26, 12, 6, 6, 2, 1, 0, 1, 0, 0),_
( 28, 13, 11, 8, 1, 1, 0, 2, 3, 0),_
( 28, 10, 6, 12, 3, 0, 0, 1, 0, 0)_
),_
( 3, 1, 0,_
( 28, 7, 3, 15, 1, 2, 0, 1, 0, 0),_
( 28, 10, 2, 6, 1, 1, 0, 1, 0, 0),_
( 28, 10, 1, 8, 1, 2, 0, 1, 0, 0),_
( 31, 0, 0, 12, 1, 0, 0, 1, 0, 0)_
),_
( 5, 7, 0,_
( 20, 0, 0, 6, 0, 11, 0, 1, 0, 0),_
( 16, 0, 0, 6, 0, 4, 0, 2, 0, 0),_
( 16, 0, 0, 6, 0, 6, 0, 4, 0, 0),_
( 16, 0, 0, 6, 0, 10, 0, 8, 0, 0)_
),_
( 3, 7, 0,_
( 20, 0, 0, 0, 0, 8, 0, 1, 0, 0),_
( 16, 0, 0, 6, 0, 4, 0, 2, 0, 0),_
( 16, 0, 0, 6, 0, 8, 0, 3, 0, 0),_
( 16, 0, 0, 6, 0, 4, 0, 1, 0, 0)_
),_
( 2, 4, 0,_
( 20, 1, 1, 0, 0, 4, 0, 2, 0, 0),_
( 20, 2, 2, 0, 0, 0, 0, 1, 0, 0),_
( 20, 2, 2, 0, 0, 4, 0, 2, 0, 0),_
( 20, 1, 1, 1, 7, 0, 3, 1, 0, 0)_
),_
( 2, 5, 0,_
( 31, 1, 1, 0, 0, 4, 0, 3, 0, 0),_
( 31, 1, 1, 0, 0, 4, 0, 2, 0, 0),_
( 31, 1, 1, 0, 0, 3, 0, 2, 0, 0),_
( 20, 1, 1, 7, 0, 4, 1, 1, 0, 0)_
),_
( 3, 4, 1,_
( 31, 0, 0, 0, 0, 5, 0, 5, 0, 1),_
( 31, 0, 0, 0, 0, 4, 0, 2, 0, 0),_
( 20, 10, 0, 0, 0, 6, 0, 5, 0, 0),_
( 20, 14, 0, 8, 1, 2, 0, 1, 0, 0)_
),_
( 5, 4, 0,_
( 28, 0, 13, 6, 0, 0, 0, 1, 0, 0),_
( 28, 0, 13, 6, 0, 0, 0, 1, 0, 0),_
( 31, 0, 19, 9, 0, 0, 0, 4, 0, 0),_
( 31, 0, 17, 8, 0, 0, 0, 2, 0, 0)_
),_
( 6, 2, 0,_
( 28, 0, 9, 6, 0, 4, 1, 3, 0, 0),_
( 28, 16, 9, 6, 1, 0, 1, 1, 0, 0),_
( 28, 16, 9, 6, 1, 0, 1, 2, 0, 0),_
( 31, 31, 31, 15, 0, 127, 0, 1, 0, 0)_
),_
( 0, 6, 0,_
( 31, 0, 13, 6, 0, 0, 2, 3, 0, 0),_
( 31, 0, 13, 6, 0, 0, 2, 4, 0, 0),_
( 31, 0, 13, 6, 0, 0, 2, 2, 0, 0),_
( 31, 0, 13, 6, 0, 0, 2, 1, 0, 0)_
),_
( 3, 4, 0,_
( 31, 0, 0, 0, 0, 5, 0, 5, 0, 0),_
( 31, 0, 0, 0, 0, 4, 0, 2, 0, 0),_
( 24, 10, 0, 0, 0, 6, 0, 5, 0, 0),_
( 20, 14, 0, 8, 1, 2, 0, 1, 0, 0)_
),_
( 3, 4, 0,_
( 31, 0, 0, 0, 0, 5, 0, 5, 0, 0),_
( 31, 0, 0, 0, 0, 4, 0, 2, 0, 0),_
( 24, 10, 0, 0, 0, 6, 0, 5, 0, 0),_
( 12, 0, 0, 6, 0, 4, 0, 1, 0, 0)_
),_
( 3, 4, 0,_
( 14, 0, 0, 0, 0, 1, 0, 5, 3, 0),_
( 14, 0, 0, 0, 0, 4, 0, 2, 0, 0),_
( 14, 10, 0, 0, 0, 6, 0, 5, 0, 0),_
( 14, 14, 0, 8, 1, 2, 0, 1, 0, 0)_
),_
( 3, 4, 0,_
( 14, 0, 0, 0, 0, 1, 0, 5, 3, 0),_
( 14, 0, 0, 0, 0, 4, 0, 2, 0, 0),_
( 14, 10, 0, 0, 0, 6, 0, 5, 0, 0),_
( 12, 0, 0, 6, 0, 2, 0, 1, 0, 0)_
),_
( 7, 5, 0,_
( 16, 0, 0, 8, 0, 4, 0, 2, 7, 0),_
( 16, 0, 0, 8, 0, 0, 0, 1, 7, 0),_
( 18, 0, 0, 9, 0, 2, 0, 2, 3, 0),_
( 18, 0, 0, 9, 0, 3, 0, 1, 3, 0)_
),_
( 7, 4, 0,_
( 24, 0, 0, 8, 0, 0, 0, 1, 3, 0),_
( 24, 0, 0, 8, 0, 2, 0, 1, 7, 0),_
( 24, 0, 0, 8, 0, 15, 0, 4, 0, 0),_
( 24, 0, 0, 8, 0, 18, 0, 0, 0, 0)_
),_
( 7, 3, 0,_
( 17, 0, 0, 7, 0, 0, 0, 1, 3, 0),_
( 17, 0, 0, 7, 0, 0, 0, 1, 7, 0),_
( 17, 0, 0, 7, 0, 8, 0, 2, 0, 0),_
( 17, 0, 0, 7, 0, 14, 0, 4, 0, 0)_
),_
( 5, 5, 0,_
( 16, 0, 13, 6, 0, 0, 0, 1, 0, 0),_
( 18, 0, 13, 6, 0, 0, 0, 0, 0, 0),_
( 20, 0, 13, 6, 0, 0, 0, 1, 0, 0),_
( 16, 0, 13, 6, 0, 0, 0, 2, 0, 0)_
),_
( 4, 4, 0,_
( 22, 0, 0, 0, 0, 1, 0, 1, 0, 0),_
( 22, 0, 0, 8, 0, 0, 0, 1, 0, 0),_
( 22, 0, 0, 0, 0, 8, 0, 1, 0, 0),_
( 22, 0, 0, 8, 0, 0, 0, 1, 0, 0)_
),_
( 4, 4, 0,_
( 17, 0, 0, 8, 0, 1, 0, 1, 0, 0),_
( 17, 0, 0, 8, 0, 0, 0, 1, 0, 0),_
( 20, 0, 0, 8, 1, 4, 0, 1, 0, 0),_
( 20, 0, 0, 8, 1, 12, 0, 1, 0, 0)_
),_
( 4, 3, 0,_
( 17, 0, 0, 8, 0, 1, 0, 1, 0, 0),_
( 17, 0, 0, 8, 0, 0, 0, 1, 0, 0),_
( 20, 0, 0, 8, 1, 4, 0, 1, 0, 0),_
( 20, 0, 0, 8, 1, 12, 0, 1, 0, 0)_
),_
( 3, 3, 0,_
( 31, 0, 0, 0, 0, 0, 0, 1, 0, 0),_
( 31, 0, 0, 0, 0, 0, 0, 1, 0, 0),_
( 31, 0, 0, 0, 0, 6, 0, 4, 0, 0),_
( 18, 0, 0, 9, 0, 0, 0, 1, 0, 0)_
),_
( 4, 2, 0,_
( 17, 0, 0, 8, 0, 1, 0, 1, 0, 0),_
( 17, 0, 0, 8, 0, 0, 0, 1, 0, 0),_
( 20, 0, 0, 8, 1, 4, 0, 1, 0, 0),_
( 20, 0, 0, 8, 1, 12, 0, 1, 0, 0)_
),_
( 4, 5, 0,_
( 17, 9, 0, 9, 1, 0, 0, 1, 0, 0),_
( 17, 0, 0, 9, 0, 0, 0, 1, 0, 0),_
( 17, 0, 0, 9, 0, 0, 0, 2, 0, 0),_
( 17, 0, 0, 9, 0, 4, 0, 1, 0, 0)_
),_
( 4, 5, 0,_
( 17, 0, 0, 9, 0, 0, 0, 1, 0, 0),_
( 17, 9, 0, 9, 2, 0, 0, 1, 0, 0),_
( 31, 0, 0, 9, 0, 0, 0, 2, 0, 0),_
( 17, 0, 0, 9, 0, 4, 0, 3, 0, 0)_
),_
( 4, 5, 0,_
( 14, 0, 0, 9, 0, 0, 0, 1, 0, 0),_
( 14, 7, 0, 9, 2, 0, 0, 1, 0, 0),_
( 31, 0, 0, 9, 0, 0, 0, 2, 0, 0),_
( 14, 0, 0, 9, 0, 4, 0, 3, 0, 0)_
),_
( 3, 5, 0,_
( 31, 0, 0, 0, 0, 8, 0, 1, 0, 0),_
( 31, 0, 0, 0, 0, 4, 0, 1, 0, 0),_
( 31, 0, 0, 0, 0, 4, 0, 1, 0, 0),_
( 20, 0, 0, 10, 0, 0, 0, 1, 0, 0)_
),_
( 1, 4, 0,_
( 31, 0, 0, 0, 0, 0, 0, 1, 0, 0),_
( 31, 0, 0, 0, 0, 2, 0, 1, 0, 0),_
( 31, 0, 0, 0, 0, 6, 0, 1, 0, 0),_
( 20, 0, 0, 10, 0, 0, 0, 1, 0, 0)_
),_
( 1, 5, 0,_
( 31, 0, 0, 0, 0, 4, 0, 1, 0, 0),_
( 31, 0, 0, 0, 0, 2, 0, 1, 0, 0),_
( 31, 0, 0, 0, 0, 2, 0, 1, 0, 0),_
( 20, 0, 0, 10, 0, 0, 0, 1, 0, 0)_
),_
( 3, 4, 0,_
( 31, 0, 0, 0, 0, 0, 0, 2, 0, 0),_
( 31, 0, 0, 0, 0, 4, 0, 1, 0, 0),_
( 31, 0, 0, 0, 0, 6, 0, 1, 0, 0),_
( 24, 0, 0, 10, 0, 0, 0, 1, 0, 0)_
),_
( 5, 5, 0,_
( 18, 0, 0, 0, 0, 3, 0, 1, 0, 0),_
( 18, 0, 0, 9, 0, 0, 0, 1, 0, 0),_
( 18, 0, 0, 9, 0, 4, 0, 1, 0, 0),_
( 31, 31, 31, 15, 0, 127, 0, 1, 0, 0)_
),_
( 4, 4, 0,_
( 20, 0, 0, 9, 0, 1, 0, 1, 0, 0),_
( 20, 0, 0, 9, 0, 0, 0, 1, 0, 0),_
( 24, 0, 0, 9, 0, 2, 0, 1, 0, 0),_
( 24, 0, 0, 9, 0, 4, 0, 1, 0, 0)_
),_
( 3, 2, 0,_
( 31, 0, 0, 0, 0, 7, 0, 1, 0, 0),_
( 31, 0, 0, 0, 0, 2, 0, 1, 0, 0),_
( 31, 0, 0, 0, 0, 6, 0, 2, 0, 0),_
( 22, 0, 0, 10, 0, 0, 0, 1, 0, 0)_
),_
( 4, 5, 0,_
( 31, 0, 0, 0, 0, 5, 0, 2, 0, 0),_
( 16, 0, 0, 8, 0, 0, 1, 1, 0, 0),_
( 31, 0, 0, 0, 0, 4, 0, 1, 0, 0),_
( 16, 0, 0, 8, 0, 0, 1, 1, 0, 0)_
),_
( 4, 4, 0,_
( 16, 0, 0, 9, 0, 12, 0, 2, 0, 0),_
( 20, 0, 0, 9, 0, 0, 1, 1, 0, 0),_
( 31, 0, 0, 0, 0, 12, 0, 2, 0, 0),_
( 16, 0, 0, 9, 0, 8, 0, 1, 0, 0)_
),_
( 6, 1, 0,_
( 31, 0, 0, 0, 0, 1, 0, 1, 0, 0),_
( 18, 0, 0, 9, 0, 0, 0, 1, 0, 0),_
( 18, 0, 0, 9, 0, 1, 0, 2, 0, 0),_
( 18, 0, 0, 9, 0, 3, 0, 3, 0, 0)_
),_
( 6, 3, 0,_
( 31, 0, 0, 0, 0, 8, 0, 2, 0, 0),_
( 20, 0, 0, 9, 0, 0, 0, 1, 0, 0),_
( 20, 0, 0, 9, 0, 4, 0, 1, 0, 0),_
( 28, 18, 0, 9, 1, 2, 0, 1, 0, 0)_
),_
( 4, 4, 0,_
( 31, 0, 0, 10, 0, 6, 0, 2, 0, 0),_
( 17, 0, 0, 10, 0, 0, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 6, 0, 2, 0, 0),_
( 17, 0, 0, 10, 0, 8, 0, 1, 0, 0)_
),_
( 6, 4, 0,_
( 13, 0, 0, 9, 0, 8, 0, 2, 3, 0),_
( 16, 0, 0, 9, 0, 0, 0, 1, 0, 0),_
( 16, 0, 0, 9, 0, 8, 0, 2, 0, 0),_
( 16, 0, 0, 9, 0, 16, 0, 4, 0, 0)_
),_
( 4, 4, 2,_
( 12, 0, 0, 0, 0, 4, 0, 1, 0, 0),_
( 20, 0, 0, 9, 0, 0, 0, 1, 0, 0),_
( 12, 0, 0, 0, 0, 10, 0, 2, 0, 2),_
( 20, 0, 0, 9, 0, 0, 0, 1, 0, 0)_
),_
( 6, 2, 0,_
( 14, 0, 0, 0, 0, 8, 0, 2, 0, 0),_
( 18, 0, 0, 9, 0, 0, 0, 1, 0, 0),_
( 18, 0, 0, 9, 0, 0, 0, 3, 0, 0),_
( 18, 0, 0, 9, 0, 2, 0, 4, 0, 0)_
),_
( 7, 4, 0,_
( 17, 0, 0, 9, 0, 4, 0, 1, 0, 0),_
( 17, 0, 0, 9, 0, 0, 0, 1, 0, 0),_
( 17, 0, 0, 9, 0, 0, 0, 1, 0, 0),_
( 31, 31, 31, 15, 0, 127, 0, 1, 0, 0)_
),_
( 6, 5, 0,_
( 31, 0, 0, 15, 0, 4, 0, 2, 0, 0),_
( 31, 0, 0, 15, 0, 1, 0, 1, 0, 0),_
( 31, 31, 31, 15, 0, 127, 0, 1, 0, 0),_
( 31, 31, 31, 15, 0, 127, 0, 1, 0, 0)_
),_
( 6, 5, 0,_
( 31, 0, 0, 15, 0, 4, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 1, 0, 1, 0, 0),_
( 31, 31, 31, 15, 0, 127, 0, 1, 0, 0),_
( 31, 31, 31, 15, 0, 127, 0, 1, 0, 0)_
),_
( 4, 2, 0,_
( 2, 0, 0, 10, 0, 0, 0, 1, 0, 0),_
( 20, 16, 0, 10, 1, 0, 0, 1, 0, 0),_
( 20, 0, 0, 10, 0, 1, 0, 2, 0, 0),_
( 20, 16, 0, 10, 1, 0, 0, 1, 0, 0)_
),_
( 3, 7, 0,_
( 16, 0, 14, 11, 0, 5, 0, 1, 0, 0),_
( 31, 0, 0, 0, 0, 0, 0, 1, 0, 0),_
( 31, 31, 31, 15, 0, 127, 0, 1, 0, 0),_
( 28, 0, 0, 11, 0, 0, 0, 1, 0, 0)_
),_
( 5, 4, 0,_
( 16, 16, 1, 9, 1, 0, 0, 4, 0, 0),_
( 28, 14, 1, 9, 1, 2, 0, 4, 0, 0),_
( 28, 14, 1, 9, 1, 2, 0, 2, 0, 0),_
( 28, 14, 1, 9, 1, 2, 0, 1, 0, 0)_
),_
( 7, 5, 0,_
( 16, 0, 0, 8, 0, 4, 0, 2, 7, 0),_
( 16, 0, 0, 8, 0, 0, 0, 1, 7, 0),_
( 18, 0, 0, 9, 0, 2, 0, 2, 3, 0),_
( 18, 0, 0, 9, 0, 3, 0, 1, 3, 0)_
),_
( 4, 5, 0,_
( 26, 4, 0, 9, 1, 1, 0, 3, 0, 0),_
( 26, 4, 0, 9, 1, 1, 0, 3, 0, 0),_
( 26, 4, 0, 9, 1, 1, 0, 1, 0, 0),_
( 26, 4, 0, 9, 1, 1, 0, 1, 0, 0)_
),_
( 5, 5, 0,_
( 28, 16, 0, 10, 1, 0, 0, 1, 0, 0),_
( 28, 16, 0, 10, 1, 0, 0, 1, 0, 0),_
( 28, 16, 0, 10, 1, 0, 0, 1, 0, 0),_
( 28, 16, 0, 10, 1, 0, 0, 1, 0, 0)_
),_
( 7, 4, 1,_
( 18, 0, 4, 5, 0, 0, 0, 1, 0, 2),_
( 18, 0, 4, 5, 0, 1, 1, 2, 1, 0),_
( 18, 0, 4, 6, 0, 2, 2, 4, 2, 0),_
( 18, 0, 4, 6, 0, 6, 3, 8, 3, 0)_
),_
( 6, 3, 0,_
( 31, 0, 0, 0, 0, 4, 0, 1, 0, 1),_
( 10, 0, 0, 7, 0, 0, 0, 1, 0, 0),_
( 10, 0, 0, 7, 0, 0, 0, 1, 0, 0),_
( 31, 31, 31, 15, 0, 127, 0, 1, 0, 0)_
),_
( 5, 5, 0,_
( 31, 14, 0, 10, 1, 0, 0, 2, 0, 0),_
( 24, 10, 0, 6, 1, 0, 0, 1, 1, 0),_
( 26, 14, 0, 9, 1, 2, 0, 2, 0, 0),_
( 28, 14, 0, 9, 1, 4, 0, 4, 0, 0)_
),_
( 7, 2, 4,_
( 16, 0, 0, 6, 0, 2, 0, 2, 7, 0),_
( 16, 0, 0, 7, 0, 0, 0, 1, 7, 0),_
( 18, 0, 0, 6, 0, 2, 0, 2, 3, 0),_
( 18, 0, 0, 7, 0, 3, 0, 1, 3, 3)_
),_
( 7, 4, 0,_
( 12, 8, 0, 6, 1, 1, 0, 1, 0, 0),_
( 15, 8, 0, 6, 1, 4, 0, 1, 1, 0),_
( 16, 0, 0, 6, 0, 8, 0, 3, 0, 0),_
( 16, 0, 0, 6, 0, 24, 0, 6, 0, 0)_
),_
( 6, 6, 0,_
( 31, 0, 0, 0, 0, 6, 0, 1, 0, 0),_
( 11, 6, 4, 7, 1, 0, 0, 1, 0, 0),_
( 31, 31, 31, 15, 0, 127, 0, 1, 0, 0),_
( 31, 31, 31, 15, 0, 127, 0, 1, 0, 0)_
),_
( 7, 4, 2,_
( 20, 0, 0, 7, 0, 2, 0, 2, 7, 0),_
( 20, 0, 0, 7, 0, 0, 0, 1, 7, 0),_
( 20, 0, 0, 8, 0, 0, 0, 2, 3, 3),_
( 20, 0, 0, 8, 0, 0, 0, 1, 3, 0)_
),_
( 6, 4, 0,_
( 31, 0, 0, 0, 0, 4, 0, 1, 0, 0),_
( 12, 0, 0, 6, 0, 0, 0, 1, 1, 0),_
( 12, 0, 0, 6, 0, 3, 0, 2, 0, 0),_
( 12, 0, 0, 6, 0, 6, 0, 3, 2, 0)_
),_
( 4, 4, 5,_
( 31, 0, 0, 0, 0, 4, 0, 1, 0, 0),_
( 26, 16, 4, 6, 1, 0, 0, 2, 0, 0),_
( 31, 0, 0, 0, 0, 0, 0, 7, 0, 0),_
( 26, 16, 5, 6, 0, 16, 0, 1, 0, 3)_
),_
( 5, 4, 0,_
( 31, 11, 0, 0, 1, 2, 0, 3, 2, 1),_
( 16, 0, 0, 6, 0, 4, 0, 1, 0, 0),_
( 16, 0, 0, 6, 0, 4, 0, 3, 0, 0),_
( 16, 0, 0, 6, 0, 8, 0, 6, 0, 0)_
),_
( 6, 2, 0,_
( 24, 0, 7, 5, 0, 8, 0, 4, 0, 0),_
( 24, 0, 7, 5, 0, 0, 0, 1, 0, 0),_
( 31, 31, 31, 15, 0, 127, 0, 1, 0, 0),_
( 31, 31, 31, 15, 0, 127, 0, 1, 0, 0)_
),_
( 3, 2, 0,_
( 31, 0, 0, 0, 0, 8, 0, 3, 0, 0),_
( 28, 16, 0, 6, 1, 6, 0, 1, 0, 0),_
( 28, 16, 0, 6, 1, 6, 0, 3, 0, 0),_
( 28, 16, 0, 6, 1, 0, 0, 1, 0, 0)_
),_
( 5, 4, 5,_
( 31, 0, 8, 5, 0, 8, 0, 4, 1, 0),_
( 28, 0, 8, 6, 0, 0, 0, 1, 0, 0),_
( 28, 0, 8, 6, 0, 0, 0, 2, 0, 2),_
( 28, 0, 8, 6, 0, 4, 0, 3, 0, 0)_
),_
( 7, 2, 0,_
( 10, 0, 0, 6, 0, 0, 0, 1, 0, 0),_
( 10, 0, 1, 6, 0, 0, 0, 1, 0, 0),_
( 10, 0, 2, 6, 0, 8, 0, 2, 0, 0),_
( 10, 0, 2, 6, 0, 12, 0, 3, 0, 0)_
),_
( 4, 3, 1,_
( 22, 0, 0, 0, 0, 7, 0, 3, 0, 1),_
( 22, 0, 0, 6, 0, 0, 0, 1, 0, 0),_
( 22, 0, 0, 0, 0, 0, 0, 2, 0, 1),_
( 22, 0, 0, 6, 0, 0, 0, 1, 0, 0)_
),_
( 4, 6, 2,_
( 22, 0, 0, 0, 0, 6, 0, 1, 0, 0),_
( 22, 0, 0, 6, 0, 0, 0, 1, 0, 0),_
( 22, 0, 0, 0, 0, 0, 0, 3, 0, 1),_
( 22, 0, 0, 6, 0, 8, 0, 1, 0, 0)_
),_
( 5, 4, 0,_
( 22, 0, 0, 0, 0, 0, 0, 3, 0, 0),_
( 22, 0, 6, 6, 0, 0, 0, 1, 0, 0),_
( 22, 0, 6, 6, 0, 3, 0, 2, 0, 0),_
( 31, 31, 31, 15, 0, 127, 0, 1, 0, 0)_
),_
( 7, 5, 0,_
( 24, 0, 7, 7, 0, 0, 0, 1, 0, 0),_
( 28, 14, 14, 15, 0, 0, 0, 1, 0, 0),_
( 31, 31, 31, 15, 0, 127, 0, 1, 0, 0),_
( 31, 31, 31, 15, 0, 127, 0, 1, 0, 0)_
),_
( 3, 0, 0,_
( 31, 0, 0, 0, 0, 1, 0, 2, 0, 0),_
( 31, 0, 0, 0, 0, 0, 0, 1, 0, 0),_
( 31, 0, 17, 8, 0, 0, 0, 1, 0, 0),_
( 24, 0, 10, 7, 0, 0, 0, 1, 0, 0)_
),_
( 3, 0, 0,_
( 31, 0, 0, 0, 0, 2, 0, 2, 0, 0),_
( 31, 0, 0, 0, 0, 0, 0, 1, 0, 0),_
( 31, 0, 17, 8, 0, 0, 0, 1, 0, 0),_
( 24, 0, 11, 5, 0, 0, 0, 1, 0, 0)_
),_
( 4, 5, 0,_
( 28, 20, 0, 0, 2, 0, 0, 2, 0, 0),_
( 28, 0, 13, 7, 0, 0, 0, 1, 0, 0),_
( 28, 0, 0, 0, 0, 0, 0, 1, 0, 0),_
( 28, 0, 13, 7, 0, 0, 0, 1, 0, 0)_
),_
( 3, 2, 0,_
( 18, 0, 0, 7, 0, 2, 0, 1, 0, 0),_
( 20, 0, 0, 8, 0, 0, 0, 1, 0, 0),_
( 31, 31, 31, 15, 0, 127, 0, 1, 0, 0),_
( 20, 0, 0, 8, 0, 0, 0, 1, 0, 0)_
),_
( 3, 0, 0,_
( 18, 0, 0, 0, 0, 0, 0, 1, 0, 0),_
( 22, 0, 0, 0, 0, 0, 0, 1, 0, 0),_
( 18, 0, 0, 0, 0, 8, 0, 2, 0, 0),_
( 22, 0, 0, 8, 0, 0, 0, 1, 0, 0)_
),_
( 4, 6, 0,_
( 15, 0, 0, 0, 0, 4, 0, 1, 0, 0),_
( 17, 0, 0, 11, 0, 0, 0, 1, 0, 0),_
( 15, 0, 0, 0, 0, 0, 0, 3, 0, 0),_
( 17, 0, 0, 11, 0, 0, 0, 1, 0, 0)_
),_
( 4, 4, 0,_
( 31, 0, 10, 6, 0, 2, 0, 5, 0, 0),_
( 24, 0, 10, 6, 0, 2, 0, 1, 0, 0),_
( 31, 0, 10, 6, 0, 0, 0, 5, 0, 0),_
( 24, 0, 10, 6, 0, 4, 0, 4, 0, 0)_
),_
( 5, 5, 6,_
( 24, 0, 15, 8, 0, 0, 0, 4, 0, 2),_
( 24, 0, 15, 8, 0, 0, 0, 1, 0, 0),_
( 22, 0, 15, 8, 0, 2, 0, 3, 0, 0),_
( 20, 0, 15, 8, 0, 4, 0, 5, 0, 0)_
),_
( 4, 3, 5,_
( 28, 0, 11, 5, 0, 0, 0, 2, 0, 0),_
( 28, 0, 11, 6, 0, 0, 0, 1, 0, 0),_
( 28, 0, 11, 5, 0, 0, 0, 1, 0, 2),_
( 28, 0, 11, 6, 0, 5, 0, 2, 0, 0)_
),_
( 5, 3, 0,_
( 31, 0, 0, 0, 0, 0, 0, 5, 0, 0),_
( 31, 0, 21, 10, 0, 0, 0, 2, 0, 0),_
( 31, 0, 21, 10, 0, 0, 0, 5, 0, 0),_
( 31, 0, 21, 10, 0, 0, 0, 7, 0, 0)_
),_
( 6, 7, 0,_
( 31, 0, 0, 0, 0, 0, 0, 0, 0, 0),_
( 31, 0, 19, 9, 0, 0, 0, 0, 0, 0),_
( 31, 0, 13, 6, 0, 4, 0, 1, 0, 0),_
( 31, 0, 11, 5, 0, 0, 0, 0, 0, 0)_
),_
( 5, 5, 0,_
( 28, 0, 0, 0, 0, 4, 0, 1, 0, 0),_
( 28, 0, 17, 8, 0, 0, 0, 0, 0, 0),_
( 28, 0, 19, 9, 0, 0, 0, 0, 0, 0),_
( 28, 0, 21, 10, 0, 0, 0, 2, 0, 0)_
),_
( 4, 7, 0,_
( 31, 0, 0, 0, 0, 0, 0, 0, 0, 0),_
( 31, 0, 19, 9, 0, 0, 0, 0, 0, 0),_
( 14, 0, 15, 7, 0, 0, 0, 0, 0, 0),_
( 31, 0, 11, 5, 0, 0, 0, 0, 0, 0)_
),_
( 6, 7, 6,_
( 7, 0, 0, 0, 0, 6, 0, 4, 0, 1),_
( 8, 0, 0, 15, 0, 0, 0, 1, 0, 0),_
( 31, 31, 31, 15, 0, 127, 0, 1, 0, 0),_
( 31, 31, 31, 15, 0, 127, 0, 1, 0, 0)_
),_
( 7, 0, 0,_
( 31, 31, 31, 15, 0, 127, 0, 1, 0, 0),_
( 31, 31, 31, 15, 0, 127, 0, 1, 0, 0),_
( 31, 31, 31, 15, 0, 127, 0, 1, 0, 0),_
( 31, 31, 31, 15, 0, 127, 0, 1, 0, 0)_
),_
( 6, 7, 0,_
( 17, 0, 17, 8, 0, 0, 0, 15, 0, 0),_
( 17, 0, 17, 8, 0, 16, 0, 1, 0, 0),_
( 31, 31, 31, 15, 0, 127, 0, 1, 0, 0),_
( 31, 31, 31, 15, 0, 127, 0, 1, 0, 0)_
),_
( 6, 7, 0,_
( 31, 0, 0, 0, 0, 0, 0, 15, 0, 0),_
( 8, 0, 0, 6, 0, 2, 0, 15, 0, 0),_
( 31, 31, 31, 15, 0, 127, 0, 1, 0, 0),_
( 31, 31, 31, 15, 0, 127, 0, 1, 0, 0)_
),_
( 5, 2, 5,_
( 31, 0, 0, 0, 0, 0, 0, 12, 0, 1),_
( 16, 0, 0, 7, 0, 2, 0, 3, 0, 0),_
( 16, 0, 0, 7, 0, 4, 0, 9, 0, 0),_
( 16, 0, 0, 7, 0, 6, 0, 12, 0, 0)_
),_
( 5, 4, 5,_
( 31, 0, 0, 0, 0, 0, 0, 13, 0, 0),_
( 31, 0, 0, 8, 0, 0, 0, 2, 0, 1),_
( 31, 31, 31, 15, 0, 127, 0, 1, 0, 0),_
( 31, 31, 31, 15, 0, 127, 0, 1, 0, 0)_
),_
( 6, 7, 5,_
( 31, 0, 0, 0, 0, 0, 0, 15, 0, 0),_
( 31, 0, 0, 8, 0, 0, 0, 0, 0, 3),_
( 31, 31, 31, 15, 0, 127, 0, 1, 0, 0),_
( 31, 31, 31, 15, 0, 127, 0, 1, 0, 0)_
),_
( 5, 7, 6,_
( 31, 0, 0, 0, 0, 0, 0, 15, 0, 0),_
( 8, 0, 0, 6, 0, 0, 0, 4, 0, 3),_
( 8, 0, 0, 6, 0, 0, 0, 8, 0, 3),_
( 8, 0, 0, 6, 0, 0, 0, 12, 0, 3)_
),_
( 5, 7, 0,_
( 31, 0, 0, 0, 0, 0, 0, 11, 0, 0),_
( 31, 0, 15, 7, 0, 0, 0, 11, 0, 0),_
( 31, 31, 31, 15, 0, 127, 0, 1, 0, 0),_
( 31, 31, 31, 15, 0, 127, 0, 1, 0, 0)_
)}
dim shared as DRUMPARAMETER drums (35 to 81) = {_
( 5, 0, 0,_
( 31, 0, 17, 8, 0, 0, 0, 3, 0, 0),_
( 31, 0, 17, 8, 0, 0, 0, 1, 0, 0),_
( 31, 0, 17, 8, 0, 0, 0, 1, 0, 0),_
( 31, 0, 17, 8, 0, 0, 0, 1, 0, 0),_
11, 8192, 35),_
( 5, 0, 0,_
( 31, 0, 15, 7, 0, 0, 0, 3, 0, 0),_
( 31, 0, 15, 7, 0, 0, 0, 1, 0, 0),_
( 31, 0, 15, 7, 0, 0, 0, 1, 0, 0),_
( 31, 0, 15, 7, 0, 0, 0, 1, 0, 0),_
14, 8192, 36),_
( 6, 7, 0,_
( 31, 0, 19, 9, 0, 0, 0, 3, 0, 0),_
( 31, 0, 19, 9, 0, 4, 0, 2, 0, 0),_
( 31, 31, 31, 15, 0, 127, 0, 1, 0, 0),_
( 31, 31, 31, 15, 0, 127, 0, 1, 0, 0),_
59, 8192, 37),_
( 5, 7, 0,_
( 31, 0, 0, 0, 0, 0, 0, 15, 0, 0),_
( 31, 24, 17, 8, 0, 0, 0, 1, 0, 0),_
( 31, 24, 17, 8, 0, 0, 0, 1, 0, 0),_
( 31, 24, 17, 8, 0, 0, 0, 1, 0, 0),_
48, 8192, 38),_
( 5, 7, 0,_
( 31, 0, 0, 0, 0, 0, 0, 15, 0, 0),_
( 31, 0, 19, 9, 0, 0, 0, 1, 1, 0),_
( 31, 0, 19, 9, 0, 0, 0, 1, 2, 0),_
( 31, 0, 19, 9, 0, 0, 0, 1, 3, 0),_
87, 6912, 39),_
( 5, 7, 0,_
( 31, 0, 0, 0, 0, 0, 0, 15, 0, 0),_
( 31, 0, 19, 9, 0, 0, 0, 1, 0, 0),_
( 31, 0, 19, 9, 0, 0, 0, 1, 0, 0),_
( 31, 0, 19, 9, 0, 0, 0, 1, 0, 0),_
55, 8192, 40),_
( 5, 0, 0,_
( 31, 0, 15, 7, 0, 0, 0, 3, 0, 0),_
( 31, 0, 15, 7, 0, 0, 0, 1, 0, 0),_
( 31, 0, 15, 7, 0, 0, 0, 1, 0, 0),_
( 31, 0, 15, 7, 0, 0, 0, 1, 0, 0),_
14, 4352, 41),_
( 6, 7, 0,_
( 31, 0, 0, 0, 0, 0, 0, 2, 0, 0),_
( 31, 0, 21, 10, 0, 0, 0, 1, 0, 0),_
( 31, 31, 31, 15, 0, 127, 0, 1, 0, 0),_
( 31, 31, 31, 15, 0, 127, 0, 1, 0, 0),_
99, 10752, 42),_
( 5, 0, 0,_
( 31, 0, 15, 7, 0, 0, 0, 3, 0, 0),_
( 31, 0, 15, 7, 0, 0, 0, 1, 0, 0),_
( 31, 0, 15, 7, 0, 0, 0, 1, 0, 0),_
( 31, 0, 15, 7, 0, 0, 0, 1, 0, 0),_
18, 5888, 43),_
( 6, 7, 0,_
( 31, 0, 0, 0, 0, 0, 0, 2, 0, 0),_
( 31, 0, 21, 10, 0, 0, 0, 1, 0, 0),_
( 31, 31, 31, 15, 0, 127, 0, 1, 0, 0),_
( 31, 31, 31, 15, 0, 127, 0, 1, 0, 0),_
100, 10752, 42),_
( 5, 0, 0,_
( 31, 0, 15, 7, 0, 0, 0, 3, 0, 0),_
( 31, 0, 15, 7, 0, 0, 0, 1, 0, 0),_
( 31, 0, 15, 7, 0, 0, 0, 1, 0, 0),_
( 31, 0, 15, 7, 0, 0, 0, 1, 0, 0),_
20, 7424, 45),_
( 6, 7, 0,_
( 31, 0, 0, 0, 0, 0, 0, 2, 0, 0),_
( 31, 0, 13, 6, 0, 0, 0, 1, 0, 0),_
( 31, 31, 31, 15, 0, 127, 0, 1, 0, 0),_
( 31, 31, 31, 15, 0, 127, 0, 1, 0, 0),_
100, 10752, 42),_
( 5, 0, 0,_
( 31, 0, 15, 7, 0, 0, 0, 3, 0, 0),_
( 31, 0, 15, 7, 0, 0, 0, 1, 0, 0),_
( 31, 0, 15, 7, 0, 0, 0, 1, 0, 0),_
( 31, 0, 15, 7, 0, 0, 0, 1, 0, 0),_
24, 8960, 47),_
( 5, 0, 0,_
( 31, 0, 15, 7, 0, 0, 0, 3, 0, 0),_
( 31, 0, 15, 7, 0, 0, 0, 1, 0, 0),_
( 31, 0, 15, 7, 0, 0, 0, 1, 0, 0),_
( 31, 0, 15, 7, 0, 0, 0, 1, 0, 0),_
27, 10496, 48),_
( 5, 7, 3,_
( 31, 0, 0, 0, 0, 0, 0, 8, 0, 1),_
( 31, 20, 11, 5, 1, 0, 0, 2, 0, 0),_
( 31, 20, 11, 5, 2, 0, 0, 3, 0, 0),_
( 31, 20, 11, 5, 3, 0, 0, 5, 0, 0),_
104, 10752, 49),_
( 5, 0, 0,_
( 31, 0, 15, 7, 0, 0, 0, 3, 0, 0),_
( 31, 0, 15, 7, 0, 0, 0, 1, 0, 0),_
( 31, 0, 15, 7, 0, 0, 0, 1, 0, 0),_
( 31, 0, 15, 7, 0, 0, 0, 1, 0, 0),_
31, 12032, 50),_
( 5, 7, 0,_
( 31, 0, 0, 0, 0, 6, 0, 8, 0, 0),_
( 31, 0, 11, 5, 0, 0, 0, 1, 0, 0),_
( 31, 0, 11, 5, 0, 0, 0, 1, 0, 0),_
( 31, 31, 31, 15, 0, 127, 0, 1, 0, 0),_
97, 5632, 51),_
( 5, 7, 3,_
( 31, 0, 0, 0, 0, 0, 0, 2, 0, 1),_
( 31, 0, 11, 5, 0, 0, 0, 1, 0, 0),_
( 31, 0, 11, 5, 0, 0, 0, 1, 0, 0),_
( 31, 31, 31, 15, 0, 127, 0, 1, 0, 0),_
94, 5632, 52),_
(7,7,0,_
( 31, 0, 17, 8, 0, 0, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
36,8192,1),_
(7,7,0,_
( 31, 0, 17, 8, 0, 0, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
36,8192,1),_
(7,7,0,_
( 31, 0, 17, 8, 0, 0, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
36,8192,1),_
(7,7,0,_
( 31, 0, 17, 8, 0, 0, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
36,8192,1),_
(7,7,0,_
( 31, 0, 17, 8, 0, 0, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
36,8192,1),_
(7,7,0,_
( 31, 0, 17, 8, 0, 0, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
36,8192,1),_
(7,7,0,_
( 31, 0, 17, 8, 0, 0, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
36,8192,1),_
(7,7,0,_
( 31, 0, 17, 8, 0, 0, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
36,8192,1),_
(7,7,0,_
( 31, 0, 17, 8, 0, 0, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
36,8192,1),_
(7,7,0,_
( 31, 0, 17, 8, 0, 0, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
36,8192,1),_
(7,7,0,_
( 31, 0, 17, 8, 0, 0, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
36,8192,1),_
(7,7,0,_
( 31, 0, 17, 8, 0, 0, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
36,8192,1),_
(7,7,0,_
( 31, 0, 17, 8, 0, 0, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
36,8192,1),_
(7,7,0,_
( 31, 0, 17, 8, 0, 0, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
36,8192,1),_
(7,7,0,_
( 31, 0, 17, 8, 0, 0, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
36,8192,1),_
(7,7,0,_
( 31, 0, 17, 8, 0, 0, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
36,8192,1),_
(7,7,0,_
( 31, 0, 17, 8, 0, 0, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
36,8192,1),_
(7,7,0,_
( 31, 0, 17, 8, 0, 0, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
36,8192,1),_
(7,7,0,_
( 31, 0, 17, 8, 0, 0, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
36,8192,1),_
(7,7,0,_
( 31, 0, 17, 8, 0, 0, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
36,8192,1),_
(7,7,0,_
( 31, 0, 17, 8, 0, 0, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
36,8192,1),_
(7,7,0,_
( 31, 0, 17, 8, 0, 0, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
36,8192,1),_
(7,7,0,_
( 31, 0, 17, 8, 0, 0, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
36,8192,1),_
(7,7,0,_
( 31, 0, 17, 8, 0, 0, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
36,8192,1),_
(7,7,0,_
( 31, 0, 17, 8, 0, 0, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
36,8192,1),_
(7,7,0,_
( 31, 0, 17, 8, 0, 0, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
36,8192,1),_
(7,7,0,_
( 31, 0, 17, 8, 0, 0, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
( 31, 0, 0, 15, 0, 127, 0, 1, 0, 0),_
36,8192,1),_
( 5, 4, 0,_
( 31, 0, 10, 0, 0, 0, 0, 15, 0, 0),_
( 31, 24, 17, 8, 0, 0, 0, 15, 0, 0),_
( 31, 24, 17, 8, 0, 0, 0, 15, 0, 0),_
( 31, 31, 31, 15, 0, 127, 0, 15, 0, 0),_
72, 3072, 80),_
( 5, 4, 0,_
( 31, 0, 5, 0, 0, 0, 0, 15, 0, 0),_
( 31, 24, 13, 6, 0, 0, 0, 15, 0, 0),_
( 31, 24, 13, 6, 0, 0, 0, 15, 0, 0),_
( 31, 31, 31, 15, 0, 127, 0, 15, 0, 0),_
72, 3072, 80)}
Code: Select all
const m_pi=3.14159265358979323846
type sine_wave_generator
declare sub set_cycle(cycle as single)
declare sub add_modulation(x as long)
declare function get_next() as integer
declare function get_next(modulation as long) as integer
position as unsigned long
_step as unsigned long
end type
enum ADSR
ATTACK
ATTACK_RELEASE
DECAY
DECAY_RELEASE
SUSTAIN
RELEASE
SOUNDOFF
FINISHED
end enum
type envelope_generator
declare sub set_rate(rate as single)
declare sub set_hold(value as single)
declare sub set_freeze(value as single)
declare sub key_off()
declare sub sound_off()
declare function get_next() as integer
state as ADSR
AR as integer
DR as integer
SR as integer
RR as integer
TL as integer
fAR as unsigned long
fDR as unsigned long
fSR as unsigned long
fRR as unsigned long
fSL as unsigned long
fTL as unsigned long
_fOR as unsigned long
fSS as unsigned long
fDRR as unsigned long
fDSS as unsigned long
current as unsigned long
rate as single
hold as single
freeze as single
declare sub update_parameters()
end type
type fm_operator
declare sub set_freq_rate(freq as single, rate as single)
declare function get_next() as integer
declare function get_next(modulate as integer) as integer
declare function get_next(lfo as integer, modulate as integer) as integer
swg as sine_wave_generator
eg as envelope_generator
ML as single
DT as single
ams_factor as long
ams_bias as long
end type
type fm_sound_generator
declare sub set_rate(rate as single)
declare sub set_frequency_multiplier(value as single)
declare sub set_damper(damper as integer)
declare sub set_sostenute(sostenute as integer)
declare sub set_freeze(freeze as integer)
declare sub set_tremolo(depth as integer, frequency as single)
declare sub set_vibrato(depth as single, frequency as single)
declare sub key_off()
declare sub sound_off()
declare function is_finished() as integer
declare function get_next() as integer
op1 as fm_operator
op2 as fm_operator
op3 as fm_operator
op4 as fm_operator
ams_lfo as sine_wave_generator
vibrato_lfo as sine_wave_generator
tremolo_lfo as sine_wave_generator
ALG as integer
FB as integer
freq as single
freq_mul as single
ams_freq as single
ams_enable as integer
tremolo_depth as integer
tremolo_freq as single
vibrato_depth as integer
vibrato_freq as single
rate as single
feedback as integer
damper as integer
sostenute as integer
end type
Type fm_note
declare function synthesize(buf as long ptr, samples as uinteger, rate as single, _left as long, _right as long) as integer
'declare sub note_off(velocity as integer)
'declare sub sound_off()
'declare sub set_frequency_multiplier(value as single)
'declare sub set_tremolo(depth as integer, freq as single)
'declare sub set_vibrato(depth as single, freq as single)
'declare sub set_damper(value as integer)
'declare sub set_sostenute(value as integer)
'declare sub set_freeze(value as integer)
declare sub release()
assign as integer
panpot as integer
fm as fm_sound_generator
velocity as integer
end type
type FMPARAMETEROP
AR as integer
DR as integer
SR as integer
RR as integer
SL as integer
TL as integer
KS as integer
ML as integer
DT as integer
AMS as integer
end type
type FMPARAMETER
ALG as integer
FB as integer
LFO as integer
op1 as FMPARAMETEROP
op2 as FMPARAMETEROP
op3 as FMPARAMETEROP
op4 as FMPARAMETEROP
end type
type DRUMPARAMETER
ALG as integer
FB as integer
LFO as integer
op1 as FMPARAMETEROP
op2 as FMPARAMETEROP
op3 as FMPARAMETEROP
op4 as FMPARAMETEROP
key as integer
panpot as integer
assign as integer
end type
type fm_note_factory
declare function note_on(program as long, note as integer, velocity as integer, frequency_multiplier as single) as fm_note ptr
declare sub clear_
programs(128) as FMPARAMETER ptr
drums(128) as DRUMPARAMETER ptr
end type
type _NOTES
note as fm_note ptr
key as integer
status as integer
_prev as _NOTES ptr
_next as _NOTES ptr
end type
type channel:
declare function synthesize(out as long ptr, samples as uinteger, rate as single, master_volume as long, master_balance as integer) as integer
declare sub reset_all_parameters()
declare sub reset_all_controller()
declare sub all_note_off()
declare sub all_sound_off()
declare sub all_sound_off_immediately()
declare sub note_off(note as integer, velocity as integer)
declare sub note_on(note as integer, velocity as integer)
declare sub polyphonic_key_pressure(note as integer, value as integer)
declare sub channel_pressure(value as integer)
declare sub control_change(control as integer, value as integer)
declare sub bank_select(value as integer)
declare sub set_damper(value as integer)
declare sub set_sostenute(value as integer)
declare sub set_freeze(value as integer)
notes as _NOTES ptr
_firstnote as _NOTES ptr
_lastnote as _NOTES ptr 'Linked list
factory as fm_note_factory ptr
default_bank as integer
program as integer
bank as integer
panpot as integer
volume as integer
expression as integer
pressure as integer
pitch_bend as integer
pitch_bend_sensitivity as integer
modulation_depth as integer
modulation_depth_range as integer
damper as integer
sostenute as integer
freeze as integer
fine_tuning as integer
coarse_tuning as integer
RPN as integer
NRPN as integer
mono as integer
mute as integer
tremolo_frequency as single
vibrato_frequency as single
frequency_multiplier as single
master_frequency_multiplier as single
system_mode as integer
declare function get_registered_parameter() as integer
declare sub set_registered_parameter(value as integer)
declare sub update_frequency_multiplier()
declare sub update_modulation()
end type
type synthesizer
declare function synthesize(_output as short ptr, samples as uinteger, rate as single) as integer
declare function synthesize_mixing(_output as long ptr, samples as uinteger, rate as single) as integer
declare sub reset()
declare sub reset_all_parameters()
declare sub reset_all_controller()
declare sub all_note_off()
declare sub all_sound_off()
declare sub all_sound_off_immediately()
declare sub sysex_message(pvdata as string)
declare sub midi_event(_command as integer, param1 as integer, param2 as integer)
declare sub set_system_mode(mode as integer)
channels(15) as channel
active_sensing as single
main_volume as integer
master_volume as integer
master_balance as integer
master_fine_tuning as integer
master_coarse_tuning as integer
master_frequency_multiplier as single
system_mode as integer
declare sub update_master_frequency_multiplier()
end type
Last edited by angros47 on May 16, 2018 21:41, edited 1 time in total.
Re: Cross-platform MIDI in pure FreeBasic!
> Since some users complained about the lack of a way to play MIDI files on all
> platforms (most solutions are windows-only), here is a solution.
COOL :-)
Suggestion: option to save a WAV file instead of using "alsathread.bas" or "winmmthread.bas".
> (if zippyshare does not work)
Other ideas:
- put it on freebasic-portal
or
- remove binaries, TAR, ZIP, B64 -> cca 60 KiB -> upload to some "pasta"
> platforms (most solutions are windows-only), here is a solution.
COOL :-)
Suggestion: option to save a WAV file instead of using "alsathread.bas" or "winmmthread.bas".
> (if zippyshare does not work)
Other ideas:
- put it on freebasic-portal
or
- remove binaries, TAR, ZIP, B64 -> cca 60 KiB -> upload to some "pasta"
Re: Cross-platform MIDI in pure FreeBasic!
This is a version that can save in to a .wav file (I used a modified version of a routine by d.j.peters to prepare the header of the file)
Code: Select all
#include "midisynth.bi"
#include "instruments.bi"
common shared synth as synthesizer
#define FCC(c) *(cptr(Uinteger Ptr,@##c))
Sub PrepareBuffer(Byval filenum As integer, Byval nRate As Uinteger=44100)
Dim As Uinteger h (10)
Dim As Uinteger BlkAlign=4
h( 0)=FCC("RIFF") ' RIFF chunk
h( 1)=0 ' size of WAVE chunk + data size
h( 2)=FCC("WAVE") ' WAVE chunk
h( 3)=FCC("fmt ") ' fmt chunk
h( 4)=16 ' size of fmt chunk
h( 5)=(2 Shl 16) Or 1 ' channels + PCM_FORMAT flag
h( 6)=nRate ' playback rate
h( 7)=BlkAlign*nRate ' bytes per sec.
h( 8)=(16 Shl 16) Or BlkAlign ' bits per sample + blockalign
h( 9)=FCC("data") ' data chunk
h(10)=0 ' size of data chunk
put #filenum, 1, h()
End Sub
dim shared size as integer
dim shared completed as integer
sub _SoundThread(ByVal userdata As Any Ptr )
const buffersize=441*2'128*32
Dim As Short lpBuffers (buffersize)
do until completed
synth.synthesize(@lpBuffers(0), Buffersize/2, 44100)
put #15, , lpBuffers()
size+=Buffersize
sleep 10
loop
end sub
'based on RealMIDI 2.00, by Sebastian Mate
dim thread_handle as any ptr
dim thread_count as uinteger ptr
open"out.wav" for binary as #15
preparebuffer 15
thread_handle = threadcreate( @_SoundThread)
synth.reset
synth.channels(9).program=120 shl 14 'Set percussion mode
sub MidiMessage (a as string, b as byte, c as byte)
synth.midi_event (asc(a),b,c)
end sub
DIM SHARED Header AS STRING * 4
DIM SHARED TweeByte AS STRING * 2
DIM SHARED VierByte AS STRING * 4
DIM SHARED FileType AS STRING * 2
FUNCTION NextNumber as ubyte
dim a as string*1
GET #1, , a
NextNumber = ASC(a)
END FUNCTION
FUNCTION Nibble (Cr as string, Lr as integer) as string
' A Nibble are 4 Bit or a half byte. Strange name!
IF Lr = 1 THEN
return LEFT(HEX(ASC(Cr) AND 240), 1)
ELSE
return RIGHT(HEX(ASC(Cr) AND 15), 1)
END IF
END FUNCTION
FUNCTION ReadVarLen as integer
dim a as string*1
GET #1, , a
dim as integer Value, Value2
Value = ASC(a)
IF (Value AND 128) THEN
Value = (Value AND 127)
DO
GET #1, , a
Value2 = ASC(a)
Value = (Value * (2 ^ 7)) + (Value2 AND 127)
LOOP WHILE (Value2 AND 128)
END IF
return Value
END FUNCTION
FUNCTION Nibble2Number (nib as string) as integer
SELECT CASE nib
CASE "0": Nibble2Number = 0
CASE "1": Nibble2Number = 1
CASE "2": Nibble2Number = 2
CASE "3": Nibble2Number = 3
CASE "4": Nibble2Number = 4
CASE "5": Nibble2Number = 5
CASE "6": Nibble2Number = 6
CASE "7": Nibble2Number = 7
CASE "8": Nibble2Number = 8
CASE "9": Nibble2Number = 9
CASE "A": Nibble2Number = 10
CASE "B": Nibble2Number = 11
CASE "C": Nibble2Number = 12
CASE "D": Nibble2Number = 13
CASE "E": Nibble2Number = 14
CASE "F": Nibble2Number = 15
END SELECT
END FUNCTION
FUNCTION ReadBPM as long
DIM temp AS LONG
dim a as string*1
GET #1, , a
IF a = CHR(3) THEN
FOR i as integer = 1 TO 3
GET #1, , a
temp = (temp * 256) + ASC(a)
NEXT i
END IF
return temp
END FUNCTION
FUNCTION ReadFourBytes as long
dim t as long
dim a as string*1
GET #1, , a
t = ASC(a) * 2 ^ 8
GET #1, , a
t = (ASC(a) + t) * 2 ^ 8
GET #1, , a
t = (ASC(a) + t) * 2 ^ 8
GET #1, , a
ReadFourBytes = t + ASC(a)
END FUNCTION
FUNCTION ReadText as string
dim a as string*1
dim temp as string
dim as integer Lengte = ReadVarLen
FOR tt as integer= 1 TO Lengte
GET #1, , a
temp = temp + a
NEXT tt
return temp
END FUNCTION
FUNCTION ReadTimeSignature as string
dim a as string*1
dim as integer t1,t2
GET #1, , a
GET #1, , a: T1 = ASC(a)
GET #1, , a: T2 = ASC(a)
GET #1, , a
GET #1, , a
return STR(T1) + " /" + STR(2 ^ T2)
END FUNCTION
FUNCTION ReadTwoBytes as short
dim a as string*1
dim t as integer
GET #1, , a
t = ASC(a) * 2 ^ 8
GET #1, , a
return t + ASC(a)
END FUNCTION
var file="TIMEWRP.MID"
OPEN file FOR BINARY AS #1
GET #1, , Header
IF Header <> "MThd" THEN PRINT "Not a valid MIDI file": STOP
GET #1, , VierByte
GET #1, , FileType
IF ASC(RIGHT(FileType, 1)) = 0 THEN
ELSE
PRINT "Multy tracks, this file type is not supported.": END
END IF
dim Tracks as integer, Tempo as integer
Tracks = ReadTwoBytes
tempo = ReadTwoBytes
GET #1, , Header
var TrkLengte = ReadFourBytes '+ LOC(1)
dim lyric as string, a as string*1
dim as string t2, n
dim as integer tl
do until eof(1)
tl = ReadVarLen ' Read the delay until we do anything and delay:
dim as double startDelay=timer
do:loop until timer>=StartDelay+(tl / tempo/1.5)
'FOR ar% = 1 TO MDelay%
' FOR Wacht = 1 TO tl * (1.5 / tempo) * 100 * WL: NEXT Wacht
'NEXT ar%
if inkey<>"" then exit do
GET #1, , a ' Get the MIDI-command...
IF a = CHR(255) THEN '... we have a meta-command!
GET #1, , a
SELECT CASE ASC(a)
CASE 0: PRINT "Sequence Number : "; ReadText
CASE 1: lyric = ReadText:'print lyric;
CASE 32: PRINT "MIDI ch. Prefix.. ": a = ReadText: REM <====== What is this ?
CASE 47: end
CASE 81: tempo = (60000000 / ReadBPM)
CASE 84: PRINT "SMPTE Offset : "; : T2 = ReadText$
CASE 88 ' Time signature
N = ReadTimeSignature
CASE 89 ' Key signature
N = ReadText
CASE 127 'Sequencer-specific Meta Event
N = ReadText
CASE ELSE
T2 = ReadText ' Unkown Meta Event
END SELECT
ELSE
IF HEX(ASC(a)) = "F0" OR HEX(ASC(a)) = "F7" THEN
T2 = ReadText
ELSE
IF Nibble(a, 1) = "8" THEN 'Send: Tune Off
var first=NextNumber
var Second=NextNumber
MidiMessage a,first, second
END IF
IF Nibble$(a, 1) = "9" THEN 'Send: Tune On
var first=NextNumber
var Second=NextNumber
MidiMessage a,first, second
END IF
IF Nibble$(a, 1) = "A" THEN 'Key after-touch
MidiMessage a,NextNumber, 0
END IF
IF Nibble$(a, 1) = "B" THEN
'MidiMessage a,NextNumber, NextNumber
NextNumber:NextNumber
END IF
IF Nibble$(a, 1) = "C" THEN ' Change voice
MidiMessage a,NextNumber, 0
synth.channels(9).program=120 shl 14 'Set percussion mode
END IF
IF Nibble$(a, 1) = "D" THEN ' <- ???
MidiMessage a,NextNumber, 0
END IF
IF Nibble$(a, 1) = "E" THEN 'Pitch wheel change
var first=NextNumber
var Second=NextNumber
MidiMessage a,first, second
END IF
END IF
END IF
loop
completed=1
put #15, 41, size
size+=36
put #15, 5, size
Re: Cross-platform MIDI in pure FreeBasic!
This reminds me a bit of your adlib PLAY replacement.
Re: Cross-platform MIDI in pure FreeBasic!
Here is a remade sequencer
Code: Select all
#include "midisynth.bi"
#include "instruments.bi"
'based on RealMIDI 2.00, by Sebastian Mate
dim thread_handle as any ptr
dim thread_count as uinteger ptr
declare sub _SoundThread(ByVal userdata As Any Ptr )
declare sub _SoundInit()
_SoundInit
thread_handle = threadcreate( @_SoundThread)
common shared synth as synthesizer
synth.reset
synth.channels(9).program=120 shl 14 'Set percussion mode
sub MidiMessage (a as ubyte, b as byte, c as byte)
synth.midi_event (a,b,c)
end sub
DIM SHARED Header AS STRING * 4
DIM SHARED TweeByte AS STRING * 2
DIM SHARED VierByte AS STRING * 4
DIM SHARED FileType AS STRING * 2
FUNCTION NextNumber as ubyte
dim a as ubyte
GET #1, , a
NextNumber = a
END FUNCTION
FUNCTION ReadVarLen as integer
dim a as ubyte
GET #1, , a
dim as integer Value, Value2
Value = a
IF (Value AND 128) THEN
Value = (Value AND 127)
DO
GET #1, , a
Value2 = a
Value = (Value * (2 ^ 7)) + (Value2 AND 127)
LOOP WHILE (Value2 AND 128)
END IF
return Value
END FUNCTION
FUNCTION ReadBPM as long
DIM temp AS LONG
dim a as ubyte
GET #1, , a
IF a = 3 THEN
FOR i as integer = 1 TO 3
GET #1, , a
temp = (temp * 256) + a
NEXT i
END IF
return temp
END FUNCTION
FUNCTION ReadFourBytes as long
dim t as long
dim a as ubyte
GET #1, , a
t = a * 2 ^ 8
GET #1, , a
t = (a + t) * 2 ^ 8
GET #1, , a
t = (a + t) * 2 ^ 8
GET #1, , a
ReadFourBytes = t + a
END FUNCTION
sub ReadText
dim a as ubyte
dim as integer Lengte = ReadVarLen
FOR tt as integer= 1 TO Lengte
GET #1, , a
NEXT tt
END sub
FUNCTION ReadTwoBytes as short
dim a as ubyte
dim t as integer
GET #1, , a
t = a * 2 ^ 8
GET #1, , a
return t + a
END FUNCTION
var file=command
OPEN file FOR BINARY AS #1
GET #1, , Header
IF Header <> "MThd" THEN PRINT "Not a valid MIDI file": STOP
GET #1, , VierByte
GET #1, , FileType
' IF ASC(RIGHT(FileType, 1)) = 0 THEN
' ELSE
' PRINT "Multy tracks, this file type is not supported.": END
' END IF
dim Tracks as integer, Divisions as integer, Tempo as integer=60000000/120
Tracks = ReadTwoBytes
Divisions = ReadTwoBytes
dim Track as String
dim Sequence(Tracks) as String
dim LastPos as integer
for tr as integer=0 to Tracks
if eof(1) then exit for
GET #1, , Header
Track=""
var TrkLength = ReadFourBytes
LastPos=LOC(1)-2
dim a as ubyte, status as ubyte
dim as integer tl
dim SeqTime as Double
dim i as integer
do
if LOC(1)-LastPos>TrkLength orelse eof (1) then exit do
tl = ReadVarLen ' Read the delay until we do anything and delay:
'dim as double startDelay=timer
'do:loop until timer>=StartDelay+(tl / tempo/1.5)
SeqTime+=(tl * tempo/Divisions/1e6)
GET #1, , a ' Get the MIDI-command...
IF a = 255 THEN '... we have a meta-command!
GET #1, , a
SELECT CASE a
CASE 47: NextNumber 'End of track
CASE 81: tempo = ReadBPM
CASE ELSE
ReadText ' Unkown Meta Event
END SELECT
ELSEIF a = &HF0 OR a = &HF7 THEN
ReadText
ELSE
if a>127 then status=a: GET #1, , a
SELECT CASE status shr 4
case &H8, &H9, &HA, &HB, &HE
Track+=mkd(SeqTime)
Track+=chr(status)
Track+=chr(a)
Track+=chr(NextNumber)
case &HC, &HD
Track+=mkd(SeqTime)
Track+=chr(status)
Track+=chr(a)
Track+=chr(0)
case else
exit do
End Select
END IF
loop
Sequence(tr)=Track
next
?"Start"
dim as double startDelay=timer
dim p(Tracks) as integer
for i as integer=0 to Tracks
p(i)=1
next
dim as integer isPlaying
do
isPlaying=0
for i as integer=0 to Tracks
if p(i)<len(Sequence(i)) then
isPlaying=1
dim SeqTime as Double=cvd(mid(Sequence(i),p(i)))
if timer>=StartDelay+SeqTime then
dim a as ubyte, b as ubyte, c as ubyte
a=asc(mid(Sequence(i),p(i)+8))
b=asc(mid(Sequence(i),p(i)+9))
c=asc(mid(Sequence(i),p(i)+10))
if a<>&H99 orelse (b>=35 andalso b<=81) then MidiMessage(a,b,c)
synth.channels(9).program=120 shl 14 'Set percussion mode
p(i)+=11
end if
end if
next
loop while isPlaying
Re: Cross-platform MIDI in pure FreeBasic!
I really want to try this. Where is _soundinit() and _soundthread() defined? Is there another source file to get?