Introduction

Lisbit is a programming language designed for creating 1-bit audio. It works by running the program that you write once for every frame of the audio output, passing in the current time as a variable called time. If the last statement in your program returns on (Lisbit's version of what other languages might call "true") the audio is turned on for that frame. By alternating which frames end with on, you can make the audio quickly turn on and off, creating audible sound.

Code in Lisbit consists of nested lists. Each list starts with an ( and ends with a ). Items in lists are separated by whitespace. Items in lists can be numbers, symbols, or other lists.

Numbers are just normal numbers. They can be positive or negative and they can have a decimal place. You can also put commas where ever you you want in them, which will simply be ignored without changing the meaning of the number. Here are some examples:


500
-30.25
10,000.56
1,00,00.00,00
			

Symbols are names for things. If Lisbit runs into a symbol when it's trying to read code, it will replace it with whatever value you've bound to it using the define command. Symols can contain letters, !, ?, and -. They can also contain numbers as long as they aren't the first character. Here are some examples:


this-is-a-symbol
is-this-a-symbol?
symbol3
			

You can also add comments where ever you want by putting text between /* and */. Comment will be ignored by Lisbit and just treated like whitespace, so feel free to use them to leave notes to yourself and anyone else who might be looking at your code.

When Lisbit is trying to read code, it does the following:

  1. Looks at the first list in the program.
  2. It expects the first item in the list to be a symbol with a command bound to it
  3. If that command is function, then it first tries to evaluate every other item in the list.
  4. It passes the rest of the list into the command as arguments
  5. The command will return a value, and that will be the result of evaluating the list.
  6. Moves on the the next list.

There are two types of the commands that can be run: functions and macros. Arguments passed to functions get evaluated as code before the function sees them, but arguments to macros get passed in directly, so the macro can choose whether it wants to evaluate them or not. This lets you build your own custom languages structures, that can be pretty powerful. Here are some examples of functions and macros getting called:


(add 1 1)

(mul (add 1 1) (sub 1 1))

(define foo 5)
(add foo 10) /* This is treated the same as (add 5 10) */

(define double (function (my-number) (add my-number my-number)))
(double 5) /* This is treated the same as (add 5 5) */
			

Audio techniques

While Lisbit gives you all the tools you need to create audio, it doesn't really point you in any particular direction when it comes to actually producing sound. This can be nice, since it lets you experiment with a lot of different techniques, but it can also make it hard to know how to start. Hopefully this section will help you figure out how to make basic notes.

You ears hear sound whenever waves of pressurised air hits your eardrum, causing it so move vibrate and send signals to your brain. If the waves of pressure are short, switching quickly between high pressure and low pressure, you'll hear a high pitched sound. If they're longer, you'll hear a low pitched sound. The larger the difference in pressure, the louder the sound will be.

Lisbit only offers you two options for pressure: on and off. This doesn't make it easy to create the complex sounds or the real world, but it can make some pretty interesting sounds and provide a fun constraint for anyone making audio.

You can create alternating waves in Lisbit by writing functions that will return on or off depending on what the time is. Here's an example of a function like that:


(define tone (function (time hz)
	(eq? (mod (floor (mul time hz)) 2) 0)))
			

This function will return a value that will switch on and off hz times per second. If you pass in a high value for hz you can use it for a hight tone, and if you pass a low value for hz you can use it for a low tone.

Since the values tone returns are just regular booleans you can pass them to functions and modify or combine sounds. Here's an example:


(and
  (tone time 300)
  (tone time 2000))
			

This example might not sound particularly pleasant, but with some creativity you can use these techniques to create some really cool sounds.

Standard constants

time - number - the current time in seconds.

on - boolean - a truthy value.

off - boolean - a falsey value.

Standard macros

define

Description

Binds a value to a symbol.

Arguments

symbol - The name of the symbol to bind to.
boolean/number/list/function - The value to bind to it.

Examples


(define pi 3.14159)
(define double (function (x) (mul x 2)))
(define no (eq? 5 6))
(define shopping-list (list oranges bread fish))
				

function

Description

Returns a new function. It also binds the symbol 'recur' to itself so you can make recursive calls.

Arguments

symbol/list - A symbol that will be bound to the list of parameters, or a list of symbols that will each be bound to one of the parameters.
expression - The code that will be executed whenever the function is called.

Examples


(function (x y) (mul x y))
(function numbers (apply mul numbers))
(define factorial (function n (if (eq? n 1) 1 (mul n (recur (sub n 1))))))
				

macro

Description

Returns a new macro. This works like a function, but it doesn't evaluate its arguments so you can evaluate them yourself.

Arguments

symbol/list - A symbol that will be bound to the list of parameters, or a list of symbols that will each be bound to one of the parameters.
expression - The code that will be executed whenever the macro is called.

Examples


(define unless
  (macro (condition if-on if-on)
	(if (not (eval condition))
	  (eval if-off)
	  (eval if-on))))
(define my-quote (macro (arg) arg))
				

quote

Description

Return an object without evalutating it.

Arguments

any - The object to be quoted.

begin

Description

Evaluate pieces of code in sequence

Arguments

expression - The code to evalute first.
more expressions, etc.
expression - The code to evaluate last. The return value of this expression will be used as the return value of begin.

Examples


(begin
  (define a 1)
  (define b 2)
  (add a b))
				

begin

Description

Evaluate the first argument. If the result is on return the result of evaluating the second argument. Otherwise return the result of the third argument if it exists.

Arguments

expression - Condition to evalute.
expression - The result if it's on.
expression - The result in all other cases.

Examples


(if (eq? 1 1) 1 0)
(if (lt? (add 1 1) (mul 1 1))
  (add 100 100)
  (mul 100 100))
				

cond

Description

Return the result of evaluating second item of the first argument who's first item evaluates to on.

Arguments

list
expression - Condition to evalute.
expression - The result if it's on.
more lists, etc.

Examples


(cond
  ((gt? 1 3) 1)
  ((gt? 2 3) 2)
  ((gt? 3 3) 3)
  ((gt? 4 3) 4) /* 4 gets returned */
  ((gt? 5 3) 5))
				

and

Description

Evaluates its arguments until it finds one that returns off, in which it returns off. If none of them are off then it returns on.

Arguments

expression - First condition to test
more expressions, etc.

Examples


(and on on)
(and (lt? 0 1) (gt? 0 -1))
				

or

Description

Evaluates its arguments until it finds one that returns on, in which it returns on. If none of them are on then it returns off.

Arguments

expression - First condition to test
more expressions, etc.

Examples


(or on off)
(or on on)
(or (eq? 1 1) (eq? 1 0))
				

Standard functions

eval

Description

Evaluate a list as code

Arguments

list - The list to evaluate.

Examples


(define code (list add 1 1))
(eval code)
				

list

Description

Create a list out of the arguments passed in.

Arguments

any - The first list item.
more of any, etc.

Examples


(list 1 2 3)
(list 1 (add 1 1) (add 1 1 1))
				

apply

Description

Call a function with arguments pulled from a list.

Arguments

function - The function to call.
list - The arguments to the function.

Examples


(apply add (list 1 2 3))
(apply and (list on on))
				

head

Description

Return the first item in an array.

Arguments

list - The list to get the item from.

Examples


(head (list 1 2 3))
				

tail

Description

Return a list with every item from a list except the first element.

Arguments

list - The list to get the items from.

Examples


(tail (list 1 2 3))
				

length

Description

Get the length of a list.

Arguments

list - The list you want the length of.

Examples


(length (list 1 2 3))
(length (list))
				

index

Description

Get the item in a list that's located at a specific index.

Arguments

list - The list you want the item from.
number - The index of the item. The first item of the list is at index 0.

Examples


(index (list 1 2 3) 0)
(index (list 1 2 3) (add 1 1))
				

print

Description

Prints whatever values you pass to it to a special console you can use for debugging. It also returns its arguments without modifying them, so you can easily stick print anywhere you want to know the value of something.

Arguments

any - The first item to print out.
more of any, etc.

Examples


(print 5)
(print 1 2 3)
(print (add 1 1))
(add (print 1) 1)
				

add

Description

Add numbers together.

Arguments

number - The first item to add.
more numbers, etc.

Examples


(add 1 1)
(add 2 2.5 3 4.5)
				

sub

Description

Subtract numbers from each other.

Arguments

number - The starting number.
number - The first number to subtract from it.
more numbers, etc.

Examples


(sub 4 2)
(sub 10 5 3 2 1)
				

mul

Description

Multiply numbers together.

Arguments

number - The first number to multiply.
more numbers, etc.

Examples


(mul 10 10)
(mul 10 20 30 40)
				

div

Description

Divide numbers by each other.

Arguments

number - The starting number.
number - The first number to divide it by.
more numbers, etc.

Examples


(div 100 10)
(div 10 2 2)
				

div

Description

Get the remainder of dividing numbers by each other.

Arguments

number - The starting number.
number - The first number to divide by it to get a remainder.
more numbers, etc.

Examples


(mod 5 2)
(mod 13 5 2)
				

exp

Description

Raise numbers to the power of each other.

Arguments

number - The starting number.
number - The first power to raise it to.
more numbers, etc.

Examples


(exp 10 2)
(exp 10 2 3)
				

log

Description

Get the logarithm of a number with a specified base.

Arguments

number - The number your getting a logarithm of.
number - The base of the first logarithm operation.
more numbers, etc.

Examples


(log 256 2)
(log 100,000,000 10 2)
				

min

Description

Get the lowest number from all the arguments.

Arguments

number - The first number to test.
more numbers, etc.

Examples


(min 1 2 5 0)
(min (add 1 1) (sub 1 1) (mul 1 1) (div 1 1))
				

max

Description

Get the highest number from all the arguments.

Arguments

number - The first number to test.
more numbers, etc.

Examples


(max 100 10000 10)
(max (add 10 10) (sub 10 10) (mul 10 10) (div 10 10))
				

not

Description

Return the inverse of a boolean argument.

Arguments

boolean - The boolean to get the inverse of.

Examples


(not off)
(not (and off on))
				

eq?

Description

Returns on if all of the arguments are equal.

Arguments

number - The first number to test.
more numbers, etc.

Examples


(eq? 1 1)
(eq? (add 1 0) (sub 1 0) (mul 1 1) (div 1 1))
				

lt?

Description

Returns on if every argument is less than the next one.

Arguments

number - The first number to test.
more numbers, etc.

Examples


(lt? 1 2 3)
(lt? (mul 1 1) (mul 10 10) (mul 100 1000))
				

gt?

Description

Returns on if every argument is greater than the next one.

Arguments

number - The first number to test.
more numbers, etc.

Examples


(gt? 3 2 1)
(gt? (mul 2 2 2 2) (mul 2 2 2) (mul 2 2))
				

xor

Description

Return on if an odd number of its arguments are on.

Arguments

boolean - The first boolean to test.
more booleans, etc.

Examples


(xor on off)
(xor on off on off)
				

xor

Description

Return on if an odd number of its arguments are on.

Arguments

boolean - The first boolean to test.
more booleans, etc.

Examples


(xor on off)
(xor on off on off)
				

floor

Description

Round down a number.

Arguments

number - The number to round down.

Examples


(floor 3.14)
(floor (div 10 3))
				

floor

Description

Round up a number.

Arguments

number - The number to round up.

Examples


(ceil 6.28)
(ceil (div 20 7))
				

rand

Description

Returns a pseudorandom number between 0 and 1 based on a seed value you supply.

Arguments

number - A seed value that's used to create a pseudorandom number. If you use the same seed multiple times, it will return the same value each time.

Examples


(rand 0)
(rand time)
				

rand-bool

Description

Pseudorandomly returns on or off based on a seed value you supply.

Arguments

number - A seed value that's used to create a pseudorandom result. If you use the same seed multiple times, it will return the same result each time.

Examples


(rand-bool 0)
(rand-bool time)