Home
Tutorials
Code Snippets
Code Samples
Downloads
Links

The Blog
Our Projects
About
Contact

::Add RageStorm to Favorites!::

The Blog | Our Projects | Guest Book | About | Contact

 
Tutorial - Sound Blaster
Author:JVS
Category:DOS
Uploaded at:15-Sep-05
Views:9334
SOUND BLASTER TUTORIAL
--------------------------------------
(c) 2005 by Jvs
--------------------------------------
*Last update on 18.08.2005

[-] BEFORE WE START [-]
-----------------------------------------------------------------------------------------------
- My english is not perfect - as you could notice, so don't be angry when
I make a mistake.
-----------------------------------------------------------------------------------------------

[-] SPECIAL THANKS [-]
------------------------------
- GIL DABAH (a.k.a Arkon) for giving me this webspace and giving me right
place for sb source :).
- STEVEN H. DON
- ANDRE BERESEL
- CRAIG JACKSON
- ETHAN BRODSKY (huge thanks)
- DAVID WELCH (huge thanks)
- DRAEDEN OF VLA
- ROB CRAIG
- JACQUES DESCHENES
- JUSTIN DELTENER

and huge thanks to djs - MARKO NASTIC and TIESTO - for making me cheerful when I was writing this tutorial.


TABLE OF CONTENTS

1. INTRODUCTION
1.0 Author
2. AUDIO PROGRAMMING
2.0 Introduction to audio programming
2.1 Basics
3. SOUND BLASTER
3.0 Introduction to SB
3.1 Interrupts
3.2 DSP Ports
3.3 Direct mode
4. DIRECT MEMORY ACCESS
4.0 About DMA
4.1 DMA Ports
4.2 Starting DMA Transfer
5. CLOSING
5.0 What I didn't mention?

1. INTRODUCTION
-----------------------------------------------------------------------------------------------

:[ 1.0 Author ]:

This tutorial is written by 4-years experienced programmer, thus there's no guarantee that information in this document is 100% perfect. For any damage caused by using information from this tutorial author does not take any responsibility. ["TRAFFIC" is currently playing in background]

I wrote this document only because I found that informations about sb programming are really badly united. I'm sick and tired of many different suggestions and propositions, stupid source codes that make you sick of them, stupid guides and documentations... so I used keyboard, I opened notepad, and wrote few words about what you really need to know if you're
going to write programs using sb sound.

You can contact me via my e-mail (jvs_prog@hotmail.com) used especially for you guyz out there who want to know more about sound blaster programming and other stuff. (emulation much prefered)

2. AUDIO PROGRAMMING
-----------------------------------------------------------------------------------------------

:[ 2.0 Introduction to audio programming ]:

Sound Blaster cards work with digital sound - waveform audio. You should know that sound in nature is represented as a waveform (when is called analog audio). When need to be stored in computer memory, computer first convert analog signals to digital signals by using ADC (Analog-to-digital converter). This process is better known as RECORDING. When it needs to play it back, computer converts digital signals into analog using DAC (Digital-to-analog converter) and guess what - you hear the sound.

The chip that contains ADC and DAC ICs (Integrated Circuits) is called DSP (Digital Signal Processor) that beside this ICs contains many other for working with sound I/O. DSP chips are used in many elecotronic devices such as video and audio recorders, sound cards and many others. There's a chip on Sound Blaster card that contains ADC and DAC ICs that's called DSP chip despite that it doesn't have all functions like real DSP chips.

:[ 2.1 Basics ]:

Well, you probably ask yourself how the sound is written in memory. How the analog sound is converted into digital sound. Well here it is - explanation.

I already said that you can think about analog sound like you think about an unvisible wave. Digital sound is an analog sound represented by digits - numbers or on computer level - bytes. When converting to digital sound you should know that you lose the quality - that's right.

Well, enough shitting. Let's back to basics. Digital sound is an array of digital samples ( simply called "samples" ) that determines the height of waveform at specified time. Sample is a number that can range from 0-255 (8-bit), 0-65536 (16-bit) and so on. Sample frequency determines the number of samples that are sent to DAC/ADC for one second - that is - the number of samples played in one second. So 22050Hz sample frequency tell us that 22050 samples make a sound of 1 second. Sample frequency is also known as sample rate.

Mono and stereo? When working with mono sound, there's only one sound channel. When you're working with stereo there are two sound channels. Channels need to be the same size - need to have same number of samples. When DAC is sending multichannel sound to output it takes all samples at specified position from all channels and make a SAMPLE FRAME.

Let's take a look at some sound buffer...

[068][164][200][000][128][128][003][241][093][128]

If this sound is 8-bit than samples are only one byte. If this sound is stereo every deuce of bytes make a sample frame. If the smaple rate of this sound is 22050Hz than every block of 22050 sample frames (which are 2 bytes in our example so it makes 22050*2=44100 bytes) make a sound of one second.

When you want to mix two sounds you only need to add corresponding samples and you've got the mixture. Detailed info about this is out of scope of this tut. There're a lot of sites that explains basic audio arithmetics.

One more thing to add before I switch to more important things - silence is at 128 in 8-bit sound. The silence line is called baseline.

3. SOUND BLASTER
-----------------------------------------------------------------------------------------------

:[ 3.0 Introduction to SB ]:

Sound Blaster is pretty old sound card used in mid 90s. All changes to SB
are actually made to its poor DSP chip.

SB's DSP chip works through I/O ports. Before I dive into details I'll explain the basic work of SB's DSP.

First, DSP can play/record sound in two modes - either using DMA (Direct Memory Access) or using CPU (obsolete). When you work with DMA, you should only program specified DMA channel that'll be used by DSP and then program DSP. Then , when you say to DSP "start" it polls one of DMA channels ( it should be one you programmed ) and it sends/recieves bytes from a memory location pointed by DMA channel that is polled. When DSP has sent/received specified number of bytes it interrupts CPU - that is - it tells CPU through IRQs (Interrupt Request Lines) to stop it's current execution and execute corresponding ISR (Interrupt Service Routine) that is determined by selected IRQ. In second mode (called direct mode) you need to send samples by hand and calculate time you should wait before you send next sample to DSP. This mode is a little bit (not just a little bit) obsolete and it uses CPU. It doesn't give any chance to CPU to execute any other code. So, some smart guyz developed DMA (which stands for "Direct Memory Access") chip that will transfer memory without any intervention of CPU ( we don't count programming DMA ). Well I don't think it is just like they say - DSP borrows the bus on some time to access RAM, so CPU can't execute some instructions that need memory access!

Well, really hard? Yep.. It is if you do not know what are interrupts, interrupt service routines, interrupt request lines... OK! Here it is - explanation.

:[ 3.1 Interrupts ]:

Interrupt stands for... interrupt. Interrupts interrupt CPU and make it execute some other code. There are two types of interrupts - software and hardware.

Software interrupts are generated by --- software/programs. They are accessible to programmer and they provide much more than one function to programmer. Well, they are number 0x10-0xFF (0x means HEX). You do not need to know about them now...

Hardware interrupts are generated by devices (such as Sound Blaster's DSP). They use physical inputs of CPU (through its microchip pins) that are called Interrupt Request Lines (IRQs). When a signal is sent on specific IRQ of CPU, CPU stops everything and executes specified ISR (Interrupt Service Routine). The memory location of ISR that CPU executes depends on IRQ line.

Hardware interrupts are numbered 0x00-0x0F. So it means that there are 16 differenct IRQ lines. IRQ lines cannot be shared!!! I'm not going to tell you which are free for use, but you should only know that IRQ5 and IRQ7 are most used IRQ lines by SB's DSP chip.

:[ 3.2 DSP Ports ]:

Beside memory address space there's I/O address space in 80x86 Intel CPUs. This address space is used to communicate with devices. Everything sent by some device should be sent at specified I/O address place called port. Well, to program the DSP and DMA you should access specified ports.

To read from a specified port we use IN instruction (assembly) or INPORTB(to read a byte from port in C). To write to a specified port we use OUT instruction (assembly) or OUTPORTB (to write a byte to specified port).

(my winamp is currently playing Marko Nastic's soundtracks - so don't be angry if I give you bad info)

So you should ask me - where are ports used by DSP? They start at specified base port that can be one of 0x220, 0x230, 0x240, 0x250, 0x260 or 0x280.

So how to find which base port my DSP uses? To find out which base port DSP uses you should try to reset DSP for each port until you get positive answer.. If no positive answer is returned - there's no Sound Blaster card or somebody took off DSP chip from your card. How to reset DSP will be covered after I give PORT MAP of DSP chip.

I will not cover all ports used by DSP (there're many dox you can find out there about ports used by SB's DSP). I'll only cover few of them.

[0x06] DSP Reset (W)
[0x0A] DSP - Read Data (R)
[0x0C] DSP - Write Data Or Command (W)
[0x0C] DSP - Write Buffer Status - bit 7 (R)
[0x0E] DSP - Data Available Status - bit 7 (R)

Port address relative to base address is placed between brackets. (W) means write-only, (R) means read-only.

First port called DSP reset port (port at address 0x06 relative to base address) is used to reset DSP. Resetting DSP can be used to autodetect which baseport is used by DSP on specified computer (more prefered than using BLASTER environment variable).

To reset DSP you should do the following:

- write 0x01 to port DSP_RESET (BASEPORT+0x06)
- wait for 3 microseconds (that's the time it takes DSP to reinitialize itself)
- write 0x00 to port DSP_RESET (BASEPORT+0x06)
- wait for 3 microsecond for results
- read byte (I'll refer to it as DATA) from DSP_DATAAVAIL (BASEPORT+0x0E) and read byte (I'll refer to it as READ) from DSP_READ (BASEPORT+0x0A). If bit 7 is set in DATA and READ is 0xAA then DSP is detected at BASEPORT. If condition failed no DSP is detect at base port BASEPORT.

Well, I don't really know why we should write 0x00 to DSP_RESET after writing 0x01 but that's it. Some other codes say something different - like you don't need to check if bit 7 in DATA is set. So, I'll give you next function for resetting DSP chip on SB:

#define DSP_RESET 0x06
#define DSP_DATAAVAIL 0x0E
#define DSP_READ 0x0A
int ResetDSP( unsinged int BasePort )
{
outportb(BasePort + DSP_RESET, 0x01); // write 0x01 to DSP_RESET
delay(10); // reinitialization
outportb(BasePort + DSP_RESET, 0x00); // write 0x00 to DSP_RESET
delay(10); // waiting for results
if ((inportb(BasePort + DSP_DATAAVAIL) & 0x80)=0x80) &&
(inportb(BasePort + DSP_READ) == 0xAA))
{
// DSP was found
return(1);
};
return(0); // No DSP found
}

Second port called DSP read port (port at address 0x0A relative to base port) is used for reading. To read from a read port you should do next:

- wait until bit 7 is set in data available status (0x0E relative to base port).
- then read from read port (0x0A)

Third port called DSP Write Data or Command (port address 0x0C relative to base port) is used for writing commands to DSP. To write command to this port you should do following:

- wait until bit 7 is set in write buffer status port (0x0C relative to base port)
- write command to this port (0x0C)

Next are some of DSP commands (I'm not going to cover all of them):

[0x10] Start DAC. 8-bit sound. Direct mode. // playback
[0x14] Start DAC. 8-bit sound. DMA mode. // playback
[0x20] Start ADC. 8-bit sound. Direct mode. // recording
[0x24] Start ADC. 8-bit sound. DMA mode. // recording
[0x40] Set time constant.
[0x48] Set block size.
[0xD1] Turn on speaker.
[0xD3] Turn off speaker.
[0xD0] Halt DMA in progress.
[0xD4] Continue DMA.
[0xE1] Get DSP Version.

With command 0x10 we tell DSP that we're going to start to transfer the
samples from our buffer to DSP in direct mode (playback).

Command 0x14 will tell DSP to poll DMA - it starts reading samples (playback).

Command 0x20 wil tell DSP that we're going to read samples from it in direct mode (recording).

Command 0x24 will tell DSP to poll DMA - it starts sending samples (recording).

Command 0x40 will set time constant. This is used to set something like sample frequency - the number of samples that are going to output in one second. To calculate time constant you should use next equation:

256 - ( 1 000 000 - sample frequency )

Command 0x48 simply sets the number of bytes it will read/write from/to DMA, after what it generates interrupt. There's also DMA port that sets the block size but those values do not need to be same. Instead it is used for smooth playback of larger sound files. I'll talk about this a little later.

Command 0xD1 will turn speaker on. This is used for compatibility with older SB versions. After you tell DSP to start to play/record sound you should turn on speaker.

Command 0xD3 turns off speaker.

Command 0xD0 will stop DMA transfer to/from DSP for a moment, until you write 0xD4 command.

Command 0xD4 continues DMA transfer which was previously halted.

Command 0xE1 tells DSP that you want to read DSP version. So once you tell DSP that you want to read version, you should read twice from DSP read port (first read returns major second returns minor).

:[ 3.3 Direct mode ]:

Well, I already said - direct mode is obsolete. It uses CPU and while you play sound, you can't do anything else. So if you don't want to know how this works just skip it. You won't learn anything from this that can help you later with DMA mode. So make your decision.

DSP is preparing for direct mode when you write command 0x10 (for 8-bit playback) or 0x20 (for 8-bit recording). To play using direct mode do following:

-1- turn on speaker
-2- write command 0x10 or 0x20 to DSP depending on what do you want to do - record or playback
-3- read ror next sample from read port (0x0A) if you're recording, or write next sample to write port (0x0C) if you're playbacking
-4- wait for the correct timing (must do it by yourself)
-5- if not the end of sound buffer goto step 2
-6- turn off speaker

4. DIRECT MEMORY ACCESS
-----------------------------------------------------------------------------------------------

:[ 4.0 About DMA ]:

DMA stands for "Direct Memory Access" and it's another chip on your motherboard beside well-known CPU. It is invented to solve the problem of impossible background transfering. It can transfer data RAM-to-device and vice-versa. It starts its background transfering when some device polls it. And, one more thing - it is not capable of generating interrupts.

What we really need to know is that DMA transfers block of memory without intervetion of CPU (a LIE!). That's what makes SB sound a reality

DMA has two DMACs (DMA Controllers). First DMAC (a.k.a DMAC1) has 4 DMA channels dedicated to 8-bit transfering while second one DMAC2 is dedicated to 16-bit transfering. We're not going to talk about DMAC2 because, actually, we are working with 8-bit mono sound.

:[ 4.1 DMA Ports ]:

Just like you program DSP, you program DMA via I/O ports.

Here are some of the ports we are going to explore:

* NOTE: All port addresses are absolute - that is - all are relative to port address zero.

[0x00] DMAC1 CH0 Address port
[0x01] DMAC1 CH0 Count port
[0x02] DMAC1 CH1 Address port
[0x03] DMAC1 CH1 Count port
[0x04] DMAC1 CH2 Address port
[0x05] DMAC1 CH2 Count port
[0x06] DMAC1 CH3 Address port
[0x07] DMAC1 CH3 Count port

DMAC1 - DMA Controller 1
CH# - Channel number #

As you can see from above every channel has its address and count port. Address port is used for setting memory location of buffer used in transfert. Count port determines the size of the buffer.

Because DMA was first invented for 16-bit systems, the address ports can take only absolute 16-bit addresses. Later when it was upgraded, to keep compatibility with older programs written for older DMA, developers only added new ports to new DMA called PAGE REGISTERS.

With this expansion, new DMA can access 32-bit memory address space, but cannot transfer memory buffers that cross page boundary. So you should care about that your buffer doesn't cross page boundary.

Here are page register ports:

[0x87] DMAC1 CH0 Page Register
[0x83] DMAC1 CH1 Page Register
[0x81] DMAC1 CH2 Page Register
[0x82] DMAC1 CH3 Page Register

That means you should convert your SEGMENT:OFFSET pointer into PAGE:OFFSET pointer.

This is how we do (not the stupid song..) . First, we have a pointer to our buffer. So you should convert SEG:OFF to PAGE:OFF pointer. Segment represent an ordinal number of 16Byte block in absolute memory. Offset is the memory address relative to segment's absolute memory location. So what do you do... Multiply segment with 16 and add offset to it. With this we got an absolute memory location. The upper 2 bytes of result are page... Really easy? Easy, only if you knew anything about stupid memory segmentation before. I forgot to mention - lower two bytes determine offset in page.

How to check if my buffer crossed page boundary? Well when you calculate your linear (absolute) address of buffer you should only add the size of your buffer to it. If page changed then your buffer crossed page boundary. All you need to do is to allocate it again and everything will be ok , unless you use buffer larger than 64K.

To write a word to those ports first write lower byte then upper.

:[ 4.2 Starting DMA Transfer ]:

- First - we should enable speaker for compatibility with older DSP versions.
- Then we set time constant via command 0x40. Already explained.
- Then calculate absolute linear address of buffer that will participate in transfer (reading from it (playback) or writing to it (record)). Get page
offset and offset in the page.
- Disable DMA channel we are going to program. To disable it we are using
single mask register port I didn't explained. It's port address is 0x0A and you should send to it a byte that is structured on the next way:

+----+-----+-----+-----+-----+-----+-----+-----+
| 0  |  0  |  0  |  0  |  0  |  M  |  CHANNEL  |
+----+-----+-----+-----+-----+-----+-----+-----+

CHANNEL - The lower two bits of this single mask control byte set channel we want to disable/enable. CH0 = 00 CH1 = 01 CH2 = 10 CH3 = 11
M - If this bit is set DSP will disable channel, otherwise it will enable it.
Rest of bits are unused.

This is used to avoid problems when some other device/s is/are trying to use this channel.
- Clear byte pointer flip-flop. Hey what's this? I never mention this. Ok there's one more DMA port that is used to tell DMA that we are going to re-program one of its channels. This port is called byte pointer flip flop and it's port address is 0x0C. To clear byte pointer flip-flop just write anything to it.
- After this we should set DMA mode. I didn't mention this ,too. The port used for setting DMA mode is at address 0x0B. You have to write a control byte for DMA mode to it. A control byte is structured like this:

+----+-----+-----+-----+-----+-----+-----+-----+
|   MODE   |  ID |  A  |   TYPE    |  CHANNEL  |
+----+-----+-----+-----+-----+-----+-----+-----+

CHANNEL - The lower two bits select channel which mode we're going to change
TYPE - This is a transfer type and it can be one of the following:

00 - Verify
01 - Write (playback) // sends memory to device which polled DMA
10 - Read (record) // receives memory from device which polled DMA

A - Auto-Initilialization Enable

I didn't mention auto-initialize mode but only difference between manual initialization and auto is that in auto mode DMA never stops transfert - it loops. I'll spit few words about this mode at the and of this tut.

ID - Increment/Decrement

0 - Increment
1 - Decrement

Determines whether the address port of selected channel increment or decrements. That is - is written address to address port of selected channel end of buffer or start of the buffer. Hope you understand ... if not, you should know that everybody use INCREMENT.

MODE - This is a bit more on hardware level than it is on software level. I'm not sure I'm going to cover all modes, nor any mode. I'll just tell you use demand mode.

00 - Demand mode
01 - Single mode
10 - Block mode
11 - Cascade mode

To explain the differences between those modes I need to access hardware level... Well I don't like it and beside that I don't know how Cascade mode really works, but beside all your head might pop if I start to explain some of those modes. Maybe in future release of this tut (at www.admiral.bizland.com).

- Remember when you calculated your page offset and offset in your page. Write that "offset in your page" to address port (first lower byte then upper)
- Write the page to page register ( it's only one byte )
- Write size of your buffer to count port (first lower byte then upper)
- Enable DMA channel
- Write number of bytes after DSP will generate interrupt. Command 0x48. Already explained. First lower byte then upper.
- Then DMA DAC 8-bit command or auto-init playback command which I didn't mention (0x1C).
- Listen to sample.

5. CLOSING
-----------------------------------------------------------------------------------------------

GO VISIT: WWW.SHDON.CJB.NET

I don't have so much time to write detailed tut I promised I'll write for my site.
But I will one day.

I didn't talk about auto-initialized mode, how to play sounds larger than 64KB and detecting IRQs, but I can only tell you to look at www.shdon.cjb.net. I explained something what you can't find in other tuts and dox, so I hope you can now easily explore Steven H. Don's source codes about programming sound blaster.

Auto-initialized mode is not present in earlier DSP version (SB 1.x , 2.x...). It is introduced in SB Pro ( correct me if I'm wrong - i'm not sure ). It is more efficient than manual initialization because it doesn't generate stupid noise at the end of DMA buffer.

I hope you know how to rewrite ISRs (Interrupt Service Routines) because I tought you can learn this with Shdon's source codes.

Good luck, my hands are...
User Contributed Comments(9)
 [1] wasim ahmad | 2006-09-21 17:00:44

hello
well sir im designing a multitasking GUI OS
im having lot of problems in designing drivers
i downloaded SB tutorial and PS/2 mouse code
but after my extreme efforts i failed to write a code which will produce some sound in my hi-fi speakers
ps/2 mouse code 2 me was perfect but it is not even executed properly under plain DOS.
Sir it will be my pleasure if you guide me or give me some url or ur greatness if u will give me
2 COMPLETE DRIVERS IN ASM OR C FOR SOUND AND PS2 MOUSE

hope u will reply
 [2] Dhinakaran.C | 2006-09-25 04:04:05

This is the good material . But my question is i want to get the audio data from a microphone using C program.Whether this material is useful for me?
guide me plz.

dhinakaran.C
 [3] R.K.Babu | 2006-10-11 08:24:14

Sir I Worked This program . It worked will in win98 in my old PC. But not in win2000 in PIV. Please Help

#define DSP_RESET 0x06
#define DSP_DATAAVAIL 0x0E
#define DSP_READ 0x0A
int ResetDSP( unsinged int BasePort )
{
outportb(BasePort + DSP_RESET, 0x01); // write 0x01 to DSP_RESET
delay(10); // reinitialization
outportb(BasePort + DSP_RESET, 0x00); // write 0x00 to DSP_RESET
delay(10); // waiting for results
if ((inportb(BasePort + DSP_DATAAVAIL) & 0x80)=0x80) &&
(inportb(BasePort + DSP_READ) == 0xAA))
{
// DSP was found
return(1);
};
return(0); // No DSP found
}
 [4] Jvs | 2006-10-20 14:43:09

[quote]But my question is i want to get the audio data from a microphone using C program.Whether this material is useful for me?[/quote]

hmm... The only way I know you can record sound from microphone is via either WaveIn API or DirectSound API. I don't know if this is possible with SB. What's your development envinronment ? Linux,dos,windows?

[quote]Sir I Worked This program . It worked will in win98 in my old PC. But not in win2000 in PIV. Please Help[/quote]

I know that NT isn't good with SB emulation.. It might be the same problem with your win2000.. Those operating systems for certain (not known to me) reason cannot emulate sound blaster sound.. I will recommend you to download VDMSound. It is a very good utility (i use it to hear sound of dos applications under XP). It is developed to emulate dos sound output on xp/2000..
 [5] Babu R.k | 2006-10-28 04:52:54

Sir I worked with DSP in win98 in Turbo c. It worked will. But it didn't detect the port itself. Please help me.
 [6] Jvs | 2006-11-01 17:47:05

I can't understand you very well.. Can you please give me more detailed info?
 [7] yassir | 2006-11-22 07:32:59


i downloaded SB tutorial but i write the code
depend the step of direct mode but the result
is no sound with speaker
#include "ALLOC.H"
#include "DOS.H"
#include "CONIO.H"
#include "STDIO.H"


unsigned int Base; //Sound Blaster base address



int ResetDSP(unsigned int Test)
{
  //Reset the DSP
  outportb (Test + 0x6, 1);
  delay(10);
  outportb (Test + 0x6, 0);
  delay(10);
  //Check if (reset was succesfull
  if ((inportb(Test + 0xE) & 0x80 == 0x80) && (inportb(Test + 0xA) ==0xAA))
  {
  //DSP was found
  Base = Test;
  return (1);
  }
  else
  //No DSP was found
  return (0);
}

void WriteDSP(unsigned char Value)
{
  while ((inportb(Base + 0xC) & 0x80) == 0x80);
  outportb (Base + 0xC, Value);
}



void speaker_on()
{

WriteDSP(0xD1);
}

void speaker_off()
{

WriteDSP(0xD3);
}

void main()
{
ResetDSP (0x220);
speaker_on();
WriteDSP(0x10);
WriteDSP(67);

delay(10);
speaker_off();

}






Sir it will be my pleasure if you guide me or give me the correct code
 [8] yassir | 2006-12-03 09:22:20


i downloaded SB tutorial but i write the code
depend the step of direct mode but the result
is no sound with speaker
#include "ALLOC.H"
#include "DOS.H"
#include "CONIO.H"
#include "STDIO.H"


unsigned int Base; //Sound Blaster base address



int ResetDSP(unsigned int Test)
{
  //Reset the DSP
  outportb (Test + 0x6, 1);
  delay(10);
  outportb (Test + 0x6, 0);
  delay(10);
  //Check if (reset was succesfull
  if ((inportb(Test + 0xE) & 0x80 == 0x80) && (inportb(Test + 0xA) ==0xAA))
  {
  //DSP was found
  Base = Test;
  return (1);
  }
  else
  //No DSP was found
  return (0);
}

void WriteDSP(unsigned char Value)
{
  while ((inportb(Base + 0xC) & 0x80) == 0x80);
  outportb (Base + 0xC, Value);
}



void speaker_on()
{

WriteDSP(0xD1);
}

void speaker_off()
{

WriteDSP(0xD3);
}

void main()
{
ResetDSP (0x220);
speaker_on();
WriteDSP(0x10);
WriteDSP(67);

delay(10);
speaker_off();

}






Sir it will be my pleasure if you guide me or give me the correct code
 [9] MOhammad | 2008-01-05 12:26:00

Hi,

I wanna generate sound of a specific frequency (e.g. 400Hz) in Assembly...could you plz help me?

Thanks&Regards.
NOTE:
Comments that will hurt anyone in any way will be deleted.
Don't ask for features, advertise or curse.
If you want to leave a message to the author use the contacts,
if you have any question in relation to your comments please use the forum.
Comments which violate any of these requests will be deleted without further
notice. Use the comment system decently.

Post your comment:
Name:
email:
Comment:
::Top 5 Tutorials::
Embedded Python[116853]
2D Rotated Rectangles Collision Detection[88946]
Keyboard Hook[77243]
UDP[65798]
HTTP Proxy[41188]

::Top 5 Samples::
2D ColDet Rotated Rectangles[11557]
PS2 Mouse Driver[6953]
Wave Format Player[5788]
Reading FAT12[5615]
CodeGuru[5355]


All rights reserved to RageStorm © 2009