Author Topic: BASSWASAPI beta  (Read 154573 times)

aybe

  • Posts: 143
Re: BASSWASAPI beta
« Reply #50 on: 27 May '10 - 15:56 »
Here is a quick & dirty utility I just made to have a better view of BassWasapi.

It retrieves all the devices then displays them in a sortable grid; I understood how it works now ;D

It's very basic but you'll see why there are so many devices detected.

So I decided to share it with you,


Create a WPF project and paste this code :

Code: [Select]
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using Un4seen.BassWasapi;

namespace BassWasapiViewer{
    /// <summary>
    ///   Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window{
        private ListSortDirection _lastDirection = ListSortDirection.Ascending;
        private GridViewColumnHeader _lastHeaderClicked;

        public MainWindow(){
            InitializeComponent();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e){
            var devices = new WasapiDevices();
        }


        private void GridViewColumnHeaderClickedHandler(object sender,
                                                        RoutedEventArgs e){
            var headerClicked =
                e.OriginalSource as GridViewColumnHeader;
            ListSortDirection direction;

            if (headerClicked != null)
            {
                if (headerClicked.Role != GridViewColumnHeaderRole.Padding)
                {
                    if (headerClicked != _lastHeaderClicked)
                    {
                        direction = ListSortDirection.Ascending;
                    }
                    else
                    {
                        if (_lastDirection == ListSortDirection.Ascending)
                        {
                            direction = ListSortDirection.Descending;
                        }
                        else
                        {
                            direction = ListSortDirection.Ascending;
                        }
                    }

                    var header = headerClicked.Column.Header as string;
                    Sort(header, direction);

                    if (direction == ListSortDirection.Ascending)
                    {
                        headerClicked.Column.HeaderTemplate =
                            Resources["HeaderTemplateArrowUp"] as DataTemplate;
                    }
                    else
                    {
                        headerClicked.Column.HeaderTemplate =
                            Resources["HeaderTemplateArrowDown"] as DataTemplate;
                    }

                    // Remove arrow from previously sorted header
                    if (_lastHeaderClicked != null && _lastHeaderClicked != headerClicked)
                    {
                        _lastHeaderClicked.Column.HeaderTemplate = null;
                    }


                    _lastHeaderClicked = headerClicked;
                    _lastDirection = direction;
                }
            }
        }

        private void Sort(string sortBy, ListSortDirection direction){
            ICollectionView dataView =
                CollectionViewSource.GetDefaultView(lv.ItemsSource);

            dataView.SortDescriptions.Clear();
            var sd = new SortDescription(sortBy, direction);
            dataView.SortDescriptions.Add(sd);
            dataView.Refresh();
        }
    }

    internal class MyClass{
        public MyClass(BASS_WASAPI_DEVICEINFO deviceinfo){
            Defperiod = deviceinfo.defperiod;
            Flags = deviceinfo.flags;
            Id = deviceinfo.id;
            IsDefault = deviceinfo.IsDefault;
            IsEnabled = deviceinfo.IsEnabled;
            IsInitialized = deviceinfo.IsInitialized;
            IsInput = deviceinfo.IsInput;
            IsLoopback = deviceinfo.IsLoopback;
            Minperiod = deviceinfo.minperiod;
            Mixchans = deviceinfo.mixchans;
            Mixfreq = deviceinfo.mixfreq;
            Name = deviceinfo.name;
            SupportsRecording = deviceinfo.SupportsRecording;
            Type = deviceinfo.type;
        }

        public float Defperiod { get; private set; }
        public BASSWASAPIDeviceInfo Flags { get; private set; }
        public string Id { get; private set; }
        public bool IsDefault { get; private set; }
        public bool IsEnabled { get; private set; }
        public bool IsInitialized { get; private set; }
        public bool IsInput { get; private set; }
        public bool IsLoopback { get; private set; }
        public float Minperiod { get; private set; }
        public int Mixchans { get; private set; }
        public int Mixfreq { get; private set; }
        public string Name { get; private set; }
        public bool SupportsRecording { get; private set; }
        public BASSWASAPIDeviceType Type { get; private set; }
    }

    internal class WasapiDevices : ObservableCollection<MyClass>{
        public WasapiDevices(){
            var bassWasapiGetDeviceInfos = BassWasapi.BASS_WASAPI_GetDeviceInfos();
            foreach (var bassWasapiGetDeviceInfo in bassWasapiGetDeviceInfos)
            {
                Add(new MyClass(bassWasapiGetDeviceInfo));
            }
        }
    }
}

Code: [Select]
<Window x:Class="BassWasapiViewer.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:BassWasapiViewer="clr-namespace:BassWasapiViewer"
        Title="MainWindow"
        Height="350"
        Width="525"
        Loaded="Window_Loaded">
    <Window.Resources>

        <BassWasapiViewer:WasapiDevices x:Key="wasapi">

        </BassWasapiViewer:WasapiDevices>

    </Window.Resources>
    <Grid>
        <ListView x:Name="lv"
                  DataContext="{Binding Source={StaticResource wasapi}}"
                  ItemsSource="{Binding }"
                  GridViewColumnHeader.Click="GridViewColumnHeaderClickedHandler">

            <ListView.View>
                <GridView AllowsColumnReorder="True">

                    <GridViewColumn Header="Name"
                                    DisplayMemberBinding="{Binding Path=Name}" />
                    <GridViewColumn Header="Type"
                                    DisplayMemberBinding="{Binding Path=Type}" />
                    <GridViewColumn Header="Flags"
                                    DisplayMemberBinding="{Binding Path=Flags}" />

                    <GridViewColumn Header="IsDefault"
                                    DisplayMemberBinding="{Binding Path=IsDefault}" />
                    <GridViewColumn Header="IsEnabled"
                                    DisplayMemberBinding="{Binding Path=IsEnabled}" />
                    <GridViewColumn Header="IsInitialized"
                                    DisplayMemberBinding="{Binding Path=IsInitialized}" />
                    <GridViewColumn Header="IsInput"
                                    DisplayMemberBinding="{Binding Path=IsInput}" />
                    <GridViewColumn Header="IsLoopback"
                                    DisplayMemberBinding="{Binding Path=IsLoopback}" />
                    <GridViewColumn Header="SupportsRecording"
                                    DisplayMemberBinding="{Binding Path=SupportsRecording}" />

                    <GridViewColumn Header="Defperiod"
                                    DisplayMemberBinding="{Binding Path=Defperiod}" />
                    <GridViewColumn Header="Minperiod"
                                    DisplayMemberBinding="{Binding Path=Minperiod}" />
                    <GridViewColumn Header="Mixchans"
                                    DisplayMemberBinding="{Binding Path=Mixchans}" />
                    <GridViewColumn Header="Mixfreq"
                                    DisplayMemberBinding="{Binding Path=Mixfreq}" />
                    <GridViewColumn Header="Id"
                                    DisplayMemberBinding="{Binding Path=Id}" />
                </GridView>
            </ListView.View>

        </ListView>
    </Grid>
</Window>


See ya !

aybe

  • Posts: 143
Re: BASSWASAPI beta
« Reply #51 on: 27 May '10 - 20:04 »
I fixed it, input devices cannot have a proc that is null !

 ;D

I'm currently having issues for EXCLUSIVE, every time I get either BASS_ERROR_ILLPARAM or BASS_ERROR_UNKNOWN.
Any parameters set for period never work. No problems when using SHARED though ...

I tried also another (Edirol UA-101) device (beside the integrated one) but it's the same.
I also checked the control panel, they are all allowed to be exclusive.

Any ideas ?

Thank you !

Code: [Select]
           var list = new List<WasapiDevice>();
            var deviceInfos = BassWasapi.BASS_WASAPI_GetDeviceInfos();
            for (int index = 0; index < deviceInfos.Length; index++)
            {
                var deviceInfo = deviceInfos[index];
                if (!deviceInfo.IsEnabled) continue;

                // Try exclusive init
                if (!BassWasapi.BASS_WASAPI_Init(index, deviceInfo.mixfreq, deviceInfo.mixchans,
                                                 BASSWASAPIInit.BASS_WASAPI_EXCLUSIVE, 8, 2, null,
                                                 IntPtr.Zero))
                {
                    var bassError = ErrCheck();
                    continue;
                }

                // Get extra infos and add this device to list
                var info = BassWasapi.BASS_WASAPI_GetInfo();
                if (info != null)
                    list.Add(new WasapiDevice(index, deviceInfo, info));

                // Done with it
                if (!BassWasapi.BASS_WASAPI_Free())
                {
                    var bassError = ErrCheck();
                }
            }
[/s]
« Last Edit: 27 May '10 - 20:28 by aybe »

martin

  • Posts: 34
Re: BASSWASAPI beta
« Reply #52 on: 29 May '10 - 08:07 »
Hi,
firstly thank you very much for this great addon!

What is the easiest way to filter out all input devices and display only the playback devices while using BassWasapi.BASS_WASAPI_GetDeviceInfo?

The other way round it is easy, but of course nearly all playback devices are at the same time input devices as well...

Thank you!
Martin

Ian @ un4seen

  • Administrator
  • Posts: 20393
Re: BASSWASAPI beta
« Reply #53 on: 31 May '10 - 16:34 »
Input devices (including loopback devices) can be identified by the BASS_DEVICE_INPUT flag in the BASS_WASAPI_DEVICEINFO.flags member, so you would do something like this...

Code: [Select]
BASS_WASAPI_DEVICEINFO info;
BASS_WASAPI_GetDeviceInfo(device, &info); // get device info
if (!(info.flags&BASS_DEVICE_INPUT)) { // check that it isn't an input device
// do something with it, eg. add to a list
}

As mentioned earlier in this thread, if you are planning to use a list as a device selector, be sure to retain the device number too (for use in the BASS_WASAPI_Init call). You can find an example of that in the RECTEST.C source file in the BASSWASAPI package.

ken

  • Posts: 739
Re: BASSWASAPI beta
« Reply #54 on: 5 Jun '10 - 13:26 »
I'm trying to use "BASS_Mixer_ChannelGetPositionEx" with Bass.NET (based on the "contest" example. But get error on Lock:

Quote
Cannot marshal 'return value': Invalid managed/unmanaged type combination (Single must be paired with R4).

How should I do it? Here is my code for getting position in C#.

Code: [Select]
public TimeSpan GetPosition
{
      get
      {
               
                TimeSpan _ts = new TimeSpan();

                BassWasapi.BASS_WASAPI_Lock(true);
                int _delay = BassWasapi.BASS_WASAPI_GetData(null,(int)Un4seen.Bass.BASSData.BASS_DATA_AVAILABLE);
                _ts = TimeSpan.FromSeconds(Bass.BASS_ChannelBytes2Seconds(_channel1, BassMix.BASS_Mixer_ChannelGetPositionEx(_channel1, BASSMode.BASS_POS_MUSIC_ORDERS, _delay)));
                BassWasapi.BASS_WASAPI_Lock(false);

            return _ts;
      }
}


BTW, is there a 64-bit version of BASSWASAPI?

/Ken

radio42

  • Posts: 4573
Re: BASSWASAPI beta
« Reply #55 on: 5 Jun '10 - 22:16 »
Have you created the mixer with the BASS_MIXER_POSEX flag.

I just made a little test and it seems I am unable to reproduce the issue - here it is working fine without any issues.
So are you probably mixing any 32-/64-bit codes?
What is your app running at? Compiled for x86 or x64?
And what versions are you using?

ken

  • Posts: 739
Re: BASSWASAPI beta
« Reply #56 on: 6 Jun '10 - 12:32 »
Have you created the mixer with the BASS_MIXER_POSEX flag.

I did not at first, but adding BASS_MIXER_POSEX give me the same error. This is a 32-bit computer (Windows 7 32) I was asking x64 for future needs.

Here is how I add mixer and wasapi, wish works perfect until posEx:
Code: [Select]
  Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_UPDATEPERIOD, 0);
            Bass.BASS_Init(-1, audioDevOut.MixFreq, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero);

            _mixer = BassMix.BASS_Mixer_StreamCreate(audioDevOut.MixFreq, 2, BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_FLOAT | BASSFlag.BASS_MIXER_NONSTOP | BASSFlag.BASS_MIXER_POSEX);

            _BassWasapiHandlerOut = new BassWasapiHandler(audioDevOut.DeviceID, false, audioDevOut.MixFreq, 2, BufferOut, 0);

            bool _retInit = _BassWasapiHandlerOut.Init();

     
            _BassWasapiHandlerOut.AddOutputSource(_mixer, BASSFlag.BASS_DEFAULT);

            bool _retStart = _BassWasapiHandlerOut.Start();


Bass.dll v2.4.5.19
Bass.Net.dll v2.4.6.5
bassmix.dll v2.4.4.2 (from wasapi)
basswasapi.dll v0.0.0.3

Ian @ un4seen

  • Administrator
  • Posts: 20393
Re: BASSWASAPI beta
« Reply #57 on: 7 Jun '10 - 15:22 »
Code: [Select]
                _ts = TimeSpan.FromSeconds(Bass.BASS_ChannelBytes2Seconds(_channel1, BassMix.BASS_Mixer_ChannelGetPositionEx(_channel1, BASSMode.BASS_POS_MUSIC_ORDERS, _delay)));

I don't know if it is the cause of your troubles, but judging by the BASS_ChannelBytes2Seconds call, I guess that is meant to be BASS_POS_BYTE rather than BASS_POS_MUSIC_ORDERS?

BTW, is there a 64-bit version of BASSWASAPI?

Yep, a 64-bit DLL is now included in the BASSWASAPI package (see 1st post).

radio42

  • Posts: 4573
Re: BASSWASAPI beta
« Reply #58 on: 7 Jun '10 - 15:43 »
Oh yes, that should be the troublesome line, as BASS_POS_MUSIC_ORDERS would return -1 for the BASS_Mixer_ChannelGetPositionEx call.
So it should definitly be BASS_POS_BYTE !

ken

  • Posts: 739
Re: BASSWASAPI beta
« Reply #59 on: 7 Jun '10 - 16:11 »
Oh yes, that should be the troublesome line, as BASS_POS_MUSIC_ORDERS would return -1 for the BASS_Mixer_ChannelGetPositionEx call.
So it should definitly be BASS_POS_BYTE !

Oh, yes that is totally wrong...

But my code hangs on BassWasapi.BASS_WASAPI_Lock(true);

It do work with just:
Code: [Select]
int _delay = BassWasapi.BASS_WASAPI_GetData(null, (int)Un4seen.Bass.BASSData.BASS_DATA_AVAILABLE);
_ts = TimeSpan.FromSeconds(Bass.BASS_ChannelBytes2Seconds(_channel1, BassMix.BASS_Mixer_ChannelGetPositionEx(_channel1, BASSMode.BASS_POS_BYTES, _delay)));

do I need BassWasapi.BASS_WASAPI_Lock(true) ? What does it do?

/Ken

stevenmmm

  • Posts: 114
Re: BASSWASAPI beta
« Reply #60 on: 8 Jun '10 - 16:22 »
i would like to use BASSWASPI such that resampling is avoided if the sample rate of the source data is supported by the device ie. use exclusive mode and set the device sample rate to that of the source data (this is for people who expect bit-perfect output). While I expect most music files will be 44100, some might have different sample rates. From what I can see the only way to play different sample rates (without resampling) is to free and re-initialise the device. Is that something you would advise against doing for any reason?
« Last Edit: 8 Jun '10 - 16:33 by stevenmmm »

Ian @ un4seen

  • Administrator
  • Posts: 20393
Re: BASSWASAPI beta
« Reply #61 on: 8 Jun '10 - 17:30 »
But my code hangs on BassWasapi.BASS_WASAPI_Lock(true);

It do work with just:
Code: [Select]
int _delay = BassWasapi.BASS_WASAPI_GetData(null, (int)Un4seen.Bass.BASSData.BASS_DATA_AVAILABLE);
_ts = TimeSpan.FromSeconds(Bass.BASS_ChannelBytes2Seconds(_channel1, BassMix.BASS_Mixer_ChannelGetPositionEx(_channel1, BASSMode.BASS_POS_BYTES, _delay)));

do I need BassWasapi.BASS_WASAPI_Lock(true) ? What does it do?

The purpose of the BASS_WASAPI_Lock call there is to prevent the mixer processing more data in the middle of the position calculations. For example, if the mixer did process some more data between the BASS_WASAPI_GetData and BASS_Mixer_ChannelGetPositionEx calls, that would invalidate the "_delay" value and result in an incorrect position being returned by BASS_Mixer_ChannelGetPositionEx.

Where are you calling that code from? I guess a timer in the main thread? Are you also using any callback functions (eg. DSPPROC/SYNCPROC), and if so, what are they doing, eg. any GUI stuff?

i would like to use BASSWASPI such that resampling is avoided if the sample rate of the source data is supported by the device ie. use exclusive mode and set the device sample rate to that of the source data (this is for people who expect bit-perfect output). While I expect most music files will be 44100, some might have different sample rates. From what I can see the only way to play different sample rates (without resampling) is to free and re-initialise the device. Is that something you would advise against doing for any reason?

No, that should be fine. As you say, it is necessary if you want to avoid resampling while using different sample rates. One issue is that it prevents gapless output, ie. there will be a small break in the sound as the device is reinitialized.

Mike Wittman

  • Posts: 20
BASSWASAPI Lock and GetData
« Reply #62 on: 8 Jun '10 - 19:25 »
Hi IAN;

Related to the two previous posts I was wondering about the purpose of Lock.

If in WASAPI Exclusive mode, using "bit-perfect" rendering; if all I'm doing is using BASS to Decode and WASAPI to render the audio, with NO mixer involved; can I use GetData for visualizations without the need for the "Lock" ?

Your thoughts are much obliged !

Mike Wittman

ken

  • Posts: 739
Re: BASSWASAPI beta
« Reply #63 on: 9 Jun '10 - 07:54 »
Where are you calling that code from? I guess a timer in the main thread? Are you also using any callback functions (eg. DSPPROC/SYNCPROC), and if so, what are they doing, eg. any GUI stuff?

Yes i'ts a timer pulling my GetPosition. I do use SyncProc for geting "mix" position and end of stream. I don't think its a thread issue, C# errormessage normaly say when I crossthread. This is the error I get when code get to "lock" I also tried to remove all my BASS_Mixer_ChannelSetSync, same thing.

Code: [Select]
Cannot marshal 'return value': Invalid managed/unmanaged type combination (Single must be paired with R4).

radio42

  • Posts: 4573
Re: BASSWASAPI beta
« Reply #64 on: 9 Jun '10 - 11:45 »
The error message indicates, that you are using/invoking a method which expects a 'float' return value.
But neither the "BASS_Mixer_ChannelGetPositionEx" nor the "BASS_WASAPI_Lock" return a float value - at least not as stated in the BASS_WASAPI docs/API.

So can you confirm which BASS_WASAPI call creates this error message?!

So I can only imagine two scenarios for the error message:
a) BASS_WASAPI indeed returns a float value - but the API is simply incorrect
b) the error message is actually thrown by another function call

Ian @ un4seen

  • Administrator
  • Posts: 20393
Re: BASSWASAPI beta
« Reply #65 on: 9 Jun '10 - 13:56 »
Related to the two previous posts I was wondering about the purpose of Lock.

If in WASAPI Exclusive mode, using "bit-perfect" rendering; if all I'm doing is using BASS to Decode and WASAPI to render the audio, with NO mixer involved; can I use GetData for visualizations without the need for the "Lock" ?

Yep, there is no need to lock in that case. It would only be used with the code above to ensure that the "_delay" value doesn't get invalidated before it is used in the BASS_Mixer_ChannelGetPositionEx call.

Yes i'ts a timer pulling my GetPosition. I do use SyncProc for geting "mix" position and end of stream. I don't think its a thread issue, C# errormessage normaly say when I crossthread. This is the error I get when code get to "lock" I also tried to remove all my BASS_Mixer_ChannelSetSync, same thing.

Code: [Select]
Cannot marshal 'return value': Invalid managed/unmanaged type combination (Single must be paired with R4).

Just to be clear, is the BASS_ChannelLock call hanging or is it generating an error?

ken

  • Posts: 739
Re: BASSWASAPI beta
« Reply #66 on: 9 Jun '10 - 16:01 »

Just to be clear, is the BASS_ChannelLock call hanging or is it generating an error?

When the code comes to BASS_ChannelLock , it "hangs" and I get this message in debug (C# with Bass.Net)
Code: [Select]
Cannot marshal 'return value': Invalid managed/unmanaged type combination (Single must be paired with R4).

radio42

  • Posts: 4573
Re: BASSWASAPI beta
« Reply #67 on: 9 Jun '10 - 16:23 »
This is even more puzzling, as BASS_ChannelLock also doesn't use any float parameters/return values.
Are you may be calling BASS_ChannelLock from within a DSPPROC?

fmcoder

  • Posts: 436
Re: BASSWASAPI beta
« Reply #68 on: 13 Jun '10 - 12:59 »
Wasapi works fine. The strange thing I noticed. If I use only WASAPI, with buffer set to "0.05" seconds, the playback latency is that 0.05 seconds. If I also use another output with DirectSound card, and there is 2 seconds buffer - the latency in WASAPI output also becomes 2 seconds. Why is that?
Both of those outputs share the same source (two splitter channels are made for 2 outputs).

UPD I noticed that if I remove the splitter creation for DS card, the latency is not increased, i.e. it stays at 0.05 seconds. That means, the splitter for Directsound card does something which affects the Wasapi output.
« Last Edit: 13 Jun '10 - 13:04 by fmcoder »

Ian @ un4seen

  • Administrator
  • Posts: 20393
Re: BASSWASAPI beta
« Reply #69 on: 14 Jun '10 - 15:15 »
To allow the splitter streams to receive all of the source data, they share a buffer. If the DirectSound output is requesting 2 seconds of data in advance and the WASAPI output is requesting only 0.05 seconds, then the splitter will have to keep 1.95 seconds of data buffered for the WASAPI output so that it doesn't miss any.

What issues is the latency causing? If it's delaying DSP/FX changes, you could apply those to the splitters rather than the source.

fmcoder

  • Posts: 436
Re: BASSWASAPI beta
« Reply #70 on: 19 Jun '10 - 13:04 »
The issues are: when user turns on'off microphone, there is a delay, or when changing track pos, and many others like this. I think I just should advice users not to use DirectSound to get rid of this latency.

Ian @ un4seen

  • Administrator
  • Posts: 20393
Re: BASSWASAPI beta
« Reply #71 on: 21 Jun '10 - 13:41 »
Couldn't you just lower the buffer (BASS_CONFIG_BUFFER) setting? If 50ms is working well with WASAPI output, then you can probably use something similar with DirectSound too, ie. 2 seconds is probably excessively conservative.

Mike Wittman

  • Posts: 20
Re: BASSWASAPI beta
« Reply #72 on: 30 Jul '10 - 15:57 »
Ian;

I was wondering if you could expose the IMMDeviceEnumerator::RegisterEndpointNotificationCallback through the WASAPI driver.

This would be helpful on a lot of points:

1) Respond to a "Default Device" change
1) A soundcard (like USB sound) is plugged in or out; so I could reorder the DeviceID's automatically.
2) For access to the "new" jack sence capabilities of Vista/7

I could do this this by writing "C" code but I prefer to do it in Delphi which poses some complexities w/ COM and Property Stores.

Any thoughts on this ?

Mike W.

Ian @ un4seen

  • Administrator
  • Posts: 20393
Re: BASSWASAPI beta
« Reply #73 on: 30 Jul '10 - 17:54 »
That may be possible to add. The current BASS release (2.4.6) actually already includes it via a currently undocumented CONFIG option, but it is a bit troublesome, so it may be removed in the next release. The trouble is, as you mention, it is COM-based, which makes it awkward to release gracefully (COM stuff can't be accessed in the DLL's DllMain function). BASSWASAPI would have the same issue, so it would probably have to be up to the user to uninitialize it before closing the app. I'll look into it.

Mike Wittman

  • Posts: 20
Re: BASSWASAPI beta
« Reply #74 on: 30 Jul '10 - 18:07 »
I appreciate you having a look-see;

I hate asking questions that appear to "trivialize" the effort involved.  My thinking was that you already had the IMMDeviceEnumerator "hanging around" and could just expose the interface .. similar to the BASS_Init function with the Directsound CLSID "hook".

Was unaware of the BASS_SetConfig option, but that would be interesting as well.