Announcement

Collapse

Forum etiquette

Our mission ...

This forum is part of our mission to promote the preservation of vintage computers through education and outreach. (In real life we also run events and have a museum.) We encourage you to join us, participate, share your knowledge, and enjoy.

This forum has been around in this format for over 15 years. These rules and guidelines help us maintain a healthy and active community, and we moderate the forum to keep things on track. Please familiarize yourself with these rules and guidelines.


Remain civil and respectful

There are several hundred people who actively participate here. People come from all different backgrounds and will have different ways of seeing things. You will not agree with everything you read here. Back-and-forth discussions are fine but do not cross the line into rude or disrespectful behavior.

Conduct yourself as you would at any other place where people come together in person to discuss their hobby. If you wouldn't say something to somebody in person, then you probably should not be writing it here.

This should be obvious but, just in case: profanity, threats, slurs against any group (sexual, racial, gender, etc.) will not be tolerated.


Stay close to the original topic being discussed
  • If you are starting a new thread choose a reasonable sub-forum to start your thread. (If you choose incorrectly don't worry, we can fix that.)
  • If you are responding to a thread, stay on topic - the original poster was trying to achieve something. You can always start a new thread instead of potentially "hijacking" an existing thread.



Contribute something meaningful

To put things in engineering terms, we value a high signal to noise ratio. Coming here should not be a waste of time.
  • This is not a chat room. If you are taking less than 30 seconds to make a post then you are probably doing something wrong. A post should be on topic, clear, and contribute something meaningful to the discussion. If people read your posts and feel that their time as been wasted, they will stop reading your posts. Worse yet, they will stop visiting and we'll lose their experience and contributions.
  • Do not bump threads.
  • Do not "necro-post" unless you are following up to a specific person on a specific thread. And even then, that person may have moved on. Just start a new thread for your related topic.
  • Use the Private Message system for posts that are targeted at a specific person.


"PM Sent!" messages (or, how to use the Private Message system)

This forum has a private message feature that we want people to use for messages that are not of general interest to other members.

In short, if you are going to reply to a thread and that reply is targeted to a specific individual and not of interest to anybody else (either now or in the future) then send a private message instead.

Here are some obvious examples of when you should not reply to a thread and use the PM system instead:
  • "PM Sent!": Do not tell the rest of us that you sent a PM ... the forum software will tell the other person that they have a PM waiting.
  • "How much is shipping to ....": This is a very specific and directed question that is not of interest to anybody else.


Why do we have this policy? Sending a "PM Sent!" type message basically wastes everybody else's time by making them having to scroll past a post in a thread that looks to be updated, when the update is not meaningful. And the person you are sending the PM to will be notified by the forum software that they have a message waiting for them. Look up at the top near the right edge where it says 'Notifications' ... if you have a PM waiting, it will tell you there.

Copyright and other legal issues

We are here to discuss vintage computing, so discussing software, books, and other intellectual property that is on-topic is fine. We don't want people using these forums to discuss or enable copyright violations or other things that are against the law; whether you agree with the law or not is irrelevant. Do not use our resources for something that is legally or morally questionable.

Our discussions here generally fall under "fair use." Telling people how to pirate a software title is an example of something that is not allowable here.


Reporting problematic posts

If you see spam, a wildly off-topic post, or something abusive or illegal please report the thread by clicking on the "Report Post" icon. (It looks like an exclamation point in a triangle and it is available under every post.) This send a notification to all of the moderators, so somebody will see it and deal with it.

If you are unsure you may consider sending a private message to a moderator instead.


New user moderation

New users are directly moderated so that we can weed spammers out early. This means that for your first 10 posts you will have some delay before they are seen. We understand this can be disruptive to the flow of conversation and we try to keep up with our new user moderation duties to avoid undue inconvenience. Please do not make duplicate posts, extra posts to bump your post count, or ask the moderators to expedite this process; 10 moderated posts will go by quickly.

New users also have a smaller personal message inbox limit and are rate limited when sending PMs to other users.


Other suggestions
  • Use Google, books, or other definitive sources. There is a lot of information out there.
  • Don't make people guess at what you are trying to say; we are not mind readers. Be clear and concise.
  • Spelling and grammar are not rated, but they do make a post easier to read.
See more
See less

Creative Music System (C/MS)???

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    Creative Music System (C/MS)???

    Does anyone have ANY information on actually programming these? I'm working on trying to have a fairly complete 'early PC' sound library and this would round out my current list...

    Right now I have PC speaker and Tandy/Jr. Sound complete, and am working on Adlib and planning a softsynth for speaker/covox/DAC -- but I'd like to get the pre-adlib creative side of the equation up and running too.

    Fun part for me right now is going to be determining if a system is fast enough to emulate tandy sound on Speaker/Covox -- I know how to do the emulation, but not entirely sure what the minimum system spec is going to be using my code...

    Though that's nowhere NEAR as much fun as trying to 'reclaim' some extra RAM on 64k systems -- anyone know how to figure out where in memory command.com is located without doing a manual scan?
    From time to time the accessibility of a website must be refreshed with the blood of owners and designers. It is its natural manure.
    CUTCODEDOWN.COM

    #2
    well, they're based on Philips SAA-1099 chips and you can find about all you should need on that right here: http://velesoft.speccy.cz/saa1099-cz.htm

    the page isn't english, but scroll down a little bit and there are document/datasheet links. most of those are english.
    sigpic

    Comment


      #3
      Originally posted by deathshadow View Post
      Does anyone have ANY information on actually programming these? I'm working on trying to have a fairly complete 'early PC' sound library and this would round out my current list...

      Right now I have PC speaker and Tandy/Jr. Sound complete, and am working on Adlib and planning a softsynth for speaker/covox/DAC -- but I'd like to get the pre-adlib creative side of the equation up and running too.

      Fun part for me right now is going to be determining if a system is fast enough to emulate tandy sound on Speaker/Covox -- I know how to do the emulation, but not entirely sure what the minimum system spec is going to be using my code...

      Though that's nowhere NEAR as much fun as trying to 'reclaim' some extra RAM on 64k systems -- anyone know how to figure out where in memory command.com is located without doing a manual scan?
      I have a booklet that came with my Soundblaster 1.5 with CMS chips entitled "C/MS Programming Information" with everything you need including sample code. See attached.
      Attached Files
      Last edited by njroadfan; February 2, 2011, 05:32 PM.

      Comment


        #4
        Originally posted by njroadfan View Post
        See attached.
        Thanks, that's just what I needed, though I thought the 1.5 didn't come with C/MS.... or was that the one where the sockets were present and you had to buy it separately?
        From time to time the accessibility of a website must be refreshed with the blood of owners and designers. It is its natural manure.
        CUTCODEDOWN.COM

        Comment


          #5
          Originally posted by deathshadow View Post
          Thanks, that's just what I needed, though I thought the 1.5 didn't come with C/MS.... or was that the one where the sockets were present and you had to buy it separately?
          In fact the sockets were present on both the SB 1.5 and 2.0, but the 2.0 requires an additional PAL chip for I/O addres decoding controll for the CMS chips. Because of this, adding CMS chips to a SB 2.0 without the PAL installed will not work, and therefore SB 2.0 cards with these chips installed are quite rare.
          Current systems owned by me:
          Vintage:IBM PC/XT submodel 087 ( 1983 ), [Kon]tiki-100 rev. C (1983), Compaq Portable I ( 1984 ), IBM PC/XT submodel 078 ( 1985 ), IBM PC/XT286 ( ~1986 ), 3x Nintendo Entertainement Systems ( 1987 ).
          Obsolete:Commodore A500 ( ~1990 ), IBM PS/2 model 70/386 type 8570-161 ( 1991 ), Atari Lynx II ( ~1992 ), Generic Intel 486SX PC ( ~1993 ), AT/T Globalyst Pentium w/FDIV bug MB ( 1994 ), Compaq 486DX4 laptop ( ~1995 ).

          Comment


            #6
            Hmm. Trying to translate their 'notes' / frequency values into actual frequencies, but their numbers don't make any sense...

            A..G = 3,31,58,83,107,130,151,172,191,209,226,242

            The gap between values DROPS as the notes go up -- that's inverse from how frequencies actually work... Does anyone know how I'd translate that into actual frequencies, or more importantly how to take a frequency and turn it into those numbers WITHOUT some fat-ass lookup table? I can handle octave conversions (simple mul/div by two) but I'll be damned if I can find a relationship between those numbers and the note frequencies.

            -- edit --

            AND those numbers for a through G do NOT match the ones in the chip documentation?!?
            From time to time the accessibility of a website must be refreshed with the blood of owners and designers. It is its natural manure.
            CUTCODEDOWN.COM

            Comment


              #7
              Originally posted by deathshadow View Post
              Hmm. Trying to translate their 'notes' / frequency values into actual frequencies, but their numbers don't make any sense...

              A..G = 3,31,58,83,107,130,151,172,191,209,226,242

              The gap between values DROPS as the notes go up -- that's inverse from how frequencies actually work... Does anyone know how I'd translate that into actual frequencies, or more importantly how to take a frequency and turn it into those numbers WITHOUT some fat-ass lookup table? I can handle octave conversions (simple mul/div by two) but I'll be damned if I can find a relationship between those numbers and the note frequencies.
              These early squarewave synthesizers are actually counters, and the number is how many ticks per wave, or how many ticks between each change of state. The octave bits are used to divide the main input clock by factors of two, which will effectively change the octave.

              Because of this, the pitch of the output solely relies on the input clock. It may well be that the CM/S and SB cards clocks them at something else than the chip documentation suggests.
              Current systems owned by me:
              Vintage:IBM PC/XT submodel 087 ( 1983 ), [Kon]tiki-100 rev. C (1983), Compaq Portable I ( 1984 ), IBM PC/XT submodel 078 ( 1985 ), IBM PC/XT286 ( ~1986 ), 3x Nintendo Entertainement Systems ( 1987 ).
              Obsolete:Commodore A500 ( ~1990 ), IBM PS/2 model 70/386 type 8570-161 ( 1991 ), Atari Lynx II ( ~1992 ), Generic Intel 486SX PC ( ~1993 ), AT/T Globalyst Pentium w/FDIV bug MB ( 1994 ), Compaq 486DX4 laptop ( ~1995 ).

              Comment


                #8
                I can see that on the output frequency skew -- but not on the gap BETWEEN frequencies. Even as a overflow counter the curve would not be backwards... If you plot A1 to A2 in actual frequencies (110 to 220) you'll find it's a concave curve A# to B being more than A to A#.... you plot thier input numbers for frequencies, it's convex -- the gap for higher notes is smaller, not larger.

                I'm trying to see if I can get a trig function to give me that curve or to find some correlation so I can convert an actual frequency to their "frequency number" on the fly... The relationship makes no sense compared to every other audio device I've dealt with. (including adlib -- which is sad when adlib makes more sense). This is gonna suck if I end up having to use a lookup table.
                From time to time the accessibility of a website must be refreshed with the blood of owners and designers. It is its natural manure.
                CUTCODEDOWN.COM

                Comment


                  #9
                  i learned how these types of synth chips worked when writing my NES emulator. yeah, they go by counters so it's usually basically a division of the clock input it's receiving. although it can get more complex than that. those big skews are strange though. i'll have a look at the doc and see if i can figure out wtf is going on there.
                  sigpic

                  Comment


                    #10
                    These old counter-based sound generators had certain limitation when it came to the tune of the lower-pitched tones. Perhaps the SAA-1099 tries to compensate for this with some well designed atrimetric between the input data and the counters?
                    Last edited by per; February 3, 2011, 01:39 PM.
                    Current systems owned by me:
                    Vintage:IBM PC/XT submodel 087 ( 1983 ), [Kon]tiki-100 rev. C (1983), Compaq Portable I ( 1984 ), IBM PC/XT submodel 078 ( 1985 ), IBM PC/XT286 ( ~1986 ), 3x Nintendo Entertainement Systems ( 1987 ).
                    Obsolete:Commodore A500 ( ~1990 ), IBM PS/2 model 70/386 type 8570-161 ( 1991 ), Atari Lynx II ( ~1992 ), Generic Intel 486SX PC ( ~1993 ), AT/T Globalyst Pentium w/FDIV bug MB ( 1994 ), Compaq 486DX4 laptop ( ~1995 ).

                    Comment


                      #11
                      I charted it out, and the deviation is wierd in that it is LITERALLY the exact opposite of the octave skew...

                      Which is to say if you draw a straight line of twelve notes from A to A, then scale the frequency of the two A's to match and the range of values on the SAA to match, the curves mirror each-other almost exactly.

                      I have NO idea how to implement that as code though. I'm using a lookup chart for now range 0..127 (there's literally NO reason to even try more resolution than that given the inefficiencies in the input curve)... which isn't too bad given it's only 128 bytes. I can live with that. Just wish I didn't have to.

                      Had another odd issue where I'm unable to get the odd-numbered channels working right (high byte on octave) -- well, they work fine on their own, but if you play the even numbered sound at the same time the odd numbered ones squeak like the octave is messed up. I'll post my code for that up later but since what I'm working on (pac man game) only needs three voices I'm just using the even numbered channels for now which works great.

                      Now back to implementing my adlib support.
                      From time to time the accessibility of a website must be refreshed with the blood of owners and designers. It is its natural manure.
                      CUTCODEDOWN.COM

                      Comment


                        #12
                        Went back to it when I realized that while the note progressions were right, it was about 400 cents out of tune -- the numbers in that CMS manual are WAY off compared to the data sheet for the chip. Not only are the frequencies reported for each octave WAY off, they don't match the datasheet for the chip -- and it turns out the clock is ON the chip. At first I thought it was just DosBox's implementation, but checking it against a real SB 1.0 confirms it.

                        I always thought CMS music sounded out of tune compared to other devices in things like Sierra games -- Looks like I was right and the games that don't "sound right" are wrong because they followed that booklet.

                        I also figured out why using the odd numbered voices was screwy -- despite them storing octaves as two voices per register (0x10..0x12), those registers are WRITE ONLY... So you can't read to mask and preserve (that's really stupid IMHO)... Strange since the enable/disable bits in register 0x14 are read/write.

                        For those curious on what I've got coded:
                        Code:
                        const
                        	CMSFreqMap:packed array[0..127] of byte=(
                        		000,003,007,011,015,019,023,027,
                        		031,034,038,041,045,048,051,055,
                        		058,061,064,066,069,072,075,077,
                        		080,083,086,088,091,094,096,099,
                        		102,104,107,109,112,114,116,119,
                        		121,123,125,128,130,132,134,136,
                        		138,141,143,145,147,149,151,153,
                        		155,157,159,161,162,164,166,168,
                        		170,172,174,175,177,179,181,182,
                        		184,186,188,189,191,193,194,196,
                        		197,199,200,202,203,205,206,208,
                        		209,210,212,213,214,216,217,218,
                        		219,221,222,223,225,226,227,228,
                        		229,231,232,233,234,235,236,237,
                        		239,240,241,242,243,244,245,246,
                        		247,249,250,251,252,253,254,255
                        	);
                        
                        type
                        	tCmsOctaveStore:packed array[0..11] of byte;
                        	
                        var 
                        	soundPort:word;
                        	cmsOctaveStore:^tCmsOctaveStore;
                        	
                        procedure cmsReset; assembler;
                        asm
                        { reset all 32 registers }
                        	mov  dx,soundPort
                        	mov  cx,1
                        @loopReset:
                        	mov  bx,cx
                        	mov  cx,$20
                        	xor  ax,ax
                        @loopRegisters:
                        	inc  dx
                        	out  dx,al
                        	inc  al
                        	xchg al,ah
                        	dec  dx
                        	out  dx,al
                        	xchg al,ah
                        	loop @loopRegisters
                        
                        { reset freq registers and enable sound }
                        	inc  dx
                        	mov  al,$1C
                        	out  dx,al
                        	dec  dx
                        	mov  al,3
                        	out  dx,al
                        
                        	mov  cx,bx
                        	loop @loopReset
                        
                        	les  di,cmsOctaveStore;
                        	mov  cx,3
                        	xor  ax,ax
                        	rep  stosw
                        end; { cmsReset }
                        
                        procedure cmsSound(voice,freq,octave,amplitudeLeft,amplitudeRight:byte); assembler;
                        asm
                        	xor  dx,dx
                        	xor  ah,ah
                        	mov  al,voice
                        
                        {
                        	octave registers are WRITE ONLY (stupid) so to preserve
                        	other voices octave settings we have to track this ourselves
                        	so let's get ES:DI pointed at the correct offset in our table
                        	ahead of time.
                        }
                        	mov  bx,ax
                        	shr  bx,1
                        	les  di,cmsOctaveStore
                        	add  di,bx
                        
                        {
                        	BL = voice mod 6 = chip voice
                        	DX = sound card port + (voice div 6)*2
                        	typically $2x0 for chip 1, $2x2 for chip 2
                        }
                        	mov  bx,6
                        	div  bx
                        	mov  bx,dx  { bl now equals chip voice }
                        	mov  dx,soundPort
                        	shl  ax,1   { deterimine which chip }
                        	add  dx,ax
                        
                        {	set amplitude }
                        	inc  dx     { set address register }
                        	mov  al,bl  { amplitudes $00..$05 }
                        	out  dx,al
                        
                        	dec  dx     { set data register }
                        	mov  al,amplitudeLeft
                        	mov  ah,amplitudeRight
                        	and  al,$0F
                        	mov  cl,4
                        	shl  ah,cl
                        	or   al,ah
                        	out  dx,al
                        
                        { set frequency }
                        	inc  dx     { set address register }
                        	mov  al,bl
                        	or   al,$08 { frequencies $08..$0D }
                        	out  dx,al
                        
                        	dec  dx { set data register }
                        	mov  al,freq
                        	out  dx,al
                        
                        { set octave }
                        	inc  dx         { set address register }
                        	mov  al,bl
                        	shr  al,1
                        	or   al,$10     { 2 octaves per register $10..$12 }
                        	out  dx,al
                        
                        	dec  dx         { set data register }
                        	mov  al,es:[di] { read from our buffer }
                        	mov  ah,octave
                        	and  ah,$07     { just in case, mask it off }
                        	mov  bh,bl
                        	and  bh,$01
                        	jnz  @voiceOdd
                        	and  al,$F8     { voice even, mask out bottom 3 bits }
                        	jmp  @outOctave
                        @voiceOdd:
                        	and  al,$8F     { voice odd, mask out bits 4..6 }
                        	mov  cl,4
                        	shl  ah,cl      { and slide our octave value over }
                        @outOctave:
                        	or   al,ah      { put the two together }
                        	out  dx,al      { and store on card}
                        	mov  es:[di],al { and in buffer }
                        
                        { freq enable }
                        	inc  dx         { set address register }
                        	mov  al,$14     { channel on/off $14 bits 0..5 }
                        	out  dx,al
                        
                        	dec  dx         { set data register }
                        	in   al,dx
                        	mov  ah,$01
                        	mov  cl,bl
                        	shl  ah,cl
                        	or   al,ah
                        	out  dx,al
                        end; { cmsSound }
                        
                        procedure cmsOutFreq(channel,freq,level:word;);
                        var
                        	outOctave,
                        	outFreq:word;
                        begin
                        	if (freq<32) or (freq>7823) or (level=0) then begin
                        		cmsSound(channel,0,0,0,0);
                        	end else begin
                        		outOctave:=4;
                        		outFreq:=freq;
                        		while (outFreq<489) do begin
                        			outFreq:=outFreq*2;
                        			dec(outOctave);
                        		end;
                        		while (outFreq>977) do begin
                        			outFreq:=outFreq div 2;
                        			inc(outOctave);
                        		end;
                        		cmsSound(
                        			channel,
                        			CMSFreqMap[((outFreq-489)*128) div 489],
                        			outOctave,
                        			level,level
                        		);
                        	end;
                        end;
                        A little rough around the edges, but it works. ( assumes you do new(cmsOctaveStore) and soundPort is set to $220 or appropriate value )
                        Last edited by deathshadow; February 4, 2011, 07:00 AM.
                        From time to time the accessibility of a website must be refreshed with the blood of owners and designers. It is its natural manure.
                        CUTCODEDOWN.COM

                        Comment


                          #13
                          Originally posted by njroadfan View Post
                          I have a booklet that came with my Soundblaster 1.5 with CMS chips entitled "C/MS Programming Information" with everything you need including sample code. See attached.
                          Hi everyone;

                          Back in 1991 I have bought a rare Sound Blaster 1.6 that was basically a SB 1.5 with the CMS chips included in it.

                          It came with that booklet with the programming information but it's a kind of incomplete because some time after i found out that we can use the 18 and 19 (24 and 25 in decimal) resgisters to produce envelopes.

                          Here is the complete registers sheet:
                          registers.jpg

                          And the registers 18 and 19 explanation:
                          envelope.jpg

                          Use register 18 to produce envelopes for channels 1-3 and register 19 to produce envelopes for channels 4-6.

                          I really don't know why this information is not present in the booklet that came with the card.

                          Cheers.

                          Comment


                            #14
                            And here are the images in a proper size:

                            Registers:
                            http://zxtech.planetaclix.pt/imagens.../registers.png

                            Envelope:
                            http://zxtech.planetaclix.pt/imagens/vcfed/envelope.png

                            Comment

                            Working...
                            X