x86 machine code (.COM file): 121 120 bytes
Hexdump:
00000000 b4 3e bb 01 00 cd 21 b4 3c 31 c9 ba 47 01 cd 21 |.>....!.<1..G..!|
00000010 42 b4 09 cd 21 be 61 01 81 fe 78 01 0f 84 e0 fe |B...!.a...x.....|
00000020 31 c0 8a 04 46 88 c3 80 e3 03 89 c1 c1 e1 05 e8 |1...F...........|
00000030 0a 00 30 db b9 40 06 e8 02 00 eb dc 30 d2 b4 02 |[email protected]...|
00000040 00 da cd 21 e2 fa c3 61 2e 73 6e 64 00 00 00 18 |...!...a.snd....|
00000050 ff ff ff ff 00 00 00 02 00 00 1f 40 00 00 00 01 |...........@....|
00000060 24 33 33 97 97 97 64 97 97 97 97 97 64 33 97 97 |$33...d.....d3..|
00000070 97 97 64 33 33 33 33 33 |..d33333|
Can be easily run under DosBox; the output is a .SND file named a.snd
. Here is a FLAC version of its output (and here the .COM file).
Commented assembly:
org 100h
start:
; close stdout
mov ah,3eh
mov bx,1
int 21h
; open a.snd
mov ah,3ch
xor cx,cx
mov dx,filename
int 21h
; write the header
inc dx
mov ah,9h
int 21h
mov si,data
.l:
; data read cycle
; quit if we reached the end of data
cmp si,eof
je 0
; read the current byte in ax (zero-extending to 16-bit)
xor ax,ax
mov al,[si]
; move to next byte
inc si
; bl: ramp increment per sample; take the low 2 bits
mov bl,al
and bl,3
; cx: length of the wave in # samples; high 6 bits, right shifted of 5
mov cx,ax
shl cx,5
; generate the tone
call gen
; generate the pause
xor bl,bl
mov cx,1600
call gen
; rinse and repeat
jmp .l
gen:
; generate a sawtooth wave
; receives length (in samples) in cx, ramp increment in bl
xor dl,dl
mov ah,2h
.l:
; increment the signal
add dl,bl
; write it
int 21h
; decrement iteration count and loop
loop .l
ret
; here be the data
; used for the file name; we recycle the .snd from the beginning
; of the file header, exploiting the fact that it starts with a zero
filename:
db "a"
header:
; .SND file header (8000 samples, mono, PCM)
db ".snd",0,0,0,24,0xff,0xff,0xff,0xff,0,0,0,2,0,0,0x1f,0x40,0,0,0,1
; terminator for int 21h/ah=9h
db '$'
data:
; generated by gendata.py
incbin "data.dat"
eof:
The data.dat
included above is an easy-to-use representation of the morse string (lower 2 bits: sawtooth wave increment per sample, upper 6 bits: sound length in samples >> 5) generated by a Python script:
#!/usr/bin/env python2
import sys
# source string
s = "..--- ----- .---- ....."
# samples
sr = 8000
conv = {
'.': 3 | (((sr/5) >> 5) & ~3), # dot: 1/5 second, dI/dt=3
'-': 3 | (((sr/5*3) >> 5) & ~3), # line: 3/5 second, dI/dt=3
' ': ((sr/5*2) >> 5) & ~3 # space: 2/5 second (+1/5 from the always-present pause), dI/dt=0 (silent)
}
sys.stdout.write(''.join(chr(conv[a]) for a in s))