[Openal] How can I play mono wav sound in specific channel?
Daniel PEACOCK
dpeacock at creativelabs.com
Thu Apr 16 08:41:37 PDT 2009
"Note that when using the “Generic Software” device, the multi-channel
buffers are mixed down to a stereo output"
The behaviour you are seeing on the "Generic Software" device is expected.
This device only supports stereo (2.0) output. It supports playback of
multi-channel buffers (e.g 5.1 or 7.1), and rather than lose any audio
contained in the extra channels, that data is mixed into the stereo output
- preserving left-right separation (e.g all the left channels of a
multichannel buffer are mixed into the output left channel and all the
right channels are mixed into the output right channel).
Your soundcard is likely to be upmixing the stereo output of the "Generic
Software" device to 5.1which is why you hear audio in all the channels.
The bottom line is that the "Generic Software" device won't let you send a
discrete signal to a side or rear channel. The other Creative devices will
all support this feature - and so will Chris' OpenAL-Soft.
Dan
Creative Labs (UK) Ltd.
Notice
The information in this message is confidential and may be legally
privileged. It is intended solely for the addressee. Access to this
message by anyone else is unauthorized. If you are not the intended
recipient, any disclosure, copying or distribution of the message, or
any action taken by you in reliance on it, is prohibited and may be
unlawful. If you have received this message in error, please delete it
and contact the sender immediately. Thank you.
Creative Labs UK Ltd company number 2658256 registered in England and Wales
at Belmont Road, Belmont Place, Maidenhead, Berkshire, SL6 6TB
Ümit Uzun
<umituzun84 at gmail
.com> To
Sent by: OpenAL
openal-bounces at op <openal at opensource.creative.com>
ensource.creative cc
.com
Subject
Re: [Openal] How can I play mono
04/16/2009 02:06 wav sound in specific channel?
PM
Hi Chris;
I have implemented your code in Framework.cpp and it works like a charm :D
Thanks so much for your awesome helps :D But I have some questions to
solve. I have implemented your suggestion on 5.1 speaker system like that;
template<typename T>
T *load_data(const T *data, int size)
{ size /= sizeof(T); T *data71 = new T[size*6]; for(int i = 0;i < size;i++)
{
data71[i*6 + 0] = 0; // front-left data71[i*6 + 1] = 0; //
front-right data71[i*6 + 2] = 0; // front-center data71[i*6 + 3] = 0;
// lfe (sub-woofer) data71[i*6 + 4] = 0; // back-left data71[i*6 + 5]
= 0; // back-right
} return data71;
}
--------------------------------------
WAVEFORMATEX fmt;
g_pWaveLoader->
GetWaveFormatExHeader(WaveID, &fmt);
if(fmt.wBitsPerSample == 8) { ALubyte *data = load_data((const
ALubyte*)pData, iDataSize); alBufferData(uiBufferID,
alGetEnumValue("AL_FORMAT_51CHN8"), data, iDataSize*6,
iFrequency); delete[] data;
} else if(fmt.wBitsPerSample == 16) { ALshort *data = load_data((const
ALshort*)pData, iDataSize); alBufferData(uiBufferID,
alGetEnumValue("AL_FORMAT_51CHN16"), data, iDataSize*6,
iFrequency); delete[] data;
} else if(fmt.wBitsPerSample == 32) { // assumes 32-bit float ALfloat
*data = load_data((const ALfloat*)pData,
iDataSize); alBufferData(uiBufferID,
alGetEnumValue("AL_FORMAT_51CHN32"), data, iDataSize*6,
iFrequency); delete[] data;
}
It works on while using Generic Hardware. I mean I can direct each sound to
each wanted channel errorless, but when I try same operation while using
Generic Software it works but it is mixing the channels. For example I want
to play on back- left, but sound is heard from front-left, back-left,
front-center and lfe and vice-versa for the back-right.
I mean Generic Software can't play related channel on related side. Do you
think it is problem of generic software or what? I have looked at the
OpenALProgrammingGuide and there is a statement about kind of this
situation but I can't really understand what does it mean? Can you explain
what could be the problem?
>From OpenALProgrammingGuide;
"The multi-channel extension provides a mechanism to play multi-channel
data via OpenAL. A variety of formats are supported. Multi-channel buffers
can be attached or queued on a source.
Note that when using the “Generic Software” device, the multi-channel
buffers are mixed down to a stereo output. On a hardware device (such as
the “Generic Hardware” device or a native device), each channel of a buffer
requires a hardware voice. So, for example playing a buffer using the
AL_FORMAT_51CHN16 format will require 6 free hardware voices. If the
hardware resources are unavailable, the call to alSourceQueueBuffers or
alSourcei will fail."
Thanks so much.
Best Regards.
2009/4/16 Chris Robinson <chris.kcat at gmail.com>
On Thursday 16 April 2009 2:53:45 am you wrote:
> Hi Chris;
>
> > ALshort monodata[samples];
> >
> > you can fill it into a 7.1 buffer like this:
> >
> > ALshort data71[samples*8];
> > for(int i = 0;i < samples;i++) {
> > data71[i*8 + 0] = 0; // front-left
> > data71[i*8 + 1] = 0; // front-right
> > data71[i*8 + 2] = 0; // front-center
> > data71[i*8 + 3] = 0; // lfe (sub-woofer)
> > data71[i*8 + 4] = 0; // back-left
> > data71[i*8 + 5] = 0; // back-right
> > data71[i*8 + 6] = monodata[i]; // side-left
> > data71[i*8 + 7] = monodata[i]; // side-right
> > }
> > alBufferData(bID, alGetEnumValue("AL_FORMAT_71CHN16"), data71,
> > samples*8*sizeof(ALshort), frequency);
> >
> I have look at the Framework and there is ALFWLoadWaveToBuffer;
>
> ALboolean ALFWLoadWaveToBuffer(const char *szWaveFile, ALuint
uiBufferID,
> ALenum eXRAMBufferMode)
> {
> WAVEID WaveID;
> ALint iDataSize, iFrequency;
> ALenum eBufferFormat;
> ALchar *pData;
> ALboolean bReturn;
>
> bReturn = AL_FALSE;
> if(g_pWaveLoader)
> {
> if(SUCCEEDED(g_pWaveLoader->LoadWaveFile(szWaveFile, &WaveID)))
> {
> if((SUCCEEDED(g_pWaveLoader->GetWaveSize(WaveID, (unsigned
> long*)&iDataSize))) &&
> (SUCCEEDED(g_pWaveLoader->GetWaveData(WaveID,
> (void**)&pData))) &&
> (SUCCEEDED(g_pWaveLoader->GetWaveFrequency(WaveID,
(unsigned
> long*)&iFrequency))) &&
> (SUCCEEDED(g_pWaveLoader->GetWaveALBufferFormat(WaveID,
> &alGetEnumValue, (unsigned long*)&eBufferFormat))))
> {
> // Set XRAM Mode (ifapplication)
> if(eaxSetBufferMode && eXRAMBufferMode)
> {
> eaxSetBufferMode(1, &uiBufferID, eXRAMBufferMode);
> }
>
> alGetError();
> alBufferData(uiBufferID, eBufferFormat, pData,
iDataSize,
> iFrequency);
>
> if(alGetError() == AL_NO_ERROR)
> {
> bReturn = AL_TRUE;
> }
>
> g_pWaveLoader->DeleteWaveFile(WaveID);
> }
> }
> }
>
> return bReturn;
> }
>
> You have given ALshort monodata[samples]; but in this code ALchar
*pData;
> This variable are same or not. because alBufferData takes void format
and
> ALchar is 1 byte and ALshort 2 byte. I can't get what should I do.
They aren't the same. That function uses pData because the loaded wave
data
may be 8-bit, or 16-bit (or possible 32-bit), so it just uses a generic
char
type.
g_pWaveLoader has a GetWaveFormatExHeader method you can use to get a
WAVEFORMATEX struct, which has a wBitsPerSample field. You need to check
that
field and act on the data depending on the value (eg. if it's 8, use
ALubyte,
if it's 16, use ALshort).
And example of doing this in C++ would be something like:
template<typename T>
T *load_data(const T *data, int size)
{ size /= sizeof(T); T *data71 = new T[size*8]; for(int i = 0;i <
size;i++) {
data71[i*8 + 0] = 0; // front-left data71[i*8 + 1] = 0; //
front-right data71[i*8 + 2] = 0; // front-center data71[i*8 + 3] =
0; // lfe (sub-woofer) data71[i*8 + 4] = 0; // back-left data71[i*8
+ 5] = 0; // back-right
data71[i*8 + 6] = data[i]; // side-left data71[i*8 + 7] = data[i];
// side-right } return data71;
}
...
WAVEFORMATEX fmt;
g_pWaveLoader->GetWaveFormatExHeader(WaveID, &fmt);
if(fmt.wBitsPerSample == 8) { ALubyte *data = load_data((const
ALubyte*)pData, iDataSize); alBufferData(uiBufferID,
alGetEnumValue("AL_FORMAT_71CHN8"), data, iDataSize*8,
iFrequency); delete[] data;
} else if(fmt.wBitsPerSample == 16) { ALshort *data = load_data((const
ALshort*)pData, iDataSize); alBufferData(uiBufferID,
alGetEnumValue("AL_FORMAT_71CHN16"), data, iDataSize*8,
iFrequency); delete[] data;
} else if(fmt.wBitsPerSample == 32) { // assumes 32-bit float ALshort
*data = load_data((const ALfloat*)pData,
iDataSize); alBufferData(uiBufferID,
alGetEnumValue("AL_FORMAT_71CHN32"), data, iDataSize*8,
iFrequency); delete[] data;
}
..
completely untested, but the concept should work. It would load the sound
so
that when it plays, it'll play out the side speakers.
_______________________________________________
Openal mailing list
Openal at opensource.creative.com
http://opensource.creative.com/mailman/listinfo/openal
--
Ümit Uzun_______________________________________________
Openal mailing list
Openal at opensource.creative.com
http://opensource.creative.com/mailman/listinfo/openal
ForwardSourceID:NT0006B3A2
More information about the Openal
mailing list