Archived

This topic is now archived and is closed to further replies.

Sound

This topic is 5109 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Lets say for a moment that I would not like to use directsound or fmod or whatever. How would I be able to mix my own sounds and send them to the soundcard?

Share this post


Link to post
Share on other sites
I''m not sure about this, but you could use OpenAL. It might (again, I''m not sure) build on top of DirectSound in Windows, but it''s platform-independent.

cya,
Drag0n

-----------------------------
"Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to build bigger and better idiots. So far, the universe is winning..." -- Rich Cook

My future web presence: Dave''s Programming Resources

Share this post


Link to post
Share on other sites
Also, there are no API functions explicitly used for mixing audio data. That is something you have to do yourself. The API mixer functions are only for adjusting the sound card''s channel volumes, i.e. wave volume, midi volume, etc.

Share this post


Link to post
Share on other sites
Ruudje, you have to use the multimedia API''s. The mixed samples can''t magically appear on the sound card. Also, the samples you mix obviously need to be in the same format, and so again would need to use the multimedia API''s to get the samples in the same format (unless you limit all your resources to a single PCM format, which would be quite stupid). Mixing can be as simple as adding and clipping the added samples. What''s so hard about that?

Share this post


Link to post
Share on other sites
well someone said to me I have to go through the windows drivers to do it... but that doesnt really tell me much. cant find any info on it.

and AP: by mixing I mean 2 sounds playing e.g. at the same time, backgroundmusic and soundeffects, not 2 samples playing directly after each other.

Share this post


Link to post
Share on other sites
The AP was talking about simulataneous sounds, not sequential ones. You have no reason to touch the sound card drivers. Only the OS interfaces with those. You mix the samples, then you send the mixed result to the OS via the wave* functions.

Share this post


Link to post
Share on other sites
I''m assuming you are asking this:

Given audio data stored digitally, how can I mix, manipulate, and playback this data without relying on DirectSound, OpenAL, or FMod for mixing, volume control, and buffer management.

The simple answer is ''do it yourself''. The more complex answer is ''explore the world of audio DSP''. If you think about what audio data is, and how it is represented, it becomes clearer.

Audio data, stored as PCM (Pulse Code Modulation) is a stream of samples. The samples are called that because they are a sampling of a waveform at a given time step. If your audio is in 44.1khz, 16 bit stereo it means that there are 32 bits of data used to represent 2 channels of audio every 1/44100 of a second.

Let''s back away from stereo and deal with monophonic sampling for now.

If a waveform is captured by a sound card''s ADC (Analog to Digital Converter) at 44.1khz, the sound card is taking a 16 bit ''snapshot'' of the waveform at each 1/44100''s of a second. You end up with a data file that has the wave form, swinging from +1 to -1 (in 16 bit audio this is +32767 to -32767 (or there abouts). When a waveform goes from +1 to -1 it is at it''s highest magnitude or amplification.

If you wanted to change the volume of the waveform all you would have to do is scale the magnitude of each sample:

for ( 0 to length of data )
{
newData = oldData * volume;
}


Because we hear data cumulative we can actually mix two sound files together:

for ( 0 to length of data )
{
newData = oldDataOne + oldDataTwo;
}

the only problem is that you will overflow your newData if the combined volumes are too high. So you really should do:

for ( 0 to length of data )
{
newData = oldDataOne / 2 + oldDataTwo / 2;
}

You run into more problems because you can get what''s called phase cancellation. Think about it. If oldDataOne at timestep n is 5000, and oldDataTwo at timestep n is -5000, adding them together gives you 0. If you were to take two samples of a sine wave, out of phase by 180 degrees (? or 90 I forget), and add them, you would cancel out your resulting sound all together.

When you mix all this data together, you will have to get it out of your system somehow. If you just want to mix data, write it to disk and play it back using SoundForge or some such. But if you want to play it out a speaker you''ll have to depend, unfortunately, on some kind of API. The reason why is that the various hardware manufacturer supply an interface to their hardware that is compliant with Win32/DirectX software. It''s the only way we can get a standard interface making sure all soundcards work with all PC applications. The good news is that you only need to touch a very small part of these applications if you want. DirectSound, the API I''ve always used, lets you create a small circular buffer with event notification, letting you know when you need to put more of your ''mixed'' audio into the playback buffer.

I''ve written a number of synth tools and audio editing programs that do this - everything is done in software, where I convert all my data to 32bit floating point (-1 to +1 normalized data) and then, right before copying it to DirectSound''s playback buffer, I convert it to 8,16 or even 24/32 bit for high end cards. Working with your digital audio as floats is very convienient and fast. The maths work out nicely and you''re not checking everything for being in range our out of range until post add:


for ( 0 to length of data )
{
float newData = (float oldDataOne + float oldDataTwo) / 2.0f;
}

Take a look at http://www.musicdsp.org/ for more information on DSP such as implementing digital filters, reverb and echo, and other great ideas.

I love messing around with this stuff, even if it is not directly related to game development. Using an API for playback in games and relying on hardware mixing is more effecient for one-shot and loop playback in games, but messing with the data directly can be a lot of fun.

Best of luck, hope that helps.

Share this post


Link to post
Share on other sites
I have no idea why you would want to send the audio to the sound card directly without using any of the os api''s. There their for a reason, so you don''t have to write the interface to hardware yourself. However, if you feel you must send the data directly to the hardware, you should look into writing your own driver, or possibly interfacing with the windows drivers.

Though, if you want to make a dos like program console program, look into how it was done during the dos era. Finding the device''s irq settings and setting it up. There will be thousands of dos examples of how to do what you ask. And very, very few for windows.

This is because the problem becomes that you need a driver for all kinds of various sound cards. Which is why windows won out over dos games... No longer the need to write drivers for every type of sound/video/joystick/etc.. card in existance.

Share this post


Link to post
Share on other sites
the problem is you cant do that anymore... you cant write directly to the ports in protected mode. but stuff like directx and fmod and openal can, so there should be a way

Share this post


Link to post
Share on other sites
When are you simply going to take our word? An application has absolutely no use in directly interfacing with the sound hardware as there are too many different types of hardware. The lowest level your application needs to use (and its the same one fmod uses when it uses the software engine) is the waveOut* WIN32 functions. Or, you can use DirectSound. Either way, there will be one or two layers of indirection between your app and the hardware which is in fact desired.

Share this post


Link to post
Share on other sites
Man, PlaySound() is way underused. People think it sucks when it works fine in most cases. You can start playback of a sound before one finishes, together, or 1 sound alone with the right params passed to it.

[edited by - bjz on December 22, 2003 1:04:21 PM]

Share this post


Link to post
Share on other sites
If you are still looking for waveOut samples there is one that is part of DirectShow sample:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/htm/audiostreamingsamplecode.asp

There relevant stuff is in the audio streaming sample, and here is the write function:


BOOL CWaveBuffer::Write(PBYTE pData, int nBytes, int& BytesWritten)
{
// ASSERT((DWORD)m_nBytes != m_Hdr.dwBufferLength);

BytesWritten = min((int)m_Hdr.dwBufferLength - m_nBytes, nBytes);
CopyMemory((PVOID)(m_Hdr.lpData + m_nBytes), (PVOID)pData, BytesWritten);
m_nBytes += BytesWritten;
if (m_nBytes == (int)m_Hdr.dwBufferLength)
{
/* Write it! */
m_nBytes = 0;
waveOutWrite(m_hWave, &m_Hdr, sizeof(WAVEHDR));
return TRUE;
}
return FALSE;
}

Share this post


Link to post
Share on other sites
quote:
Original post by Ruudje
the problem is you cant do that anymore... you cant write directly to the ports in protected mode. but stuff like directx and fmod and openal can, so there should be a way


Your right, I should have been more specific. What you could do is write a dos program (ie. use a compiler that can create dos code. I think VC++ V1.52 was the last MS compiler that did. Though there are others that might still). Most versions of windows should be able to handle a true dos program. But again, this is not truly the solution you need, writing to the hardware is not a good idea.

fmod uses software (or hardware through API calls) for mixing. And for play sounds fmod uses selectable drivers.

Linux : oss, alsa, esd;
Windows : dsound, winmm;

Edited for clarity

[edited by - pjcast on December 22, 2003 1:38:00 PM]

Share this post


Link to post
Share on other sites