small corrections
This commit is contained in:
parent
2556747357
commit
5ce317b7ab
|
@ -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
|
||||
|
||||
|
@ -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} :)
|
||||
|
|
Loading…
Reference in New Issue