Jump to content

Photo

Sound list player in Forth. Audition tool for sounds?


20 replies to this topic

#1 TheBF OFFLINE  

TheBF

    Dragonstomper

  • 616 posts
  • Location:The Great White North

Posted Mon Sep 4, 2017 6:42 PM

I saw some super posts in the archives about sound ripppers and stuff related to sound so I thought I would take a run making a sound list player.

 

All of this can be done in FB Forth or TF as well. However there are some words that will need adjustment.  

The missing words would be MS, which is just a quick delay loop.

 

: MS   8 0 DO LOOP ;  ( something like this, 8 is "about" the correct number for 1 MS)

 

And PAUSE which is a noop.   

 

: PAUSE  ;    will fix that quickly.

 

And ?NUMBER in CAMEL Forth is non-standard, but Lee created an equivalent in FB Forth for another one of my posts a while back.

(Will find that and post here)

 

However what a little player like this might be good for is trying out some data to listen to it for ALC programmers.

 

You can feed it sounds lists from the keyboard and play them to see how you like the sound.

 

Couple of things to be aware of:

 

1.  This player turns all 4 sound channels off when it gets to the end of a list with the word SILENT.

     If you use the TI player you will need to add the string of bytes to turn off your sounds.

 

2. The BYTES word does not use commas, so sound lists tried here will have to have the commas removed.

 

3. UN-comment SND! for other Forth systems or use the equivalent word to write a byte to the sound chip address.

 

4. LSHIFT is the ANS Forth word, but TF uses <<  for the same thing I believe. Not sure about FB Forth .

 

How it works:

 

PLAY$   takes the address of a string of bytes with a count byte at the start and a time duration byte at the end.

              It converts the duration byte to milliseconds assuming a 1/60 of a second ISR time.

              It then computes the start and end address of the sound bytes and loops through them sending each one to SND! (the chip address)

              When the loop is completed it waits for the duration of milliseconds.

 

PLAY    Is the high level word to use for playing a sound list.  It simply looks to see if there is a non-zero byte count in a sound string.

             While that is true is calls PLAY$.

             Then using the count byte it computes the address of the next string in the list and plays the next string until it hits a final ZERO.

 

CREATE  XXXX   is Forth's way of making a new word in the Dictionary of words and will return the start of the data address of that new word.

          

BYTES   is a compiler directive that was created to parse the input stream, convert the data to a number and compile it into the next byte of memory.

              It could have been done with the C, primitive but it makes the lists harder to read  ( example  AA C, 7 C,  DE C,  ETC... )

 

I believe the code here will run with the CAMEL99 version in GITHUB /BIN folder.  (did not try it yet)

 

I stole some sounds from PARSEC for FIRE and EXPLODE and I must confess it was a religious experience to hear those sounds come out my Forth system.  ;-)

 

If you get it working type:

 

3 SHOTS at the console.   That does 3 FIRE sounds and then runs the EXPLODE list.  Memories...

 

Spoiler

Edited by TheBF, Mon Sep 4, 2017 6:43 PM.


#2 Lee Stewart OFFLINE  

Lee Stewart

    River Patroller

  • 3,695 posts
  • Location:Silver Run, Maryland

Posted Mon Sep 4, 2017 7:04 PM

LSHIFT is SLA in fbForth—just as in TMS9900 Assembler. The other shifts also have the same names as their TMS9900 Assembler counterparts: SRA SRL SRC

 

...lee


  • RXB likes this

#3 TheBF OFFLINE  

TheBF

    Dragonstomper

  • Topic Starter
  • 616 posts
  • Location:The Great White North

Posted Mon Sep 4, 2017 7:36 PM

Thanks Lee!



#4 TheBF OFFLINE  

TheBF

    Dragonstomper

  • Topic Starter
  • 616 posts
  • Location:The Great White North

Posted Sat Nov 25, 2017 8:26 AM

So in the first post we saw how to make a Ti-99 sound list player in Forth .

 

In next few posts I will show you a few different ways that you could do this in Forth.

Forth is programmed by making new words to tame the problem.

 

One way to talk about sound is to use scientific words like Herz (Hz) and decibels (dB)

 

The following code takes all the problems of talking to the TMS9919 chip gives you

a handful of new words to make it easy.

 

After compiling this code into the system you could make the famous TI sounds like this:

: BEEP  ( -- ) GEN1  1398 Hz  -4 dB  170 MS  MUTE ;
: HONK  ( -- ) GEN1   218 Hz   0 dB  170 MS  MUTE ;

Does this code need any explanation?  Not too much.

So although Forth can look very strange at the low levels, because after all it is not much higher than Assembly language at its core,

with very little effort you can make into something just right for the problem at hand.

 

Here is the code to accomplish this:

 

Spoiler

 

In a future post we will talk about controlling the sound chip with musical words rather than scientific words.


Edited by TheBF, Sat Nov 25, 2017 1:04 PM.


#5 Lee Stewart OFFLINE  

Lee Stewart

    River Patroller

  • 3,695 posts
  • Location:Silver Run, Maryland

Posted Sat Nov 25, 2017 11:03 AM

Very nice!—but, though perfectly legitimate, your use of >FCODE without explanation as the name of two different words may confuse the Forth neophyte.  :)

 

...lee



#6 TheBF OFFLINE  

TheBF

    Dragonstomper

  • Topic Starter
  • 616 posts
  • Location:The Great White North

Posted Sat Nov 25, 2017 12:49 PM

You caught me again!

 

I was cleaning this file up and didn't notice that I renamed that word like that.  I will fix it.

 

For the Forth curious, Forth has what is called in academic circles as a "hyper-static" name space.

Which means you can create a function, variable or whatever with the same name as something that

was define before and still use the previous definition while making the new one.

 

It's not recommended but it can be done! (as you see in my code)

 

B

 

*EDIT*  It's gone now.

 

Thanks Lee


Edited by TheBF, Sat Nov 25, 2017 1:05 PM.


#7 TheBF OFFLINE  

TheBF

    Dragonstomper

  • Topic Starter
  • 616 posts
  • Location:The Great White North

Posted Sun Nov 26, 2017 2:10 PM

Having control the of the sound chip we can now move forward to create a Musical Lexicon.

 

This is some code that I wrote for the IBM PC internal speaker sound. With the  SOUND words

we created before and the Forth word MS (milli-second delay) it was simple to make this

work on the TI-99.

 

The concept here is that musical notes need a duration and an off-time to separate each note.

We use music math and terminology here by setting beats per minute (BPM). This sets how long a Whole-note will last in mS.

A whole note fills an entire "measure" or Bar of music.

 

We also set a FEEL for the music which is fed to the EXPRESSION calculator and that sets the ON_TIME and OFF_TIME variables.

With that all we need to do to play a note is :

: PLAY      ( fcode -- )
             ?BREAK                     \ halts if function 4 pressed
             OSC @ OR  SPLIT SND! SND!    \ add osc# & write the freq code to the chip
             0 ATTENUATE  ON_TIME @ MS    \ open the channel
            15 ATTENUATE OFF_TIME @ MS  ; \ close the channel

You can see we check for a BREAK, then send the freq-code (fcode) to the correct Oscillator, open the channel for the ON_TIME.

Then we close the channel and wait for an OFF_TIME.

 

You may notice I don't use the words HZ and DB for control. This is because those words have overhead for human use.

We pre-compute the FCODE for notes in this system because the TI-99 is not a speed demon. :-)

 

The word ATTENUATE is like DB but uses the native values of 0 .. 15 rather than making it look nice ( 0 .. -30 DB)

But they are doing the same things to the sound chip, just faster.

 

Paste the SOUND.FTH file into your emulator first then paste in MUSIC.FTH (the spoiler code here).

 

Then type in the examples:

 

TWINKLE

BAGPIPES

VARIATION

 

If you know a little music it's easy to program your own music.

 

Note names go first and the system uses that note length until you change it.

 

Spoiler

Edited by TheBF, Sun Nov 26, 2017 2:30 PM.


#8 Lee Stewart OFFLINE  

Lee Stewart

    River Patroller

  • 3,695 posts
  • Location:Silver Run, Maryland

Posted Sun Nov 26, 2017 3:06 PM

This looks good.  I am going to have to work through all this early next month.

 

...lee



#9 TheBF OFFLINE  

TheBF

    Dragonstomper

  • Topic Starter
  • 616 posts
  • Location:The Great White North

Posted Sun Nov 26, 2017 3:22 PM

This looks good.  I am going to have to work through all this early next month.

 

...lee

 

I don't want to stress you out.  I am just having fun making this system do tricks.

 

Now I need to put my thinking cap on and get DSRLINK working...  it's not simple.

 

:-)



#10 Lee Stewart OFFLINE  

Lee Stewart

    River Patroller

  • 3,695 posts
  • Location:Silver Run, Maryland

Posted Sun Nov 26, 2017 6:59 PM

 

I don't want to stress you out.  I am just having fun making this system do tricks.

 

Now I need to put my thinking cap on and get DSRLINK working...  it's not simple.

 

:-)

 

No worries.

 

Have you looked at how I implemented DSRLNK in fbForth?  I used MG’s (Millers Graphics) version, which invokes the GPL DSRLNK in the console.  Willsy also used the MG version in TurboForth.  If you don’t care about tape or GROM DSRs, the TI Forth version will do.  It is essentially a duplicate of the E/A cartridge’s DSRLNK.

 

...lee



#11 TheBF OFFLINE  

TheBF

    Dragonstomper

  • Topic Starter
  • 616 posts
  • Location:The Great White North

Posted Sun Nov 26, 2017 9:32 PM

 

No worries.

 

Have you looked at how I implemented DSRLNK in fbForth?  I used MG’s (Millers Graphics) version, which invokes the GPL DSRLNK in the console.  Willsy also used the MG version in TurboForth.  If you don’t care about tape or GROM DSRs, the TI Forth version will do.  It is essentially a duplicate of the E/A cartridge’s DSRLNK.

 

...lee

 

 

I looked at it but will it work for EA5 Binary format programs?



#12 Lee Stewart OFFLINE  

Lee Stewart

    River Patroller

  • 3,695 posts
  • Location:Silver Run, Maryland

Posted Mon Nov 27, 2017 8:56 AM

 

 

I looked at it but will it work for EA5 Binary format programs?

 

Certainly—but DSRLNK is not a program loader.  You would need to manage that additional feature yourself with the information available in the file(s) to be loaded.  It is all there: address to load, number of bytes to load and where to branch to start the program.  You would need to use I/O opcode 5 (LOAD) and a VRAM buffer large enough to store the largest file.  You could also load the files in chunks.  TI Forth loads the FORTHSAVE binary in two chunks—one for high RAM and one for low RAM.  FORTHSAVE is not an E/A5 file, however—just a binary memory image.  Of course, then you need to parse the loaded binary to get the load address, number of bytes to load there and whether there is another file to load.  I think the first six bytes has this information, though I don't remember the order.  I believe the start address is at the end of the last file.

 

LOAD, by the way, does not require OPEN before it nor CLOSE after it.  Sorry if most of this is old news.

 

...lee



#13 TheBF OFFLINE  

TheBF

    Dragonstomper

  • Topic Starter
  • 616 posts
  • Location:The Great White North

Posted Mon Nov 27, 2017 10:42 AM

Ok thanks for the pointers. I will take another run at it.

 

I want to make use of Forth functions for the mundane stuff like file name massaging and such.

I have some cool little code routines called SKIP and SCAN that let me fly through strings.

So I want to set things up with Forth to reuse code as much as possible and then kick off the OS

to do its magic and come back to me.

 

We shall see if I can figure it out.

 

B



#14 Lee Stewart OFFLINE  

Lee Stewart

    River Patroller

  • 3,695 posts
  • Location:Silver Run, Maryland

Posted Wed Dec 6, 2017 11:23 PM

Looking back at post #1, there is a bit that needs to be changed for it to work in fbForth 2.0.  fbForth 2.0 already has processing of sound tables built into its ISR.  The part of the code required for SHOTS can be reduced to the code in the following spoiler:

 

Spoiler
 
The other sound tables can be managed similarly as EXPLODE and FIRESND with, of course, the inconvenience of converting byte arrays to word arrays for DATA[ ... ]DATA .  <address> 0 PLAY will push sound table addresses to the sound stack if a sound table is already playing.  The fbForth 2.0 ISR processing has the advantage of not holding up program execution waiting for a sound table to finish.  I do like BYTES for sound tables because they are much easier to read that way!  In fact, when I decided on DATA[ ... ]DATA , I had debated on having a similar construct for byte data.
 
All that said, it will still be a useful exercise to convert CAMEL99 to fbForth 2.0 code.  Here are a few things that will need to be done:
  • For BYTES , I will need to know the function of $BUF and PLACE ,  (I probably forgot—remember I'm old!).
  • PLAY will need to be called something else.
  • SND! should be OK.
  • LSHIFT is SLA .
  • CREATE works differently in fbForth 2.0 than CAMEL99 or TurboForth.  It is intended for use within other defining words ( : VARIABLE CONSTANT <BUILDS CODE: ASM: ).  It creates a header just like the other two Forths, but the code field points to the parameter field instead of code that leaves the parameter field address on the stack.  Its smudge bit is also set to prevent the word being defined from being found until its definition is finished.  We would need to define a similar creation word with a different name:  : SPAWN <BUILDS DOES> ; .  This is exactly the definition of VARIABLE but for the comma between <BUILDS and DOES> , which requires a number on the stack before defining a new variable.
  • PAUSE is a very different word in fbForth as well as TI Forth.  It is used to detect whether a user has tapped the Any Key to pause an action (usually display) or FCTN+4 to break out of the routine.  Once paused, the user can resume with the Any Key or break out with FCTN+4.  When it finally finishes, it leaves a flag on the stack, 0 (false) for no key or the second tap of the Any Key and 1 (true) for FCTN+4.  Anyway, fbForth already has a no-op word:  NOP
That is all I can think of at the moment.  I will work on it.
 
...lee


#15 TheBF OFFLINE  

TheBF

    Dragonstomper

  • Topic Starter
  • 616 posts
  • Location:The Great White North

Posted Thu Dec 7, 2017 7:27 AM

 

Looking back at post #1, there is a bit that needs to be changed for it to work in fbForth 2.0.  fbForth 2.0 already has processing of sound tables built into its ISR.  The part of the code required for SHOTS can be reduced to the code in the following spoiler:

 

Spoiler
 
The other sound tables can be managed similarly as EXPLODE and FIRESND with, of course, the inconvenience of converting byte arrays to word arrays for DATA[ ... ]DATA .  <address> 0 PLAY will push sound table addresses to the sound stack if a sound table is already playing.  The fbForth 2.0 ISR processing has the advantage of not holding up program execution waiting for a sound table to finish.  I do like BYTES for sound tables because they are much easier to read that way!  In fact, when I decided on DATA[ ... ]DATA , I had debated on having a similar construct for byte data.
 
All that said, it will still be a useful exercise to convert CAMEL99 to fbForth 2.0 code.  Here are a few things that will need to be done:
  • For BYTES , I will need to know the function of $BUF and PLACE ,  (I probably forgot—remember I'm old!).
  • PLAY will need to be called something else.
  • SND! should be OK.
  • LSHIFT is SLA .
  • CREATE works differently in fbForth 2.0 than CAMEL99 or TurboForth.  It is intended for use within other defining words ( : VARIABLE CONSTANT <BUILDS CODE: ASM: ).It creates a header just like the other two Forths, but the code field points to the parameter field instead of code that leaves the parameter field address on the stack.  Its smudge bit is also set to prevent the word being defined from being found until its definition is finished.  We would need to define a similar creation word with a different name:  : SPAWN <BUILDS DOES> ; .  This is exactly the definition of VARIABLE but for the comma between <BUILDS and DOES> , which requires a number on the stack before defining a new variable.
  • PAUSE is a very different word in fbForth as well as TI Forth.  It is used to detect whether a user has tapped the Any Key to pause an action (usually display) or FCTN+4 to break out of the routine.  Once paused, the user can resume with the Any Key or break out with FCTN+4.  When it finally finishes, it leaves a flag on the stack, 0 (false) for no key or the second tap of the Any Key and 1 (true) for FCTN+4.  Anyway, fbForth already has a no-op word:  NOP
That is all I can think of at the moment.  I will work on it.
 
...lee

 

 

Sounds good Lee,

 

I will get you the code for the words you are looking for. Yes I quite like the BYTES format for these sound strings and I have since changed it to BYTE just to be more like TI Assembler. This would mean then you could explore making sound lists interactively from the Forth console and then take the code and put it in an ASM program by just adding the '>" and commas.

 

I am also considering making a sound list compiler.  This would let you use language like Hz , dB and mS to describe you sounds but the result will create a sound list data structure. That might be cool for FB Forth users to have in the tool box.



#16 TheBF OFFLINE  

TheBF

    Dragonstomper

  • Topic Starter
  • 616 posts
  • Location:The Great White North

Posted Thu Dec 7, 2017 8:36 AM

PLACE is a word in GForth and I think was first used by Wil Baden (RIP) who's real name was Neil Baud. He has a great legacy of Forth utilities for managing text.

It's all ANS 94 Forth, but still full of great ideas.

So PLACE is not a "standard" word, but very handy to PLACE a stack string (addr len --) into a buffer as a counted string.

 

Here is the CAMEL Forth version by Brad Rodriguez.  I found you can replace the MOVE word with CMOVE for most circumstances, because we seldom have overlapping string buffers in Forth, however the use of MOVE is technically correct.

: MOVE        ( src dst n -- )  \ version for 1 address unit = 1 char
              >R
              2DUP SWAP DUP
              R@ +                \ -- ... dst src src+n
              WITHIN
              IF    R> CMOVE>         \ src <= dst < src+n
              ELSE  R> CMOVE  THEN ;  \ otherwise

\ CAMEL Forth calls this ">COUNTED"
: PLACE       ( src n dst -- ) 2DUP C! CHAR+ SWAP MOVE ;

$BUF in my system was a temp buffer that I was using all the time. I have since retired it and will create buffers as needed.

You could use PAD I think depending on how PAD is implemented in FB Forth.

 

 

(albeit slower)



#17 Lee Stewart OFFLINE  

Lee Stewart

    River Patroller

  • 3,695 posts
  • Location:Silver Run, Maryland

Posted Fri Dec 8, 2017 8:30 PM

PLACE is a word in GForth and I think was first used by Wil Baden (RIP) who's real name was Neil Baud. He has a great legacy of Forth utilities for managing text.

It's all ANS 94 Forth, but still full of great ideas.

So PLACE is not a "standard" word, but very handy to PLACE a stack string (addr len --) into a buffer as a counted string.

 

Here is the CAMEL Forth version by Brad Rodriguez.  I found you can replace the MOVE word with CMOVE for most circumstances, because we seldom have overlapping string buffers in Forth, however the use of MOVE is technically correct.

: MOVE        ( src dst n -- )  \ version for 1 address unit = 1 char
              >R
              2DUP SWAP DUP
              R@ +                \ -- ... dst src src+n
              WITHIN
              IF    R> CMOVE>         \ src <= dst < src+n
              ELSE  R> CMOVE  THEN ;  \ otherwise

\ CAMEL Forth calls this ">COUNTED"
: PLACE       ( src n dst -- ) 2DUP C! CHAR+ SWAP MOVE ;

$BUF in my system was a temp buffer that I was using all the time. I have since retired it and will create buffers as needed.

You could use PAD I think depending on how PAD is implemented in FB Forth.

 

(albeit slower)

 

When I saw the above code, I saw where I could cut the ALC for MOVE short by 12 bytes by popping the count, shifting it left 1 bit (doubling it) and jumping into the ALC for CMOVE .  This doubles the number of times through the loop, but it works easily enough.  I don't know whether the 12 bytes saved is worth the extra time through the copy loop, however.  

 

The-e-e-n I got creative when I saw CMOVE> and realized that, with 32 more bytes (?) for a net loss of 20 bytes, I could make CMOVE overlap safe!  That is when all hell broke loose!!  :evil:  :-o  That is when I remembered that FILL and ERASE depend on the unsafe overlap behavior of CMOVE to work.  :dunce: That is when I remembered I had gone through this exercise before and it is probably documented somewhere in the fbForth development thread—did I tell you I am old?  That was a little discouraging.  :(   Maybe I should add CMOVE> (I think I have a little room left) and make MOVE (always copies words, i.e., 2 bytes, each time through the loop) overlap safe (I think I am safe there).  I'm rambling.  I will stop talking now...

 

...lee



#18 TheBF OFFLINE  

TheBF

    Dragonstomper

  • Topic Starter
  • 616 posts
  • Location:The Great White North

Posted Sat Dec 9, 2017 7:58 AM

LOL.  I have gone done some of those rabbit holes too.  I limit my spinning on these things if they get too long.

 

I wrote a version of MOVE that does 16 bit cells and so is 2X faster than CMOVE, but I could not make it work with PLACE.

It was 1 byte off probably due to 9900 byte order, but I didn't waste much time on it.  I am on my laptop at the moment and the code is on my desktop machine I will get it up here shortly and also some new words for controlling sound without sound lists for anyone who wants to try it that way.



#19 Lee Stewart OFFLINE  

Lee Stewart

    River Patroller

  • 3,695 posts
  • Location:Silver Run, Maryland

Posted Sat Dec 9, 2017 10:07 AM

LOL.  I have gone done some of those rabbit holes too.  I limit my spinning on these things if they get too long.

 

I wrote a version of MOVE that does 16 bit cells and so is 2X faster than CMOVE, but I could not make it work with PLACE.

It was 1 byte off probably due to 9900 byte order, but I didn't waste much time on it.  I am on my laptop at the moment and the code is on my desktop machine I will get it up here shortly and also some new words for controlling sound without sound lists for anyone who wants to try it that way.

 

I am still not sure what I will do re MOVE , CMOVE and CMOVE> , but, as far as I can tell, from figForth to ANS proposed Forth-2016, MOVE always copies cells, i.e., 16-bit, 2-byte words.  To make an overlap-safe, byte move, I would call it something else— BMOVE or CMOVESF , perhaps?

 

...lee



#20 TheBF OFFLINE  

TheBF

    Dragonstomper

  • Topic Starter
  • 616 posts
  • Location:The Great White North

Posted Sat Dec 9, 2017 11:32 AM

Yes that is my observation too. And I'd like have a way to MOVE data 2 bytes at a time in the kernel. 

 

I been struggling with naming as well.  Perhaps for CAMEL Forth I will move it closer to 2012 standard and add MOVE (16 bit)

I have already done some of that anyway.

I can simply put the "smart" code into PLACE  itself or remove it completely and include a warning about overlapping strings in the docs.  I lean towards simplicity versus overly "smart" words.

 

But I still need to figure out how make MOVE work inside PLACE rather than using CMOVE.  The TI machine still baffles me at times.



#21 TheBF OFFLINE  

TheBF

    Dragonstomper

  • Topic Starter
  • 616 posts
  • Location:The Great White North

Posted Sat Dec 9, 2017 2:22 PM

I have had some fun with minimalist sound chip control words that don't need the ISR to work.

 

*These words work on FB-Forth, Turbo Forth and CAMEL99 Forth.*

 

It all starts with a word to write a byte to the 9919 chip. I call it SND!. (sound store in Forth speak)

HEX
: SND!    ( c -- ) 8400 C! ;

Then you need a little delay.  CAMEL99 uses the 9901 chips timer to make MS, a delay in milliseconds.

It is simple to emulate for another TI Forth system.

: MS      ( n -- )  0 DO   8 0 DO LOOP   LOOP ;

Controlling the noise channel is the simplest.  The word NOISE takes 1 parameter.

 

Thierry Nouspikel shows it this way:

1 1 1 0 0 w r r 
  >E      | | |
          | 0 0 : 6991 Hz 
          | 0 1 : 3496 Hz 
          | 1 0 : 1748 Hz 
          | 1 1 : freq of generator 3 
          | 
          0 : Periodic noise 
          1 : White noise

The Forth word to do this:

: NOISE   ( n -- ) E0 OR SND! ; \ n selects the noise type

We just take the parameter n, OR it with >E0 and send it off to the chip.

In real terms it means this:

  • 0, 1 or 2 give you 1 of the three frequencies listed as very high harmonic content waveforms. (not very useful)
  • 4 ,  5 or  6   gives you 3 flavours of noise.
  • 7 as a parameter lets you control this oscillator with the frequency of channel 3
    (this mode is fun cuz it let's get real BASS notes out of the chip. More later ...)

 

If it's easier for you to work in Binary, you can program it like this.

2 BASE ! ( switch to BASE 2)
000 NOISE
001 NOISE
010 NOISE
011 NOISE
100 NOISE
101 NOISE
110 NOISE
111 NOISE

Once the noise chip is given the parameter you need to set the attenuator to control the volume of the sound.

In DECIMAL arithmetic we have 0 to 14 as the volume range, Level 15 is OFF.

0 NOISE-DB has the least attenuation so that is full volume.

 

Our word for controlling the attenutator is NOISE-DB and with it we can make a quick NOISE-OFF word to kill the noise.

: NOISE-DB   ( db --) F MIN F0 OR SND! ;
: NOISE-OFF  ( -- )   F NOISE-DB ;

But to really make synthetic sounds you need control of the "sound envelope";  how fast the sound comes on and goes off.

So we created NOISE-UP & NOISE-DOWN.  They each take a delay number to control the rise time and decay time.

(They could be made more interesting by take the start and end volume as parameters as well)

HEX
: NOISE-UP    ( speed  -- ) 2  F  DO  I NOISE-DB  DUP MS   -1 +LOOP DROP ;
: NOISE-DOWN ( speed -- )   F  2  DO  I NOISE-DB  DUP MS     LOOP DROP NOISE-OFF ;

With those you can make a nice SWOOSH sound this simply.

: SWOOSH    ( -- )
            NOISE-OFF
            5 NOISE
            8 NOISE-UP
            20 NOISE-DOWN ;





0 user(s) are browsing this forum

0 members, 0 guests, 0 anonymous users