Skip to content

paulguy/pcspkrplay

Repository files navigation

PC Speaker Player - pcspkrplay

Introduction
------------

This program will play PC speaker music in Linux using the Linux input 
devices API.  Currently loosely based on Megazeux style play statements, but
might break on some less compliant play strings.

If you were looking to play PCM sound and music through the PC speaker, this
isn't what you want.  Look in to the ALSA driver snd-pcsp for that.  It'll make
your PC speaker in to a plain old ALSA "card" for programs to output audio to.


Compiling
---------

Executing:
make

should build it for you.  This doesn't depend on anything special that 
wouldn't come with linux.


Usage
-----

<executable> <options>

Options:
--decompile / -d
	After compiling, decompile back to music string.  (Currently disabled)

--device    / -e device
	Select event device, default is
	/dev/input/by-path/platform-pcspkr-event-spkr.

--filename  / -f filename
	Read from filename instead of standard input.

--quiet     / -q
	Don't play, only compile (and optionally decompile) then quit.

--display   / -s
	Display playback status.

--help      / -h
	Print quick help/usage.

--debug
	Enable debug mode.  Prints information on program state after each
	command	is executed.

You will need full read/write access to the event device you wish to use.
Look up the chmod command for information on setting that up.


Music String Format
-------------------

Mostly based on Megazeux's play statement format, but extended for more 
features.

C, D, E, F, G, A, B
	Play a note.

0, 1, 2, 3, 4, 5, 6
	Select octave, default is 3.

#, $
	Placed after a note, moves the note up or down a semitone.  B# is
	accepted and becomes C on the next octave except for 6B#, E becomes F,
	C$ becomes B on the previous octave except for 0C$.

Z, T, S, I, Q, H, W
	Select note duration, 64th, 32nd, 16th, 8th, quarter, half, whole.
	Default is 32nd.

+, -
	Increase or decrease octave by 1, clips at 0 and 6.                  

.
	Change duration of folloing notes by 150%.  Can be unset with another
	'.', can override '!'.

!
	Change duration of following notes by 1/3.  Can be unset with another
	'!', can override '.'.

&string&
	Ignores string.  Normally used to play a sample in Megazeux, but for
	this program, you can use it for comments.

*
	Extended command
	bb
		Change BPM.  (see VM COMMANDS for argument format)

	db
		Change to custom note division.  (see VM COMMANDS for argument format)

	VM COMMANDS
	-----------
		VM commands follow the same format as Extended commands, but
	provide	much more robust control and program flow.

	Numbers:
		A number entered in a command can be from 0 to 16777215.  Since
	this language doesn't really require spaces, termination is done after
	8 digits have been read in, or a nondigit (start of a new command) is
	reached.  If the next command is an octave change command, you will
	have to terminate the number with a ^.

	Examples
	*b123cdefg - Set BPM to 123, then play CDEFG.
	*b60^2cdefg - Set BPM to 60, set octave to 2, then play CDEFG.

	Registers:
		The language includes 26 registers, represented by the letters a
	through z.  o, d, b and l have special meanings for octave, divisor, BPM
	and duration.  The previous commands used to modify these values also
	modify these registers, but in a more limited way.  The rest are special
	purpose and can be used freely.  Any special purpose registers brought
	out of range will be set to a more sane value.

	Commands:
		Commands consist of a letter and possible arguments following. 
	An argument can either be a numerical value or a register, specified by
	a n or an r, or b if it can take both.  Currently there are no
	instructions that only take a numerical value.

	nb
		Play a note from 1(C) to 12(B), or 0 to play a rest.

	mrb
		Move a value or register (b) in to register (r).

	arb
		Add a value or register (b) to register (r).

	srb
		Subtract a value or register (b) from register (r).

	crb
		Compare a value or register (b) with register (r).  Used for
		conditional jumping to specify the items to be compared.

	ib
		Jump to command position in value or register (b) if comparison
		is inequal.

	eb
		Jump to command position in value or register (b) if comparison
		is equal.

	gb
		Jump to command position in value or register (b) if second
		item in comparison is greater.

	lb
		Jump to command position in value or register (b) if second
		item in comparison is less.

	jb
		Jump to command position in value or register unconditionally.

	>b
		Branch to a subroutine which can return to the command directly
		after this one.

	r
		Return from a subroutine.

	f
		Clear flags after a comparison.  It's important that this is
		done after a comparison in most situations.

	:
		Create a label.

	h
		Halt program execution.

	Labels:
		The argument to any of the jump commands, as well as branch can 
	be preceded with a : (eg: *j:0) which will say to jump to position at
	label 0.  Labels are created with the *: command.  They are
	automatically assigned valuessequentially.  The first *: will be label
	0, the next will be label 1, then 2 and so on.

|
	Doesn't do anything and isn't detected by the engine in any way, but
	this will always be reserved to be used as a bar/separator.

Unknown or malformed commands are ignored.


Examples
--------

echo "cdefgab+c" | ./pcspkrplay
	Play C major scale at octave 3 with 32nd notes.

echo "q2cdefgab+c" | ./pcspkrplay
	Play C major scale at octave 2 with quarter notes.

./pcspkrplay -f song.txt
	Play song.txt.

./pcspkrplay -f song.txt -q --decompile >song_optimized.txt
	Compile then decompile song, size-optimizing it, but don't play it.


Troubleshooting
---------------

open: No such file or directory
	Make sure the file exists, and if it's a different name, provide it to
pcspkrplay using the -e argument.  You might also need to load the PC
speaker driver, pcspkr with:
modprobe pcspkr

open: Operation not permitted
	Make sure you have adequate permission to read and write to the pc
speaker event device.  If you don't you can use something like this as root:
chmod a+rw /dev/input/by-path/platform-pcspkr-event-spkr
NOTE: Running pcspkrplay as root will work but you shouldn't run anything as
root unless you absolutely cannot avoid it.

ioctl: Inappropriate ioctl for device
	The device attempted to use isn't a Linux input device.

Device X does not support sound.
	The input device attempted to use doesn't expose a beeper speaker
interface.

Segmentation fault/Floating point exception/Arithmetic exception/*** glibc
detected: ... ***/etc.
	The program has crashed due to a bug.  Please post a bug report and the
song which failed on the github page at http:/paulguy/pcspkerplay
and I will see about fixing it.

VM EXCEPTION: ...
	If not in debug mode, this can mean either a problem with your song, or
a bug in the program.  If you feel your song is written correctly and that a bug
in the program is at fault, please post a bug report.  If it reports
DEVICE_ERROR, it could more likely be a bug unrelated to your song at all.

Credits
-------
Design and Program - Paul "paulguy"
Makefile and some help teaching me GIT - Mike Swanson "Chungy"
Example Song - Original: DJ Shadow, PC Speaker cover: "neffy"

About

Play music through the PC speaker in Linux

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages