Using BASS_SAMPLE_3D on Linux with a 7.1 card - No Side Channel Audio?

Started by superhac,

superhac

Hi!

Let me start with some background on my setup: 
  • Linux (ubuntu 24.04)
  • Using the info structs my sound card is name=ICUSBAUDIO7D: USB Audio, enabled=1, speakers=8
  • A mono wav file.  1 channel.

I first started by modifying the speakers.c example like this:
#include <string.h>
#include <regex.h>
#include "bass.h"
#include <stdio.h>
#include <unistd.h>

int BASS_DEVICE_ID = 8;
char* MONO_WAV = "new.wav";


void playChannel(unsigned int speaker)
{
        HSTREAM rets = BASS_StreamCreateFile(FALSE, MONO_WAV, 0, 0, speaker | BASS_SAMPLE_FLOAT | BASS_SAMPLE_MONO);
        BASS_ChannelPlay(rets, TRUE);
        while(BASS_ChannelIsActive(rets) == BASS_ACTIVE_PLAYING) {
                sleep(.5);
        }
        BASS_ChannelFree(rets);
}

const char * getChannelName(unsigned int channel)
{
            switch (channel)
                        {
                                case 0: return "BASS_SPEAKER_FRONTLEFT";
                                case 1: return "BASS_SPEAKER_FRONTRIGHT";
                                case 2: return "BASS_SPEAKER_REARLEFT";
                                case 3: return "BASS_SPEAKER_REARRIGHT";
                                case 4: return "BASS_SPEAKER_CENTER";
                                case 5: return "BASS_SPEAKER_LFE";
                                case 6: return "BASS_SPEAKER_SIDELEFT";
                                case 7: return "BASS_SPEAKER_SIDERIGHT";
                        }

}


int main(int argc, char* argv[])
{
        // 5.1 Setup
        unsigned int sixChan[6] = {BASS_SPEAKER_FRONTLEFT, BASS_SPEAKER_FRONTRIGHT, BASS_SPEAKER_REARLEFT, BASS_SPEAKER_REARRIGHT,
                                   BASS_SPEAKER_CENTER, BASS_SPEAKER_LFE};
        // 7.1 Setup
        unsigned int eightChan[8] = {BASS_SPEAKER_FRONTLEFT, BASS_SPEAKER_FRONTRIGHT, BASS_SPEAKER_REARLEFT, BASS_SPEAKER_REARRIGHT, BASS_SPEAKER_CENTER,
                                     BASS_SPEAKER_LFE, BASS_SPEAKER_SIDELEFT, BASS_SPEAKER_SIDERIGHT};

        printf("Loading: %s\n", MONO_WAV);

        // check the correct BASS was loaded
        if (HIWORD(BASS_GetVersion()) != BASSVERSION) {
                printf("An incorrect version of BASS was loaded");
                return 0;
        }

        // initialize default device
        if (!BASS_Init(BASS_DEVICE_ID, 44100, 0, NULL, NULL)) {
                printf("Can't initialize device");
                return 0;
        }

        BASS_INFO info;
        BASS_GetInfo(&info);
        printf("BASS version: %d\n", BASS_GetVersion());
        printf("Speakers Detected: %d\n", info.speakers);

        if (info.speakers == 6) {
                for(int i=0; i < sizeof(sixChan) / sizeof(sixChan[0]);i++)
                {
                         printf(" Playing Channel: %s \n" , getChannelName(i));
                         playChannel(sixChan[i]);
                }
        }
        else if (info.speakers == 8) {
                for(int i=0; i < sizeof(eightChan) / sizeof(eightChan[0]);i++)
                {
                         printf(" Playing Channel: %s \n" , getChannelName(i));
                         playChannel(eightChan[i]);
                }
        }

        BASS_Free();
        return 0;
}

This works great and all speakers will play my mono wav as shown:
Loading: new.wav
BASS version: 33820928
Speakers Detected: 8
 Playing Channel: BASS_SPEAKER_FRONTLEFT
 Playing Channel: BASS_SPEAKER_FRONTRIGHT
 Playing Channel: BASS_SPEAKER_REARLEFT
 Playing Channel: BASS_SPEAKER_REARRIGHT
 Playing Channel: BASS_SPEAKER_CENTER
 Playing Channel: BASS_SPEAKER_LFE
 Playing Channel: BASS_SPEAKER_SIDELEFT
 Playing Channel: BASS_SPEAKER_SIDERIGHT

Now my next step was moving over to the 3dtest.c example.  It detects that I have more then 2 speakers and asks "Multiple speakers were detected. Would you like to use them?"  I choose yes.  I then load my WAV file, press play and set some x and y values for movement.  I get audio out of all the speakers except for the SIDE LEFT and SIDE RIGHT speakers.

Does the BASS 3D audio not support the side speakers?   

Thanks!

Ian @ un4seen

BASS does indeed currently only use up to 6 speakers for 3D output (5 really as LFE isn't used). If you happen to want to try generating 3D output on more speakers yourself, that is possible with BASS_StreamCreate (the "chans" parameter goes higher than 6).

superhac

Hi Ian.  Thanks for the reply.  I went in and adjusted the 3dtest.c example using this call and I get error 21 (BASS_ERROR_NO3D) when setting up the stream via:

newchan = BASS_StreamCreate(44100, 8, BASS_SAMPLE_3D , MyStreamProc, 0)
My callback:
DWORD CALLBACK MyStreamProc(HSTREAM handle, void *buffer, DWORD length, void *user)
{
    DWORD c = fread(buffer, 1, length, file); // read the file into the buffer
    if (feof(file)) c |= BASS_STREAMPROC_END; // end of the file/stream
    return c;
}

I'm using the same mono WAV file. 

Am I doing it right?

Thanks.

Ian @ un4seen

Unfortunately, it won't be quite that simple. What I meant was that, rather than enabling BASS's 3D processing with the BASS_SAMPLE_3D flag, it would be possible to implement custom 3D processing (eg. calculate the level of the sound for each speaker) and output that via a custom stream. It could perhaps be simplified a bit by using the BASSmix add-on's matrix mixing feature. For example, you could create an 8 channel/speaker mixer (with BASS_Mixer_StreamCreate) and plug the sound into that (with BASS_Mixer_StreamAddChannel), and then use a matrix (with BASS_Mixer_ChannelSetMatrix) to set the level of the sound on each of the speakers. Note you would still need to do the level calculations yourself then, but not the sample data processing.

superhac

Ok.  After I re-read your message and continued to play around, it clicked that what you were stating was I need to manually do all the positional audio processing vs using the 3Dsound bass provides.   I get it now.

Thanks for you quick help and response on this!