small corrections

This commit is contained in:
sejo 2021-10-12 20:49:28 -05:00
parent 2556747357
commit 5ce317b7ab
1 changed files with 62 additions and 34 deletions

View File

@ -1,6 +1,6 @@
# uxn tutorial: day 7, more devices
this is the seventh and last section of the <(uxn tutorial)>! here we talk about the devices in the varvara computer that we haven't covered yet: audio, file, and datetime.
this is the seventh and last section of the {uxn tutorial}! here we talk about the devices in the varvara computer that we haven't covered yet: audio, file, and datetime.
this should be a light and calm end of our journey, as it has to do less with programming logic and more with the input and output conventions in these devices.
@ -44,7 +44,9 @@ we can use a structure like the following, where the filename and reserved memor
@load-file ( -- )
;file/name .File/name DEO2 ( set address of file path )
#00ff .File/length DEO2 ( will attempt to read 255 bytes )
;file/data .File/load DEO2 ( set address for the data to read, and read )
( set address for the data to read, and do read )
;file/data .File/load DEO2
( check the success byte and jump accordingly )
.File/success DEI2 #0000 EQU2 ,&failed JCN
@ -62,7 +64,9 @@ RTN
&data $ff ( reserving 255 bytes for the data )
```
note that in this case we are writing a character to the console according to the success short being zero or not, but we could decide to take any action that we consider appropriate.
note that for the filename we are using the raw string rune (") that allows us to write several characters in program memory until a whitespace is found.
int this example we are writing a character to the console according to the success short being zero or not, but we could decide to take any action that we consider appropriate.
also, in this example we are not really concerned with how many bytes were actually read: keep in mind that this information is stored in File/success until another read or write happens!
@ -85,8 +89,12 @@ the following program will write "hello" and a newline (0a) into a file called "
```
@save-file ( -- )
;file/name .File/name DEO2 ( set file name )
#0006 .File/length DEO2 ( will attempt to write 6 files )
;file/data .File/save DEO2 ( set data starting address, and write )
#0006 .File/length DEO2 ( will attempt to write 6 bytes )
( set data starting address, and do write )
;file/data .File/save DEO2
( read and evaluate success byte )
.File/success DEI2 #0006 NEQ2 ,&failed JCN
&success
@ -116,11 +124,11 @@ for example, if we wanted to continue writing to our file after the "hello" and
#0006 .File/offset-ls DEO2
```
and then the next write will not overwrite the file, but append to it.
and then the next write will not overwrite the file, but append to it starting at position 6 (i.e. just after the newline)
## a brief case study: the theme file
varvara programs written by 100r tend to have the ability to read a "theme" file that contains six bytes corresponding to the three shorts for the system colors.
programs for the varvara computer written by 100r tend to have the ability to read a "theme" file that contains six bytes corresponding to the three shorts for the system colors.
this file has the name ".theme" and can be written to a local directory from nasu, using the ctrl+p shortcut.
@ -134,7 +142,9 @@ we could adapt our previous subroutine in order to load the theme file and apply
@load-theme ( -- )
;theme/name .File/name DEO2 ( set address of file path )
#0006 .File/length DEO2 ( will attempt to read 6 bytes )
;theme/data .File/load DEO2 ( set address for the data to read, and read )
( set address for the data to read, and do read )
;theme/data .File/load DEO2
( check the success byte and jump accordingly )
.File/success DEI2 #0006 NEQ2 ,&failed JCN
@ -168,7 +178,9 @@ and for doing the opposite operation, we can read the system colors into our res
;theme/name .File/name DEO2 ( set address of file path )
#0006 .File/length DEO2 ( will attempt to write 6 bytes )
;theme/data .File/save DEO2 ( set address for the data and write )
( set address for the data and do write )
;theme/data .File/save DEO2
( check the success byte and jump accordingly )
.File/success DEI2 #0006 NEQ2 ,&failed JCN
@ -187,7 +199,7 @@ i invite you to compare these subroutines with the ones present in the 100r prog
# the datetime device
the datetime device can be useful for low resolution timing and/or for visualizations of time.
the datetime device can be useful for low precision timing and/or for visualizations of time.
it has several fields that we can read, all of them based on the current system time and timezone:
@ -198,12 +210,12 @@ it has several fields that we can read, all of them based on the current system
* the year short corresponds to the number of year in the so called common era
* the month byte counts the months since january (i.e. january is 0, february 1, and so on)
* the day byte counts the days in the month starting from 1
* the hour, minute and second bytes correspond to what one would expect
* dotw (day of the week) is a byte counts the days since sunday (i.e sunday is 0, monday is 1, and so on)
* doty (day of the year) is a byte counts the days since january 1 (i.e. jan 1st is 0, jan 2nd is 1, and so on)
* the hour, minute and second bytes correspond to what one would expect: their values go from 0 to 23, or 0 to 59 respectively.
* dotw (day of the week) is a byte that counts the days since sunday (i.e sunday is 0, monday is 1, tuesday is 2, and so on)
* doty (day of the year) is a byte that counts the days since january 1 (i.e. jan 1st is 0, jan 2nd is 1, and so on)
* isdst (is daylight saving time) is a flag, 01 if it's daylight saving time and 00 if it's not.
it should be straightforward to use them! e.g. in order to read the hour of the day into the stack:
based on this, it should be straightforward for you to use them! e.g. in order to read the hour of the day into the stack, we'd do:
```
.DateTime/hour DEI
@ -215,7 +227,7 @@ maybe you can use these values as coordinates for some sprites, or maybe you can
or what about conditionally drawing sprites, and/or changing the system colors depending on the time? :)
remember that for timing with a little bit more resolution, you can count the times that the screen vector has been fired!
remember that for timing events with a little bit more precison, you can count the times that the screen vector has been fired!
# the audio device
@ -224,10 +236,10 @@ at last, the audio device! or i should say, the audio devices!
varvara has four identical stereo devices (or "channels"), that get mixed before going into the speakers/headphones:
```
|30 @Audio0 [ &vector $2 &position $2 &output $1 &pad $3 &adsr $2 &length $2 &addr $2 &volume $1 &pitch $1 ]
|40 @Audio1 [ &vector $2 &position $2 &output $1 &pad $3 &adsr $2 &length $2 &addr $2 &volume $1 &pitch $1 ]
|50 @Audio2 [ &vector $2 &position $2 &output $1 &pad $3 &adsr $2 &length $2 &addr $2 &volume $1 &pitch $1 ]
|60 @Audio3 [ &vector $2 &position $2 &output $1 &pad $3 &adsr $2 &length $2 &addr $2 &volume $1 &pitch $1 ]
|30 @Audio0 [ &vector $2 &position $2 &output $1 &pad $3 &adsr $2 &length $2 &addr $2 &volume $1 &pitch $1 ]
|40 @Audio1 [ &vector $2 &position $2 &output $1 &pad $3 &adsr $2 &length $2 &addr $2 &volume $1 &pitch $1 ]
|50 @Audio2 [ &vector $2 &position $2 &output $1 &pad $3 &adsr $2 &length $2 &addr $2 &volume $1 &pitch $1 ]
|60 @Audio3 [ &vector $2 &position $2 &output $1 &pad $3 &adsr $2 &length $2 &addr $2 &volume $1 &pitch $1 ]
```
similar to how in the screen device we can draw by pointing to addresses with sprite data, in the audio devices we will be able to play sounds by pointing to addresses with audio data ("samples").
@ -319,7 +331,9 @@ the audio.channels.tal example in the uxn repository, has several of them, all o
and what do these numbers mean?
in the context of varvara, we can understand them as multiple unsigned bytes (u8) that correspond to amplitudes of the sound wave that compose the sample. a "playhead" visits each of these numbers for a given time, and uses them to set the amplitude of the sound.
in the context of varvara, we can understand them as multiple unsigned bytes (u8) that correspond to amplitudes of the sound wave that compose the sample.
a "playhead" visits each of these numbers during a specific time, and uses them to set the amplitude of the sound wave.
for example, in the case of the saw sample, if we look at it as single bytes instead of shorts, we can see that it consists in a series of numbers going from 00 to fd, increasing by 03 at a time:
@ -329,7 +343,9 @@ for example, in the case of the saw sample, if we look at it as single bytes ins
( etc )
```
the sound wave will have the shape of a ramp going up over time. and if we loop it, over time we would have a ramp going up, and then returning quickly to 00, multiple times: i.e. a "sawtooth" shape.
the sound wave will have the shape of a ramp going up over time.
and if we loop it, we would have a ramp going up, and then returning quickly to 00, multiple times: i.e. a "sawtooth" shape.
similar to how we have dealt with sprites and with the file device above, in order to set a sample in the audio device, we just have to write its address and its length:
@ -342,11 +358,11 @@ the frequency at which this sample is played (i.e. at which the wave amplitude t
## pitch
the pitch byte is similar to the sprite byte in that it makes the sample start playing whenever we write to it.
the pitch byte makes the sample start playing whenever we write to it, similar to how the sprite byte performs the drawing of the sprite when we write to it.
the first 7 bits (from right to left) of the byte correspond to a midi note (and therefore to the frequency at which the sample will be played), and the eighth bit is a flag: when it's 0 the sample will be looped, and when it's 1 it won't.
the first 7 bits (from right to left) of the byte correspond to a midi note (and therefore to the frequency at which the sample will be played), and the eighth bit is a flag: when it's 0 the sample will be looped, and when it's 1 the sample will be played only once.
normally we will want to loop the sample in order to generate a tone based on it. only when the sample is long enough it will make sense to not loop it.
normally we will want to loop the sample in order to generate a tone based on it. only when the sample is long enough it will make sense to not loop it and play it once.
regarding the midi note bits, it's a good idea to have a midi table around to see the hexadecimal values corresponding to different notes.
@ -354,7 +370,9 @@ regarding the midi note bits, it's a good idea to have a midi table around to se
middle C (C4, or 3c in midi) is assumed to be the default pitch of the samples.
so in theory, the following program should play our sample at that frequency, or not?
### a "sample" program
in theory, the following program should play our sample at that frequency, or not?
```
( hello-sound.tal )
@ -371,7 +389,9 @@ so in theory, the following program should play our sample at that frequency, or
BRK
```
almost there! in order to actually hear the sound, we need two more things: to set the volume of the device, and to set the ADSR envelope!
not really!
but almost there! in order to actually hear the sound, we need two more things: to set the volume of the device, and to set the ADSR envelope!
## volume
@ -385,9 +405,11 @@ the following would set the maximum volume in the device:
#ff .Audio0/volume DEO ( set maximum volume in left and right )
```
although the samples are mono, we can pan them with the volume byte in order to get stereo sound!
## ADSR envelope
the last component we need in order to play audio, is the ADSR envelope.
the last component we need in order to play audio is the ADSR envelope.
ADSR stands for attack, decay, sustain, and release. it is the name of a common "envelope" that modulates the amplitude of a sound from beginning to end.
@ -400,9 +422,11 @@ in the varvara computer, the ADSR components work as follows:
each of these transitions are done linearly.
in the ADSR short, there is one nibble for each of the components: therefore each one can have a duration from 0 to f.
in the ADSR short of the audio device, there is one nibble for each of the components: therefore each one can have a duration from 0 to f.
the units for these durations are 15ths of a second. for example, if the duration of the attack component is 'f', then it will last one second.
the units for these durations are 15ths of a second.
as an example, if the duration of the attack component is 'f', then it will last one second (15/15 second, in decimal).
the following will set the maximum duration on each of the components, making the sound last 4 seconds:
@ -443,13 +467,15 @@ and how does the sound changes when you use a different sample? can you find or
## playing more than once
once we have set up our audio device with a sample, length, ADSR envelope and volume, we could play it again and again only by (re)writing a pitch at a different moment.
once we have set up our audio device with a sample, length, ADSR envelope and volume, we could play it again and again by (re)writing a pitch at a different moment; the other parameters can be left untouched.
keep in mind that every time you write a pitch, the playback of the sample and the shape of the envelope starts over.
### some ideas
what if you implement playing different pitches by pressing different keys on the keyboard? you could use our previous examples, but writing a pitch to the device instead of e.g. incrementing a coordinate :)
or what about complementing our pong program from <(uxn tutorial day 6)> with sound, having the device playing a sound whenever there's a bounce of the ball?
or what about complementing our pong program from {uxn tutorial day 6} with sound effects, having the device playing a note whenever there's a bounce of the ball?
or what if you use the screen vector to time the repetitive playing of a note? or what about you have it play a melody by following a sequence of notes? could this sequence come from a text file? :)
@ -474,9 +500,11 @@ in any case, don't hesitate to share what you create! :)
# the end
hey! you made it to the end of the tutorial series! congratulations!
hey! believe it or not, this is the end!
i hope you enjoyed it and i hope you see it just as the start of your uxn journey!
you made it to the end of the tutorial series! congratulations!
i hope you enjoyed it and i hope you see it as just the start of your uxn journey!
we'd love to see what you create! don't hesitate to share it in mastodon, the forum, or in the irc channel (or even via e-mail!)
@ -491,4 +519,4 @@ see you around!
# support
if you enjoyed this tutorial and found it helpful, consider sharing it and giving it your <(support)> :)
if you enjoyed this tutorial and found it helpful, consider sharing it and giving it your {support} :)