Tarinaa ei kerrota vain sanoilla, vaan se jatkuu tavoissa, liikkeissä, musiikissa, artefakteissa, perspektiivien jäävuorten vedenpäälisinä huippuina - siinä, kuinka valo heijastuu kuunylisinä kaarina taulun maalipinnasta.
Yläasteikäisenä onnistuin myymään pari kirjoittamaani tietokoneohjelmaa, joista ensimmäinen oli Valkeakosken Energialaitokselle tehty veloitushintaohjelma ja toinen äidinkielenopettajallemme "Kieli on systeemi"-peli. Kummastakin sain huimat 500 markkaa, mikä tuossa iässä käytännössä tarkoitti, että rahat oli tuhlattu cd:hin lyhyessä ajassa. Joskus noihin aikoihin tietokoneemme "siirtyi" huoneeseeni koska minä sitä kuitenkin aina käytin ja aloin myös saamaan käyttää modeemiamme purkkeihin soittamiseen, mutta tämä oli perheessä tarkkaan kontrolloitu, koska puhelinlaskut olivat noihin aikoihin minuuttitaksalla. Paikallispuhelumaksulla pystyi soittamaan muistaakseni Hämeen läänin alueella, joten soittelin lähinnä Lahtelaisiin purkkeihin, mutta myös Valkeakoskella oli omansa, R.A.Law, jota pyöritti tuntemani kaveri. Tietokoneemme mukana tullut modeemi taisi olla 2400bps nopeudeltaan ja muistan vieläkin, kun sain säästettyä oman 14400bps modeemin, jota pyöräilin innoissani postiin hakemaan.
Yhdeksännellä luokalla '92 osallistuin Datatähti-kisaan ja pääsinkin loppukilpailuihin Helsinkiin, Osuuspankin hulpeaan merenrannalla olevaan kompleksiin. Se oli minulle silmiäavaava kokemus ja olen erittäin kiitollinen, että noita kilpailuita järjestettiin. Paripäiväisen kilpailun aikana tutustuin myös Esaan, joka kilpaili silloin lukion sarjassa ja muutenkin vanhemmat kilpailijat tuntuivat lähinnä joltain mystisiltä guruilta silloisen minäni näkökulmasta. Alla valokuva lapusta, jonka olen säästänyt tuolta reissulta, johon Esa kirjoitti minulle ylös pyöritysmatriisien kaavoja. Esa myös esitteli assyllä koodaamaansa sinus scrolleria ja Future Crew:n Wildfire selitti, kuinka palettirotaatiota käytetään plasman tekemiseen. Tunsin itseni tuolloin täysin aloittelijaksi ja opin noiden parin päivän aikana varmaan saman verran asioita kuin normaalisti kuukausissa - olin kuin pesusieni, joka janosi tietoa tältä Suomen hakkereiden kermalta. Silloin opin myös, että maailmassa hiihtää porukkaa, joilla on mukanaan aina pari "taskumodeemia" varmuuden varalta :) Nämä tulivatkin käyttöön, kun valojen sammuttamisen jälkeen yritimme tehdä kaikkemme, että onnistuisimme soittamaan Osuuspankin laskuun jonnekin ulkomaille, sillä huoneissamme oli puhelinpistokkeet. Ainoa ongelma oli, että käytössämme oli vain ko. laitoksen tietokone, jossa oli ainoastaan MS-DOS:n GW-Basic asennettuna, mutta kollektiivisesti muistimme tarpeeksi modeemin ohjauskomentoja, jotta onnistuimme yön aikana kirjoittamaan terminaaliohjelman sillä. Nukahdin tosin ennen kuin varsinainen yhteys saatiin muodostumaan. Tulin lopulta yläasteen sarjassa neljänneksi ja osallistuin lisäksi IOI-olympiavalmennukseen. Tuolloin pääsin varajäseneksi Suomen joukkueeseen. Kotiin päästyäni aloinkin heti opettelemaan assembly-ohjelmointia ja tilasin kirjan EGA/VGA:n hardware-ohjelmoinnista, sillä monet demoefektit vaativat kaikenlaista kikkailua tuolla tasolla, kun prosessorin aika pyrittiin säästämään muille asioille.
pyöritysmatriisioppia 9-luokalla
Lukion viimeisellä '95 pääsin toisen kerran Datatähti-loppukilpailuun (alla linkki valokuvaan), jossa tulin toiseksi. Tuolloin pääsin myös IOI-joukkueeseen ja onnistuinkin saamaan hopeamitalin Hollannissa järjestetyissä kisoissa. Järjestelyt olivat hienot ja meillä olisi ollut mahdollisuus mennä kuuntelemaan Dijkstran pitämää luentoakin kilpailijoille, mutta olimme aika väsyneitä sinä aamuna ja Samuli totesikin, että on jo nähnyt Tampereen yliopiston Erkki Mäkisen, joten jätimme luennon väliin. Ensimmäinen kilpailupäivä meni kisoissa hieman totuttelun merkeissä, mutta jälkimmäisestä päivästä olen erityisen ylpeä: Sain kolme ohjelmointitehtävää tehtyä tunnin ajoissa valmiiksi ja yli-itsevarmana palautin tehtävät etuajassa (idiootti!) ja olinkin unohtanut keskimmäisestä tehtävästä, että annetussa graafissa saattoi olla silmukoita noodista samaan noodiin. Onneksi tästä meni vain yksi testitapaus ja viimeisestä tehtävästä meni toinen, koska en ollut optimoinut vakiokerrointa parhaaksi mahdolliseksi (ko. tehtävässä algoritmia vastaan laitettiin "pelaamaan" toinen algoritmi, joka antoi sille aina mahdollisimman pahan syötteen), mutta loppujen lopuksi sain maailman kolmanneksi parhaat pisteet jälkimmäiseltä päivältä, mm. paremmat kuin ko. kisan lopulta voittanut venäläinen Victor Bargachev.
Kari, 17-18v, vietti monet kesäpäivät demoryhmämme toisen muusikon ja osa-aika-dj:n vanhempien puisen omakotitalon vintillä koodatessa musarutiinia Gravis-äänikortille. Kyseinen laite oli siitä mielenkiintoinen, että sillä oli oma muisti, josta kortin prosessori miksasi moniraitaisen äänen ilman tarvetta varsinaiselle koneen pääprosessorille. Lopullinen engine oli noin 5000 riviä x86 assyä ja luulen, että se oli ensimmäinen kunnolla 16-bittisiä sampleja tukeva rutiini. GUS:ssa nimittäin oli sellainen rajoitus, että 16-bittisiä sampleja ei pystynyt automaattisesti soittamaan 256 kilon muistipankkirajojen yli, joten suurin osa tuosta koodista oli itse asiassa kirjoitettu vain hyppimään noiden rajojen yli pitkille sampleille kortin tuottaman interuptin avulla ja hallitsemaan kortin muistiavaruutta siten, että uusia sampleja pystyi lataamaan lennosta keskusmuistista musiikin soidessa (mikä aiheutti myös fragmentaatiota kortin muistissa). Koska netistä ei katoa mikään, minkä sinne on kerran laittanut, löytyy kirjoittamani moduuliformaatti näköjään vieläkin jostain. Kopion tekstin alle turvaan, koska olen vähän huonosti säilönyt näitä vanhoja tekeleitä.
Kaverini kirjoitti Pascalilla sävellysohjelman käyttöliittymän tuon kirjoittamani rutiinin päälle ja osallistuimmekin Assembly '94:n musacomboon parilla kappaleella, koska silloin oli mahdollista jättää myös oma ohjelma noiden soittamiseen. Kaverillani oli dj-hommiensa myötä kotonaan usein kilowatin ammattivahvistin ja rakentamansa 15 tuuman refleksikaiutin bassoille ja kuuntelimme taustalla tämäntapaista humppaa nuoruuden huumassa:
Musiikkirutiinini tiedostoformaatti, josta näkyy myös kätevästi tuetut ominaisuudet:
From: husberg@proffa.cc.tut.fi (Husberg Fredrik)
Newsgroups: alt.binaries.sounds.utilities
Subject: Re: Playemd: newest version & EMD module format specs
Date: 24 Aug 1994 14:14:53 GMT
Organization: Tampere University of Technology, Computing Centre
Dirk / ELASTIK
husberg@proffa.cc.tut.fi
=====================================================================
EMD module/song format for (A)dvanced 16-(B)it (T)racker ABT
=====================================================================
Last update 14.8.1994
---------------------------------------------------------------------
Note!
This is NOT the final version of the EMD-module format. There
will be some minor changes in the near future (like new features) but
they are always placed to those entries and that is the
reason why they are not going to affect playing of these old EMDs
with future versions of ABT. This file has been written in hurry and
because of that there may be some mistakes in this file. If you have
questions concerning EMD or ABT please contact:
Dirk/Elastik
Internet:
husberg@lehtori.cc.tut.fi
husberg@proffa.cc.tut.fi
Snailmail:
Koulutie 10
SF-36200 Kangasala
Finland
---------------------------------------------------------------------
What is EMD? It's new sample based sound/music module format.
The letters E,M and D come from the words Extended MOD. EMD-module format
is much like the normal MOD but with new features and it's designed to be
used with the ABT, Advanced 16Bit Tracker made by Kari Visala and Mikko
Blomqvist. Here is the short description of the current EMD format, which
should help you to use EMDs freely in your own projects.
PLEASE, NO MODIFICATIONS
-------------------
EMD-file structure:
-------------------
OFFSET 0 Header:
=================
size description
--------------------------------------------------------------------------
4 bytes 'EMOD' , these four bytes are used to identify an EMD-file
1 byte Version number of the module 4 high order bits = major version
4 low order bits = minor version
for example version 1.0 -> 00010000b
8 bytes (for later use..)
OFFSET 13 Module-info part:
============================
size description
--------------------------------------------------------------------------
32 bytes Name of the song (32 chars, no any ending chracters) IBM-ascii
1 byte Number of the instruments
2 bytes Length of the pattern list
1 byte Number of the patterns-1 (0 = there is only 1 pattern)
32 bytes Values of the pan positions of the channels in the beginning of
the song. (0-full left, 15-full right) byte/channel
2 bytes Starting tempo, default=125 bpm
bpm = beats per minute (8 rows in pattern = 1 beat)
1 byte 0 = module
1 = song ( no sample wave-data stored to this file)
1 byte 0 = normal patterns
1 = packed patterns :-)
1 byte Number of channels (1..32)
1 byte This byte is only for modules:
0 = Samples are stored in normal 16-bit signed format (like WAV)
1 = Samples are in coded format
Coding of the samples:
This next process has been done to every single byte of sample
raw data when module is saved: (so, if you want to uncode samples,
do the steps backwards)
1. step first and last bit of byte changed
2. step neg
Here is the code I use to uncode these:
mov al,[byte of sample data]
mov bl,al
and bl,10000000b
shr bl,7
mov bh,al
and bh,00000001b
shl bh,7
and al,01111110b
add al,bl
add al,bh
mov [sample data],al ; uncoded byte saved
The reason for coding those samples was that we didn't want
that everyone would be able to rip our 16 bit samples straight
from our asm'94 compo-modules, but I thought that this file
format description should be complete and so I included uncoding
info. This feature won't have any future use.
9 bytes
OFFSET 96 Sample info part:
============================
This part of the file contains all settings and info for the samples.
Sample wave-data is not here. One sample takes 250 bytes of space and
they are saved to the module consecutive. So, the size of this part
is number of instruments * 250 bytes
size description
--------------------------------------------------------------------------
1 byte Number of the instrument in pattern data (1-99)
4 bytes Length of the sample in bytes
32 bytes Name of the sample (no any ending characters) IBM-ascii
12 bytes File name of the sample (used with song files)
format: XXXXXXXX.XXX
72 bytes Breakpoint information: ( 18*4 bytes )
18 breakpoints:
4 bytes = Offset from the beginning of the sample in words
So, if sample is 50000 bytes long, then 25000 in
breakpoints is the end of the sample.
2 consecutive breakpoints = 1 loop (9 loops)
9 bytes Directions of the loops
1 byte/loop : 0 = no loop
1 = forward loop
2 = bi-directional loop
1 byte Active loop of the sample in the beginning of the song :
0 = no loop on (default)
1..9 = loop #
108 bytes ADSR values (9 different ADSR for each instrument) (9*12 bytes)
1 ADSR value:
4 bytes offset(place) of the decay point
4 bytes offset(place) of the sustain point
1 byte Attack value ( always in the start of the sample)
1 byte Decay value
1 byte Sustain value
1 byte Release value ( always in the end of the sample)
ADSR control for samples isn't used by ABT in any way.
Only the space is reserved for these values. It is very likely
that ABT will never use this feature in the future because of
the limitations of the module-style music and these bytes could
be replaced by some other data.
1 byte Active ADSR number 1-9 (0= no ADSR)
2 bytes overall volume of the sample in the beginning of the song
value from 0 to 4095.
1 byte finetune+128 ( Default=128, player converts this value to a
signed byte, -128..127: 0 = normal finetune.
-64 = halfnote downwards
64 = halfnote upwards
1 byte midi on/off, 0 = normal GUS sample
1 = midi instrument
1 byte midi channel+1, 0...16
0 -> none,
1 -> channel 0, ... , 16 -> channel 15
1 byte midi preset instrument number
0 -> no preset instrument choosed from the ABT,
note is played on synthesizer with choosed instrument
1 byte Direct load on/off
1 = instrument is loaded directly to gusdram
0 = instrument only in EMS in the start of the song
3 bytes
OFFSET 96+250*inst# Pattern list:
==================================
Here is the play order of patterns. Length of this part is in the
module info part. One pattern takes 1 byte of memory and because of
that song can only contain 255 different patterns. Numbers of the patterns
are stored here so that the first byte is the number of the first played
pattern and so on...
OFFSET 96+250*inst#+pattlstsize Patterns:
===========================================
This part of the file contains all data for the patterns.
Patterns are stored here so that the first pattern here is
the pattern marked with 0 in the patternlist, second is pattern 1 and so on.
Size of a pattern is 13+channel#*pattern_length*5 bytes.
size description
--------------------------------------------------------------------------
8 bytes Name of the pattern in IBM-ascii format with no ending character
1 byte Length of the pattern (how many rows, default=64)
4 bytes
Here is some kind of pseudo-code presenting the way ABT stores patterns to
EMD file:
for y=1 to pattern_length
for x=1 to #channels
1 byte Note = 0..255, 0 = no note,
1 = C-1 and so on...
If pattern-packing is enabled in the moduleinfo
part:
255 = because note,sample#,effect and params would
all be zeros, program saves only one byte
here (255) and those other 4 bytes aren't
saved.
1 byte Number of the sample, 0=empty instrument, only stops playing sample
1 byte Effect command 1-99, 0 = no effect
1 byte Parameter 1 for the effect
1 byte Parameter 2 for the effect
next x
next y
OFFSET XXXX Channel volumes:
==============================
Here are the beginning volumes for each channel.
One volume takes one byte, which is from 0 to 255 (default=255,max)
and 32 channels are always stored. So, the size of this part is
always 32 bytes.
OFFSET XXXX Raw wave data of samples:
=======================================
Only modules have this part of an EMD-file, in songs there is no sample raw
data. All samples are stored here without any marks between them.
Samples are stored so that the first sample here has the smallest number.
All data is signed 16-bit, which is same as 16-bit wav files.
Sample data can also be in coded format (read the module-info part).
End of EMD-file.
========================================================================
Currently supported effect commands of ABT:
========================================================================
There will be more effect commands in the near future, but here are all
the basic commands for ABT, which are already ready (midi efx-commands
aren't here yet) :
Effect command is a number between 1 and 99. One effect can have maximum
2 parameters, both 0-99, or one parameter from 0 to 9999 (par1*100+par2).
Efx# Description and parameters
----------------------------------------------------------------------------
1 Set volume 0-4095 (values is exponential)
11 Set linear volume 0-511
3 Set tempo 0-???? (beats per minute, 125=default, 8 rows = beat)
5 Set pan-value for a channel: param1=channel#(0-31),
if param1>31 , then current channel (where the efx-command is)
will be used for effect.
param2=pan-value from 0(left)-15(right)
17 Break pattern: This efx-command jumps to the selected row of
next pattern in the song. (next row after efx isn't played)
param1=row# of next pattern
18 Position jump: Changes the song position and the row# played next.
param1=which pattern in pattern list (0=first)
param2=which row
2 Volume slide: param1&2=new volume (0-4095) (slide is exponential)
82 Set length of a volume slide: param1=how many rows volume slide
will take if tempo isn't changed. (0 is also 1 row)
This variable is independent for each of the channels.
6 Pitch up: param1=How many halfnotes upward,
param2=length of bend in rows with current tempo (0 is same as 1)
7 Pitch down: Same as pitch up, but downwards
13 Load&remove sample from gusdram:
param1=number of the instrument to be loaded throught DMA
(0=no sample loaded)
param2=which instrument is unloaded from the gusdram
(0=no instrument unloaded)
22 Set frequency: If this efx-command is on the same row with note,
note isn't played, but only frequency of currently playing
sample is changed to the given note.
15 Effect channel play: Plays unloaded sample from EMS throught DMA.
( This efx-command isn't used yet)
84 Set Vibrato waveform: param1: 0=sine, 1=saw, 2=sqr, 3=ramp down
4 Vibrato: param1=Depth 0-99 (63=halfnote to both directions)
param2=speed of the vibrato 0-99: (param2/5)Hz 1/5Hz - 20Hz
34 Vibrato off
19 Arpeggio: middle note = basenote+param1*halfnote
high note = basenote+param2*halfnote
Major : 190407 Minor : 190307
89 Set speed of the arpeggio param1=how many notes played during
one row of pattern. (default=3, the whole chord played on
every row of pattern) (0 is same as 3)
9 Tremolo (always sine) param1=depth/4 -> Volume can varies from 0 to
400 in both directions. param2=speed of tremolo(same as vibrato)
38 Tremolo off
24 Note delay: param1:delay 0-99, "100"=next row
Note: All the effects that control the frequency of the sound can be used
simultaneously with effects that control the volume.
joskus 96-97 soodasimme (Päivölä - Suomi sanakirja) useimmat yöt DMI:n labrassa aina aamu viiteen saakka. Kyseissä huoneessa ei ollut lainkaan ikkunoita sekä rikkinäinen ilmastointi, joka piti huoneen talvella shortsikeleissä, joten periaatteessa siellä oli helppo unohtaa kellon- ja vuodenaika. Tilassa oli Genelecin monitorit, joista kuuntelimme musiikkia vuoroissa hommia tehdessä. Meidän lisäksi siellä työskenteli yksi kaveri, joka jätti vaikutuksen mm. koodaamalla copper barit ms-dos:n debugilla 10 minuutissa.* Alla kolme piisiä, jotka jäivät mieleen hänen cd:ltään, kun loput kuulostivat lähinnä siltä, että kaiuttimet hajosivat.
Silloin koodasin C++:lla ray tracerin tilavuusmalleille ja visualisoimme mm. The Visible Human Project:in datasetin. Alla ohjelman tuottama esimerkkikuva. Kaverimme teki sitten vastaavan ohjelman ms-dos:lle assemblyllä (oma versioni oli x-ikkunointia käyttävä), jonka möimme Heurekan tiedekeskuksen kiertävään näyttelyyn.
* Olen tuntenut vain yhden toisen kaverin, joka oli yhtä ripeä koodaamaan. IOI-valmennuksessa joskus annoin lämmittelytehtävän, jossa ohjelmalle annettiin syötteenä palikkapinon etu- ja sivuprofiilit ja ohjelman piti tulostaa minimi- ja maksimimäärät palikoita, jotka voivat tuottaa kyseisen profiilin. Alle 10 minuutin kuluttua paperien jakamisesta minulle tuotiin valmis toimiva ohjelma.
Future Crew:n Second Reality-demon näkeminen -93 keravalaisen koulun 40-asteisessa liikuntasalissa vaikutti syvästi nuoreen minuun. Kannattaa katsoa myös Demoscene-dokumentti tästä legendaarisesta demogroupista ja alla Youtube-linkki autenttiseen videopätkään demon tekemisestä.
Toisaalta, pitkälle on tultu vuodesta -93, kun katsoo alla olevaa vuoden 2007 Assemblyjen voittajademoa tai vuonna 2008 julkaistua Masagin-demoa. Koneiden tehon kasvettua ja kiihdytettyjen näytönohjainten myötä ohjelmoinnin rooli demoissa on pienentynyt ja grafiikalla sekä musiikilla on suurempi rooli.