Author Topic: ASIO dont work with HDSPe AIO  (Read 242 times)

udo

  • Posts: 29
ASIO dont work with HDSPe AIO
« on: 17 Jul '17 - 08:49 »
Hi,

We are using the professional audio PCIe card from RME (HDSPe AIO 38-Channel) with the ASIO interface. The problem is, that the bassasio.dll has probably protocol problems with the ASIO interface from the RME card. The bassasio.dll is sending the correct sample rate and buffer size to the RME-card. The first output port is correct to, in my example port 4 (AES digital out).   But we get only playback on the first channel 4 (which is the left channel) and no playback on output 5 (which is right channel). If we select the first channel as 5 we have only playback on the right channel. The sound quality is very bad, because it is playing too slow  and distorted. The RME card is a 192kHz 24 Bit cardůmaybe this is helpful.

I┤m using the original ASIO C-example: contest -c 4 xx.wav. (-c is the only change at contest to set the first output).
The wave is a ripped file with 41000Hz

If i┤m using the same hardware setup with the XMPlayer and the ASIO plugin it works 100% correct with the RME-card.

Here the RME-Card:
http://www.rme-audio.de/en/products/hdspe_aio.php?from=singlemessage&isappinstalled=0%27

Maybe the problem is that this card dont support 32-bit?

We also use M2Tech card, there all works fine.

thanks
« Last Edit: 17 Jul '17 - 16:51 by udo »

Ian @ un4seen

  • Administrator
  • Posts: 20152
Re: ASIO dont work with HDSPe AIO
« Reply #1 on: 17 Jul '17 - 17:56 »
Strange that it would be fine with the XMPlay ASIO plugin but not BASSASIO. Did you set the first output to channel 4 in the XMPlay ASIO plugin's options too?

Please post your modified CONTEST.C source file to have a look at. In the working M2Tech card's case, are you also using your new "-c" option then or is that without it?

udo

  • Posts: 29
Re: ASIO dont work with HDSPe AIO
« Reply #2 on: 17 Jul '17 - 18:18 »
Quote
Did you set the first output to channel 4 in the XMPlay ASIO plugin's options too?
Yes, it was the same hardware, so we had to use output 4 and 5.

The different to M2Tech(another computer) is that there is only output 0 and 1 available and it supports 32-bit.

Quote
In the working M2Tech card's case, are you also using your new "-c" option then or is that without it?
I used the same contest, with and without -c

M2Tech is the hiFaceDAC UAC2: http://www.m2tech.biz/it/hiface_dac.html

Here the modified code:
Code: [Select]
/*
ASIO version of the BASS simple console player
Copyright (c) 1999-2015 Un4seen Developments Ltd.
*/

#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <math.h>
#include "bassasio.h"
#include "bass.h"

// display error messages
void Error(const char *text)
{
printf("Error(%d/%d): %s\n",BASS_ErrorGetCode(),BASS_ASIO_ErrorGetCode(),text);
BASS_ASIO_Free();
BASS_Free();
exit(0);
}

// ASIO function
DWORD CALLBACK AsioProc(BOOL input, DWORD channel, void *buffer, DWORD length, void *user)
{
DWORD c=BASS_ChannelGetData((DWORD)user,buffer,length);
if (c==-1) c=0; // an error, no data
return c;
}

void ListDevices()
{
BASS_ASIO_DEVICEINFO di;
int a;
for (a=0;BASS_ASIO_GetDeviceInfo(a,&di);a++) {
printf("dev %d: %s\n",a,di.name);
}
}

void main(int argc, char **argv)
{
DWORD chan,time;
BOOL ismod;
QWORD pos;
int a,device=0, channel=0;
BASS_CHANNELINFO i;

printf("Simple console mode BASS+ASIO example: MOD/MPx/OGG/WAV player\n"
"--------------------------------------------------------------\n");

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

for (a=1;a<argc;a++) {
if (!strcmp(argv[a],"-l")) {
ListDevices();
return;
}
else if (!strcmp(argv[a], "-d") && a + 1 < argc)
{
device = atoi(argv[++a]);
}
else if (!strcmp(argv[a], "-c") && a + 1 < argc)
{
channel = atoi(argv[++a]);

printf("channel is %u\n", channel);
}
else break;
}
if (a!=argc-1) {
printf("\tusage: contest [-l] [-d #] <file>\n"
"\t-l = list devices\n"
"\t-d = device number\n");
return;
}

// not playing anything via BASS, so don't need an update thread
BASS_SetConfig(BASS_CONFIG_UPDATETHREADS,0);
// setup BASS - "no sound" device
BASS_Init(0,48000,0,0,NULL);

// try streaming the file/url
if ((chan=BASS_StreamCreateFile(FALSE,argv[argc-1],0,0,BASS_SAMPLE_LOOP|BASS_STREAM_DECODE|BASS_SAMPLE_FLOAT))
|| (chan=BASS_StreamCreateURL(argv[argc-1],0,BASS_SAMPLE_LOOP|BASS_STREAM_DECODE|BASS_SAMPLE_FLOAT,0,0))) {
pos=BASS_ChannelGetLength(chan,BASS_POS_BYTE);
if (BASS_StreamGetFilePosition(chan,BASS_FILEPOS_DOWNLOAD)!=-1) {
// streaming from the internet
if (pos!=-1)
printf("streaming internet file [%I64u bytes]",pos);
else
printf("streaming internet file");
} else
printf("streaming file [%I64u bytes]",pos);
ismod=FALSE;
} else {
// try loading the MOD (with looping, sensitive ramping, and calculate the duration)
if (!(chan=BASS_MusicLoad(FALSE,argv[argc-1],0,0,BASS_SAMPLE_LOOP|BASS_STREAM_DECODE|BASS_SAMPLE_FLOAT|BASS_MUSIC_RAMPS|BASS_MUSIC_PRESCAN,0)))
// not a MOD either
Error("Can't play the file");
{ // count channels
float dummy;
for (a=0;BASS_ChannelGetAttribute(chan,BASS_ATTRIB_MUSIC_VOL_CHAN+a,&dummy);a++);
}
printf("playing MOD music \"%s\" [%u chans, %u orders]",
BASS_ChannelGetTags(chan,BASS_TAG_MUSIC_NAME),a,BASS_ChannelGetLength(chan,BASS_POS_MUSIC_ORDER));
pos=BASS_ChannelGetLength(chan,BASS_POS_BYTE);
ismod=TRUE;
}

// display the time length
if (pos!=-1) {
time=(DWORD)BASS_ChannelBytes2Seconds(chan,pos);
printf(" %u:%02u\n",time/60,time%60);
} else // no time length available
printf("\n");

// setup ASIO stuff
if (!BASS_ASIO_Init(device,BASS_ASIO_THREAD))
Error("Can't initialize ASIO device");
BASS_ChannelGetInfo(chan,&i);
BASS_ASIO_ChannelEnable(0,channel,AsioProc,(void*)chan); // enable 1st output channel
for (a=1;a<i.chans;a++)
BASS_ASIO_ChannelJoin(0,a,0); // and join the next channels to it
if (i.chans==1) BASS_ASIO_ChannelEnableMirror(1,0,0); // mirror mono channel to form stereo output
BASS_ASIO_ChannelSetFormat(0,channel,BASS_ASIO_FORMAT_FLOAT); // set the source format (float)
BASS_ASIO_ChannelSetRate(0, channel,i.freq); // set the source rate
BASS_ASIO_SetRate(i.freq); // try to set the device rate too (saves resampling)
if (!BASS_ASIO_Start(0,0)) // start output using default buffer/latency
Error("Can't start ASIO output");

while (!_kbhit() && BASS_ChannelIsActive(chan)) {
// display some stuff and wait a bit
pos=BASS_ChannelGetPosition(chan,BASS_POS_BYTE);
time=BASS_ChannelBytes2Seconds(chan,pos);
printf("pos %09I64u",pos);
if (ismod) {
pos=BASS_ChannelGetPosition(chan,BASS_POS_MUSIC_ORDER);
printf(" (%03u:%03u)",LOWORD(pos),HIWORD(pos));
}
printf(" - %u:%02u - L ",time/60,time%60);
{
DWORD level=BASS_ASIO_ChannelGetLevel(0,channel)*32768; // left channel level
for (a=27204;a>200;a=a*2/3) putchar(level>=a?'*':'-');
putchar(' ');
if (BASS_ASIO_ChannelIsActive(0,1))
level=BASS_ASIO_ChannelGetLevel(0,channel +1)*32768; // right channel level
for (a=210;a<32768;a=a*3/2) putchar(level>=a?'*':'-');
}
printf(" R - cpu %.2f%%  \r",BASS_ASIO_GetCPU());
fflush(stdout);
Sleep(50);
}
printf("                                                                             \r");

{ // wind the frequency and volume down...
float freq=BASS_ASIO_ChannelGetRate(0,channel),f;
for (f=0;f<1;f+=0.04) {
BASS_ASIO_ChannelSetRate(0,channel,freq*(1-f)); // set sample rate
if (f>0.6) BASS_ASIO_ChannelSetVolume(0,-1,pow(10,-5*(f-0.6))); // set volume
Sleep(20);
}
}

BASS_ASIO_Free();
BASS_Free();
}


Ian @ un4seen

  • Administrator
  • Posts: 20152
Re: ASIO dont work with HDSPe AIO
« Reply #3 on: 18 Jul '17 - 18:02 »
Code: [Select]
for (a=1;a<i.chans;a++)
BASS_ASIO_ChannelJoin(0,a,0); // and join the next channels to it
if (i.chans==1) BASS_ASIO_ChannelEnableMirror(1,0,0); // mirror mono channel to form stereo output

I think that code is the cause of the problem. It is still joining the additional channel(s) to the 1st channel, rather than the channel specified with the new "-c" option. It should probably look like this:

Code: [Select]
for (a=1;a<i.chans;a++)
BASS_ASIO_ChannelJoin(0,channel+a,channel); // and join the next channels to it
if (i.chans==1) BASS_ASIO_ChannelEnableMirror(channel+1,0,channel); // mirror mono channel to form stereo output

udo

  • Posts: 29
Re: ASIO dont work with HDSPe AIO
« Reply #4 on: 19 Jul '17 - 09:40 »
Thank you, it works. :)

But now i have another problem.
- play a wav with 44100 samplingrate, all is ok
- play a wav with 96000, its disorted
- play the 96000-wav again, all ok
It means the change to another Samplingrate plays disorted, i need to start it again.
Is there somthing missing at initialisation?
This dont happen with M2Tech and has nothing to do with output-numbers(also with 0,1).

Ian @ un4seen

  • Administrator
  • Posts: 20152
Re: ASIO dont work with HDSPe AIO
« Reply #5 on: 19 Jul '17 - 13:30 »
To narrow down what/where the problem is, does removing the BASS_ASIO_SetRate call prevent the problem? Please also use BASS_ASIO_SetNotify to enable notifications, and see if any notifications are received.

Code: [Select]
void CALLBACK AsioNotify(DWORD notify, void *user)
{
printf("\nnotify(%d)\n", notify);
}

...
// setup ASIO stuff
if (!BASS_ASIO_Init(device,BASS_ASIO_THREAD))
Error("Can't initialize ASIO device");
BASS_ASIO_SetNotify(AsioNotify, NULL);
...

udo

  • Posts: 29
Re: ASIO dont work with HDSPe AIO
« Reply #6 on: 19 Jul '17 - 15:32 »
To narrow down what/where the problem is, does removing the BASS_ASIO_SetRate call prevent the problem?
If i dont call BASS_ASIO_SetRate(i.freq) its not disorted. But this would not be right, the driver shows a rate which was setted some time before.

Quote
Please also use BASS_ASIO_SetNotify to enable notifications, and see if any notifications are received.
I used this but there is never a console-output, Callback not called.
« Last Edit: 19 Jul '17 - 15:36 by udo »

Ian @ un4seen

  • Administrator
  • Posts: 20152
Re: ASIO dont work with HDSPe AIO
« Reply #7 on: 19 Jul '17 - 16:50 »
To narrow down what/where the problem is, does removing the BASS_ASIO_SetRate call prevent the problem?
If i dont call BASS_ASIO_SetRate(i.freq) its not disorted. But this would not be right, the driver shows a rate which was setted some time before.

BASS_ASIO_ChannelSetRate is also called, so BASSASIO will convert the sample data to the device's rate if necessary.

If you put back the BASS_ASIO_SetRate call, is it returning TRUE? If so, perhaps it's that the device takes a little time to change its rate. What happens if you add a delay between the BASS_ASIO_SetRate and BASS_ASIO_Start calls?

udo

  • Posts: 29
Re: ASIO dont work with HDSPe AIO
« Reply #8 on: 19 Jul '17 - 19:19 »
Quote
If you put back the BASS_ASIO_SetRate call, is it returning TRUE?
It always return TRUE. The driver shows the right rate.

Quote
If so, perhaps it's that the device takes a little time to change its rate. What happens if you add a delay between the BASS_ASIO_SetRate and BASS_ASIO_Start calls?
I added Sleep(1000) after BASS_ASIO_SetRate(i.freq) but still the same Problem.

BTW, XMPlayer plays all exact at same hardware.
Is it ok that the bassasio.dll is 2 years older than xmp-asio.dll?

Are you able to reproduce this? We can send you a RME-card if necessary.
« Last Edit: 20 Jul '17 - 08:06 by udo »

Ian @ un4seen

  • Administrator
  • Posts: 20152
Re: ASIO dont work with HDSPe AIO
« Reply #9 on: 20 Jul '17 - 17:46 »
An updated BASSASIO build that you could try is available here:

   www.un4seen.com/stuff/bassasio.zip

BASSASIO and the XMPlay ASIO plugin set the device's rate in exactly the same way though, so it's strange that one would work and not the other. I wonder if the problem is related to the thread that's hosting the ASIO driver; some drivers can be fussy about that. What happens if you try to run similar code in a GUI app rather than a console app, and remove the BASS_ASIO_THREAD flag from the BASS_ASIO_Init call? You could use the DSPTEST.C example as a starting point and modify it something like this:

Code: [Select]
...
// only playing stereo, so may as well set that up now...
BASS_ASIO_ChannelEnable(0,4,&AsioProc,0); // enable output channel 4
BASS_ASIO_ChannelJoin(0,5,4); // and join channel 5 to it
...

udo

  • Posts: 29
Re: ASIO dont work with HDSPe AIO
« Reply #10 on: 20 Jul '17 - 19:03 »
OK, i tried the new bassasio.dll but it doesnt help.

Could it be that the bass.dll is the reason, since BASS_ChannelGetData((DWORD)user,buffer,length) will provide the data in CALLBACK AsioProc?
BTW, the RME-driver always shows the right samplingrate.

Quote
What happens if you try to run similar code in a GUI app rather than a console app, and remove the BASS_ASIO_THREAD flag from the BASS_ASIO_Init call?
I guess that sample is already without BASS_ASIO_THREAD: BASS_ASIO_Init(0,0).
There is the same problem but a second start of the same file dont help like in contest.

Strange is that i can change 44100 to 48000 and reverse without problems but not at higher rates.
Also i tried to call BASS_ASIO_ChannelSetRate and BASS_ASIO_SetRate twice with a delay, but no success.
« Last Edit: 21 Jul '17 - 07:33 by udo »

Ian @ un4seen

  • Administrator
  • Posts: 20152
Re: ASIO dont work with HDSPe AIO
« Reply #11 on: 21 Jul '17 - 13:12 »
I have an idea what may be happening. Please try calling BASS_ASIO_GetInfo before and after BASS_ASIO_SetRate, and check if the bufmin/max/pref/gran values have changed. If bufpref has changed, try using the new value in the BASS_ASIO_Start call.

udo

  • Posts: 29
Re: ASIO dont work with HDSPe AIO
« Reply #12 on: 21 Jul '17 - 15:34 »
Super! You had the right idea  :) It works perfect!
Thank you!

I thought that BASS_ASIO_Start(0,0) already uses the prefered buffer?
But whats the different to a M2tech-card and why a second start with the same file was ok?
« Last Edit: 21 Jul '17 - 16:13 by udo »

Ian @ un4seen

  • Administrator
  • Posts: 20152
Re: ASIO dont work with HDSPe AIO
« Reply #13 on: 21 Jul '17 - 17:38 »
Great to hear that worked!

When BASS_ASIO_Start is called with buffer=0, it will leave the buffer length as it is, eg. as set in a previous BASS_ASIO_Start call. Currently, the buffer length starts out as the preferred length at the time of the BASS_ASIO_Init call. In your RME card's case, it sounds like the preferred buffer length may change when the sample rate does. For convenience, here's an update that adds the option of using buffer=-1 in a BASS_ASIO_Start call to request the preferred buffer length:

   www.un4seen.com/stuff/bassasio.zip

It also won't set the initial buffer length until the first BASS_ASIO_Start call. So if you call BASS_ASIO_SetRate before that, the preferred buffer length for the new rate should get used. This should allow your code above to work properly without modification.

udo

  • Posts: 29
Re: ASIO dont work with HDSPe AIO
« Reply #14 on: 24 Jul '17 - 10:17 »
Thank you, also the new dll works.
At RME-Driver it was also important to set a bigger buffer to prevent some interference noise.