25 May '13 - 17:31 *
Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length
 
   Home   Help Search Login Register  
Pages: 1 ... 8 9 [10] 11 12
  Reply  |  Print  
Author Topic: BASSWASAPI beta  (Read 71777 times)
Wishmaster
Posts: 124


« Reply #180 on: 4 Nov '11 - 01:49 »
Reply with quoteQuote

Hi. Thank you for your reply. 

Maybe it just me but, If I want to initialize all available devices in a loop
Would it not  be better if WASABIPROC were exported to another function
Something like with BASS_ChannelSetDSP()
I do not even know whether it's possible or not

Var  DevInfo : BASS_WASAPI_DEVICEINFO;

 Device:= 0;
while (BASS_WASAPI_GetDeviceInfo(Device,  DevInfo)  <>False) do
   begin
      if not BASS_WASAPI_Init(…) then
       // error

     Inc(Device)
   End;

   BASS_WASAPI_SetDevice();
   BASS_WASAPI_SetProc(device :  Integer; WASAPIPROC *proc,);
   BASS_WASAPI_Start();

Thx.
Logged
Ian @ un4seen
Administrator
Posts: 15276


« Reply #181 on: 4 Nov '11 - 16:24 »
Reply with quoteQuote

Is there a particular reason that you want to initialize all devices?

If you would like to be able to change the WASAPIPROC function on the fly, perhaps you could implement a wrapper function for that, ie. you pass the wrapper function to BASS_WASAPI_Init and the wrapper calls the function that you want to do the processing. You could use a single wrapper function to handle multiple devices by making use of BASS_WASAPI_GetDevice in it (to check which device the callback is dealing with), or you could use the "user" parameter to identify the device.
Logged
Wishmaster
Posts: 124


« Reply #182 on: 15 Nov '11 - 07:49 »
Reply with quoteQuote

hi

I'm writing a universal Audio Component (Delphi), and I´m  try to make it as easy to use as possible!
The end user must only decide which system he wants to use (WASAPI, ASIO, ...) during initialization

I have the same function´s  for all systems!

Example
function Set_Device(Device : DWORD ) : Bool;
begin
  if DS then
   Result:=BASS_SetDevice(Device);
  if ASIO then
   Result:= BASS_ASIO_SetDevice(Device);
  if WASAPI then
   Result:= BASS_WASAPI_SetDevice(Device);
end;
I mean that's the reason for the BASS_WASAPI_SetDevice function so that you can simultaneously use multiple devices right?


I have another question. BASS_ChannelPause does not work if I use WASAPI. So what is the best way
to pause or stop  a specific channel.


Thx.
Logged
Ian @ un4seen
Administrator
Posts: 15276


« Reply #183 on: 15 Nov '11 - 15:02 »
Reply with quoteQuote

BASS_ChannelPause only applies to BASS playback, ie. when BASS_ChannelPlay is used. To pause a "decoding channel" (created with the BASS_STREAM_DECODE flag), you can simply stop calling BASS_ChannelGetData on it, eg. in the WASAPIPROC function. You can also use BASS_WASAPI_Stop to pause the device, and BASS_WASAPI_Start to resume it.
Logged
Ian @ un4seen
Administrator
Posts: 15276


« Reply #184 on: 20 Dec '11 - 17:49 »
Reply with quoteQuote

A little update is up (see the 1st post), which allows dynamic loading of BASSWASAPI, or rather dynamic unloading. Dynamically unloading BASSWASAPI could result in a crash due to there being unreleased device notification COM stuff, but that can now be avoided by calling BASS_WASAPI_SetNotify with proc=NULL prior to calling FreeLibrary (to unload BASSWASAPI).
Logged
Silhwan
Posts: 81


« Reply #185 on: 7 Feb '12 - 08:46 »
Reply with quoteQuote

My last post - regarding the required modification of a data structure for Delphi XE2 at 64bit mode - is disappeared.
The non-Delphi users may not encounter this problem by automatic 64bit alignment of address (or pointer) fields of data structure by compiler.
But I had spent a few days to find out the reason of fatal error by mis-alignment of data structure at run time.
 
Anyway I have found another problem of a WASAPI function - BASS_WASAPI_SetVolume at shared mode.
I think that it is preferable that BASS_WASAPI_SetVolume should take effect only on its own session (= the program which calls BASS_WASAPI_SetVolume) at shared mode.
But BASS_WASAPI_SetVolume takes effect on whole system (= end point device such as Speaker or Headphone.)

I made a component - TAudioVolume - which can control end point volume or session volume seperately, so Delphi users can use it to escape this problem.
Logged
Ian @ un4seen
Administrator
Posts: 15276


« Reply #186 on: 7 Feb '12 - 17:23 »
Reply with quoteQuote

My last post - regarding the required modification of a data structure for Delphi XE2 at 64bit mode - is disappeared.
The non-Delphi users may not encounter this problem by automatic 64bit alignment of address (or pointer) fields of data structure by compiler.
But I had spent a few days to find out the reason of fatal error by mis-alignment of data structure at run time.

Are you referring to this post?

   www.un4seen.com/forum/?topic=9038.msg93623#msg93623

That was indeed a structure alignment issue. Unless told otherwise (eg. via a "pragma pack"), I think pretty much all C/C++ compilers will align a 64-bit pointer to an 8-byte boundary, which means there will be 4 bytes of padding inserted between the "ctype" and "name" members of the BASS_PLUGINFORM structure on a 64-bit platform.

Anyway I have found another problem of a WASAPI function - BASS_WASAPI_SetVolume at shared mode.
I think that it is preferable that BASS_WASAPI_SetVolume should take effect only on its own session (= the program which calls BASS_WASAPI_SetVolume) at shared mode.
But BASS_WASAPI_SetVolume takes effect on whole system (= end point device such as Speaker or Headphone.)

Yes, the BASSWASAPI volume functions (eg. BASS_WASAPI_SetVolume/Mute) do indeed deal with the device/endpoint volume level rather than the session. I will look into adding a session volume control option.
Logged
Silhwan
Posts: 81


« Reply #187 on: 7 Feb '12 - 22:22 »
Reply with quoteQuote

Oops ! 
Sorry, I totally forgot the correct post where I had posted.

And I have found another problem of a WASAPI function - BASS_WASAPI_SetMute.
The function BASS_WASAPI_SetMute does not operate at my system (Windows 7 32bit, shared mode).
I have also experenced this problem at debugging my TAudioVolume component.
The mute of end point device requires a tricky code as follows,
   if mute then i := 0 else i := 1; // mute: Bool, i: integer
      AudioEndpointVolume.SetMute(BOOL(i), @GUID_TAudioVolume);
Logged
Ian @ un4seen
Administrator
Posts: 15276


« Reply #188 on: 8 Feb '12 - 17:13 »
Reply with quoteQuote

Another Delphi user (off forum) encountered that same problem recently. The reason for it is that Delphi's "true" is -1, while WASAPI expects "true" to be 1. I will do something for that too, at the same time as the session volume stuff.
Logged
yps
Posts: 107


« Reply #189 on: 9 Feb '12 - 12:58 »
Reply with quoteQuote

I have added WASAPI support to the latest release of my software, and it works very well. Great job!

However, some people experience the infamous BASS_ERROR_UNKNOWN on BASS_WASAPI_Init. All of them use one of the M-Audio Delta cards. The demo applications from the BASSWASAPI package seem to work fine though, so there must be something wrong in the way the cards are initialized in my code.

Here's how the init section looks like:

      // Determine freq, chans, and flags according to configuration
      flags := BASS_WASAPI_AUTOFORMAT;
      if fMode = wmShared then begin
        freq := 0;
        chans := 0;
      end
      else begin
        flags := flags or BASS_WASAPI_EXCLUSIVE;
        freq := fSampleRate;
        chans := fChannels;
      end;

      // Initialize the device
      CheckBassCall('BASS_WASAPI_Init',
                    BASS_WASAPI_Init(fDeviceIndex, freq, chans, flags,
                                     fBufferSize/1000, fUpdatePeriod/1000,
                                     PlaybackWASAPIProc, self));

Any obvious mistakes here?

Is there a debug version available that could help to track down the exact reason for the unknown error?

By the way, are there any special requirements for the way COM was initialized for the calling thread? Or will a plain CoInitialize do?
Logged
Ian @ un4seen
Administrator
Posts: 15276


« Reply #190 on: 9 Feb '12 - 13:46 »
Reply with quoteQuote

Is there a debug version available that could help to track down the exact reason for the unknown error?

Yep, I'll send you a debug version to get more info. BASS_ERROR_UNKNOWN will be the result when device initialization fails for some reason that BASSWASAPI doesn't specifically check for, eg. it isn't because the device is busy or that the sample format is unsupported.

By the way, are there any special requirements for the way COM was initialized for the calling thread? Or will a plain CoInitialize do?

I think that will work, but CoInitializeEx with COINIT_MULTITHREADED may be better. If COM hasn't already been initialized, then BASSWASAPI will do that itself.
Logged
yps
Posts: 107


« Reply #191 on: 11 Feb '12 - 07:51 »
Reply with quoteQuote

With the help of a debug version Ian sent me, it turned out that the M-Audio driver expects COM to be initialized, which wasn't the case for the background thread from which BASS_WASAPI_Init was called. A simple call to CoInitializeEx just before BASS_WASAPI_Init solved the problem.

Thank you again, Ian, excellent support!
Logged
Ian @ un4seen
Administrator
Posts: 15276


« Reply #192 on: 13 Feb '12 - 16:01 »
Reply with quoteQuote

An update is now available in the 1st post. It adds a BASS_WASAPI_SESSIONVOL flag to have the volume related functions deal with the session volume rather than the device/endpoint volume. BASS_WASAPI_SetMute has also been updated to translate any non-0 "mute" value to 1, to get around the Delphi "true" value issue.
Logged
WACKA
Posts: 14


« Reply #193 on: 14 Feb '12 - 11:27 »
Reply with quoteQuote

Hi Ian,

I have a small issue with basswasapi and bit depth.

When using WASAPI, what i see on my dcs gear is that all material is up sampled to 24 bit, but the frequency stays true to the origial  material..
so all cd rips seem to play at 24 bit / 44.1khz with wasapi turned on.

Is there any way/flag to make sure it will output at its source depth?

N.b. I am using bass_mix for outputting the streams:

...
 BassMix.BASS_Mixer_StreamCreate(this.k, this.l, BASSFlag.BASS_SAMPLE_FLOAT | BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_MIXER_RESUME);
...
BassMix.BASS_Mixer_StreamAddChannel(stream, channel, streamflags);

Best regards,

Conor


Logged
radio42
Posts: 4012


« Reply #194 on: 14 Feb '12 - 13:03 »
Reply with quoteQuote

That depends if you are using WASAPI in Shared or Exclusive mode.

In shared mode WASAPI must use the resolution as defined in your windows sound control panel and each application will use these settings!
This is true for the sample rate as well as the bit depth.

In exclusive mode you have more control over it and might define this yourself. However,
for convenience, devices are always initialized (by BASSWASAPI) to use their highest sample resolution and that is then converted to 32-bit floating-point, so that WASAPIPROC callback functions and the BASS_WASAPI_PutData and BASS_WASAPI_GetData functions are always dealing with the same sample format.

As such you don't have much control over the effective bit depth being used.

In any case, WASAPI in general needs a constant format once initialized.
Logged
Ian @ un4seen
Administrator
Posts: 15276


« Reply #195 on: 14 Feb '12 - 14:04 »
Reply with quoteQuote

By default, BASSWASAPI will use the highest resolution/bitdepth supported by the driver in exclusive mode, but it is possible to restrict that via the HIWORD of the BASS_WASAPI_Init "flags" parameter. For example, to limit it to 16-bit...

BASS_WASAPI_Init(-1, 44100, 2, MAKELONG(BASS_WASAPI_EXCLUSIVE, BASS_WASAPI_FORMAT_16BIT), 0.5, 0, MyWasapiProc, NULL);
Logged
WACKA
Posts: 14


« Reply #196 on: 14 Feb '12 - 15:08 »
Reply with quoteQuote

Thanks for the reply guys,
both are really useful and just what I need
Logged
Silhwan
Posts: 81


« Reply #197 on: 18 Feb '12 - 01:56 »
Reply with quoteQuote

The WASAPIAPI does not have a function for smooth change of volume level.
I tried several times to make the function with BASS_ChannelSlideAttribute applied to mixer channel but failed.
(Click noise at the end of slide operation for mute/unmute)
So, I have made this unit and posted for Delphi users.

// Unit WasapiVolumeSlide
//
//  This unit slides the volume level of WASAPI, which is equivalent to BASS_ChannelSlideAttribute
//   with attribute BASS_ATTRIB_VOL.
//  This unit uses my TAudioVolume component because modified version which uses BASS_WASAPI_Set... functions
//   does not operate as expected.
//  You can get TAudioVolume component at following url,
//    http://www.torry.net/quicksearchd.php?String=TAudioVolume&Title=Yes
//
//   written by Silhwan Hyun  (hyunsh@hanafos.com)


unit WasapiVolumeSlide;

interface

uses Windows, Classes, Messages, {basswasapi,} AudioVolume;

const
// Flags
  fSlideForMute   = 1;  // execute extra sentences for mute
  fSlideForUnmute = 2;  // execute extra sentences for unmute
  fKnotifyAtEnd   = 4;  // post message at the end of a slide

type
  TWasapiSlideThread = class(TThread)
  private
    { Private declarations }
    ThreadTimer : HWND;

    FFlags       : DWORD;
    FMsgReceiver : hwnd;
    FSlideEndMsg : hwnd;
    FAudioVolume : TAudioVolume;
    FInitVolume  : single;
    FFinalVolume : single;
    FStepValue   : single;
    FMidVolume   : single;
    procedure DoOnTimer;

  protected
    procedure Execute; override;

  public
    constructor Create(AudioVolume: TAudioVolume; PeriodMS: DWORD; FinalVol: single;
                       MsgReceiver: hwnd; SlideEndMsg, Flags: DWORD);
    destructor  Destroy; override;

  end;

// The main program should create an instance of TAudioVolume prior to calling this procedure.
//   Mute : true on mute, false on unmute
//   AudioVolume : an instance of TAudioVolume
//   PeriodMS : the sliding period in milliseconds
//   MsgReceiver : handle to the message handler of main program
//   SlideEndMsg : message used for posting message at the end of a slide
  procedure WasapiSmoothMute(Mute: boolean; AudioVolume : TAudioVolume; PeriodMS: DWORD;
         MsgReceiver: hwnd; SlideEndMsg: DWORD);

implementation

const
  MaxVolume = 1.0;  // Volume range : 0 ~ 1.0
  StepMs = 10;      // Step up/down interval = 10ms

constructor TWasapiSlideThread.Create(AudioVolume: TAudioVolume; PeriodMS: DWORD; FinalVol: single;
                                          MsgReceiver: hwnd; SlideEndMsg, Flags: DWORD);
begin
  FreeOnTerminate := true;
  if FinalVol > MaxVolume then
    FFinalVolume := MaxVolume
  else if FFinalVolume < 0 then
    FFinalVolume := 0
  else
    FFinalVolume := FinalVol;

  ThreadTimer := CreateWaitableTimer(nil, false, 'ThreadTimer');
  if ThreadTimer <> 0 then
  begin
    FAudioVolume := AudioVolume;
    FFlags := Flags;
    if (FFlags and fSlideForUnmute) = fSlideForUnmute then
    begin
      FAudioVolume.SetVolume(0);     // BASS_WASAPI_SetVolume(true, 0);
      FAudioVolume.SetMute(False);   // BASS_WASAPI_SetMute(false);
    end;

    FInitVolume := FAudioVolume.GetVolume;  // FInitVolume := BASS_WASAPI_GetVolume(true);
    FStepValue := (FFinalVolume - FInitVolume) / (PeriodMS / StepMS);
    FMidVolume := FInitVolume;
    FMsgReceiver := MsgReceiver;
    FSlideEndMsg := SlideEndMsg;
  end;

  inherited Create(false);  // starts on creation
end;

destructor TWasapiSlideThread.Destroy;
begin

  inherited Destroy;
end;

procedure TWasapiSlideThread.Execute;
const
  _SECOND = 10000000;   // 100 nanosecond intervals
var
  qwDueTime: int64;
  liDueTime: _LARGE_INTEGER;
begin
  if ThreadTimer = 0 then
  begin
    if (FFlags and fKnotifyAtEnd) = fKnotifyAtEnd then
      PostMessage(FMsgReceiver, FSlideEndMsg, 0{=fail}, 0);
    exit;
  end;

 // Create a negative 64-bit integer that will be used to
 // signal the timer 1/8 seconds from now.
   qwDueTime := -1 * (_SECOND div 8);

 // Copy the relative time into a LARGE_INTEGER.
  liDueTime.LowPart  := DWORD(qwDueTime and $FFFFFFFF);
  liDueTime.HighPart := longint(qwDueTime shr 32);
  if SetWaitableTimer(ThreadTimer, // handle to a timer object
                      TLargeInteger(liDueTime), // when timer will become signaled
                      StepMS, // periodic timer interval
                      nil,    // pointer to the completion routine
                      nil,    // data passed to the completion routine
                      false{flag for resume state}) then

     repeat
       if WaitForSingleObject(ThreadTimer, 1000{1sec}) = WAIT_OBJECT_0 then
         DoOnTimer
       else begin
         if (FFlags and fKnotifyAtEnd) = fKnotifyAtEnd then
           PostMessage(FMsgReceiver, FSlideEndMsg, 0{=fail}, 0);

         Terminate;
       end;
     until Terminated;
end;

procedure TWasapiSlideThread.DoOnTimer;
begin
  if FInitVolume = FFinalVolume then
    FMidVolume := FFinalVolume
  else
    FMidVolume := FMidVolume + FStepValue;
  if FStepValue > 0 then
  begin
    if FMidVolume > FFinalVolume then
      FMidVolume := FFinalVolume
  end else
    if FMidVolume < FFinalVolume then
      FMidVolume := FFinalVolume;

  FAudioVolume.SetVolume(FMidVolume); // BASS_WASAPI_SetVolume(true, FMidVolume);

  if FMidVolume = FFinalVolume then
  begin
    CancelWaitableTimer(ThreadTimer);
    CloseHandle (ThreadTimer);
    if (FFlags and fSlideForMute) = fSlideForMute then
    begin
      FAudioVolume.SetMute(true);  // BASS_WASAPI_SetMute(true);
      FAudioVolume.SetVolume(FInitVolume); // BASS_WASAPI_SetVolume(true, FInitVolume);
    end;
    if (FFlags and fKnotifyAtEnd) = fKnotifyAtEnd then
      PostMessage(FMsgReceiver, FSlideEndMsg, 1{=success}, 0);

    Terminate;
  end;
end;

procedure WasapiSmoothMute(Mute: boolean; AudioVolume: TAudioVolume; PeriodMS: DWORD;
       MsgReceiver: hwnd; SlideEndMsg: DWORD);
var
  WasapiSlideThread: TWasapiSlideThread;
begin
  if Mute = AudioVolume.IsMuted then
    exit;

  if Mute then
    WasapiSlideThread := TWasapiSlideThread.Create(AudioVolume, PeriodMS, 0,
                                         MsgReceiver, SlideEndMsg, fSlideForMute or fKnotifyAtEnd)
  else
    WasapiSlideThread := TWasapiSlideThread.Create(AudioVolume, PeriodMS, AudioVolume.GetVolume,
                                         MsgReceiver, SlideEndMsg, fSlideForUnmute or fKnotifyAtEnd);
end;

end.
« Last Edit: 18 Feb '12 - 02:18 by Silhwan » Logged
Subbu
Posts: 40


« Reply #198 on: 20 Feb '12 - 05:32 »
Reply with quoteQuote

Hi Ian,
I want to use BassWasApi in C# pls help me how can i do it?
Logged
radio42
Posts: 4012


« Reply #199 on: 20 Feb '12 - 09:00 »
Reply with quoteQuote

Have you taken a look to the BASS.NET documentation - it contains various Wasapi samples?
What are you exactly looking for?
Logged
Pages: 1 ... 8 9 [10] 11 12
  Reply  |  Print  
 
Jump to:  

Powered by SMF 1.1.18 | SMF © 2013, Simple Machines