├── COPYING ├── README.md ├── flow.c ├── flow2.c ├── flow3.c ├── flow4.c ├── flow5.c ├── flow_param.c └── period.py /COPYING: -------------------------------------------------------------------------------- 1 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 2 | Version 2, December 2004 3 | 4 | Copyright (C) 2019 Olga Ustiuzhanina 5 | 6 | Everyone is permitted to copy and distribute verbatim or modified 7 | copies of this license document, and changing it is allowed as long 8 | as the name is changed. 9 | 10 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 11 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 12 | 13 | 0. You just DO WHAT THE FUCK YOU WANT TO. 14 | 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Flow is an nearly infinite procedural composition based around mixing lots of saw waves detuned in a particular manner. To check it out you can either compile and play yourself. 2 | 3 | Please use the highest level of optimization provided by your compiler. Generating music in realtime is a hard task requiring lots of CPU instructions and heavy optimization! 4 | 5 | gcc -Ofast flow.c -o flow 6 | ./flow | aplay -r44100 7 | 8 | Or, you can stream it from my server. Every person streaming it hears the same part of this composition. 9 | 10 | curl -L laserbat.pw/flow | aplay -r 44100 11 | 12 | If you don't have a linux machine nearby, you can just listen to a pre-recorded OGG fragment of this composition: 13 | 14 | https://laserbat.pw/stuff/flow.ogg 15 | 16 | With default constants, flow will keep playing for 13.2 million of years without repeating. This limitation is caused by finite size 64-bit integers. 17 | 18 | flow2.c is slightly different version of this composition, in which synths are played in harmony. 19 | 20 | ## Flow 3 / Pulses 21 | 22 | An extended composition based on flow/flow2 with slight nonlinear dependency between synths. 23 | 24 | gcc -Ofast flow3.c -o flow3 25 | ./flow3 | aplay -c2 -r44100 26 | 27 | Or 28 | 29 | curl -L laserbat.pw/pulses | aplay -c2 -r44100 # Uses 64 synths instead of 128 to reduce load on my VPS 30 | 31 | Feel free to play around with \#define's in source code to find a variation that sounds best to you! 32 | 33 | ## Troubleshooting 34 | 35 | If your PC is too weak to run these programs in real-time, you can speed them up by reducing accuracy of computations. In flow/flow2: 36 | 37 | #define COUNT 7 38 | 39 | Replace 7 with 6 or 5. The program will use 2^COUNT synths to generate music. 40 | 41 | In flow3: 42 | 43 | #define SYNTH_COUNT 128 44 | 45 | Replace 128 with 64 or any number smaller than 128. The program will use SYNTH\_COUNT synths to generate music. 46 | -------------------------------------------------------------------------------- /flow.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2019 Olga Ustiuzhanina 3 | * 4 | * This program is free software. It comes without any warranty, to 5 | * the extent permitted by applicable law. You can redistribute it 6 | * and/or modify it under the terms of the Do What The Fuck You Want 7 | * To Public License, Version 2, as published by Sam Hocevar. See 8 | * the COPYING file for more details. 9 | */ 10 | 11 | #include 12 | #include 13 | 14 | #define COUNT 7 15 | #define DIV 1000 16 | 17 | uint8_t saw(uint64_t t){ 18 | return t & 255; 19 | } 20 | 21 | uint8_t mix(uint64_t t){ 22 | double freq, scale; 23 | uint64_t res = 0; 24 | uint64_t i, j; 25 | 26 | for (i = 0; i < (1< 0){ 31 | freq += (j & 1) * scale; 32 | j >>= 1; 33 | scale /= DIV; 34 | } 35 | 36 | res += saw(t * freq); 37 | } 38 | 39 | return res / (1< 3 | * 4 | * This program is free software. It comes without any warranty, to 5 | * the extent permitted by applicable law. You can redistribute it 6 | * and/or modify it under the terms of the Do What The Fuck You Want 7 | * To Public License, Version 2, as published by Sam Hocevar. See 8 | * the COPYING file for more details. 9 | */ 10 | 11 | #include 12 | #include 13 | 14 | #define C1 0xe5764 15 | #define C2 0xb4a7b 16 | #define C3 0xe96a7 17 | #define C4 0xb9ee9 18 | #define C5 0x24892 19 | 20 | #define MIN_THIRD 1.189 21 | #define MAJ_THIRD 1.126 22 | #define FIFTH 1.498 23 | 24 | #define COUNT 6 25 | #define DIV 1000 26 | 27 | uint64_t global_t; 28 | 29 | uint8_t saw(uint64_t t){ 30 | return ((t & 255) + ((t + 1) & 255) + ((t + 2) & 255)) / 3; 31 | } 32 | 33 | uint8_t mix(uint64_t t){ 34 | double freq, scale; 35 | uint64_t res = 0; 36 | uint64_t i, j; 37 | 38 | for (i = 0; i < (1< 0){ 43 | freq += (j & 1) * scale; 44 | j >>= 1; 45 | scale /= DIV; 46 | } 47 | 48 | res += saw(t * freq); 49 | } 50 | 51 | return res / (1<> 18) & 1) return ( 56 | mix(t) + 57 | mix(t * MAJ_THIRD + C1) + 58 | mix(t * FIFTH + C2) 59 | ) / 3; 60 | 61 | return ( 62 | mix(t) + 63 | mix(t * MIN_THIRD + C1) + 64 | mix(t * FIFTH + C2) 65 | ) / 3; 66 | } 67 | 68 | uint8_t octaves(uint64_t t){ 69 | return ( 70 | chord( t * (1 + saw(global_t / 21) / 1024)) + 71 | chord(2 * t * (1 + saw(global_t / 19) / 1024) + C3) + 72 | chord(4 * t * (1 + saw(global_t / 18) / 768) + C4) 73 | ) / 3; 74 | } 75 | 76 | uint8_t stereo(uint64_t t){ 77 | uint8_t channel = t & 1; 78 | t >>= 1; 79 | 80 | if (channel == 0) return octaves(t); 81 | return octaves(t * 1.01 + C5); 82 | } 83 | 84 | int main(void){ 85 | uint64_t t = 0; 86 | 87 | while(1){ 88 | t += 1; 89 | global_t += 1; 90 | putchar(stereo(t)); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /flow3.c: -------------------------------------------------------------------------------- 1 | // This file produces 44100 Hz, 2 channel, unsigned 8 bit raw PCM 2 | // If you're on linux you can play it using aplay: 3 | // $ ./flow3 | aplay -r44100 -c2 4 | 5 | #include 6 | #include 7 | 8 | // I highly recommend playing with these constants as different values 9 | // produces different timbres and different musical development. 10 | 11 | // Be warned that high SYNTH_COUNT can make this program very slow. 12 | 13 | #define SYNTH_COUNT 128 14 | 15 | #define GLOBAL_PITCH 0.005 16 | #define DETUNE_START 0.001 17 | #define DETUNE_STEP 100 18 | #define FREQ_START 0.8 19 | 20 | #define LEFT_NONLIN 2 21 | #define RIGHT_NONLIN -3 22 | 23 | #define OCTAVE_DOWN 0.5 24 | #define MIN_THIRD 1.2 25 | #define MAJ_THIRD 1.125 26 | #define P_FIFTH 1.5 27 | 28 | double table[SYNTH_COUNT]; 29 | 30 | uint8_t saw(uint64_t t){ 31 | return t & 255; 32 | } 33 | 34 | void init_table(void) { 35 | uint16_t i, j; 36 | 37 | for (i = 0; i < SYNTH_COUNT; i ++){ 38 | double freq, scale; 39 | freq = FREQ_START; 40 | scale = DETUNE_START; 41 | 42 | j = i; 43 | while (j > 0){ 44 | freq += (j & 1) * scale; 45 | j >>= 1; 46 | scale /= DETUNE_STEP; 47 | } 48 | 49 | table[i] = freq; 50 | } 51 | } 52 | 53 | uint8_t mix(uint64_t t, double mul){ 54 | double freq; 55 | double shift = 0, out = 0, max = 0; 56 | double val, amp; 57 | 58 | uint16_t i; 59 | uint8_t chan = t & 1; 60 | 61 | t >>= 1; 62 | 63 | for (i = 0; i < SYNTH_COUNT; i ++){ 64 | freq = table[i]; 65 | amp = ((double)(i + 1) / (double)(SYNTH_COUNT)); 66 | val = saw(0.5 + mul * freq * t + shift); 67 | 68 | shift += val; 69 | max += amp; 70 | 71 | out += val * (chan ? amp : 1 - amp); 72 | shift += chan ? LEFT_NONLIN : RIGHT_NONLIN; 73 | } 74 | 75 | return (uint8_t)(out / max + 0.5); 76 | } 77 | 78 | uint8_t chord(uint64_t t, double mul){ 79 | return ( 80 | mix(t, mul) + 81 | mix(t, mul * P_FIFTH) + 82 | mix(t, mul * (((t >> 20) & 1) ? MAJ_THIRD : MIN_THIRD)) + 83 | mix(t, mul * OCTAVE_DOWN) 84 | ) >> 2; 85 | } 86 | 87 | uint8_t octaves(uint64_t t, double mul){ 88 | return ( 89 | chord(t, mul * OCTAVE_DOWN) + 90 | chord(t, mul) 91 | ) >> 1; 92 | } 93 | 94 | int main(void){ 95 | uint64_t t = 0; 96 | 97 | init_table(); 98 | 99 | while(1){ 100 | t += 1; 101 | putchar(octaves(t, GLOBAL_PITCH)); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /flow4.c: -------------------------------------------------------------------------------- 1 | // This file produces 44100 Hz, 2 channel, unsigned 8 bit raw PCM 2 | // If you're on linux you can play it using aplay: 3 | // $ ./flow3 | aplay -r44100 -c2 4 | 5 | #include 6 | #include 7 | 8 | // I highly recommend playing with these constants as different values 9 | // produces different timbres and different musical development. 10 | 11 | // Be warned that high SYNTH_COUNT can make this program very slow. 12 | 13 | #define SYNTH_COUNT 1024 14 | 15 | #define GLOBAL_PITCH 0.025 16 | #define DETUNE_START 0.0001 17 | #define DETUNE_STEP 1000 18 | #define FREQ_START 1 19 | 20 | #define LEFT_NONLIN 2 21 | #define RIGHT_NONLIN -3 22 | 23 | #define OCTAVE_DOWN 0.5 24 | #define MIN_THIRD 1.2 25 | #define MAJ_THIRD 1.125 26 | #define P_FIFTH 1.5 27 | 28 | double table[SYNTH_COUNT]; 29 | 30 | uint8_t saw(uint64_t t){ 31 | return t & 255; 32 | } 33 | 34 | void init_table(void) { 35 | uint16_t i, j; 36 | 37 | for (i = 0; i < SYNTH_COUNT; i ++){ 38 | double freq, scale; 39 | freq = FREQ_START; 40 | scale = DETUNE_START; 41 | 42 | j = i; 43 | while (j > 0){ 44 | freq += (j & 1) * scale; 45 | j >>= 1; 46 | scale /= DETUNE_STEP; 47 | } 48 | 49 | table[i] = freq; 50 | } 51 | } 52 | 53 | uint8_t mix(uint64_t t, double mul){ 54 | double freq; 55 | double shift = 0, out = 0, max = 0; 56 | double val, amp; 57 | 58 | uint16_t i; 59 | uint8_t chan = t & 1; 60 | 61 | t >>= 1; 62 | 63 | for (i = 0; i < SYNTH_COUNT; i ++){ 64 | freq = table[i]; 65 | amp = ((double)(i + 1) / (double)(SYNTH_COUNT)); 66 | val = saw(0.5 + mul * freq * t + shift); 67 | 68 | shift = val * (t >> 16) * 2; 69 | max += amp; 70 | 71 | out += val * (chan ? amp : 1 - amp); 72 | shift += chan ? LEFT_NONLIN : RIGHT_NONLIN; 73 | } 74 | 75 | return (uint8_t)(out / max + 0.5); 76 | } 77 | 78 | uint8_t chord(uint64_t t, double mul){ 79 | return ( 80 | mix(t, mul) + 81 | mix(t, mul * P_FIFTH) + 82 | mix(t, mul * (((t >> 20) & 1) ? MAJ_THIRD : MIN_THIRD)) + 83 | mix(t, mul * OCTAVE_DOWN) 84 | ) >> 2; 85 | } 86 | 87 | uint8_t octaves(uint64_t t, double mul){ 88 | return ( 89 | chord(t, mul * OCTAVE_DOWN) + 90 | chord(t, mul) 91 | ) >> 1; 92 | } 93 | 94 | int main(void){ 95 | uint64_t t = 0; 96 | 97 | init_table(); 98 | 99 | while(1){ 100 | t += 1; 101 | putchar(mix(t, GLOBAL_PITCH)); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /flow5.c: -------------------------------------------------------------------------------- 1 | // This file produces 44100 Hz, 2 channel, unsigned 8 bit raw PCM 2 | // If you're on linux you can play it using aplay: 3 | // $ ./flow5 | aplay -r44100 -c2 4 | 5 | #include 6 | #include 7 | 8 | // I highly recommend playing with these constants as different values 9 | // produces different timbres and different musical development. 10 | 11 | // Be warned that high SYNTH_COUNT can make this program very slow. 12 | 13 | #define STEP_COUNT 8 14 | #define SYNTH_COUNT 160 15 | 16 | #define GLOBAL_PITCH 0.01 17 | #define DETUNE_START 0.0001 18 | #define DETUNE_STEP 5 19 | #define FREQ_START 1 20 | 21 | #define SHIFT_MUL 10 22 | 23 | #define LEFT_NONLIN 2 24 | #define RIGHT_NONLIN -3 25 | 26 | #define MIN_THIRD 1.189207115002721 27 | #define MAJ_THIRD 1.259921049894873 28 | 29 | double table[SYNTH_COUNT]; 30 | 31 | uint8_t saw(uint64_t t){ 32 | return t & 255; 33 | } 34 | 35 | void init_table(void) { 36 | uint16_t i, j; 37 | 38 | for (i = 0; i < SYNTH_COUNT; i ++){ 39 | double freq, scale; 40 | freq = FREQ_START; 41 | scale = DETUNE_START; 42 | 43 | j = i; 44 | while (j > 0){ 45 | freq += (j & 1) * scale; 46 | j >>= 1; 47 | scale /= DETUNE_STEP; 48 | } 49 | 50 | table[i] = freq; 51 | } 52 | } 53 | 54 | uint8_t mix(uint64_t t, double mul){ 55 | double freq; 56 | double shift = 0, out = 0, max = 0; 57 | double val, amp; 58 | 59 | uint16_t i; 60 | uint8_t chan = t & 1; 61 | 62 | t >>= 1; 63 | 64 | for (i = 0; i < SYNTH_COUNT; i ++){ 65 | freq = table[i]; 66 | amp = ((double)(i + 1) / (double)(SYNTH_COUNT)); 67 | val = saw(0.5 + mul * freq * t + shift); 68 | 69 | shift = val * SHIFT_MUL; 70 | max += amp; 71 | 72 | out += val * (chan ? amp : 1 - amp); 73 | shift += chan ? LEFT_NONLIN : RIGHT_NONLIN; 74 | } 75 | 76 | return (uint8_t)(out / max + 0.5); 77 | } 78 | 79 | uint8_t chord(uint64_t t, double mul){ 80 | uint32_t i; 81 | double out = 0; 82 | 83 | for(i = 0; i < STEP_COUNT / 2; i ++) { 84 | out += mix(t, mul); 85 | mul *= MAJ_THIRD; 86 | out += mix(t, mul); 87 | mul *= MIN_THIRD; 88 | } 89 | 90 | out /= STEP_COUNT; 91 | 92 | return (uint8_t) out; 93 | } 94 | 95 | int main(void){ 96 | uint64_t t = 0; 97 | 98 | init_table(); 99 | 100 | while(1){ 101 | t += 1; 102 | putchar(chord(t, GLOBAL_PITCH)); 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /flow_param.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define MAX_SYNTHS 2048 6 | 7 | #define OCTAVE_DOWN 0.5 8 | #define MIN_THIRD 1.2 9 | #define MAJ_THIRD 1.125 10 | #define P_FIFTH 1.5 11 | 12 | uint16_t synth_count = 128; 13 | 14 | double global_pitch = 0.005; 15 | double detune_start = 0.001; 16 | double detune_step = 100; 17 | double freq_start = 0.8; 18 | 19 | int16_t left_nonlin = 2; 20 | int16_t right_nonlin = -3; 21 | 22 | 23 | double table[MAX_SYNTHS]; 24 | 25 | uint8_t saw(uint64_t t){ 26 | return t & 255; 27 | } 28 | 29 | void init_table(void) { 30 | uint16_t i, j; 31 | 32 | for (i = 0; i < synth_count; i ++){ 33 | double freq, scale; 34 | freq = freq_start; 35 | scale = detune_start; 36 | 37 | j = i; 38 | while (j > 0){ 39 | freq += (j & 1) * scale; 40 | j >>= 1; 41 | scale /= detune_step; 42 | } 43 | 44 | table[i] = freq; 45 | } 46 | } 47 | 48 | uint8_t mix(uint64_t t, double mul){ 49 | double freq; 50 | double shift = 0, out = 0, max = 0; 51 | double val, amp; 52 | 53 | uint16_t i; 54 | uint8_t chan = t & 1; 55 | 56 | t >>= 1; 57 | 58 | for (i = 0; i < synth_count; i ++){ 59 | freq = table[i]; 60 | amp = ((double)(i + 1) / (double)(synth_count)); 61 | val = saw(0.5 + mul * freq * t + shift); 62 | 63 | shift += val; 64 | max += amp; 65 | 66 | out += val * (chan ? amp : 1 - amp); 67 | shift += chan ? left_nonlin : right_nonlin; 68 | } 69 | 70 | return (uint8_t)(out / max + 0.5); 71 | } 72 | 73 | uint8_t chord(uint64_t t, double mul){ 74 | return ( 75 | mix(t, mul) + 76 | mix(t, mul * P_FIFTH) + 77 | mix(t, mul * (((t >> 20) & 1) ? MAJ_THIRD : MIN_THIRD)) + 78 | mix(t, mul * OCTAVE_DOWN) 79 | ) >> 2; 80 | } 81 | 82 | uint8_t octaves(uint64_t t, double mul){ 83 | return ( 84 | chord(t, mul * OCTAVE_DOWN) + 85 | chord(t, mul) 86 | ) >> 1; 87 | } 88 | 89 | int help(void){ 90 | printf("Available parameters:\n" 91 | "\t-c VAL\t\tnumber of synths (int)\n" 92 | "\t-l VAL\t\tleft channel feedback (int)\n" 93 | "\t-r VAL\t\tright channel feedback (int)\n" 94 | "\t-f VAL\t\tstarting frequency (double)\n" 95 | "\t-g VAL\t\tglobal pitch multiplier (double)\n" 96 | "\t-d VAL\t\tstarting detune (double)\n" 97 | "\t-s VAL\t\tdetune step (double)\n" 98 | "\t-S VAL\t\tnumber of samples to skip (long long int)\n" 99 | ); 100 | return -1; 101 | } 102 | 103 | int main(int argc, char *argv[]){ 104 | uint64_t t = 0; 105 | int16_t i, j; 106 | 107 | for (i = 1; i < argc; i ++) { 108 | if (argv[i][0] == '-') { 109 | switch (argv[i][1]) { 110 | case 'h': 111 | help(); 112 | return 0; 113 | case 'c': 114 | i += 1; 115 | synth_count = atoi(argv[i]); 116 | break; 117 | case 'l': 118 | i += 1; 119 | left_nonlin = atoi(argv[i]); 120 | break; 121 | case 'r': 122 | i += 1; 123 | right_nonlin = atoi(argv[i]); 124 | break; 125 | case 'f': 126 | i += 1; 127 | freq_start = atof(argv[i]); 128 | break; 129 | case 'g': 130 | i += 1; 131 | global_pitch = atof(argv[i]); 132 | break; 133 | case 'd': 134 | i += 1; 135 | detune_start = atof(argv[i]); 136 | break; 137 | case 's': 138 | i += 1; 139 | detune_step = atof(argv[i]); 140 | break; 141 | case 'S': 142 | i += 1; 143 | t += atoll(argv[i]); 144 | break; 145 | default: 146 | return help(); 147 | } 148 | } else return help(); 149 | } 150 | 151 | init_table(); 152 | 153 | while(1){ 154 | t += 1; 155 | putchar(octaves(t, global_pitch)); 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /period.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | # 4 | # Copyright © 2019 Olga Ustiuzhanina 5 | # 6 | # This program is free software. It comes without any warranty, to 7 | # the extent permitted by applicable law. You can redistribute it 8 | # and/or modify it under the terms of the Do What The Fuck You Want 9 | # To Public License, Version 2, as published by Sam Hocevar. See 10 | # the COPYING file for more details. 11 | # 12 | 13 | from fractions import Fraction, gcd 14 | from math import log10 15 | 16 | def lcm(x, y): 17 | return abs(x * y) / gcd(x, y) 18 | 19 | COUNT=7 20 | DIV=1000 21 | 22 | result = 1 23 | freqs = [] 24 | 25 | for i in range(0, 2**COUNT): 26 | freq = Fraction(1, 2) 27 | scale = Fraction(1, 10) 28 | 29 | j = i 30 | while j > 0: 31 | freq += (j & 1) * scale 32 | j >>= 1 33 | scale /= DIV 34 | result = lcm(result, 1 / freq) 35 | 36 | print(result * 256) 37 | #print(10 ** (log10(DIV) * (COUNT - 1) + 1) * 256) 38 | --------------------------------------------------------------------------------