[Openal] How can I play mono wav sound in specific channel?
Chris Robinson
chris.kcat at gmail.com
Thu Apr 16 03:38:23 PDT 2009
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.
More information about the Openal
mailing list