//////////////////////////////// ////// 31EDO PIANO V. 0.5 ////// ///////// written in ///////// ////////// Pixilang ////////// ///////////// by ///////////// // Hs, also known as iShrimp, // //////// specially for //////// ///////// Warmplace.Ru ///////// //////////////////////////////// // Settings samplerate = 44100 voices = 10 lowpassfilter = 1 // will the sound decay with LPF? keywidth = 0 // from 4 to 128; 0 - auto greykeyheight = 6 // from 1 to 8; 6 is default blackkeyheight = 4 // from 1 to 8; 4 is default visualizeaudio = 1 displayfps = 1 storesettings = 1 // will the timbre and key mapping be stored? // End of settings // Get screen size xsize = get_xsize(get_screen()) ysize = get_ysize(get_screen()) xsize2 = xsize div 2 ysize2 = ysize div 2 // N.of harmonics = 33. N.of samples = 64. spqa = new(33, 1, FLOAT32) // square of amplitude, real, imaginary parts spre = new(64, 1, FLOAT32) spim = new(64, 1, FLOAT32) re = new(64, 1, FLOAT32) // buffers for FFT function im = new(64, 1, FLOAT32) samp = new(64, 1, FLOAT32) // sample amplitudes from -1 to 1 audiosamp = new(64, 1, FLOAT32) // this is a copy for audio synthesizer wasedited = 0 // Generate initial wave and calculate its spectrum if storesettings {stream = fopen("31.dat", "rb")} else {stream = 0} if stream { fread(samp, 256, stream) op_cn(OP_LIMIT_TOP, samp, 1.0) op_cn(OP_LIMIT_BOTTOM, samp, -1.0) } else { samp[0] = 0 i = 1 while (i < 16) { samp[i] = samp[i-1] * 0.75 + 0.251 i + 1 } i = 16 while (i < 32) { samp[i] = 1 - samp[i-16] i + 1 } i = 32 while (i < 64) { samp[i] = -samp[63-i] i + 1 } } directfft() copy(audiosamp, samp) // Calculate screen areas: spectrum, waveform, keyboard spcol = (xsize2 - 22) div 33 spwidth = spcol * 33 spx = xsize2 - spwidth wavewidth = xsize - spwidth - 44 separatorx = (wavewidth - spwidth) div 2 if keywidth { kw = keywidth if kw > 128 { kw = 128 } if kw > xsize2 { kw = xsize2 } if kw < 4 { kw = 4 } } else { kw = xsize div 63 if kw < 4 { kw = 4 } } octwidth = kw * 31 wholeoctaves = xsize div (octwidth) // Octaves used are from 0th to 8th if wholeoctaves > 6 { kw = xsize div 155 + 1 octwidth = kw * 31 wholeoctaves = xsize div (octwidth) } if wholeoctaves > 0 { startoct1 = 4 // A4 = 440 Hz endoct1 = wholeoctaves + 5 if endoct1 > 8 { startoct1 - (endoct1 - 8) endoct1 = 8 offset1 = xsize2 - octwidth * (wholeoctaves + 1) } else { offset1 = -(wholeoctaves * octwidth) div 2 - octwidth } startoct2 = 4 - wholeoctaves endoct2 = 5 if startoct2 < 0 { endoct2 - startoct2 startoct2 = 0 offset2 = -xsize2 } else { offset2 = offset1 } } else { startoct1 = 5 endoct1 = 5 offset1 = xsize2 - octwidth startoct2 = 5 endoct2 = 5 offset2 = -xsize2 } firstkey = startoct2 * 31 lastkey = endoct1 * 31 + 30 kvblock = ysize2 div 16 if kvblock <= 0 { kvblock = 1 } rowy1 = ysize2 - kvblock * 16 - 1 rowy2 = ysize2 - kvblock * 8 - 1 swh = rowy1 + ysize2 - 24 if swh < 32 { swh = 32 } kw1 = kw - 1 // key sizes for faster display kw2 = kw * 2 - 1 kw4 = kw * 4 - 1 kw5 = kw * 5 - 1 kwd2 = kw div 2 if greykeyheight < 1 || greykeyheight > 8 {greykeyheight = 6} if blackkeyheight < 1 || blackkeyheight > 8 {blackkeyheight = 8} khwhite = kvblock * 8 - 1 khgrey = kvblock * greykeyheight - 1 khblack = kvblock * blackkeyheight - 1 touch = new(10) // Touch status: 0 - inactive, 1 - active touchx = new(10) touchy = new(10) clean (touch) clean (touchx) clean (touchy) key = new(279) // Keyboard status: 0 - inactive, 1 - being pressed, 2 - pressed, -1 - being released. For PC keyboard: 0, 3, 4, -2 keyvoice = new(279) // a voice corresponding to that key keycolour = new(279) keycolourinactive = new(279) keycolouractive = new(279) clean (key) clean (keyvoice) // PC keyboard names: from 0 to 159. If a character is ' ' (32) - this key is not supported. \\ interpretiruetsja kak \ kbd = " BT R ' *+,-./0123456789 ; = [\\] `abcdefghijklmnopqrstuvwxyz ^V<>IDHE{}A SC " keymap = new(279, 2, INT16) // Number of PC key that's assigned to synth key (two for each), or 32 if none if stream { fread(keymap, 1116, stream) fclose(stream) } else { clean (keymap, 32) } // Key colours kcwhite = #F0F0F0 kcgrey = #A0A0A0 kcblack = #303030 kcactive = #F01010 kbdcolour = #33AAFF notefreq = new(279, 1, FLOAT32) i = 0 while (i < 279) { notefreq[i] = 440 * pow(2, (i - 148) / 31) // A4 = 440 Hz keycolourinactive[i] = getkeycolour(i % 31) keycolouractive[i] = get_blend(kcactive, keycolourinactive[i], 70) keycolour[i] = keycolourinactive[i] i + 1 } // Synthesizer if voices <= 0 { voices = 1 } if voices >= 32 { voices = 32 } frequency = new(voices, 1, FLOAT32) phase = new(voices, 1, FLOAT32) // typically from 0 to 1. Result = sin(2*pi*phase). phasedelta = new(voices, 1, FLOAT32) // =frequency/samplerate amplitude = new(voices, 1, FLOAT32) // from 0 to 1 value = new(voices, 1, FLOAT32) // it is stored for low-pass filter vmode = new(voices) // 0 - silent, 1 - pressed, 2 - released clean (value) clean (vmode) queue = 0 // current voice to be activated decay1 = 1 - 0.15 / samplerate decay2 = 1 - 1.5 / samplerate suppression = 0.0 // for low-pass filter pi2 = 2.0 * M_PI amp = 0.0 // dlja raznyh vremennyh nuzhd ampd = 0.0 // to zhe, no dlja potoka display // Audio visualization avsize = xsize avbuf = new(avsize) clean(avbuf) avaxis = (rowy1 - ysize2) div 2 avscale = (rowy1 + ysize2) div 2 //avmutex = mutex_create() if lowpassfilter { set_audio_callback(audio_callback_filtered, 0, samplerate, INT16, 1) } else { set_audio_callback(audio_callback, 0, samplerate, INT16, 1) } text = "" char = " " fn audio_callback_filtered( $stream, $userdata, $channels, $frames, $output_time_in_system_ticks ) { $f = 0 while($f < $frames) { $output = 0.0 $v = 0 while($v < voices) { if vmode[$v] { if vmode[$v] == 1 { amplitude[$v] * decay1 } else { amplitude[$v] * decay2 } phase[$v] = mod(phase[$v] + phasedelta[$v], 1.0) suppression = exp(-frequency[$v] / samplerate / (sqrt(1 / amplitude[$v] / amplitude[$v] - 1) / pi2)) value[$v] = suppression * value[$v] + (1.0 - suppression) * audiosamp[phase[$v] * 64] //* amplitude[$v] $output + value[$v] } $v + 1 } $channels[0][$f] = $output * 2048 $f + 1 } if visualizeaudio { if avsize > $frames { avsize = $frames } copy(avbuf, $channels[0], 0, 0, avsize) } ret(1) } fn audio_callback( $stream, $userdata, $channels, $frames, $output_time_in_system_ticks ) { $f = 0 while($f < $frames) { $output = 0.0 $v = 0 while($v < voices) { if vmode[$v] { if vmode[$v] == 1 { amplitude[$v] * decay1 } else { amplitude[$v] * decay2 } phase[$v] = mod(phase[$v] + phasedelta[$v], 1.0) $output + audiosamp[phase[$v] * 64] * amplitude[$v] } $v + 1 } $channels[0][$f] = $output * 2048 $f + 1 } if visualizeaudio { //mutex_lock(avmutex) if avsize > $frames { avsize = $frames } copy(avbuf, $channels[0], 0, 0, avsize) //mutex_unlock(avmutex) } ret(1) } continue_flag = 1 display_thrd = thread_create(display, THREAD_FLAG_AUTO_DESTROY) while 1 { // first: ready to release all the keys pressed by mouse; continue 3 -> 4 i = firstkey while (i <= lastkey) { if key[i] < 0 { key[i] = 0 } if key[i] > 0 && key[i] < 3 { key[i] = -1 } if key[i] == 3 {key[i] = 4} i + 1 } // get events while(get_event()) { if EVT[EVT_TYPE] == EVT_QUIT { set_audio_callback(-1) continue_flag = 0 if storesettings { stream = fopen("31.dat", "wb") if stream { fwrite(samp, 256, stream) fwrite(keymap, 1116, stream) fclose(stream) } } halt } if EVT[EVT_TYPE] == EVT_MOUSEBUTTONDOWN { touch[0] = 1 touchx[0] = EVT[EVT_X] touchy[0] = EVT[EVT_Y] } if EVT[EVT_TYPE] == EVT_MOUSEMOVE { touchx[0] = EVT[EVT_X] touchy[0] = EVT[EVT_Y] } if EVT[EVT_TYPE] == EVT_MOUSEBUTTONUP { touch[0] = 0 } if EVT[EVT_TYPE] == EVT_TOUCHBEGIN { touch[EVT[EVT_SCANCODE]] = 1 touchx[EVT[EVT_SCANCODE]] = EVT[EVT_X] touchy[EVT[EVT_SCANCODE]] = EVT[EVT_Y] } if EVT[EVT_TYPE] == EVT_TOUCHMOVE { touchx[EVT[EVT_SCANCODE]] = EVT[EVT_X] touchy[EVT[EVT_SCANCODE]] = EVT[EVT_Y] } if EVT[EVT_TYPE] == EVT_TOUCHEND { touch[EVT[EVT_SCANCODE]] = 0 } if EVT[EVT_TYPE] == EVT_BUTTONDOWN { kbdkey = EVT[EVT_KEY] if kbdkey > 0 && kbdkey < 160 { if kbd[kbdkey] > 32 // podderzhivaemaja klavisha? { i = firstkey while (i <= lastkey) { if keymap[i, 0] != kbdkey && keymap[i, 1] != kbdkey // not assigned { if key[i] == -1 // was pressed with mouse { keymap[i, 1] = keymap[i, 0] keymap[i, 0] = kbdkey } } else { // emulirovat' nazhatie if key[i] <= 0 // ne nazhata s klaviatury { key[i] = 3 } } i + 1 } } else { if kbdkey == 32 // space - clear keys { i = firstkey while (i <= lastkey) { if key[i] == -1 // was pressed with mouse { keymap[i, 0] = 32 keymap[i, 1] = 32 } i + 1 } } } } } if EVT[EVT_TYPE] == EVT_BUTTONUP { kbdkey = EVT[EVT_KEY] if kbdkey > 0 && kbdkey < 160 { if kbd[kbdkey] > 32 // podderzhivaemaja klavisha? { i = firstkey while (i <= lastkey) { if keymap[i, 0] == kbdkey || keymap[i, 1] == kbdkey // naznachena dlya etoj noty { if key[i] > 2 // nazhata s klaviatury { key[i] = -2 } } i + 1 } } } } } // Touch processing editwave = 0 editspec = 0 i = 0 while (i < 10) { if touch[i] { if touchy[i]>=-ysize2 && touchy[i]<=swh-ysize2 // Upper part editing { n = (touchx[i]+xsize2)*64 div wavewidth // Waveform if n>=0 && n<64 { samp[n] = 1-2*(touchy[i]+ysize2)/swh editwave = 1 } n = (touchx[i]-spx) div spcol // Spectrum if n>=0 && n<33 && editwave == 0 { amp = pow(10, 0.4 - 8.8*(touchy[i]+ysize2)/swh) * 4096 // square of amplitude if spqa[n]>0.0000000001 { amp = sqrt (amp / spqa[n]) // Get a coefficient spre[n] * amp spim[n] * amp if n>0 && n<32 // Not to multiply 0th and 32nd harmonics twice { spre[64-n] * amp // Po rezul'tatu FFT garmoniki 0 i 32 - dejstvitel'nye chisla spim[64-n] * amp // (tol'ko kosinus); garmoniki 1...31 simmetrichny 63...33. } spqa[n] * amp * amp } else // Vo izbezhanie delenija na 0, ili na pochti 0 { spre[n] = amp spim[n] = 0 if n>0 // There is no 64th element { spre[64-n] = amp spim[64-n] = 0 } spqa[n] = amp * amp } editspec = 1 } } else { if touchy[i] >= rowy2 // Lower row { x0 = touchx[i] - offset2 y0 = touchy[i] - rowy2 o = x0 div octwidth // N.of octave, 0 is first from the left in row x0 - o * octwidth n = findkey(x0 div kw, y0 div kvblock) + (o + startoct2) * 31 if key[n] < 0 {key[n] = 2} if key[n] == 0 {key[n] = 1} } else { if touchy[i] >= rowy1 // Upper row { x0 = touchx[i] - offset1 y0 = touchy[i] - rowy1 o = x0 div octwidth // N.of octave, 0 is first from the left in row x0 - o * octwidth n = findkey(x0 div kw, y0 div kvblock) + (o + startoct1) * 31 if key[n] < 0 {key[n] = 2} if key[n] == 0 {key[n] = 1} } } } } i + 1 } if editwave { directfft() } else // Editing waveform has greater priority { if editspec { inversefft() } else { if wasedited == 1 // if nothing is being edited now, but something was 1 frame ago: { spqa[0] = 0 // remove the constant offset spre[0] = 0 spim[0] = 0 amp = op_cn(OP_SUM, samp, 0) op_cn(OP_SUB, samp, amp / 64) amp = op_cn(OP_MAXABS, samp, 0) // find the maximum and normalize if amp > 1 { op_cn(OP_DIV, samp, amp) op_cn(OP_DIV, spre, amp) op_cn(OP_DIV, spim, amp) op_cn(OP_DIV, spqa, amp * amp) } copy(audiosamp, samp) } } } if editwave | editspec { wasedited = 1 } else { wasedited = 0 } i = firstkey while (i <= lastkey) // set the notes on/off { if key[i] == 1 || key[i] == 3 { vmode[queue] = 0 frequency[queue] = notefreq[i] phase[queue] = 0 phasedelta[queue] = frequency[queue] / samplerate amplitude[queue] = 1 keyvoice[i] = queue vmode[queue] = 1 queue + 1 if queue >= voices { queue = 0 } keycolour[i] = keycolouractive[i] } if key[i] < 0 { vmode[keyvoice[i]] = 2 keycolour[i] = keycolourinactive[i] } i + 1 } } fn display() // Vyneseno v otdel'nyj potok { while continue_flag { clean(text) transp(96) // Clear screen and display the data clear() if visualizeaudio { transp(255) ii = 0 nn = -avsize div 2 while (ii < avsize) { y00 = avaxis - avbuf[ii] * avscale div 8192 if y00 < avaxis {fbox(nn, y00, 1, avaxis - y00, #E030E0)} else {fbox(nn, avaxis, 1, y00 - avaxis, #E030E0)} ii + 1 nn + 1 } transp(96) } fbox (-xsize2, -ysize2, wavewidth, swh, #106000) fbox (spx, -ysize2, spwidth, swh, #503000) transp(255) // Prozrachnost' zamedljaet otrisovku v ~3.5 raza x00 = -wavewidth / 128.0 - xsize2 y00 = (1 - samp[63]) * swh / 2 - ysize2 ii = 0 while (ii < 64) // Draw the waveform { x1 = (wavewidth * (ii * 2 + 1)) / 128.0 - xsize2 y1 = (1 - samp[ii]) * swh / 2 - ysize2 line (x00, y00, x1, y1, #20F000) fbox (x1-1, y1-1, 3, 3, #20F000) x00 = x1 y00 = y1 ii + 1 } line (x00, y00, wavewidth - xsize2, (y1 + (1 - samp[0]) * swh / 2 - ysize2) / 2, #20F000) transp(160) ii = 0 while (ii < 33) // Draw the spectrum { ampd = spqa[ii] / 4096 // this is square of amplitude; from 0 to 1 if ampd > 0.0000000001 {ampd = log10(ampd)} else {ampd = -10.0} // 1 unit = 5 dBs; form 0 to -50 dB y00 = (0.4 - ampd) * swh / 8.8 - ysize2 // y axis from 2 to -42 dB y1 = swh - ysize2 if y00 >= y1 {y00 = y1 - 1} fbox(spcol * ii + spx, y00, spcol - 1, y1 - y00, #F08000) ii + 1 } transp(255) // Draw the keyboard oo = startoct1 while (oo <= endoct1) // Draw first keyboard row { octx = offset1 + (oo - startoct1) * octwidth startkey = oo * 31 drawkbd(rowy1) oo + 1 } oo = startoct1 while (oo <= endoct1) // Print key names { octx = offset1 + (oo - startoct1) * octwidth ii = 0 while (ii <= 30) { nn = oo * 31 + ii // number of key if keymap[nn, 0] != 32 { char[0] = kbd[keymap[nn, 0]] print (char, octx + kw * ii + kwd2, rowy1, kbdcolour, TOP) if keymap[nn, 1] != 32 { char[0] = kbd[keymap[nn, 1]] print (char, octx + kw * ii + kwd2, rowy1 + 12, kbdcolour, TOP) } } ii + 1 } oo + 1 } oo = startoct2 while (oo <= endoct2) // Draw second keyboard row { octx = offset2 + (oo - startoct2) * octwidth startkey = oo * 31 drawkbd(rowy2) oo + 1 } oo = startoct2 while (oo <= endoct2) // Print key names { octx = offset2 + (oo - startoct2) * octwidth ii = 0 while (ii <= 30) { nn = oo * 31 + ii // number of key if keymap[nn, 0] != 32 { char[0] = kbd[keymap[nn, 0]] print (char, octx + kw * ii + kwd2, rowy2, kbdcolour, TOP) if keymap[nn, 1] != 32 { char[0] = kbd[keymap[nn, 1]] print (char, octx + kw * ii + kwd2, rowy2 + 12, kbdcolour, TOP) } } ii + 1 } oo + 1 } print ("WAVEFORM", -xsize2, -ysize2, #90D060, TOP | LEFT)// Draw text labels print ("HARMONICS", xsize2, -ysize2, #D0A060, TOP | RIGHT) print ("0dB", spx, 2 * swh div 44 - ysize2, #C0C0C0, RIGHT) print ("-10dB", spx, 12 * swh div 44 - ysize2, #C0C0C0, RIGHT) print ("-20dB", spx, 22 * swh div 44 - ysize2, #C0C0C0, RIGHT) print ("-30dB", spx, 32 * swh div 44 - ysize2, #C0C0C0, RIGHT) print ("-40dB", spx, 42 * swh div 44 - ysize2, #C0C0C0, RIGHT) print ("0", spcol div 2 + spx, swh - ysize2 + 1, #C0C0C0, TOP) print ("2", 5 * spcol div 2 + spx, swh - ysize2 + 1, #C0C0C0, TOP) print ("4", 9 * spcol div 2 + spx, swh - ysize2 + 1, #C0C0C0, TOP) print ("8", 17 * spcol div 2 + spx, swh - ysize2 + 1, #C0C0C0, TOP) print ("16", 33 * spcol div 2 + spx, swh - ysize2 + 1, #C0C0C0, TOP) print ("24", 49 * spcol div 2 + spx, swh - ysize2 + 1, #C0C0C0, TOP) print ("32^", xsize2, swh - ysize2 + 1, #C0C0C0, TOP | RIGHT) if displayfps { num_to_str (text, FPS) print (text, 1 - xsize2, swh - ysize2 + 1, #307020, TOP | LEFT) } print ("31EDO keyboard", 0, rowy1 - 1, #F080F0, BOTTOM) frame() } } fn drawkbd($yoffset) { fbox(octx, $yoffset, kw4, khwhite, keycolour[startkey+1]) fbox(octx + kw * 4, $yoffset, kw5, khwhite, keycolour[startkey+6]) fbox(octx + kw * 9, $yoffset, kw4, khwhite, keycolour[startkey+11]) fbox(octx + kw * 13, $yoffset, kw4, khwhite, keycolour[startkey+14]) fbox(octx + kw * 17, $yoffset, kw5, khwhite, keycolour[startkey+19]) fbox(octx + kw * 22, $yoffset, kw5, khwhite, keycolour[startkey+24]) fbox(octx + kw * 27, $yoffset, kw4, khwhite, keycolour[startkey+29]) fbox(octx, $yoffset, kw1, khgrey, keycolour[startkey]) fbox(octx + kw * 2, $yoffset, kw2, khgrey, keycolour[startkey+2]) fbox(octx + kw * 4, $yoffset, kw2, khgrey, keycolour[startkey+5]) fbox(octx + kw * 7, $yoffset, kw2, khgrey, keycolour[startkey+7]) fbox(octx + kw * 9, $yoffset, kw2, khgrey, keycolour[startkey+10]) fbox(octx + kw * 12, $yoffset, kw1, khgrey, keycolour[startkey+12]) fbox(octx + kw * 13, $yoffset, kw1, khgrey, keycolour[startkey+13]) fbox(octx + kw * 15, $yoffset, kw2, khgrey, keycolour[startkey+15]) fbox(octx + kw * 17, $yoffset, kw2, khgrey, keycolour[startkey+18]) fbox(octx + kw * 20, $yoffset, kw2, khgrey, keycolour[startkey+20]) fbox(octx + kw * 22, $yoffset, kw2, khgrey, keycolour[startkey+23]) fbox(octx + kw * 25, $yoffset, kw2, khgrey, keycolour[startkey+25]) fbox(octx + kw * 27, $yoffset, kw2, khgrey, keycolour[startkey+28]) fbox(octx + kw * 30, $yoffset, kw1, khgrey, keycolour[startkey+30]) fbox(octx + kw * 3, $yoffset, kw1, khblack, keycolour[startkey+3]) fbox(octx + kw * 4, $yoffset, kw1, khblack, keycolour[startkey+4]) fbox(octx + kw * 8, $yoffset, kw1, khblack, keycolour[startkey+8]) fbox(octx + kw * 9, $yoffset, kw1, khblack, keycolour[startkey+9]) fbox(octx + kw * 16, $yoffset, kw1, khblack, keycolour[startkey+16]) fbox(octx + kw * 17, $yoffset, kw1, khblack, keycolour[startkey+17]) fbox(octx + kw * 21, $yoffset, kw1, khblack, keycolour[startkey+21]) fbox(octx + kw * 22, $yoffset, kw1, khblack, keycolour[startkey+22]) fbox(octx + kw * 26, $yoffset, kw1, khblack, keycolour[startkey+26]) fbox(octx + kw * 27, $yoffset, kw1, khblack, keycolour[startkey+27]) } fn findkey($kx, $ky) // Plohoj kod? Byvaet i huzhe... { if $kx <= 3 {$kn = 1} else { if $kx <= 8 {$kn = 6} else { if $kx <= 12 {$kn = 11} else { if $kx <= 16 {$kn = 14} else { if $kx <= 21 {$kn = 19} else { if $kx <= 26 {$kn = 24} else {$kn = 29} } } } } } if $ky < greykeyheight { if $kx == 0 {$kn = 0} else { if $kx == 2 || $kx == 3 {$kn = 2} else { if $kx == 4 || $kx == 5 {$kn = 5} else { if $kx == 7 || $kx == 8 {$kn = 7} else { if $kx == 9 || $kx == 10 {$kn = 10} else { if $kx == 12 {$kn = 12} else { if $kx == 13 {$kn = 13} else { if $kx == 15 || $kx == 16 {$kn = 15} else { if $kx == 17 || $kx == 18 {$kn = 18} else { if $kx == 20 || $kx == 21 {$kn = 20} else { if $kx == 22 || $kx == 23 {$kn = 23} else { if $kx == 25 || $kx == 26 {$kn = 25} else { if $kx == 27 || $kx == 28 {$kn = 28} else { if $kx == 30 {$kn = 30} } } } } } } } } } } } } } } if $ky < blackkeyheight { if $kx==3||$kx==4||$kx==8||$kx==9||$kx==16||$kx==17||$kx==21||$kx==22||$kx==26||$kx==27 {$kn = $kx} } ret ($kn) } fn getkeycolour($kn) // argument ot 0 do 30 { if $kn==1||$kn==6||$kn==11||$kn==14||$kn==19||$kn==24||$kn==29 {ret(kcwhite)} if $kn==3||$kn==4||$kn==8||$kn==9||$kn==16||$kn==17||$kn==21||$kn==22||$kn==26||$kn==27 {ret(kcblack)} ret(kcgrey) } fn directfft() { copy (re, samp) clean (im) fft (0, im, re, 64) copy (spre, re) copy (spim, im) op_cc (OP_MUL, re, re, 0, 0, 33) op_cc (OP_MUL, im, im, 0, 0, 33) op_cc (OP_ADD, re, im, 0, 0, 33) copy (spqa, re, 0, 0, 33) // Amplituda hranitsja v vide kvadrata amplitudy } fn inversefft() { copy (re, spre) copy (im, spim) fft (1, im, re, 64) copy (samp, re) }