[Openal] How can I play mono wav sound in specific channel?

Ümit Uzun umituzun84 at gmail.com
Thu Apr 16 06:06:03 PDT 2009


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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://opensource.creative.com/pipermail/openal/attachments/20090416/6895efcd/attachment.html


More information about the Openal mailing list