Musical Quines on an ASCII Piano

22

7

There are 88 keys on a standard piano and 95 printable ascii characters (hex codes 20 through 7E):

 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~

('character' refers to any printable-ASCII character from here on)

In this JSFiddle I've taken advantage of that and made a simple syntax that generates piano tunes using AudioSynth. (If anyone can direct me to a linkable set of real piano note sounds I'll be grateful.)

Each character in the input string besides () 01+- corresponds to one piano key:

 CHARACTER:  !   "   #   $   %   &   '   *   ,   .   /   2   3   4   5   6   7   8   9   :   ;   <   =   >   ?   @   A   B   C   D   E   F   G   H   I   J   K   L   M   N   O   P   Q   R   S   T   U   V   W   X   Y   Z   [   \   ]   ^   _   `   a   b   c   d   e   f   g   h   i   j   k   l   m   n   o   p   q   r   s   t   u   v   w   x   y   z   {   |   }   ~
KEY NUMBER:  1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18  19  20  21  22  23  24  25  26  27  28  29  30  31  32  33  34  35  36  37  38  39  40  41  42  43  44  45  46  47  48  49  50  51  52  53  54  55  56  57  58  59  60  61  62  63  64  65  66  67  68  69  70  71  72  73  74  75  76  77  78  79  80  81  82  83  84  85  86  87  88
      NOTE:  A  A#   B   C  C#   D  D#   E   F  F#   G  G#   A  A#   B   C  C#   D  D#   E   F  F#   G  G#   A  A#   B   C  C#   D  D#   E   F  F#   G  G#   A  A#   B   C  C#   D  D#   E   F  F#   G  G#   A  A#   B   C  C#   D  D#   E   F  F#   G  G#   A  A#   B   C  C#   D  D#   E   F  F#   G  G#   A  A#   B   C  C#   D  D#   E   F  F#   G  G#   A  A#   B   C
    OCTAVE:  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   8

So RPNPRRR plays the first 7 notes of Mary Had a Little Lamb using the preset timing parameters you can see in the JSFiddle.

Space () represents a musical rest that lasts for one note interval. So RPNPRRR PPP RUU plays the first 13 notes of Mary Had a Little Lamb with rests in their proper places.

If any character besides ()01 is prefixed by a sequence of 0's and 1's (regex [01]+), that sequence is read as a binary number b, and the character is replaced with b copies of itself. So 101A11 10+1-0B01C becomes AAAAA ++-C because 101 = 5, 11 = 3, etc. (A sequence of 0's and 1's at the end of the string has no effect.)

Matched parentheses (()) serve two purposes:

  1. If their content does not end with a sequence of 0's and 1's, all the notes are played at the same time as a chord (which otherwise is no different than a note). So (NQU) is a C minor chord on octave 4.
    If duplicate notes are present their sound is also duplicated. So (NN) and (NNN) sound different.
  2. If their content does end with a sequence of 0's and 1's, that sequence is read as a binary number b, and the parentheses and their content are replaced with b copies of the content. So (NQU11) becomes 9 individual notes: NQUNQUNQU.

Parentheses Details:

  • Nesting replicating parentheses (purpose 2) is fine: (N(QU10)11)(NQUQU11)NQUQUNQUQUNQUQU.
  • Nesting non-replicating parentheses (purpose 1) is fine but has no effect: (A((+)C)) is the same as (A+C).
  • You can also combine both: ((N(QU10))11)(NQUQU)(NQUQU)(NQUQU).
  • A sequence of 0's and 1's before non-replicating parentheses repeats them in the same way individual characters are repeated. So 10(NQU) becomes (NQU)(NQU).
  • A sequence of 0's and 1's before replicating parentheses has no effect.
  • ( must always have a matching ), but not vice-versa: e.g. N) is valid.

Plus (+) and minus (-) respectively increase and decrease the the duration of notes or the time interval between notes, depending on their context:

  • When inside non-replicating parentheses, they immediately increase or decrease the note duration variable by some preset number of milliseconds (see JSFiddle). So (++)N will play N at a longer duration than normal.
  • When outside non-replicating parentheses, they increase or decrease the interval between the start of the next note and the note after it (and each subsequent interval) by some preset number of milliseconds. So in ++NP the interval between the N and P is longer than usual.

The duration of notes and the time interval between them cannot drop below 0.

Challenge

I intentionally chose () 01+- to be the 7 special characters because they can be innocuously placed in many contexts in lots of programming languages.

Your task is to write a quine in 512 bytes or less that produces the best sounding tune when the code itself is used as the input string in the JSFiddle.

You may choose any initial values (non-negative integers) for the 4 interval/duration parameters, but your tune must not last more than 10 minutes. You should also tell us if your tune sounds best in a particular instrument.

Rules

  • Only tabs, newlines, and printable-ASCII are allowed in your code. All non-printable ASCII is ignored by the tune creator.
  • Output may go to a file or stdout or the closest alternative (e.g. JS alert). There is no input.
  • No reading of source code. It must be a true quine.
  • The removal of any 3 contiguous source characters must make the program no longer function as a quine. This is to ensure people don't write a good song in a string then have a tiny quine portion to output it.
    • So if your program was MYCODE then MYC, MYE, MDE, and ODE should all not be quines (they may error or output something else).

This is a popularity-contest, the highest voted answer wins.

Update: Relaxed last rule.

Calvin's Hobbies

Posted 2014-09-03T10:27:52.667

Reputation: 84 000

3You can play Mary Had a Little Lamb on a phone keypad, too: 3212333 222 399 (try it, it comes out perfectly.) – Level River St – 2014-09-03T11:00:11.843

There are plenty of free soundfonts for piano. Also, nice JSFiddle! – qwr – 2014-09-04T01:33:51.713

I've never seen the last rule in any challenge before, quite effective as intended, I think. – justhalf – 2014-09-04T01:55:16.180

@qwr Do you know of any sets of all 88 keys that can be directly linked in this fashion? I looked a bit but couldn't find any.

– Calvin's Hobbies – 2014-09-04T01:58:36.877

Answers

6

C

I decided I liked the low rumbling noise generated by the string /**/ which is not-so-coincidentally the way to open and close a comment in C. The only other interesting bit here is that 34 for a " is replaced by 35-1(Ending in a 1 intentionally) to avoid god-awful chords. I also tried to make the ending sound dramatic. I really did. I intend to edit this later to make it sound a bit better.

/**/char*p= "/**/char*p= %c%s%c; int main(){printf(p,34,p,35-1);p++;/**/}/**/";
int main(){printf(p,34,p,35-1);p++;/**/}/**/

To my understanding of the rules, the commented sections still pass the final rule because their removal results in a failed quine.

BrainSteel

Posted 2014-09-03T10:27:52.667

Reputation: 5 132

3"I intend to edit this later to make it sound a bit better." It's been almost a year. I'm starting to think you won't be editing this later to make it sound better. :P – Alex A. – 2015-08-24T02:29:37.550

@AlexA. Over a year now! – wizzwizz4 – 2015-10-23T15:58:30.660

5

J

Yeah, I think you can guess how this is going to go.

It's hard to get anything cool done in J without parens, and since you can rarely end them with 0s and 1s, most things sound like someone sitting on the high and low halves of the keyboard at the same time. I tried my best, I'll have you know.

Here's a funky baseline for piano, I think. I really don't know the first thing about composition, I just grabbed a quine and twiddled the numbers around a bit.

(23 23,~,~i.124+-100){,'(23 23,~,~i.124+-100){,'''

And, just for fun, play this one as EDM. I call it Japhex Twin.

".s=:'''".s=:'',''''''''&,@(,&'''''''')@(#~>:@(=&''''''''))s'

You can confirm the quineiness of these fine snippets of code at tryj.tk.

algorithmshark

Posted 2014-09-03T10:27:52.667

Reputation: 8 144

1This actually could pass for music. Great! :) – Emil – 2014-09-24T15:48:52.180

4

Musique Concrete with Python

I don't have a lot of time today but I wanted to get an answer in. The genre is an excuse for not sounding like anything. Maybe a sound effect in a video game?

BFIN10=r"print('BFIN10=r\"'+BFIN10+'\"'+'\nexec(BFIN10)')"
exec(BFIN10)

qwr

Posted 2014-09-03T10:27:52.667

Reputation: 8 929

Actually doesn't sound too bad! – Claudiu – 2014-09-23T20:25:10.270

Every Yoko Ono album ever – William Barbosa – 2014-09-24T17:32:42.487

4

C

int(printf)(char*,...); (main)(){char*b=",*",i=(34),*m=("int(printf)(char*,...); (main)(){char*b="),
*z="%s%c%s%c,i=(34),*m=(%c%s%c)%sz=%c%s%c,*B=%c%s%c,*f=(%c%s%c)%s(/*)*/%s/*(*/);}//(+++fim)",*B="(f,
i,m,z),(i,z,m),(m,i),(f,b),(m,i),(m,i),(f,z,m),(m,i),(f,z,b),(m,i),(b,z),(B,i),(38,i),(29,B),(26,i),
(26,i),(B,f),(42,i),(i,m,f),B",*f=(";(printf)");(printf)(/*)*/(f,i,m,z),(i,z,m),(m,i),(f,b),(m,i),(m
,i),(f,z,m),(m,i),(f,z,b),(m,i),(b,z),(B,i),(38,i),(29,B),(26,i),(26,i),(B,f),(42,i),(i,m,f),B/*(*/)
;}//(+++fim)

Broken up with line breaks for presentation purposes only; this is only a quine (and only meets length requirements) if newlines are removed.

The printf declaration was needed to compile (printf). /*(*/ and /*)*/ were used to match parentheses in the code, while a mix of parentheses and the comma operator were used to form chords from the printf parameters.

Edit: Shortened to fit size requirements as well as make the piece go a bit faster.

This sounds best on the piano.

es1024

Posted 2014-09-03T10:27:52.667

Reputation: 8 953

2I like it! It starts off kind of slow but everything from token 130 onward is powerfully haunting. You used the screechiness to your advantage. – Calvin's Hobbies – 2014-09-27T01:57:42.007

This one could pass for Fantasy for Orchestra! :P – Soham Chowdhury – 2014-09-27T07:42:50.963

2

I liked the old version better but this is still my favorite song here. I'm trying to give you the bounty but for some reason that's not working. See meta: http://meta.codegolf.stackexchange.com/questions/2263/why-cant-i-award-my-bounty

– Calvin's Hobbies – 2014-09-30T00:49:29.923

3

Scheme

This may not be particularly melodic (actually it sounds like somebody dropped a dead pig into a baby-grand), but at least it is a short piece of music. It would be difficult to make anything much longer or less dead-flying-pig-like in scheme.

((lambda (x) (list x (list 'quote x))) '(lambda (x) (list x (list 'quote x))))

Penguino

Posted 2014-09-03T10:27:52.667

Reputation: 231

1Ow, my ears.... – Claudiu – 2014-09-23T20:24:36.827

2

Für Golfscript

":H;GHGHCFDA;[34]H+2*{-};":H;GHGHCFDA;[34]H+2*{-};

This satisfies the letter of the no-three-consecutive-letter-removal rule, though not the intent, I gather.

Claudiu

Posted 2014-09-03T10:27:52.667

Reputation: 3 870

1

Cobra / Batch

@number float# 2>nul||@echo off
/# 2>nul
for /f "delims=" %%a in (%0) do echo %%a
#/# 2>nul
class P# 2>nul
    def main# 2>nul
        r="# 2>nul"# 2>nul
        s="@number float{3}||@echo off{2}/{3}{2}for /f {1}delims={1} %%a in (%0) do echo %%a{2}#/{3}{2}class P{3}{2}    def main{3}{2}      r={1}{3}{1}{3}{2}       s={1}{0}{1}{3}{2}       Console.write(s,s,34to char,10to char){3}"# 2>nul
        Console.write(s,s,34to char,10to char,r)# 2>nul

Technically not a quine in Batch (it reads it's own source). It is however a quine in Cobra.

It sounds best with the piano mode, somewhat like ghost-level music from a Super Mario World-era video game.

Οurous

Posted 2014-09-03T10:27:52.667

Reputation: 7 916

1

Pyth

J"+K+N+J+N+\K+N+K+NJ"K"J"+K+N+J+N+\K+N+K+NJ

Best played with the fourth setting (amount + and - change interval) at around 20, rest at defaults. Sounds best on the piano.

isaacg

Posted 2014-09-03T10:27:52.667

Reputation: 39 268

0

Haskell

(I'm not sure whether the variable name violates the last rule.)

main=putStr$  jjlmjiebab ++ {--} show jjlmjiebab;jjlmjiebab = "main=putStr$  jjlmjiebab ++ {--} show jjlmjiebab;jjlmjiebab = "

Best played on piano with 1000 millisecond note duration and 250 millisecond note interval, with standard + and - values.

archaephyrryx

Posted 2014-09-03T10:27:52.667

Reputation: 1 035