Author Topic: My program crashes when using the GIGAPORT HD+  (Read 1103 times)

jd

  • Posts: 2
Hi,
My C# program replays mp3s continuously until stopped.  It also has a few features to not play anything for a few seconds before replaying.  It works fine with the M-Audio Delta 1010LT and the Asio4ALL drivers but when my client tries to play it with the  GIGAPORT HD+, the program crashes.

  It will play the first time, then stutters and the program crashes.  I am not sure why it is crashing as I am not getting any exceptions.  I am posting my code hoping someone with more experience with the BASS.NET libraries can point out where I might be erring.

Thanks

Code: [Select]
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using Un4seen.Bass;
using Un4seen.BassAsio;

namespace JDPlayer.VP
{
internal class Asio
{
private const int Freq = 22050;
private TextBox _tb;
private string _musicDirectory;
private ASIOPROC _myAsioProc; // make it global, so that it can not be removed by the Garbage Collector
private readonly Dictionary<int, int> _streamDict = new Dictionary<int, int>();
            internal bool Running { get; set; }

internal bool Asio_Start(int deviceId, BASSInit init, BASSFlag flag, BASSASIOFormat format, TextBox musicDebugTb)
{
                //TextBox for debugging purposes
_tb = musicDebugTb;
try
{
// now setup ASIO
_myAsioProc = new ASIOPROC(AsioCallback);

//License
                    //BassNet.Registration("email@host.com", "123456");

_musicDirectory = AppDomain.CurrentDomain.BaseDirectory + "tunes";
var initResult = Bass.BASS_Init(deviceId, Freq, init, IntPtr.Zero);
Log(initResult, string.Format("Bass.BASS_Init device:{0}, Freq:{1}, init:{2}", deviceId, Freq, init));

var initAsioResult = BassAsio.BASS_ASIO_Init(deviceId, BASSASIOInit.BASS_ASIO_THREAD);
Log(initAsioResult, string.Format("BassAsio.BASS_ASIO_Init device:{0}, BASSASIOInit.BASS_ASIO_THREAD:{1}", deviceId, BASSASIOInit.BASS_ASIO_THREAD));
var asioInitError = BassAsio.BASS_ASIO_ErrorGetCode();

if (asioInitError == BASSError.BASS_ERROR_DEVICE)
{

VPLog.LogError("Could not find sound card.");
return false;
}
if (asioInitError != BASSError.BASS_OK)
{

VPLog.LogError("Unknown Error initializing sound card. " + asioInitError);
return false;
}
   const string channelLogfrmt = "Setup Channel BassAsio.BASS_ASIO_ChannelEnable isInput:{0}, channel:{1}";
var channelSetup = BassAsio.BASS_ASIO_ChannelEnable(false, 0, _myAsioProc, IntPtr.Zero);
Log(channelSetup, string.Format(channelLogfrmt, false, 0));

channelSetup = BassAsio.BASS_ASIO_ChannelEnable(false, 1, _myAsioProc, IntPtr.Zero);
Log(channelSetup, string.Format(channelLogfrmt, false, 1));

channelSetup = BassAsio.BASS_ASIO_ChannelEnable(false, 2, _myAsioProc, IntPtr.Zero);
Log(channelSetup, string.Format(channelLogfrmt, false, 2));

channelSetup = BassAsio.BASS_ASIO_ChannelEnable(false, 3, _myAsioProc, IntPtr.Zero);
Log(channelSetup, string.Format(channelLogfrmt, false, 3));

channelSetup = BassAsio.BASS_ASIO_ChannelEnable(false, 4, _myAsioProc, IntPtr.Zero);
Log(channelSetup, string.Format(channelLogfrmt, false, 4));

channelSetup = BassAsio.BASS_ASIO_ChannelEnable(false, 5, _myAsioProc, IntPtr.Zero);
Log(channelSetup, string.Format(channelLogfrmt, false, 5));

channelSetup = BassAsio.BASS_ASIO_ChannelEnable(false, 6, _myAsioProc, IntPtr.Zero);
Log(channelSetup, string.Format(channelLogfrmt, false, 6));

channelSetup = BassAsio.BASS_ASIO_ChannelEnable(false, 7, _myAsioProc, IntPtr.Zero);
Log(channelSetup, string.Format(channelLogfrmt, false, 7));

var asiostarted = BassAsio.BASS_ASIO_Start(512);
Log(asiostarted, string.Format("Start Asio BassAsio.BASS_ASIO_Start buflen:{0}", 512));

Running = true;
Log(asiostarted, String.Format("Asio Device Started device:{0}, BASSInit:{1}, BASSFlag:{2}, BASSASIOFormat:{3}", deviceId, init, flag, format));
}
catch (Exception e)
{
Log(false, e.Message);
VPLog.LogError(e);
}
return true;
}

internal void Asio_Stop()
{
try
{

var asioStop = BassAsio.BASS_ASIO_Stop();
Log(asioStop, "Stop ASIO BassAsio.BASS_ASIO_Stop ");

var asioFree = BassAsio.BASS_ASIO_Free();
Log(asioFree, "Free Asio BassAsio.BASS_ASIO_Free");

Running = false;
}
catch (Exception e)
{
Log(false, e.Message);
VPLog.LogError(e);
}
}

            private int AsioCallback(bool input, int channel, IntPtr buffer, int length, IntPtr user)
            {
                // Note: 'user' contains the underlying stream channel (see above)
                // We can simply use the bass method to get some data from a decoding channel  
                // and store it to the asio buffer in the same moment...
                try
                {
                    var data = Bass.BASS_ChannelGetData(user.ToInt32(), buffer, length);

                    return data;
                }
                catch (Exception e)
                {
                    Log(false, e.Message);
                    VPLog.LogError(e);
                    return 0;
                }
            }


            private void EnableChannel(int channel, int freq, string filename, BASSFlag flag, BASSASIOFormat format)
            {
                try
                {
                    //BassNet.Registration("email@host.com", "123456");
                    if (Paths.FileExists(filename))
                    {
                        //If the channel was previously assigned a stream, free it.
                        var prevStream = 0;
                        _streamDict.TryGetValue(channel, out prevStream);
                        if (prevStream != 0)
                        {
                            var streamFree = Bass.BASS_StreamFree(prevStream);
                            Log(streamFree, string.Format("Free Stream Bass.BASS_StreamFree stream:{0}", prevStream));
                        }

                        //create new stream
                        var stream = Bass.BASS_StreamCreateFile(filename, 0, 0, flag);
                        Log(stream != 0, string.Format("Create Stream Bass.BASS_StreamCreateFile filename:{0}, offset:{1}, length:{2}, BASSFlag:{3}", filename, 0, 0, flag));

                        if (stream != 0)
                        {

                            // enable output channel
                            var enableresult = BassAsio.BASS_ASIO_ChannelEnable(false, channel, _myAsioProc, new IntPtr(stream));
                            Log(enableresult, string.Format("Enable Channel  BassAsio.BASS_ASIO_ChannelEnable isInput:{0}, channel:{1}", false, channel));

                            var freqresult = BassAsio.BASS_ASIO_SetRate(freq); // set the device rate
                            Log(freqresult, string.Format("Set frequency  BassAsio.BASS_ASIO_SetRate freq:{0}", freq));

                            var rateresult = BassAsio.BASS_ASIO_ChannelSetRate(false, channel, freq); // set the channel's rate
                            Log(rateresult, string.Format("Set channel rate BassAsio.BASS_ASIO_ChannelSetRate isInput:{0}, channel:{1}, freq:{2}", false, channel, freq));

                            var formatresult = BassAsio.BASS_ASIO_ChannelSetFormat(false, channel, format);
                            Log(formatresult, string.Format("Set channel format BassAsio.BASS_ASIO_ChannelSetFormat isInput:{0}, channel:{1}, freq:{2}", false, channel, format));

                            //Add channel to dictionary to close stream latter
                            if (_streamDict.ContainsKey(channel))
                            {
                                _streamDict.Remove(channel);
                            }
                            _streamDict.Add(channel, stream);
                        }
                    }
                    else VPLog.LogError("Tunes error " + filename + " was not found.");
                }
                catch (Exception e)
                {
                    Log(false, e.Message);
                    VPLog.LogError(e);
                }
            }

            internal void Play(string filename, int channel, BASSFlag flag, BASSASIOFormat format)
            {
                EnableChannel(channel, Freq, _musicDirectory + @"\" + filename, flag, format);
            }

            internal void PlaySilence(int channel, BASSFlag flag, BASSASIOFormat format)
            {
                EnableChannel(channel, Freq, _musicDirectory + @"\000.mp3", flag, format);
            }

internal void AdjustVolume(int channel, int volume)
{
try
{
var setVol = BassAsio.BASS_ASIO_ChannelSetVolume(false, channel, (float)(volume) / 100f);
Log(setVol, "Set Volume BassAsio.BASS_ASIO_ChannelSetVolume" + string.Format("isInput:{0}, channel:{1}, volume:{2}", false, channel, (float)(volume) / 100f));
     }
catch (Exception e)
{
Log(false, e.Message);
VPLog.LogError(e);
}
}

            internal static List<BASS_ASIO_DEVICEINFO> DeviceList()
            {
                var devices = new List<BASS_ASIO_DEVICEINFO>();
                try
                {
                    var info = new BASS_ASIO_DEVICEINFO();
                    for (int n = 0; BassAsio.BASS_ASIO_GetDeviceInfo(n, info); n++)
                    {
                        devices.Add(info);
                    }
                }
                catch (Exception e)
                {
                    VPLog.LogError(e);
                }
                return devices;
            }

            private string isError(bool goodres)
            {
                return goodres ? "Ok " : "Error ";
            }

   delegate void LogCallBack(bool goodres, string text);
            private void Log(bool goodresult, string text)
            {
                if (_tb != null && _tb.InvokeRequired)
                {
                    var d = new LogCallBack(Log);
                    _tb.Invoke(d, new object[] { goodresult, text });
                }
                else
                {

                    var logtext = isError(goodresult) + text + "\r\n" + (goodresult ? "" : "Error Code = " + BassAsio.BASS_ASIO_ErrorGetCode()) + "\r\n";

                    if (_tb != null) _tb.Text = logtext + "\r\n" + _tb.Text;
                    VPLog.LogError(logtext);
                }
            }

}
}


« Last Edit: 16 Sep '13 - 17:59 by jd »

Ian @ un4seen

  • Administrator
  • Posts: 24589
Re: My program crashes when using the GIGAPORT HD+
« Reply #1 on: 16 Sep '13 - 13:52 »
I see you are already doing some logging. Please post the log output from when the crash occurs, to narrow down where the crash is occurring. Please post any info that Windows/.Net gives on the crash too.

jd

  • Posts: 2
Re: My program crashes when using the GIGAPORT HD+
« Reply #2 on: 18 Sep '13 - 00:11 »
Hi Ian,
    I figured out what the problem was. I was giving BassAsio.BASS_ASIO_Start(buflen); a buffer length that wasn't support by the device.  I figured it out because it was the command that never showed up in the log file because the program crashed and I couldn't get any error codes or even .Net exceptions.  If BASS.Net were to check the parameters and give an Error_code instead of crashing, it would make the library easier to work with.  If that is too hard to implement, examples of how to check if parameters are valid for each method would come in quite handy.

Thx

Ian @ un4seen

  • Administrator
  • Posts: 24589
Re: My program crashes when using the GIGAPORT HD+
« Reply #3 on: 19 Sep '13 - 12:57 »
That sounds the like the ASIO driver is crashing when it's asked to create the ASIO buffers (the buffers are allocated by the driver rather than BASSASIO). BASS_ASIO_Start doesn't restrict the requested buffer length ("buflen" parameter) and leaves it up to the driver to determine whether it's valid, as the ASIO spec states that an ASIO driver should fail the request gracefully (return an error code rather than crash) if the length is not supported.