Author Topic: BASSASIO BASS_ERROR_UNKNOWN  (Read 888 times)

3delite

  • Posts: 932
BASSASIO BASS_ERROR_UNKNOWN
« on: 11 Jan '15 - 15:33 »
Hi!

Working on native DSD playback and I have a problem with BASSASIO.
The OS is Win7 64bit and a Sound Blaster Z card with it's official ASIO driver.

The problem is that it seems that if ASIO is initialized once and then if I want to initialize it again with different parameters then BASS_ASIO_Start() fails and the error code is BASS_ERROR_UNKNOWN. If I try to initialize it again with the same parameters again then it succeeds.

I need to switch format to DSD mode and then back to normal mode, depending on the audio file to play.
On program startup ASIO is initialized to 96000/32bit float/4 channels, then to play a test MP3 file I free the existing ASIO device and try to init it again for the MP3, 44100/16bit/2 channels. It fails, then I call this second init function again, then it succeeds.
If I exit the app. and start it again, then the init fails, calling the init again it's successful, so the problem is persistent across program exit and startup so it seems it's a driver issue.

Right now in my app. if the init fails, I call it again and this seems working fine, but this is not so nice.

Here are the 2 init functions (the first is for the global mixer channel, the second is for actual file):

Code: [Select]
function ASIOPlay(Silent: Boolean): Boolean;
var
    ASIOInfo: BASS_ASIO_INFO;
    i: Integer;
    ChanInfo: BASS_CHANNELINFO;
    ASIOChanInfo: BASS_ASIO_CHANNELINFO;
    Volume: Float;
    ActiveChannels: Integer;
begin
    Result := False;
    try
        BASS_ASIO_SetDevice(ASIOPlaybackDevice);
        BASS_ASIO_Free;
        //* Init ASIO device
        if NOT BASS_ASIO_Init(ASIOPlaybackDevice, BASS_ASIO_THREAD) then begin
            Settingswindow.EditASIOStatus.Text := 'ERROR: ' + SettingsWindow.ComboBoxASIO.Text;
            Settingswindow.EditASIOStatus.Hint := Settingswindow.EditASIOStatus.Text;
            Log('Error: Can''t initialize selected ASIO output device: ' + SettingsWindow.ComboBoxASIO.Text, False);
            if NOT Silent then begin
                Showmessage('Error: Can''t initialize selected ASIO output device: ' + SettingsWindow.ComboBoxASIO.Text);
            end;
        end else begin
            //BASSLatency := 0;
            BASS_ASIO_GetInfo(ASIOInfo);
            Log('BASS successfully initialized ASIO output device: ' + ASIOInfo.Name, False);
            Settingswindow.EditASIOStatus.Text := 'OK: ' + ASIOInfo.Name;
            Settingswindow.EditASIOStatus.Hint := Settingswindow.EditASIOStatus.Text;
            MainForm.LabelStatus2.Caption := STR_Ready;
        end;
        ActiveChannels := 0;
        if NOT BASS_ASIO_Stop then begin
            //Log('Error: BASS_ASIO_Stop', True);
        end;
        if NOT BASS_ASIO_SetDSD(False) then begin
            Log('Error: BASS_ChannelGetInfo(), code: ' + IntToStr(BASS_ASIO_ErrorGetCode), True);
            Exit;
        end;
        if NOT BASS_ChannelGetInfo(MainMixer, ChanInfo) then begin
            Log('Error: BASS_ChannelGetInfo(), code: ' + IntToStr(BASS_ASIO_ErrorGetCode), True);
            Exit;
        end;
        if NOT BASS_ASIO_ChannelEnable(False, 0, @ASIOProc, Pointer(MainMixer)) then begin
            Log('Error: BASS_ASIO_ChannelEnable(), code: ' + IntToStr(BASS_ASIO_ErrorGetCode), True);
            Exit;
        end else begin
            Inc(ActiveChannels);
        end;
        for i := 1 to ChanInfo.chans - 1 do begin
            if NOT BASS_ASIO_ChannelJoin(False, i, 0) then begin
                Log('Error: BASS_ASIO_ChannelJoin: ' + IntToStr(i), True);
            end else begin
                Inc(ActiveChannels);
            end;
            if SAMPLE_FLOAT then begin
                if NOT BASS_ASIO_ChannelSetFormat(False, i - 1, BASS_ASIO_FORMAT_FLOAT) then begin
                    Log('Error: BASS_ASIO_ChannelSetFormat(BASS_ASIO_FORMAT_FLOAT), code: ' + IntToStr(BASS_ASIO_ErrorGetCode), True);
                    Exit;
                end;
            end else begin
                if NOT BASS_ASIO_ChannelSetFormat(False, i - 1, BASS_ASIO_FORMAT_16BIT) then begin
                    Log('Error: BASS_ASIO_ChannelSetFormat(BASS_ASIO_FORMAT_16BIT), code: ' + IntToStr(BASS_ASIO_ErrorGetCode), True);
                    Exit;
                end;
            end;
            if NOT BASS_ASIO_ChannelSetRate(False, i - 1, ChanInfo.freq) then begin
                Log('Error: BASS_ASIO_ChannelSetRate(' + IntToStr(ChanInfo.freq) + '), code: ' + IntToStr(BASS_ASIO_ErrorGetCode), True);
                Exit;
            end;
        end;
        SettingsWindow.LabelASIOSpeakers.Caption := IntToStr(ActiveChannels) + ' channels';
        // try to set the device rate too (saves resampling)
        if NOT BASS_ASIO_SetRate(ChanInfo.freq) then begin
            Log('Error: BASS_ASIO_SetRate(' + IntToStr(ChanInfo.freq) + '), code: ' + IntToStr(BASS_ASIO_ErrorGetCode), True);
            Exit;
        end else begin
            SettingsWindow.LabelASIOSampleRate.Caption := IntToStr(Trunc(BASS_ASIO_GetRate)) + ' Hz';
        end;
        if NOT BASS_ASIO_Start(0, 0) then begin
            Log('Error: Can''t start ASIO output, code: ' + IntToStr(BASS_ASIO_ErrorGetCode), False); //* Here I get the BASS_ERROR_UNKNOWN error
            SettingsWindow.EditASIOStatus.Text := 'Error: Can''t start ASIO output, code: ' + IntToStr(BASS_ASIO_ErrorGetCode);
            if NOT Silent then begin
                Showmessage('Error: Can''t start ASIO output, code: ' + IntToStr(BASS_ASIO_ErrorGetCode));
            end;
        end else begin
            ASIOIsInDSDMode := False;
            Result := True;
        end;
        BASS_ASIO_ChannelSetVolume(False, - 1, (100 - MainForm.TrackBarDigVolumeR.Position) / 100);
        SettingsWindow.LabelASIOLatency.Caption := IntToStr(BASS_ASIO_GetLatency(False)) + ' samples';
        case BASS_ASIO_ChannelGetFormat(False, 0) of
            BASS_ASIO_FORMAT_16BIT: SettingsWindow.LabelASIODataFormat.Caption := '16-bit integer';
            BASS_ASIO_FORMAT_24BIT: SettingsWindow.LabelASIODataFormat.Caption := '24-bit integer';
            BASS_ASIO_FORMAT_32BIT: SettingsWindow.LabelASIODataFormat.Caption := '32-bit integer';
            BASS_ASIO_FORMAT_FLOAT: SettingsWindow.LabelASIODataFormat.Caption := '32-bit floating-point';
        end;
    finally
        if NOT Result then begin
            BASS_ASIO_Free;
        end;
    end;
end;

Code: [Select]
function PlayDSDThroughASIO(Index: Integer): Boolean;
var
    i: Integer;
    ChanInfo: BASS_CHANNELINFO;
    Rate: Single;
begin
    Result := False;
    try
        BASS_ASIO_SetDevice(DSDASIOPlaybackDevice);
        if NOT BASS_ASIO_Stop then begin
            //Log('Error: BASS_ASIO_Stop(), code: ' + IntToStr(BASS_ASIO_ErrorGetCode), True);
        end;
        BASS_ASIO_Free;
        if NOT BASS_ASIO_Init(DSDASIOPlaybackDevice, BASS_ASIO_THREAD) then begin
            Log('Error: BASS_ASIO_Init(), code: ' + IntToStr(BASS_ASIO_ErrorGetCode), False);
            Exit;
        end;
        //if NOT BASS_ASIO_SetDSD(True) then begin // switch the ASIO device to DSD mode
        //    Log('Error: BASS_ASIO_SetDSD(True)', False);
        //end;
        BASS_ChannelGetInfo(Streams.Index[Index].Channel, ChanInfo); // get the sample format (for channel count)
        //BASS_ChannelGetAttribute(Streams.Index[Index].Channel, BASS_ATTRIB_DSD_RATE, Rate); // get the DSD rate
        //if NOT BASS_ASIO_SetRate(Rate) then begin // set the device to that rate
        //    Log('Error: BASS_ASIO_SetRate(' + FloatToStr(Rate) + '), code: ' + IntToStr(BASS_ASIO_ErrorGetCode), False);
        //end;
        if NOT BASS_ASIO_SetRate(ChanInfo.freq) then begin
            Log('Error: BASS_ASIO_SetRate(' + IntToStr(ChanInfo.freq) + '), code: ' + IntToStr(BASS_ASIO_ErrorGetCode), False);
            Exit;
        end;

        if NOT BASS_ASIO_ChannelEnable(False, 0, @DSDASIOProc, Pointer(Streams.Index[Index].Channel)) then begin
            Log('Error: BASS_ASIO_ChannelEnable(), code: ' + IntToStr(BASS_ASIO_ErrorGetCode), False);
            Exit;
        end;
        DSDThroughASIOChannel := Streams.Index[Index].Channel;
        for i := 1 to ChanInfo.chans - 1 do begin
            if NOT BASS_ASIO_ChannelJoin(False, i, 0) then begin
                Log('Error: BASS_ASIO_ChannelJoin(' + IntToStr(i) + '), code: ' + IntToStr(BASS_ASIO_ErrorGetCode), True);
                Exit;
            end else begin

                if NOT BASS_ASIO_ChannelSetFormat(False, i - 1, BASS_ASIO_FORMAT_16BIT) then begin
                    Log('Error: BASS_ASIO_ChannelSetFormat(BASS_ASIO_FORMAT_16BIT), code: ' + IntToStr(BASS_ASIO_ErrorGetCode), False);
                end;

            end;
        end;
        //if NOT BASS_ASIO_ChannelSetFormat(False, 0, BASS_ASIO_FORMAT_DSD_MSB) then begin // set the data format (DSD with MSB 1st)
        //    Log('Error: BASS_ASIO_ChannelSetFormat(BASS_ASIO_FORMAT_DSD_MSB), code: ' + IntToStr(BASS_ASIO_ErrorGetCode), False);
        //    Exit;
        //end;
        if NOT BASS_ASIO_Start(0, 0) then begin
            Log('Error: Can''t start DSD ASIO output, code: ' + IntToStr(BASS_ASIO_ErrorGetCode), False); //* Here I get the BASS_ERROR_UNKNOWN error
            Exit;
        end else begin
            Streams.Index[Index].Playing := plPlaying;
            Log('Successfully started DSD ASIO output for stream: ' + Streams.Index[Index].Name, False);
            ASIOIsInDSDMode := True;
            Result := True;
        end;
    finally
        if NOT Result then begin
            BASS_ASIO_Free;
        end;
    end;
end;

The code right now works with MP3s, I can't afford a DSD DAC right now, so I thought to code it for MP3 and then just change the function parameters to DSD when it's working.

Thank you!
« Last Edit: 11 Jan '15 - 20:44 by 3delite »

3delite

  • Posts: 932
Re: BASSASIO BASS_ERROR_UNKNOWN
« Reply #1 on: 12 Jan '15 - 04:26 »
A little more testing: seems that BASS_ASIO_SetRate() with a different then previous setting is causing the error.

Ian @ un4seen

  • Administrator
  • Posts: 21368
Re: BASSASIO BASS_ERROR_UNKNOWN
« Reply #2 on: 12 Jan '15 - 17:30 »
BASS_ERROR_UNKNOWN indicates that the ASIO driver either failed to create the ASIO channel buffers or failed to start processing them. I'll send you a debug BASSASIO version to get some info on that.

3delite

  • Posts: 932
Re: BASSASIO BASS_ERROR_UNKNOWN
« Reply #3 on: 12 Jan '15 - 22:30 »
Ok. Thank you!