Jump to content

Photo

Assembly language sound effects

Assembly Sound

38 replies to this topic

#1 Asmusr ONLINE  

Asmusr

    River Patroller

  • 2,892 posts
  • Location:Denmark

Posted Wed Jul 24, 2013 1:28 AM

I would like to add some sound effects to my game that are a little more interesting than the usual square wave crash and chime examples from the A/E manual. Do you have any suggestions for tricks or techniques to use to produce other effects or wave forms? I have read about the sample trick used by the Sound FX program, but I have no room for samples, so it has to be programmed and relatively short, but it doesn't have to be limited to a 60 FPS data feed.

One idea I have is to rapidly changing the frequency on two generators slightly out of sync to obtain an illusion of phase shifting. I have no idea if that's possible or what that would sound like.

Before I start experimenting, are there any limitations to the sound emulation in Classic99 and MESS that I should be aware of?

#2 Willsy OFFLINE  

Willsy

    River Patroller

  • 3,079 posts
  • Location:Uzbekistan (no, really!)

Posted Wed Jul 24, 2013 2:02 AM

One idea I have is to rapidly changing the frequency on two generators slightly out of sync to obtain an illusion of phase shifting. I have no idea if that's possible or what that would sound like.


That's a trick i've often used and it works well. By varying the pitch of one channel slightly you can get some nice phase effects.

#3 sometimes99er OFFLINE  

sometimes99er

    River Patroller

  • 4,143 posts

Posted Wed Jul 24, 2013 2:05 AM

I think 60 FPS will be efficient for any sound effect. Also real time manipulation.

The ISR will play all channels but only one track. For example, if you tryout BurgerTime, the music will stop every other second for sound effects to play. Like if you want to play music and have lasers or explosions at the same time, you have to plan which channels to use for what (or get more advanced than that), and also write your own multi track player, like ISR but capable of playing more than one track at the same time.

Having one frequency slight off from another can generate rich sound dynamics. This demonstrates the difference between one frequency and two close to each other.

100 CALL SOUND(1000,110,0)

100 CALL SOUND(1000,110,0,111,0)

I haven’t replicated my problems with Classic99 on other computers (yes, will do), but often have to go and check things like quality of smoothness, sound and speech on MESS. Classic99 appears rather jerky and I loose joystick control within 2 to about 25 minutes, MESS and Win994a works fine for trying to beat a score with MunchMan etc.

I once used a sound spectrum analyzer (PC) to sample frequencies in chunks of 1/60 of a sec. Works fine with “clean” sound effects from any source, but then even simple music and speech becomes pretty unrecognizable.

:)

#4 nanochess OFFLINE  

nanochess

    Processorus Polyglotus

  • 5,574 posts
  • Coding something good
  • Location:Mexico City

Posted Wed Jul 24, 2013 8:02 AM

There are various simple yet interesting sounds that can be done using a single channel. In my games I distinguish a start effect and doing effect routines.

I use to "dump" sound at start of interruption so it doesn't "change" place in time, and most of times I've a counter/frequency value for each sound.

Like these (of course, add a volume setting)

1. Bump: start: count = 0x07. var = 0x0300 doing: if (!count) return; count--; channel3 = var; var += 0x20;
2. Laser: start count = 0x03. var = 0x0100 doing: if (!count) return; count--; channel3 = var; var >>= 1;
3. New life: start: count = 0x20. var = 0x0200 doing: if (!count) return; if (count & 1) return; count--; channel3 = var; var = var - (var >> 4)

Sometimes I also play with volume setting.

You can also put two tones in same channel, playing in alternate frames.

#5 retroclouds OFFLINE  

retroclouds

    Stargunner

  • 1,636 posts
  • Location:Germany

Posted Wed Jul 24, 2013 12:13 PM

You might want to check out the sound player by Tursi and the sound player by Marc, both are assembly language routines and a lot more advanced compared to the ISR da-dee-do player :-)

On a sidenote, I seem to recall that the Colecovision had an advanced sound player embedded in the OS7 bios.

Edited by retroclouds, Wed Jul 24, 2013 12:17 PM.


#6 Tursi OFFLINE  

Tursi

    Quadrunner

  • 5,292 posts
  • HarmlessLion
  • Location:BUR

Posted Wed Jul 24, 2013 6:35 PM

Before I start experimenting, are there any limitations to the sound emulation in Classic99 and MESS that I should be aware of?


Classic99 currently can't cope with sound changes faster than 60hz, it'll drop them. That's the only limitation I'm aware of with it.

Oh, and it won't attempt to generate extremely high (inaudible) frequencies. (I can't remember the cutoff). But this does prevent it from working with samples.

Edited by Tursi, Wed Jul 24, 2013 6:35 PM.


#7 nanochess OFFLINE  

nanochess

    Processorus Polyglotus

  • 5,574 posts
  • Coding something good
  • Location:Mexico City

Posted Thu Jul 25, 2013 7:35 AM

Because I'm "moving" between MSX and Colecovision, I didn't use any BIOS routines but my own music player and routines for sound effects.

#8 Airshack OFFLINE  

Airshack

    Dragonstomper

  • 802 posts
  • Location:Phoenix, AZ

Posted Sun May 6, 2018 11:34 AM

 

You might want to check out the sound player by Tursi and the sound player by Marc, both are assembly language routines and a lot more advanced compared to the ISR da-dee-do player :-)

On a sidenote, I seem to recall that the Colecovision had an advanced sound player embedded in the OS7 bios.

I'll be searching for information on these players....any advances in the past five years?



#9 Tursi OFFLINE  

Tursi

    Quadrunner

  • 5,292 posts
  • HarmlessLion
  • Location:BUR

Posted Tue May 15, 2018 1:23 AM

The download for mine is here: http://harmlesslion.com/software/vgm

#10 TheBF OFFLINE  

TheBF

    Dragonstomper

  • 760 posts
  • Location:The Great White North

Posted Sun Jun 3, 2018 7:41 PM

9919 nibbles

 

I have a question for the gang who code assembly language.

 

I want a fast way to convert the frequency divider value for the 9919 into the 2 bytes I need to send to the chip.

I have chosen to keep the bytes together before I send them so that they I can handle them as 1 integer. Maybe that's not the best decision either.

Anyway I have it down to 4 instructions, but I am curious if there is a better way?

 

Currently in Forth Assembler I have this to convert >0ABC to >0CAB.

( TOS is alias for R4,  W is alias for R8)

 CODE >FCODE           \ TOS = 0ABC
          TOS W MOV,   \ DUP -> W
          TOS 4 SRL,   \ TOS =00AB 
          W 8 SLA,     \ W = BC00
          W 0F00 ANDI, \ W = 0C00
          W TOS A,     \ TOS = 0CAB 


#11 FarmerPotato OFFLINE  

FarmerPotato

    Chopper Commander

  • 122 posts
  • Location:Austin, TX

Posted Mon Jun 4, 2018 12:15 AM

I have a similar problem (math on the interval) so I looked at this in detail.

 
If TOS is just a register as you say,
 
TOS 4 SRC,
TOS W MOV,
W 4 SRL,
W TOS MOVB,
Classic99 reports 114 cycles for your version, 84 for this.
 
Tips:
 
W SWPB, is faster than W 8 SLA,
 
When you need to operate on the LSB, and you know the WP, skip the SWPB for a tiny improvement
 
8317 @() TOS AB,
 
Shifts won't work if TOS needs to be *SP. FORTH assembler will happily take SP *? 4 SRC, but it isn't detected as an out of bounds condition and produces SP 5 SRC,
 
Best,
-Erik


#12 TheBF OFFLINE  

TheBF

    Dragonstomper

  • 760 posts
  • Location:The Great White North

Posted Mon Jun 4, 2018 6:19 AM

 

I have a similar problem (math on the interval) so I looked at this in detail.

 
If TOS is just a register as you say,
 
TOS 4 SRC,
TOS W MOV,
W 4 SRL,
W TOS MOVB,
Classic99 reports 114 cycles for your version, 84 for this.
 
Tips:
 
W SWPB, is faster than W 8 SLA,
 
When you need to operate on the LSB, and you know the WP, skip the SWPB for a tiny improvement
 
8317 @() TOS AB,
 
Shifts won't work if TOS needs to be *SP. FORTH assembler will happily take SP *? 4 SRC, but it isn't detected as an out of bounds condition and produces SP 5 SRC,
 
Best,
-Erik

 

 

 

Thanks for the assistance Erik.  This is a great help.  

114 clocks was far better than my Forth version but with your help it comes down even more.

Funny thing, i used the swap byte instruction from Forth and missed it here.  

 

Thanks again.

 

Brian



#13 TheBF OFFLINE  

TheBF

    Dragonstomper

  • 760 posts
  • Location:The Great White North

Posted Mon Jun 4, 2018 6:28 AM

 

I have a similar problem (math on the interval) so I looked at this in detail.

 
If TOS is just a register as you say,

 

From the above comments:

 

Please explain "math on the interval"

 

 

For clarification, Camel99 Forth caches the top of the data stack in R4. This makes some primitives very simple.

It came into common practice with commercial Forth systems in the late 1980s as I recall but was never part of FIG Forth to my knowledge.

 

Example:

 

CODE @   *TOS TOS MOV,  NEXT, ENDCODE

 

It means you have to manage that register a little differently but there is a net  8..10% speedup on most CPUs.

 

 

B



#14 Lee Stewart ONLINE  

Lee Stewart

    River Patroller

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

Posted Mon Jun 4, 2018 7:18 AM

For clarification, Camel99 Forth caches the top of the data stack in R4. This makes some primitives very simple.

It came into common practice with commercial Forth systems in the late 1980s as I recall but was never part of FIG Forth to my knowledge.

 

Right—fig-Forth, as implemented for the TMS9900, used the registers in the Forth context as

R0 \
R1  |
R2  |
R3   \ These registers are available. They are used 
R4   / only within fbForth words written in ALC.
R5  |
R6  |
R7 /
UP    Points to base of User Variable area
SP    Parameter Stack Pointer
W     Inner Interpreter current Word pointer
R11   Linkage for subroutines in ALC routines
R12   Used for CRU instructions
IP    Interpretive Pointer
RP    Return Stack Pointer
NEXT  Points to the next instruction fetch routine 

...lee



#15 FarmerPotato OFFLINE  

FarmerPotato

    Chopper Commander

  • 122 posts
  • Location:Austin, TX

Posted Mon Jun 4, 2018 3:09 PM

 

From the above comments:

 

Please explain "math on the interval"

 
"Math on the interval"
 
Problem statement: Given the cmd bytes for a tone, generate a table that varies the frequency between plus/minus one half step.
 
I'll post my solution later. In brief, I interpolate between two interval (period register) values. A list of sound chip command bytes is created when a note begins and sent to the chip on 1/60th sec ticks.


#16 TheBF OFFLINE  

TheBF

    Dragonstomper

  • 760 posts
  • Location:The Great White North

Posted Mon Jun 4, 2018 3:39 PM

Ah yes.  I am very interested in that.

 

My solution is pretty simple, I take the frequency of the oscillator as a 32bit integer and divide it by the audio frequency and now I use your improved code to roll the nibbles into the command bytes.

Looks like this at the moment.  My oscillator is off by .8 Hz at the moment, but it still makes music that sounds in tune over a couple of octaves or so.

 

With your help it now looks like this:

DECIMAL
 : f(clk) ( -- d)  46324 1  ;   \ this is 111,860 as 32 bit int.

CODE >FCODE ( 0abc -- 0cab) \ version by Farmer Potato Atariage
            0B44 ,          \ TOS 4 SRC,   \ C0AB
            0948 ,          \ TOS W MOV,   \ DUP
            0948 ,          \ W 4 SRL,     \ 0C0A
            D108 ,          \ W TOS MOVB,  \ 0CAB
            NEXT,           \ 8 BYTES, 28 uS :-)
            ENDCODE

\ convert freq. to 9919 chip code
: HZ>CODE  ( freq -- fcode ) f(clk) ROT UM/MOD NIP >FCODE ;

I send the 2 command bytes to the chip in sequence, and typically then send the attenuator value and then I delay.

I am curious what about the advantages of sending the bytes on  interrupt timing. 

 

For reference the old Forth >FCODE was this: (SPLIT and FUSE are 2 CODE words I created to deal with CELL->BYTE->CELL conversion)

: >FCODE ( 0abc -- 0cab)
          4 LSHIFT  ( -- abc0 )
          ><        ( -- c0ab )
          SPLIT     ( -- ab c0)
          4 RSHIFT  ( -- ab  c)
          FUSE  ;   ( -- 0cab)  \ 18 BYTES 400 uS


#17 TheBF OFFLINE  

TheBF

    Dragonstomper

  • 760 posts
  • Location:The Great White North

Posted Tue Jun 5, 2018 7:05 AM

I would like to add some sound effects to my game that are a little more interesting than the usual square wave crash and chime examples from the A/E manual. Do you have any suggestions for tricks or techniques to use to produce other effects or wave forms? I have read about the sample trick used by the Sound FX program, but I have no room for samples, so it has to be programmed and relatively short, but it doesn't have to be limited to a 60 FPS data feed.

One idea I have is to rapidly changing the frequency on two generators slightly out of sync to obtain an illusion of phase shifting. I have no idea if that's possible or what that would sound like.

Before I start experimenting, are there any limitations to the sound emulation in Classic99 and MESS that I should be aware of?

 

 

Maaany years ago I did a music program in electronic music. One the things that I notice people do not use too much in the earlier games was envelope control.

The Parsec explosion is a notable exception in the way it fades out.

 

A large part of the uniqueness of a sound is how it starts, sustains and decays. This is commonly called sound envelope.

 

I have been playing with this in Forth but it can of course be done in assembler.   The difference between a  "PING" sound and a "PLINK" sound is simple how fast you make it decay after it comes on.  If you make a loop that drops the volume form 0 to >0F at variable speeds you can hear it.  PING takes 250..500 mS to decay and PLINK decays at in 40 or 50 mS as I recall. 

 

I will post my examples for you when I get back to my desktop machine.



#18 Asmusr ONLINE  

Asmusr

    River Patroller

  • Topic Starter
  • 2,892 posts
  • Location:Denmark

Posted Tue Jun 5, 2018 8:44 AM

I will post my examples for you when I get back to my desktop machine.

 

That's great, but it's not so important to me as it was 5 years ago.  :)



#19 Asmusr ONLINE  

Asmusr

    River Patroller

  • Topic Starter
  • 2,892 posts
  • Location:Denmark

Posted Tue Jun 5, 2018 8:58 AM

I made a very simple sound player using 'envelopes' for my 4K compo entry. It couldn't actually do the whole attack/decay/sustain/release thing but it could play pings and zaps and explosions by specifying only the start value, the count, and the change in volume, frequency or both. This can save a lot of bytes compared to storing raw sound lists. 



#20 FarmerPotato OFFLINE  

FarmerPotato

    Chopper Commander

  • 122 posts
  • Location:Austin, TX

Posted Tue Jun 5, 2018 11:49 AM

 

Ah yes.  I am very interested in that.

 

My solution is pretty simple, I take the frequency of the oscillator as a 32bit integer and divide it by the audio frequency and now I use your improved code to roll the nibbles into the command bytes.

Looks like this at the moment.  My oscillator is off by .8 Hz at the moment, but it still makes music that sounds in tune over a couple of octaves or so.

 

With your help it now looks like this:

DECIMAL
 : f(clk) ( -- d)  46324 1  ;   \ this is 111,860 as 32 bit int.

CODE >FCODE ( 0abc -- 0cab) \ version by Farmer Potato Atariage
            0B44 ,          \ TOS 4 SRC,   \ C0AB
            0948 ,          \ TOS W MOV,   \ DUP
            0948 ,          \ W 4 SRL,     \ 0C0A
            D108 ,          \ W TOS MOVB,  \ 0CAB
            NEXT,           \ 8 BYTES, 28 uS :-)
            ENDCODE

\ convert freq. to 9919 chip code
: HZ>CODE  ( freq -- fcode ) f(clk) ROT UM/MOD NIP >FCODE ;
 
The advantage of doing everything in the interrupt service routine is precise timing.  The console sound list format uses a number of ticks (1/60th seconds) to idle before loading the next group of bytes. Alternately, in a game you might have the ISR just decrement some timers. Then the main game loop checks the timers, pushes sound bytes, moves sprites, etc. In FORTI the MUSIC ISR plays in the background so that, naturally, you can keep programming (or fiddling with the music by changing the tempo variable.)
 
 
You might want to add nearest rounding to HZ>CODE. The sound cmd byte table in the E/A manual incorporates rounding. For instance, 110 Hz is N=1016.916 or 1017 and the code is 093F. Your code rounds toward 0 and gives 093E. That makes a bias toward sharp. The error is 1% by the time you get to D#6 at 1244.51 Hz, where rounding down gives 1256.86 Hz. 
 
But that's inconsequential. Interestingly, a real piano is tuned sharp in that octave, but for reasons that don't apply here. (In physical strings, harmonics of A3 tend sharp, so A6 is tuned sharp to match.)
 
 
For comparison, here is the table from FORTI. It uses the rounded values.
 
( A+) 93F , 03C , A38 , 735 , 732 , A2F , ( 110)
( D#) F2C , 72A , 128 , D25 , B23 , B21 ,
( A ) C1F , 01E , 51C , C1A , 419 , D17 , ( 220)
( D#) 816 , 315 , 014 , E12 , D11 , D10 ,
( A ) E0F , 00F , 20E , 60D , A0C , E0B , ( 440)
( D#) 40B , A0A , 00A , 709 , F08 , 708 ,
( A ) F07 , 807 , 107 , B06 , 506 , F05 , ( 880)
( D#) A05 , 505 , 005 , C04 , 704 , 304 ,
( A ) 004 , C03 , 903 , 503 , 203 , 003 , ( 1760) 
( D#) D02 , A02 , 802 , 602 , 402 , 202 ,

Main thread for that is 

May the FORTH Musical offering - FORTI Decompiled

 



#21 TheBF OFFLINE  

TheBF

    Dragonstomper

  • 760 posts
  • Location:The Great White North

Posted Tue Jun 5, 2018 1:15 PM

I made a very simple sound player using 'envelopes' for my 4K compo entry. It couldn't actually do the whole attack/decay/sustain/release thing but it could play pings and zaps and explosions by specifying only the start value, the count, and the change in volume, frequency or both. This can save a lot of bytes compared to storing raw sound lists. 

 

LOL.  I did not read the date of your post. Glad to hear it all worked out.



#22 TheBF OFFLINE  

TheBF

    Dragonstomper

  • 760 posts
  • Location:The Great White North

Posted Tue Jun 5, 2018 1:25 PM

 

 
The advantage of doing everything in the interrupt service routine is precise timing.  The console sound list format uses a number of ticks (1/60th seconds) to idle before loading the next group of bytes. Alternately, in a game you might have the ISR just decrement some timers. Then the main game loop checks the timers, pushes sound bytes, moves sprites, etc. In FORTI the MUSIC ISR plays in the background so that, naturally, you can keep programming (or fiddling with the music by changing the tempo variable.)
 
 
You might want to add nearest rounding to HZ>CODE. The sound cmd byte table in the E/A manual incorporates rounding. For instance, 110 Hz is N=1016.916 or 1017 and the code is 093F. Your code rounds toward 0 and gives 093E. That makes a bias toward sharp. The error is 1% by the time you get to D#6 at 1244.51 Hz, where rounding down gives 1256.86 Hz. 
 
But that's inconsequential. Interestingly, a real piano is tuned sharp in that octave, but for reasons that don't apply here. (In physical strings, harmonics of A3 tend sharp, so A6 is tuned sharp to match.)
 
 
For comparison, here is the table from FORTI. It uses the rounded values.
 
( A+) 93F , 03C , A38 , 735 , 732 , A2F , ( 110)
( D#) F2C , 72A , 128 , D25 , B23 , B21 ,
( A ) C1F , 01E , 51C , C1A , 419 , D17 , ( 220)
( D#) 816 , 315 , 014 , E12 , D11 , D10 ,
( A ) E0F , 00F , 20E , 60D , A0C , E0B , ( 440)
( D#) 40B , A0A , 00A , 709 , F08 , 708 ,
( A ) F07 , 807 , 107 , B06 , 506 , F05 , ( 880)
( D#) A05 , 505 , 005 , C04 , 704 , 304 ,
( A ) 004 , C03 , 903 , 503 , 203 , 003 , ( 1760) 
( D#) D02 , A02 , 802 , 602 , 402 , 202 ,

Main thread for that is 

May the FORTH Musical offering - FORTI Decompiled

 

 

 

This is great information. Thank you again.

 

For my demo music system I made a note creator rather than a table.  It works like this:

\ note object creator
: NOTE:   ( freq -- )
           CREATE           \ compile time: create a name in the dictionary
                  HZ>CODE , \ convert freq to 9919 code. Compile into note

           DOES> @ PLAY ; \ run time:  fetch the number, play the note

​Then all I had to do was this:

\ FREQ  NATURAL    FREQ  ACCIDENTAL    EN-HARMONIC
\ -------------    ----------------   ----------------
  110 NOTE: A2
  131 NOTE: C3     139 NOTE: C#3       : DB3 C#3 ;
  147 NOTE: D3     156 NOTE: D#3       : Eb3 D#3 ;
  165 NOTE: E3
  175 NOTE: F3     185 NOTE: F#3       : Gb3 F#3 ;
  196 NOTE: G3     208 NOTE: G#3       : Ab3 G#3 ;
  220 NOTE: A3     233 NOTE: A#3       : Bb3 A#3 ;
  247 NOTE: B3
  262 NOTE: C4     277 NOTE: C#4       : Db4 C#4 ;
  294 NOTE: D4     311 NOTE: D#4       : Eb4 D#4 ;
  329 NOTE: E4
  349 NOTE: F4     370 NOTE: F#4       : Gb4 F#4 ;
  392 NOTE: G4     415 NOTE: G#4       : Ab4 G#4 ;
  440 NOTE: A4     466 NOTE: A#4       : Bb4 A#4 ;
  494 NOTE: B4
  523 NOTE: C5     554 NOTE: C#5       : Db5 C#5 ;
  587 NOTE: D5     622 NOTE: D#5       : Eb5 D#5 ;
  659 NOTE: E5
  698 NOTE: F5     740 NOTE: F#5       : Gb5 F#5 ;
  784 NOTE: G5     831 NOTE: G#5       : Ab5 G#5 ;
  880 NOTE: A5     932 NOTE: A#5       : Bb5 A#5 ;
  988 NOTE: B5
 1047 NOTE: C6

Now I have a choice.  Just re-write my notes using your table values or figure out how to calculate better.

I did consider raising my 32bit clock frequency to 111861 Hz. That is closer to reality than 111860. I will check the results against a tuner.

However your table is a lot simpler to use.!

 

My music player is not multi-tasking nor is it multi-voiced yet but here is script in Forth that plays a single voice quite nicely.

For timing I am using the 9901 chip timer, calibrated to provided 1/60 of a second and also switch tasks while it waits.

It seems pretty solid, but you could break it if you are not careful.

: TWINKLE
     NORMAL  72 BPM
     GEN1   1/8  A3 A3 E4 E4 F#4 F#4   1/4 E4
            1/8  D4 D4 C#4 C#4  B3 B3  1/4 A3
            STACCATTO
            1/8  E4 E4 D4 D4 C#4 C#4   1/4 B3
            NORMAL
            1/8  E4 E4 D4 D4 C#4 C#4   1/4 B3
            DETACHE
            1/8  A3 A3 E4 E4 F#4 F#4   1/4 E4
            1/8  RIT. D4 D4  RIT. C#4  C#4
                 RIT. B3  RIT. B3   RIT. 1/2. A3 ;


#23 FarmerPotato OFFLINE  

FarmerPotato

    Chopper Commander

  • 122 posts
  • Location:Austin, TX

Posted Tue Jun 5, 2018 2:34 PM

Rounding can be something like this:
( d1 n1 -- d1+n1/2 n1)
( add 1/2 n1 to d1. kludge, ignores overflow)
: +F2/ ROT OVER 2 / + ROT ROT ;


#24 TheBF OFFLINE  

TheBF

    Dragonstomper

  • 760 posts
  • Location:The Great White North

Posted Tue Jun 5, 2018 3:24 PM

 

Rounding can be something like this:
( d1 n1 -- d1+n1/2 n1)
( add 1/2 n1 to d1. kludge, ignores overflow)
: +F2/ ROT OVER 2 / + ROT ROT ;

 

 

 

I will give this a try.  Thanks

 

I can reduce this a bit with a couple of CODE words in my system.

: +F2/   ROT OVER 2/ + -ROT  ;


#25 TheBF OFFLINE  

TheBF

    Dragonstomper

  • 760 posts
  • Location:The Great White North

Posted Tue Jun 5, 2018 8:31 PM

So after looking at your table I realized I could solve this the other way around.

 

Given f=440 and the correct command byte=>FE, what should f(clk) be?

 

The answer is 111,760 Hz.  So I changed that value and my 440 is a real A.  And octaves sound more in tune now albeit not musically perfect.

 

So by fudging the clock frequency I get better command byte values.

 

If I am correct your values will generate the tempered scale and mine are the mathematical values, correct at 440Hz and drifting off of musical values at the low and high end.

 

For my technical lexicon consisting of Hz and dB commands this is fine. 

For my music player I am going to switch everything to your values.

 

For comparison:

( A+) 93F ,  ( 110)
( A )  C1F ,  ( 220)
( A )  E0F ,  ( 440)
( A )  F07 ,  ( 880)
( A )  004 ,  ( 1760)
 

 

B

 

 

Attached Files







Also tagged with one or more of these keywords: Assembly, Sound

0 user(s) are browsing this forum

0 members, 0 guests, 0 anonymous users