Code Golf & the Bitshift Variations - Computerphile
HTML-код
- Опубликовано: 11 сен 2024
- Thanks to Audible for supporting our channel. Get a free 30 day trial at www.audible.com...
A short jumble of letters & symbols that plays a long, musical tune? This is code Golf and Rob Miles' musical composition: "The Bitshift Variations in C minor"
Link to Code: txti.es/bitshif...
Thanks to Nottingham Hackspace for providing us with a place to film
Rob's Soundcloud account with the tune : Bitshift Variations in C Minor by robertskmiles
/ bitshift-variations-in...
EXTRA BITS: • EXTRA BITS: Code Golf ...
The Brain Scanner: • Brain Scanner - Comput...
Brian Kerninghan on Bell Labs: • The Factory of Ideas: ...
Computer That Changed Everything - Altair 8800: • Computer That Changed ...
Binary Addition & Overflow: • Binary Addition & Over...
/ computerphile
/ computer_phile
This video was filmed and edited by Sean Riley.
Computer Science at the University of Nottingham: bit.ly/nottscom...
Computerphile is a sister project to Brady Haran's Numberphile. More at www.bradyharan.com
2:20 This reminded me of this: "When C coders talk about strong typing they mean hitting the keys harder" ;)
I love Rob Miles.
The Compiler Complaining, that we're TORTURING the C language. LMAO.
The fact that you said "I can't do maths" just gave me hope for actually completing my engineering program.
The difference is he know what maths to do
did you?
Instead of piping it to aplay wrote it to a file called music.
After ~a minute I had 1,7 GB - 63,38 hours - of awesome music!
Worth it!
If you use hurd (I wish they could get that working properly), then you could have a filter (a file, that looks is realy an executable, but looks like a file). Can you do that with fuse. Oh but it will not auto mount.
You can use a named pipe (fifo) for this.
You can now pipe that file to aplay! cat music.txt | aplay
broer gun
That type of music is also called "bytebeat" on the interweb and if you're into that kind of wierd stuff I recommend the work of Jerobeam Fenderson who makes "oscilloscope music" the concept is different of bytebeat but it's still incredibly interesting, the sound is similar and you get visuals along with it.
You don't need the ";" in front of main I think. saves 1 byte.
+The Aaaargh I just tested that, and you are correct. :D
+The Aaaargh Also return is not a function, it doesn't need parens. return x, not return(x). Save 1 more byte.
2 bytes*
return x is one byte shorter than return(x), not 2. Mind the space.
Had to test aplay, a sql backup file sounds like grindcore.
bad idea, some clever person may re-interpret the file by taking the sound and thus maybe compromising his security!
I just tried, it really sound like a cheap scooter engine running at full power xDD
"C is a strongly typed language." That, my friend, is a VERY bold claim. :-)
I think the term "explicitly typed" is better here
Perfect jump-off point to explain Kolmogorov complexity!
When did Jean-Ralphio get into coding?
What an accurate drawing of a sine wave.
I noticed that too lol
You just have to type sin(x) on whatever to get a proper plot.
I think it's because of 3D effect
Could you please not use semi-circle waves as "sine"-waves? - I have generated semi-circle waves once. They sound god-awful.
+Kram1032 lol what do they sound like?
+ericsbuds They sound similar to triangle waves.
Luc Ritchie yup, awful.
NNOTM triangle waves are way more pleasant!
for anyone wondering, that app he used is called pitchlab, and its excellent. it's designed for tuning instruments, but it's still fun to play around with.
Can you please provide a "human-readable"(just not a code golf) version of the program?
Love it anyway!
+GodlikeBlock There's nothing much here to make it human readable, to be honest. Most of the code is bitwise operations on integers, and you can't really make them "human-readable" in the usual sense.
At most, we could comment on what each piece is doing, but most of the "magic numbers" and operations were likely coded randomly and then the program was run to see if they sounded good. This is usually how we do this.
It's extremely difficult for a human to look at the code and predict what the music will sound like. At most, we can get a sense of the timbre generated, which is why he mentions the bit on sawtooth waves.
That's not exactly what i meant.
by "Human-readable" i mean things like: giving variables proper names, actually using the "int" keyword, using proper lines/indentation and all that.
its not that i want to read the code like a book, but rather make it easier for me to understand.
comments could be helpful,. but are not reqirered.
but I guess you're right, by "human-readable" i could easily have meant what you described, i'm sorry =]
+GodlikeBlock except if you know what the int specifier is then you probably understand code and could decipher the original. its not going to make it any easier to read if its spaced out with a few extra keywords, etc.
Sure, here you go. This is the best I can do.
int g(int sample, int x, int t, int overdrive) {
return (
(
3 & x & ( // some arbitrary manipulation of the timbre generated below
sample * // multiply the current sample number (pretty much the current time) to...
// the following block creates an array of 8 chars (a string) and reads each letter
// as an int. These seem to be used for composing a general rule for the melody,
// but maybe they have to do with the timbre, as if two instruments
// I'm not sure which
(
(
3 & sample >> 16 // if this is true
?
"BY}6YB6%" // use this string as a melody source
:
"Qj}6jQ6%" // otherwise use this one
)[t % 8] // cycle over which character to use based on the parameter t
+
51 // add 51 arbitrarily, possibly to increase volume and/or to get a different melody?
) >> overdrive // divide result by 2^overdrive
)
)
+1ucasvb
The strings decide the notes being played, effectively. The repetition in the strings sort of sets up what key and what octave you are using. Without that, the range would be higher, or the song would be heavily dissonant.
Code Golf!!!! This is my favorite game in all of the Internet and it is great that it is getting some attention! Thanks Computerphile!
In C, _signed_ eight bit is the same as a character [not _unsigned_ as stated in the video]. However, it's true that putchar accepts a signed integer as an argument, and emits an unsigned eight-bit value.
Wow, I remember piping my files through aplay this one time but I never thought something like this would be cool. I love you Rob.
The loop variable is incremented in the loop. You could probably shave off a character by incrementing it the first time it is read (++I), though I believe that location is not defined. You can shave off 3 characters if the loop can start with 1 (argc, first parameter to main, is 1).
Robert Miles I've not been able to try it, unfortunately, but how different is it if you start the loop from 1 instead of 0? If the audio output is all but identical, it might still count. :-) (At a glance, it seems like i = 0 generates silence, anyway.)
Can't you save one character by removing the brackets around the quantity being returned by the g function? i.e., "return x;" instead of "return(x);".
The code has a set of function-like parentheses on the return statement. In both code-golf and readability sense that's just two extra characters.
In a Java class we were supposed to make an object to represent a playing card, and I instead made an int to represent a card and used bitwise operators at the front to determine the suit. an int instead of an object, I'd call that a birdie.
2 bits suit, 4 bits number. And I assume the Jokers were either number 0 or number 15?
The title of this video gave me no clue that it was about bytebeat music. Bit of a pleasant surprise, I love that stuff. :)
I really like this kind of coding whether or not it is important.
I really like this guy :D He is very intelligent and entertaining.
0:19 this is how i feel about the entire haskell language lol
That code snippet is the most brilliant thing ever! That just made my day!
1) If you use pulseaudio, change "aplay" to "aplay -D pulse"
2) It's even more fun with "aplay -r 16000"
You should be careful when you describe waveforms like sawtooth to be "easily generated." As far as chiptunes go, yes, it is extremely easy to generate, but it should be noted that this method also creates a ton of aliasing distortion because the signal is not band-limited.
ColaEuphoria can you explain what that last clause means for us mere mortals?
@@MamboBean343 I can highly recommend watching some videos where they demonstrate harmonics and aliasing with audio and visual aids. But because I like writing answers:
A sampled signal is able to represent any frequency up to half its sample rate (this halfway point is called the "Nyquist frequency"). If the frequency it tries to encode is higher than the Nyquist, the recording will end up making a mathematically related frequency instead, which is called aliasing. So, if the sample rate is 8000hz, and you try to encode a frequency of 5000 hertz (1000 hz over the Nyquist), the resulting signal will be 4000hz instead (1000hz under). This aliasing is usually considered unpleasant to listen to, and is usually an accident in the first place.
Programmatically generating a "perfect" saw or square wave like OP talks about attempts to create a signal with *infinite* harmonic frequencies. Since the signal isn't infinite and can only contain a limited amount, that means lots of frequencies get aliased. So programmers writing signal generation code usually write more advanced algorithms that are "band-limited" meaning they can only generate frequencies up to the Nyquist frequency.
Tried the code and it worked great.
This is the first one in a while that was genuinely beyond me for most of it.
For general purpose coding you usually don't want to minimize code size because smaller code does not necessarily mean faster computation and you also need to take into account stability, reliability and security as well as how much time you need to put into crafting the code. But for time critical low level code written in machine language you may need to minimize size in order to be clock cycle perfect and also fit within the registers available. Examples would be firmwares, control systems and parts of the graphics code in video games.
+Anders Öhlund I understand the point "smaller code does not necessarily mean faster computation". But why "and you also need to take into account stability, reliability and security"...why a smaller code would be less reliable or less secure?
+Russell Teapot The real issue with smaller code is that fewer people are able to understand it fully. When you're using abbreviations and unintuitive but shorter ways to write things, the chances of someone later maintaining that code screwing it up are higher. There's a programming philosophy called "clean code" where one of the main points is to make the code so it can be fully understood by the most basic programmer with little experience in that specific language and at the end of a rough work day. Often enough, I find bugs by just stretching out the code a bit to be more readable. When some peace of code is too compact/smart/elegant, a logic error can slip by another programmer whose job it is to review that piece of code and then that piece of code is running a nuclear power plant. That would be bad.
ROB MILES IS BACK! YAAAAAY!
Does this count as code golf? Usually, code golf requires some sort of competition to do something very specific.
Having an open-ended goal of "making a program that makes music" wouldn't fit this criteria.
code golf-solitaire?
If you were to try to get a similar result in fewer bytes you wouldn't be designing software in traditional way per se. Demo as in demoscene is a more fitting term.
+cyberconsumer Exactly. This is more demo-ish than code-golf-ish
+1ucasvb There are records for shortest program that does X. Chess is a popular one for example.
+TheAnoniemo That's still a very specific kind of program. Shortest code to make music isn't specific. Shortest code to play Beethoven's 9th Symphony would be.
Wow, this is one of the best videos I've seen in a long while. Amazing.
Just tried this on my Raspberry Pi and I must say, I'm impressed. Thank you for sharing it :)
Could you upload a clean recording of the entire song (after calculating how long it lasts), for those of us who don't have Linux?
+NeatNit Run it in a VM, say Virtualbox.
+NeatNit plfgr.eu.org/hdd/tinycodemelody.wav here you go 30 min of it, used $ ./a.out | ffmpeg -f u8 -ar 8000 -i - -t "30:00" tinycodemelody.wav
+NeatNit Wait. You don't run linux. Why may i ask ?
Any sufficiently advanced linux user can run any windows program and soon to be any mac application.
***** I dual boot between win 10 and xubuntu and I feel there are reasons to use both. I seem to have bad luck with linux software stability and availability.
TheAnoniemo Then you're not sufficiently advanced, I myself have had no problems I have only experienced one dependency hell and I don't get any errors. If you become good with linux then you'll never return to windows and especially the new excuse for a windows operating system there are too many bugs, security issues, graphical errors and enforced features to ever make it worthwhile.
The title stood out to me, because i'm actually working on a golf sim right now in Blender/Python (just started like an hour ago)
The provided code:
:1:80: error: second parameter of 'main' (argument array) must be of type 'char **'
:1:80: error: third parameter of 'main' (environment) must be of type 'char **'
Awesome episode! Would love to know more about the coded music theory behind this
I simply loved this video! I enjoyed being able to play around with the code. More videos like this, please!! Hahaha
I made a mp3 out of the output on my 64-bit linux-box. The file is 825M huge and plays almost 74:34 hours - I mismatched the output on the display of the player for minutes, first.
BTW: The sine-wave looks a little bit different than two hemicycles; but I must admit it's easier to draw. :)
Edit: I think, 74,5 hours is way to long for an “optimized length” of the audio. The parameter type of »putchar« is »int« on my system, and it's a 64-bit-system. Is there an other “optimal” point to interrupt the for-loop than »INT_MAX« - which is 2147483647 on my system?
that's such a great piece of code. I like the music it makes.
More ways to shorten it: echo can use single quotes, so you don't have to escape the double quotes in middle (4 bytes). You can redo it as a HERE document, instead of echo, which takes as many characters (including 2 required newlines) as 'echo ', so you won't even need the single quotes (another 2 bytes). Remove the extra parenthesis after the 'return' - return is NOT a function-like statement, and the parentheses around the value returned is a bad practice (another 2 bytes - but this one you really should have known).
I have not been able to shorten the actual code, besides for the comments I already posted on this topic. BTW, if '.' is in your path, you can save another 2 bytes, but I don't know if that counts.
+Menachem Salomon
I thought I'd already done some of those... On closer inspection the version that's in the video is not the shortest version I've got, which is this:
pastebin.com/tRXZBZWx
I see that it's meant to run on a command line, but how to I get it to run? It says it's expecting an identifier or ( before the string
Love the lil ukuleles in the background
o snap I use that app to tune my guitar. (fucking love this dude, hes always on a topic that intrigues the fuck out of me.)
I remember on the ZX spectrum writing a boot loader. It had to fit into very little memory (optimized for memory size): it had lines like goto sign pi (3 keystrokes + shifts, and 3 bytes). I may remember that wrong as that will do the same as run, and that is one byte, one keystroke. I remember arranging for it to start in the middle, so that I could use run as a goto 1. sign pi evaluates to 1 and takes 2 bytes of code. Where as 1 takes 5 bytes (is is floating point).
It occurs to me that you could probably make these last insane amounts of time using Mersenne Primes- by subtracting 1 from 2**n, you often get a prime number, and if the period of each part is a different Mersenne prime, the music will last for a massive amount of time without repeating.
I think I know where those ukulele end credits in Robert Miles videos are being recorded...
Do you have an un-golfed version of this? The nested parens and quotes make it difficult for me to read it. Vim's syntax highlighter can't even handle it.
C is a statically typed language, but actually quite weakly typed -- it doesn't hide the fact that everything is actually bytes underneath.
Code golf is awesome!!
Best oveflow animation ever ! :D
How do you use the given code to actually listen the music ?
I studied The Curious Incident in high school. That was a very interesting read. I'd recommend it.
+Jared Mulconry I don't seem to recall understanding it. :(
CODE GOLF! Hurra you did something about code golf.
3:45 A little mistake. That graph is not a sine, it's a circular waveform which has a similar harmonic distribution. But good video anyways. The music they talk about is "ByteBeat", and there are many websites where you can try writing your own C and JS expressions to create sounds. There's even a research paper about it but I don't have the link now
Old sound chips create the frequency by dividing a base input frequency, coming from the master clock, or some already divided value of it.
The oscillator of a sound channel is clocked by this frequency, but only every x-th clock actually causes the next sample to be output. That x is what the software can manipulate, to change the divisor value in the equation and get different frequencies.
This however also makes the precision and "in-tune-ness" of the oscillator get progressively worse as you go higher in frequency, because you start to divide by lower and lower numbers.
+za909returns Neat! So let's say the clock runs at 1 Mhz. This is the base input frequency. If I divide it by 1000 (so I output only on the 1000th clock), I obtain 1000 Hz soundwaves. Right?
+za909returns what was the clock frequency of one of those chips?
You got it right, that's exactly what happens. The division is there to regulate the frequency.
The NES gets the same rate initially as the CPU, 1.789773 MHz
However, the audio circuitry is integrated into the CPU, so it makes sense really...
The APU (Audio Processing Unit) gets this frequency divided by 2. But that's not all. The rest depends on the which sound channel we're speaking of. For example, the NES APU has two pulse waves, with configurable pulse width to control the timbre of the sound. A sequencer is involved that outputs 8 samples repeatedly to create the pulse wave (The samples are either 0 or the current volume level of the channel), so the actual frequency you get to divide is 1.789773 MHz / 16
Also, the divisor is also limited by the number of bits available. The divisor in the NES APU channels is 11-bit wide, so you can divide by 1-2048.
The chip of the Sega Master System, the Texas Instruments SN76489 only has a 10-bit divisor, so you get a smaller range of possibly frequencies. The Atari POKEY has 8-bit divisors by default, but you can sacrifice channels to combine two divisors for 16-bit ones.
It is very late, and im not sure if anyone has suggested this because I didn't read ALL of the comments, but you can save 4 more bytes by using single quotes for the echo and then removing the backslashes in the code itself and just using double quotes
How would one go about getting a MIDI file of this song?
This was awesome, please make more videos about coding and stuff, like this one :)
This is my new favourite thing.
Dude, thanks for spoiling the plot to the book :D
Very very interesting indeed. I love the 5 string bass as well:) As a bass player I loved it.
Awesome!
What program/vm is used in this video to program?
Oh, you are in NottingHack
This.... is beautiful!
That's real neat!
Kinda silly how my only points on codegolf stackexchange are from a popularity contest
I can't get the code to work, someone send help!
This guy makes me want to be a programmer.
+Eamon Burke Do it! :D It's so much fun! ^^
+Eamon Burke JUST DO IT!!! (excuse me for the Shia Lebouf thing). I suggest you to learn Python. I'm learning it and it seems pretty easy (at least the very basics). Do it.. I promise: you won't regret that. All sorts of random and silly ideas will come to your mind and you can try to code them to see if they works. Like Noah wrote "It's so much fun" indeed!
I can only agree. It takes a bit of time to learn it properly but its just soo much fun creating things
Nameguy or you can simply program as a hobby without worrying too much about the thing, taking it easy.
Actually, I seem to be able to remove " -xc -&&" and replace that with ; and it runs fine on (GCC) 6.3.1 20170306. That saves six bytes. && does some error checking which really isn't needed, and the shell handles the fact that there isn't a .c extension. I'm wondering if a.out can be truncated in some way with something like a shell expansion symbol? Back to the lab.
What app is that at 7:02 ? PitchLab?
I can't seem to find it even though I peeked the splash screen
+andrew kim Yes it is
Very cool
With 256 characters, wouldn't some of them have to represent negative values? Amplitude is usually -1, 0 +1. So if you have 256 available positions, wouldn't it be -127, 0 +128?
Timely reply here. The program outputs integer values [0-255]. It's up to the program aplay to interpret these and relay the signal to your audio playback devices, going through whatever transformations are necessary to actually drive a speaker. What probably happens is that 0-127 are considered "negative" and 129-255 are considered "positive", with 0 at 128.
What is the name of his phone app generating that information, 31,1 Hz = B0 ?
Peace out :)
It's called PitchLab
How to run this file program?
whats up with the ukuleles?
One can program audio from code. Neat, will definitely check it ou!
suuuper cool!
"It assumes"? Surely there's default tables in UNIX? Like when I used Pascal it was layered to Assembler code?
Damned be you all - scriptkiddies. (⌒▽⌒)
I think you messed up somewhere, Sean. C is *not* strongly typed! C allows for implicit type casting and inference in various situations, and you even mentioned this yourself in the video. I think you meant statically typed, where types are checked and assigned at compile-time instead of at runtime. Otherwise, spectacular video!
Where was this filmed? The surroundings are very peculiar and there are people walking through so it is definitely not an office or a classroom.
+Killian Maladath I'd guess a student's mess.
+Killian Maladath It is clearly some sort of common area at a university/college. My guess given the apparent size would be a department post grad lounge.
What exactly is ...\"BY}6YB6%\":\"... in there for?
Ah, gotcha. The backslashes were there for the echo | gcc
that song is giving me flashbacks to pirating software in the early 2000s!
Where can I get that "Do Not Be On Fire" poster you guys got on the wall there xD
this is amazing
Very interesting
What does the "3 & i >> 16 ?" part mean, It looks like if(3 and i shifted right 16) but that isn't an if statement....
& (and) is a bit operation; in an if statement it is comparing true/false. With integers/bytes, it compares each byte and outputs a byte where the & operation is applied to each bit on the two inputs. For example, 5(00000101) & 6(00000110) = 4(00000100). Hope it helps
+ProfessorG I already knew about the bit and but a number does not naturally evaluate to true or false, like if(6) that doesn't make sense... if 6 what...
H3H3 is back on RUclips!
I loved it!
BTW, It depends on alsa-utils.
I had to install it to run the code.
2:19 I think he meant to say _statically typed_ -as C lets you "type pun" and converts between certain types implicitly, i.e. has a -_-weak-_- type system.-
+Pontus Lundström You're right. (I also said square wave once when I meant sawtooth wave)
+Pontus Lundström I think those definitions have morphed a bit over the years. A weakly typed language would be javascript. Looking at wikipedia though, your assessment about static typing seems accurate. I used to hear "strongly typed" to mean what is now apparently statically typed. C just allows certain implicit type conversion, although there are very specific and well defined rules for when this can happen. Any time a type (class) has a constructor that accepts a single parameter of another type, the compiler is allowed to implicitly convert one type to another, as a one way operation. It can not, however, perform a chain of two conversions where it converts to an intermediate type and then to the desired type. For built in numerical types, the idea of a constructor is built in to the compiler itself, but it can be thought of this way. There is a single step between a void* and an int, basically a reinterpret_cast. This also applies mainly to rvalues, not variables that you declare in your code. Anything you declare as an int can never just become a bool or a float all of a sudden. It retains its type, but functions which know how to convert an int to what they want are allowed to do so. In Javascript, a single 'var' can hold an integer value one moment, and a string the next. The type of the variable itself is fluid. That's what distinguishes a weakly typed language.
+DFPercush You're probably right about the definitions changing over time. If you look up Wikipedia for "Strong and weak typing" or "Type system" you'll find even their definitions aren't completely unambiguous so I guess we might be debating apples vs. oranges here. That also means my initial statement is strictly correct only until the word "as" :)
What you say about JavaScript is correct. However, it's working on a much higher abstraction level compared to C thanks to its _dynamicity_ some of which I think you mixed into your comment about what is representative of a weak type system. Also, talking about classes, constructors and reinterpret_cast is confusing as C and C++ are two distinct languages. Fortunately, in C++ casts like void* -> SomeType* or vice versa aren't allowed implicitly but in C they are.
Pontus Lundström
Interesting note about void* conversions being allowed in C but not C++. In my experience you can implicitly assign any pointer to a void*, but void* must be explicitly cast if you want to use it for anything else.
+DFPercush Ah, my bad, you are indeed allowed to assign _any non-function pointer_ to void* implicitly.
in c does ' do the job as " or is it like java were ' is just for chars. if not remove \" and replace it with '.
Shame the code doesn't work on Mac - 2 errors are raised:
:1:80: error: second parameter of 'main' (argument array) must be of type
'char **'
:1:80: error: third parameter of 'main' (environment) must be of type
'char **'
I just made a comment with working Mac code
This reminds me alot about Caustic's 8Bit Synth :)
Nice video!
Custom console?
Why not just implement the unknown 5-state busy beaver and output its position as a note? It's still unknown how long it would take for the music from that to repeat, if ever -- the behavior is highly irregular.