Take the 2-minute tour ×
Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. It's 100% free, no registration required.

I used to play the oboe, the instrument that is, for some reason, used to tune the orchestra to A440. Anyways, continuing on with my story, I was bad at it and quit.

Write a program that generates a valid, full scale, 5 second, WAV file with a sample rate of 44.1 kHz that plays a 440 Hz (+3/-1 Hz) tone. Your code is responsible for generating the structure of the file format; no external resources.

+75 penalty if the tone does not approximate a sine wave (harmonic power must be less than 1% of the fundamental--a good polynomial approximation should be able to exceed 20 dB; I think parabolic is about -28 dB)

share|improve this question
2  
define "sine wave". Is it okay if I use a truncated triangle wave, a parabolic wave or (say) a 20-line approximation, or I have to get it right within a few ULP? –  Jan Dvorak Feb 5 at 12:41
2  
Specifically, having a measurable metric as part of the goal (say, using Audacity spectral analysis) would be optimal. –  Tobia Feb 5 at 13:10
    
Can you clarify rules for amplitude? Does it have to be 0 dBFS? Or, taking it to the extreme, can I use only 1 bit, and just toggle the bit 880 times a second? –  dvnrrs Feb 7 at 22:14
    
@dvnrrs yeah, full scale is basically what I was going for in saying "audible" (was trying to avoid 1 LSB WAVs). –  Nick T Feb 8 at 3:17
    
@Tobia I loosened "sine" to be things that are very-nearly-sinusoidal, if a polynomial or other approximation would work better. –  Nick T Feb 8 at 3:25

3 Answers 3

GolfScript, 89 bytes

This GolfScript program contains non-printable characters, so I'm providing it as a hex dump. On Unixish systems with the xxd program installed, you can feed this hex dump to xxd -r to reconstruct the actual program.

0000000: 2752 4946 4678 5d03 0057 4156 4566 6d74  'RIFFx]..WAVEfmt
0000010: 2010 0000 0001 0001 0044 ac00 0044 ac00   ........D...D..
0000020: 0001 0008 0064 6174 6154 5d03 0027 2784  .....dataT]..''.
0000030: 8c94 9ba3 abb2 bac1 c7ce d4da e0e5 e9ee  ................
0000040: f2f5 f8fa fcfe ffff 272e 2d31 252b 2e7b  ........'.-1%+.{
0000050: 7e7d 252b 3232 3035 2a                   ~}%+2205*

The output of this program is a 220,545 byte 44.1 kHz 8-bit PCM WAV file that should play a 441 Hz tone for five seconds.

The code itself simply consists of two literal single-quoted strings: the first one contains a minimal WAV header, while the second 25-byte string, representing a quarter of the sine wave, is cloned, reversed, joined to the original, cloned again, inverted, joined again and finally repeated 2205 times to produce the actual audio data.

Ps. The output of the program above includes as extra trailing 0x0A byte (i.e. a line feed), which is technically not part of the WAV data. Since it lies past the end of the RIFF chunk, reasonable decoders should ignore it. (This could be fixed, at the cost of two extra bytes of code.)

share|improve this answer
1  
"generate a ... WAV file with a sample rate of 44.1 kHz" –  Jan Dvorak Feb 5 at 13:38
    
@JanDvorak: Oh. I could've sworn that wasn't there when I started writing this, but maybe I just missed it. :-( –  Ilmari Karonen Feb 5 at 13:40
    
@JanDvorak: OK, fixed it, now it's 44.1 kHz. –  Ilmari Karonen Feb 5 at 14:11

C, 204 bytes

Won't win, but here it is anyway :-)

x;main(i){char *h="riff\xec\xda& wave\x86\x8d\x94@0   ! ! d\xcc  \xa8x! \" 0 \x84\x81\x94\x81\xc8\xda& ";for(i=45;--i;)putchar(*h++-' ');for(;i++<220500;){x=(32767*sin(i/15.952));printf("%c%c",x,x>>8);}}

Needs to be compiled with the maths library, of course.

Outputs a 5-second WAV file to stdout (16-bit samples, 44.1 kHz sampling), but this can easily be redirected to a file (e.g., ./a.out >foo.wav)

share|improve this answer

R, 285 characters

S=44100;s=sin(0:(5*S-1)*pi*880/S);c=32767*s/max(abs(s));a=file("c.wav","wb");w=writeChar;W=function(x,z)writeBin(as.integer(x),a,z,e="little");w("RIFF",a,4,NULL);W(441036,4);w("WAVEfmt ",a,8,NULL);W(16,4);W(c(1,1),2);W(S*1:2,4);W(c(2,16),2);w("data",a,4,NULL);W(S*10,4);W(c,2);close(a)

Create a wav file called c.wav in the working directory.

Indented:

S=44100
s=sin(0:(5*S-1)*pi*880/S) #Sin Wave
c=32767*s/max(abs(s)) #Normalized
a=file("c.wav","wb") #Open connection with empty wav file
w=writeChar #Write characters
W=function(x,z)writeBin(as.integer(x),a,z,e="little") #Write binary data
w("RIFF",a,4,NULL)
W(441036,4)
w("WAVEfmt ",a,8,NULL)
W(16,4)
W(c(1,1),2)
W(S*1:2,4)
W(c(2,16),2)
w("data",a,4,NULL)
W(S*10,4)
W(c,2)
close(a)
share|improve this answer
    
no external resources –  Fez Vrasta Feb 5 at 12:54
    
how is this an external resource? –  plannapus Feb 5 at 12:55
2  
"Your code is responsible for generating the structure of the file format" - this means that you can't use writeWave. The challenge lies in implementing the wav spec. –  Jan Dvorak Feb 5 at 12:56
    
ok ok, before I rewrite it, is the creation of the sinewave itself at least ok with you guys like that? –  plannapus Feb 5 at 13:04
    
It's fine for me. –  Jan Dvorak Feb 5 at 13:05

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.