Пример #1
0
        public void Start()
        {
            Bass.BASS_Init(-1, 44100, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero);
            Bass.BASS_RecordInit(-1);
            _myRecProc = new RECORDPROC(MyRecording);
            int   inputsource = 0;
            int   settings    = 0;
            float vol         = 0;

            while (settings != -1)
            {
                settings = Bass.BASS_RecordGetInput(inputsource, ref vol);
                if (Bass.BASS_RecordGetInputName(inputsource) == "Speakers")
                {
                    break;
                }
                inputsource++;
            }

            Bass.BASS_RecordSetInput(inputsource, BASSInput.BASS_INPUT_ON, 0.5F);

            int recChannel = Bass.BASS_RecordStart(44100, 2, BASSFlag.BASS_RECORD_PAUSE, 50, _myRecProc, IntPtr.Zero);

            Bass.BASS_ChannelPlay(recChannel, false);
        }
Пример #2
0
    BASSTimer timerBPM            = new BASSTimer(20);         //New instance of a timer from the Bass Lib (interval for a Tick event 20ms)

    // Start is called before the first frame update
    void Start()
    {
        if (Bass.BASS_RecordInit(-1))                 //If the default device(-1) is initializaed successfully
        {
            Debug.Log("Device initialized");          //Tell that the device can be used
            _myRecProc = new RECORDPROC(MyRecording); //Set _myRecProc as the code from MyRecording

            //Get channel handle (Record at samplerate,with num of channels,Start the recording paused,User instance data to pass to the callback function)
            recHandle = Bass.BASS_RecordStart(44100, 2, BASSFlag.BASS_RECORD_PAUSE, _myRecProc, IntPtr.Zero); //start recording but paused AND set recHandle = to recording's handle
            Bass.BASS_ChannelPlay(recHandle, false);                                                          //resume playback of (recHandle,don't restart from beggining)
            Debug.Log("recHandle:" + recHandle.ToString());                                                   //Show the handle ID

            //get samplerate
            BASS_CHANNELINFO info = new BASS_CHANNELINFO();                             //create a new info instance
            Bass.BASS_ChannelGetInfo(recHandle, info);                                  //Retrieve info of the channel (channel to get info from, where to store info)
            Debug.Log("Channels: " + info.chans.ToString() + " Freq: " + info.freq.ToString());
            if (Bass.BASS_ChannelIsActive(recHandle) == BASSActive.BASS_ACTIVE_PLAYING) //Check if the channel is active
            {
                Debug.Log("The Channel is playing/recording");
            }
            timerBPM.Tick += timerBPM_Tick;     //Define the callback function for the timer
            //if I have a got a recHandle && the playback status of the recHandle is successful
            if (recHandle != 0 && Bass.BASS_ChannelPlay(recHandle, false))
            {
                _bpm.Reset(info.freq);      //set bpm  frequency to the one retrieved from the channel
                this.timerBPM.Start();      //Start the timer
            }
        }
        else
        {
            Debug.Log("Device could not be initialized");   //Tell that the operation failed
        }
    }
Пример #3
0
        private void buttonStartRec_Click(object sender, System.EventArgs e)
        {
            this.buttonStartRec.Enabled = false;
            this.labelRec.Text          = "Recording...";

            // start recording paused
            _myRecProc = new RECORDPROC(MyRecoring);
            _recHandle = Bass.BASS_RecordStart(44100, 2, BASSFlag.BASS_RECORD_PAUSE, _myRecProc, new IntPtr(_encHandle));

            // needs 'lame.exe' !
            // the recorded data will be written to a file called rectest.mp3
            // create the encoder...192kbps, stereo
            // MP3 encoder setup
            lame                       = new EncoderLAME(_recHandle);
            lame.InputFile             = null;  //STDIN
            lame.OutputFile            = "rectest.mp3";
            lame.LAME_Bitrate          = (int)EncoderLAME.BITRATE.kbps_192;
            lame.LAME_Mode             = EncoderLAME.LAMEMode.Default;
            lame.LAME_TargetSampleRate = (int)EncoderLAME.SAMPLERATE.Hz_44100;
            lame.LAME_Quality          = EncoderLAME.LAMEQuality.Quality;

            monBuffer.Clear();
            checkBoxMonitor.Checked = false;

            // create a live recording WaveForm
            WF = new WaveForm();
            WF.FrameResolution = 0.01f;             // 10ms are nice
            // start a live recording waveform with 5sec. init size and 2sec. next size
            WF.RenderStartRecording(_recHandle, 5f, 2f);

            // really start recording
            lame.Start(null, IntPtr.Zero, false);
            Bass.BASS_ChannelPlay(_recHandle, false);
        }
Пример #4
0
 public Microphone(int device)
 {
     this.device = device;
     rpro        = new RECORDPROC(MyRecording);
     Bass.BASS_RecordInit(device);
     ID = Bass.BASS_RecordStart(Global.DefaultSampleRate * 2, 1, BASSFlag.BASS_DEFAULT, rpro, IntPtr.Zero);
 }
Пример #5
0
        /// <summary>
        /// Create a new recording with custom settings
        /// </summary>
        /// <param name="strFileName">File Name</param>
        /// <param name="samplerate">Sample rate</param>
        /// <param name="channels">Channels</param>
        /// <param name="bitrate">Bitrate</param>
        /// <param name="stereomode">Stereo mode</param>
        public PodcasterRecording(string strFileName, int samplerate, int channels, int bitrate, StereoMode stereomode)
        {
            if (!strFileName.ToLower().EndsWith(".mp3"))
            {
                // TODO: implement other codecs
                throw new Exception("Currently, Podcaster only works with MP3 files");
            }

            _myRecProc = new RECORDPROC(RecordAudio);
            _recHandle = Bass.BASS_RecordStart(samplerate, channels, BASSFlag.BASS_RECORD_PAUSE, _myRecProc, IntPtr.Zero);

            lame = new EncoderLAME(_recHandle);
            lame.InputFile = null;
            lame.OutputFile = strFileName;
            lame.LAME_Bitrate = bitrate;

            switch (stereomode)
            {
                case StereoMode.JointStereo:
                    lame.LAME_Mode = EncoderLAME.LAMEMode.JointStereo;
                    break;
                case StereoMode.Mono:
                    lame.LAME_Mode = EncoderLAME.LAMEMode.Mono;
                    break;
                default:
                    lame.LAME_Mode = EncoderLAME.LAMEMode.Stereo;
                    break;
            }

            lame.LAME_TargetSampleRate = samplerate;
            lame.LAME_Quality = EncoderLAME.LAMEQuality.Quality;
        }
Пример #6
0
        public bool StartListening()
        {
            bool res = false;

            Stream = Bass.FALSE;

            if (Bass.BASS_RecordInit(Device))
            {
                _myRecProc = new RECORDPROC(MyRecording);

                Stream = Bass.BASS_RecordStart(44100, 2, BASSFlag.BASS_RECORD_PAUSE, _myRecProc, IntPtr.Zero);

                if (Stream != Bass.FALSE)
                {
                    // start recording
                    res = Bass.BASS_ChannelPlay(Stream, false);

                    samplerate = GetSampleRate();

                    processingTimer.Start();
                }
            }

            return(res);
        }
Пример #7
0
        private void StartRecording()
        {
            // var device = Bass.BASS_RecordGetDeviceInfos().FirstOrDefault();
            if (Bass.BASS_RecordInit(-1))
            {
                Debug.Log("[BassMicrophoneHandler] BASS_RecordInit = true");

                _recordProc      = OnRecord;
                _recordingHandle = Bass.BASS_RecordStart(
                    AudioSettings.outputSampleRate,
                    1,
                    BASSFlag.BASS_SAMPLE_FLOAT | BASSFlag.BASS_RECORD_PAUSE,
                    _recordProc,
                    IntPtr.Zero
                    );

                if (_recordingHandle == Bass.FALSE)
                {
                    Debug.LogError($"[BassMicrophoneHandler] BASS_RecordStart returned 0!");
                    return;
                }
                else
                {
                    Debug.Log($"[BassMicrophoneHandler] Recording Handle: {_recordingHandle}");
                    var play = Bass.BASS_ChannelPlay(_recordingHandle, false);
                    Debug.Log("[BassMicrophoneHandler] BASS_ChannelPlay == " + play);
                }
            }
            else
            {
                Debug.LogError("[BassMicrophoneHandler] BASS_RecordInit == False!");
            }
        }
Пример #8
0
        private void startRecordMp3()
        {
            InitSound();


            try
            {
                if (Bass.BASS_ChannelIsActive(_blogStreamHandle) == BASSActive.BASS_ACTIVE_PLAYING)
                {
                    Msg("Still Playing MP3");
                    return;
                }
                if (Bass.BASS_ChannelIsActive(pcmImportStreamHandle) == BASSActive.BASS_ACTIVE_PLAYING)
                {
                    Msg("Still Playing PCM");
                    return;
                }

                if (pcmMemStrm != null)
                {
                    pcmMemStrm.Close();
                }
                pcmMemStrm = new MemoryStream();
                // start recording paused
                _PcmRecProc = new RECORDPROC(PcmRecordingCallBack);


                _PcmRecHandle = Bass.BASS_RecordStart(44100, 2, BASSFlag.BASS_RECORD_PAUSE, _PcmRecProc, IntPtr.Zero);



                BASSError error = Bass.BASS_ErrorGetCode();
                Msg(Enum.GetName(typeof(BASSError), error));

                bool lameStarted = StartLameEncoding(_PcmRecHandle);

                if (!lameStarted)
                {
                    MessageBox.Show("Lame.exe may not be present");
                }

                Bass.BASS_ChannelPlay(_PcmRecHandle, false);

                Msg("Recording");
                recording = true;
            }
            catch (Exception ex)
            {
                // Also try to modify options to "prefer 32bits"
                // System.BadImageFormatException' s'est produite dans Bass.Net.dll
                Console.Write(ex.Message + "\r");
                Msg(ex.Message);
                Msg("bassenc.dll may not be present");
                Msg("Failed to Record");
            }
        }
Пример #9
0
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="dataOutput">录音数据输出委托[第一个参数:设备索引;第二个参数:数据;第三个参数:数据长度]</param>
        /// <param name="device">录音设备索引,-1 = default device, 0 = first. BASS_RecordGetDeviceInfo can be used to enumerate the available devices</param>
        public SoundRecorder(Action <int, byte[], int> dataOutput, int device = 0)
        {
            if (dataOutput == null)
            {
                throw new ArgumentNullException(nameof(dataOutput));
            }

            RecordHelper.RecordInit(device);
            this._device     = device;
            this._dataOutput = dataOutput;
            this._recordPro  = new RECORDPROC(RecordProCallback);
        }
Пример #10
0
        /// <summary>
        /// Starts recording.
        /// </summary>
        /// <param name="freq">The sample rate to record at... 0 = device's current sample rate. </param>
        /// <param name="chans">The number of channels... 1 = mono, 2 = stereo, etc. 0 = device's current channel count</param>
        /// <param name="flags">A combination of these flags.
        /// BASS_SAMPLE_8BITS Use 8-bit resolution. If neither this or the BASS_SAMPLE_FLOAT flag are specified, then the recorded data is 16-bit.
        /// BASS_SAMPLE_FLOAT Use 32-bit floating-point sample data.See Floating-point channels for info.
        /// BASS_RECORD_PAUSE Start the recording paused.
        /// The HIWORD - use MAKELONG(flags, period) - can be used to set the period(in milliseconds) between calls to the callback function.
        ///              The minimum period is 5ms, the maximum is half the BASS_CONFIG_REC_BUFFER setting. If the period specified is outside this range, it is automatically capped. The default is 100ms.
        /// </param>
        /// <param name="proc">The user defined function to receive the recorded sample data... can be NULL if you do not wish to use a callback. </param>
        /// <param name="user">User instance data to pass to the callback function. </param>
        /// <returns>If successful, the new recording's handle is returned, else throw WavException. </returns>
        public static int RecordStart(int freq, int chans, BASSFlag flags, RECORDPROC proc, IntPtr user)
        {
            int flagRet = (int)flags + 20 << 8;
            int handle  = NativeMethods.BASS_RecordStart(freq, chans, flags, proc, user);

            if (handle == 0)
            {
                throw new WavException(BassErrorCode.GetErrorInfo());
            }

            return(handle);
        }
Пример #11
0
        public ReplayMic(int device)
        {
            rpro = new RECORDPROC(MyRecording);
            Bass.BASS_RecordInit(device);
            MicID = Bass.BASS_RecordStart(Global.DefaultSampleRate, 1, BASSFlag.BASS_DEFAULT, rpro, IntPtr.Zero);

            nowDecoding = Bass.BASS_StreamCreatePush(Global.DefaultSampleRate, 1, BASSFlag.BASS_STREAM_DECODE, IntPtr.Zero);
            PlayID      = Un4seen.Bass.AddOn.Fx.BassFx.BASS_FX_TempoCreate(nowDecoding, BASSFlag.BASS_DEFAULT);

            Bass.BASS_ChannelPlay(nowDecoding, false);
            Bass.BASS_ChannelPlay(PlayID, true);
        }
Пример #12
0
 private void InitBassapi(int deviceId)
 {
     if (deviceId != -1)
     {
         if (Bass.BASS_GetDeviceInfo(deviceId) == null)
         {
             deviceId = -1;
         }
     }
     Bass.BASS_RecordInit(-1);
     _recordProc = new RECORDPROC(RecordProc);
     _recordChan = Bass.BASS_RecordStart(44100, 2, BASSFlag.BASS_DEFAULT, 10, _recordProc, IntPtr.Zero);
 }
Пример #13
0
        public CBassRecord()
        {
            Init();
            _Buffer = new CBuffer[CSettings.MaxNumPlayer];
            for (int i = 0; i < _Buffer.Length; i++)
            {
                _Buffer[i] = new CBuffer();
            }

            _recHandle = new int[_Devices.Count];
            _myRecProc = new RECORDPROC(MyRecording);

            _DeviceConfig = _Devices.ToArray();
        }
Пример #14
0
 public static void Start()
 {
     if (IsReady = Bass.BASS_RecordInit(/*Properties.Settings.Default.BassRecordDevice*/ -1))
     {
         string fileTitle  = "Tile";
         string fileToSave = Path.Combine(Environment.CurrentDirectory,
                                          string.Format("{0}.{1}.wav", fileTitle, DateTime.Now.ToString("yyyy-MM-dd.HH-mm-ss")));
         //if (!Directory.Exists(Properties.Settings.Default.RecordsFolder))
         //    Directory.CreateDirectory(Properties.Settings.Default.RecordsFolder);
         recordFileStream_ = new FileStream(fileToSave, FileMode.Create);
         _recordProc       = new RECORDPROC(RecordProc);
         IsRecording       = (Handle = Bass.BASS_RecordStart(44100, 2, BASSFlag.BASS_RECORD_PAUSE, 50, _recordProc,
                                                             IntPtr.Zero)) != 0;
         if (IsRecording)
         {
             Bass.BASS_ChannelPlay(Handle, false);
         }
     }
 }
Пример #15
0
        public void init(int Device)
        {
            if(inicialized)
            {
                Bass.BASS_RecordFree();
            }

            Bass.BASS_RecordInit(-1);
            Un4seen.Bass.BASSError error;
            if((error=Bass.BASS_ErrorGetCode())!=0)
                MessageBox.Show("Bass Error Code: "+error, "Music Error", MessageBoxButtons.OK, MessageBoxIcon.Hand);
            Bass.BASS_RecordSetDevice(Device);
            if ((error = Bass.BASS_ErrorGetCode()) != 0)
                MessageBox.Show("Bass Error Code: " + error, "Music Error", MessageBoxButtons.OK, MessageBoxIcon.Hand);

            myRecProc = new RECORDPROC(MyRecording);
            recChannel = Bass.BASS_RecordStart(22050, 2, BASSFlag.BASS_RECORD_PAUSE, myRecProc, IntPtr.Zero);
            Bass.BASS_ChannelPlay(recChannel, false);
            updateTimer = new Un4seen.Bass.BASSTimer(50);
            updateTimer.Tick += new EventHandler(timerUpdate_Tick);
            mySpectrumInit();
            inicialized = true;
        }
Пример #16
0
 public static extern int BASS_RecordStart(int freq, int chans, BASSFlag flags, RECORDPROC proc, IntPtr user);
Пример #17
0
 public static extern uint BASS_RecordStart(uint freq, uint chans, uint flags, RECORDPROC proc, IntPtr user);
Пример #18
0
 public VoiceChat(Options.MainConfig config)
 {
     this.deviceName   = config.DeviceRead;
     this.recordProc   = new RECORDPROC(recordDevice_audioReceived);
     this.recordHandle = Bass.BASS_RecordStart(SAMPLE_RATE, CHANNEL_COUNT, BASSFlag.BASS_RECORD_PAUSE, this.recordProc, IntPtr.Zero);
 }
Пример #19
0
 public static int BASS_RecordStart(int freq, int chans, BASSFlag flags, int period, RECORDPROC proc, IntPtr user)
 {
     return(BASS_RecordStart(freq, chans, (BASSFlag)Utils.MakeLong((int)flags, period), proc, user));
 }
Пример #20
0
        /// <summary>
        /// Starts recording.
        /// </summary>
        /// <param name="freq">The sample rate to record at... 0 = device's current sample rate. </param>
        /// <param name="chans">The number of channels... 1 = mono, 2 = stereo, etc. 0 = device's current channel count</param>
        /// <param name="flags">A combination of these flags.
        /// BASS_SAMPLE_8BITS Use 8-bit resolution. If neither this or the BASS_SAMPLE_FLOAT flag are specified, then the recorded data is 16-bit.
        /// BASS_SAMPLE_FLOAT Use 32-bit floating-point sample data.See Floating-point channels for info.
        /// BASS_RECORD_PAUSE Start the recording paused.
        /// The HIWORD - use MAKELONG(flags, period) - can be used to set the period(in milliseconds) between calls to the callback function.
        ///              The minimum period is 5ms, the maximum is half the BASS_CONFIG_REC_BUFFER setting. If the period specified is outside this range, it is automatically capped. The default is 100ms.
        /// </param>
        /// <param name="period">Set the period(in milliseconds) between calls to the callback function(Un4seen.Bass.RECORDPROC).
        /// The minimum period is 5ms, the maximum the maximum is half the BASS_CONFIG_REC_BUFFER setting.
        /// If the period specified is outside this range, it is automatically capped. The default is 100ms</param>
        /// <param name="proc">The user defined function to receive the recorded sample data... can be NULL if you do not wish to use a callback. </param>
        /// <param name="user">User instance data to pass to the callback function. </param>
        /// <returns>If successful, the new recording's handle is returned, else throw WavException. </returns>
        public static int RecordStart(int freq, int chans, BASSFlag flags, int period, RECORDPROC proc, IntPtr user)
        {
            int handle = NativeMethods.BASS_RecordStart(freq, chans, (BASSFlag)Utils.MakeLong((int)flags, period), proc, user);

            if (handle == 0)
            {
                throw new WavException(BassErrorCode.GetErrorInfo());
            }

            return(handle);
        }
Пример #21
0
 public static extern int BASS_RecordStart(int freq, int chans, BASSFlag flags, RECORDPROC proc, IntPtr user);
Пример #22
0
        private void button1_Click(object sender, System.EventArgs e)
        {
            Bass.BASS_StreamFree(_Stream);
            this.textBox1.Text = "";
            _url = this.comboBoxURL.Text;
            // test BASS_StreamCreateURL

            bool isWMA = false;

            if (_url != String.Empty)
            {
                this.textBox1.Text += "URL: " + _url + Environment.NewLine;
                // create the stream
                _Stream = Bass.BASS_StreamCreateURL(_url, 0, BASSFlag.BASS_STREAM_STATUS, myStreamCreateURL, IntPtr.Zero);
                if (_Stream == 0)
                {
                    // try WMA streams...
                    _Stream = BassWma.BASS_WMA_StreamCreateFile(_url, 0, 0, BASSFlag.BASS_DEFAULT);
                    if (_Stream != 0)
                    {
                        isWMA = true;
                    }
                    else
                    {
                        // error
                        this.statusBar1.Text = "ERROR...";
                        return;
                    }
                }
                _tagInfo = new TAG_INFO(_url);
                BASS_CHANNELINFO info = Bass.BASS_ChannelGetInfo(_Stream);
                if (info.ctype == BASSChannelType.BASS_CTYPE_STREAM_WMA)
                {
                    isWMA = true;
                }
                // ok, do some pre-buffering...
                this.statusBar1.Text = "Buffering...";
                if (!isWMA)
                {
                    // display buffering for MP3, OGG...
                    while (true)
                    {
                        long len = Bass.BASS_StreamGetFilePosition(_Stream, BASSStreamFilePosition.BASS_FILEPOS_END);
                        if (len == -1)
                        {
                            break;                             // typical for WMA streams
                        }
                        // percentage of buffer filled
                        float progress = (
                            Bass.BASS_StreamGetFilePosition(_Stream, BASSStreamFilePosition.BASS_FILEPOS_DOWNLOAD) -
                            Bass.BASS_StreamGetFilePosition(_Stream, BASSStreamFilePosition.BASS_FILEPOS_CURRENT)
                            ) * 100f / len;

                        if (progress > 75f)
                        {
                            break;                             // over 75% full, enough
                        }

                        this.statusBar1.Text = String.Format("Buffering... {0}%", progress);
                    }
                }
                else
                {
                    // display buffering for WMA...
                    while (true)
                    {
                        long len = Bass.BASS_StreamGetFilePosition(_Stream, BASSStreamFilePosition.BASS_FILEPOS_WMA_BUFFER);
                        if (len == -1L)
                        {
                            break;
                        }
                        // percentage of buffer filled
                        if (len > 75L)
                        {
                            break;                             // over 75% full, enough
                        }

                        this.statusBar1.Text = String.Format("Buffering... {0}%", len);
                    }
                }

                // get the meta tags (manually - will not work for WMA streams here)
                string[] icy = Bass.BASS_ChannelGetTagsICY(_Stream);
                if (icy == null)
                {
                    // try http...
                    icy = Bass.BASS_ChannelGetTagsHTTP(_Stream);
                }
                if (icy != null)
                {
                    foreach (string tag in icy)
                    {
                        this.textBox1.Text += "ICY: " + tag + Environment.NewLine;
                    }
                }
                // get the initial meta data (streamed title...)
                icy = Bass.BASS_ChannelGetTagsMETA(_Stream);
                if (icy != null)
                {
                    foreach (string tag in icy)
                    {
                        this.textBox1.Text += "Meta: " + tag + Environment.NewLine;
                    }
                }
                else
                {
                    // an ogg stream meta can be obtained here
                    icy = Bass.BASS_ChannelGetTagsOGG(_Stream);
                    if (icy != null)
                    {
                        foreach (string tag in icy)
                        {
                            this.textBox1.Text += "Meta: " + tag + Environment.NewLine;
                        }
                    }
                }

                // alternatively to the above, you might use the TAG_INFO (see BassTags add-on)
                // This will also work for WMA streams here ;-)
                if (BassTags.BASS_TAG_GetFromURL(_Stream, _tagInfo))
                {
                    // and display what we get
                    this.textBoxAlbum.Text   = _tagInfo.album;
                    this.textBoxArtist.Text  = _tagInfo.artist;
                    this.textBoxTitle.Text   = _tagInfo.title;
                    this.textBoxComment.Text = _tagInfo.comment;
                    this.textBoxGenre.Text   = _tagInfo.genre;
                    this.textBoxYear.Text    = _tagInfo.year;
                }

                // set a sync to get the title updates out of the meta data...
                mySync = new SYNCPROC(MetaSync);
                Bass.BASS_ChannelSetSync(_Stream, BASSSync.BASS_SYNC_META, 0, mySync, IntPtr.Zero);
                Bass.BASS_ChannelSetSync(_Stream, BASSSync.BASS_SYNC_WMA_CHANGE, 0, mySync, IntPtr.Zero);

                // start recording...
                int rechandle = 0;
                if (Bass.BASS_RecordInit(-1))
                {
                    _byteswritten = 0;
                    myRecProc     = new RECORDPROC(MyRecoring);
                    rechandle     = Bass.BASS_RecordStart(44100, 2, BASSFlag.BASS_RECORD_PAUSE, myRecProc, IntPtr.Zero);
                }
                this.statusBar1.Text = "Playling...";
                // play the stream
                Bass.BASS_ChannelPlay(_Stream, false);
                // record the stream
                Bass.BASS_ChannelPlay(rechandle, false);
            }
        }
Пример #23
0
 public static int BASS_RecordStart(int freq, int chans, BASSFlag flags, int period, RECORDPROC proc, IntPtr user)
 {
     return BASS_RecordStart(freq, chans, (BASSFlag) Utils.MakeLong((int) flags, period), proc, user);
 }
        private async Task <bool> Init(string configPath, string agentsPath, string commandsPath)
        {
            this.configPath   = configPath;
            this.agentsPath   = agentsPath;
            this.commandsPath = commandsPath;

            // create discord client
            Discord                  = new DiscordSocketClient();
            Discord.JoinedGuild     += Discord_JoinedGuild;
            Discord.LeftGuild       += Discord_LeftGuild;
            Discord.MessageReceived += Discord_MessageReceived;
            Discord.Log             += Log;
            Discord.Ready           += Discord_Ready;

            commandService      = new CommandService();
            commandService.Log += Log;
            try {
                CommandsAssembly = Assembly.LoadFile(Path.GetFullPath(commandsPath));
                await commandService.AddModulesAsync(CommandsAssembly);
            } catch (Exception ex) {
                Log(LogSeverity.Error, "Failed to load commands assembly at \"" + commandsPath + "\"", ex);
                return(false);
            }

            // install commands
            ModifyServices(x => x
                           .AddSingleton(Discord)
                           .AddSingleton(commandService)
                           );

            // load config
            if (!ReloadConfig())
            {
                return(false);
            }

            // export embedded bot agent as reference
            if (!Directory.Exists(agentsPath))
            {
                Directory.CreateDirectory(agentsPath);
            }
            File.WriteAllBytes(Path.Combine(agentsPath, "tomoko.json"), Resources.tomoko);

            // load agent
            if (!ReloadAgent())
            {
                return(false);
            }

            // capture console exit
            consoleCtrlHandler = new WinApi.HandlerRoutine(consoleCtrl);
            WinApi.SetConsoleCtrlHandler(consoleCtrlHandler, true);

            // init record device
            if (Config.speakEnabled)
            {
                recordDevice = -1;
                if (Config.speakRecordingDevice != null)
                {
                    var devices = Bass.BASS_RecordGetDeviceInfos();
                    for (int i = 0; i < devices.Length; i++)
                    {
                        if (devices[i].name == Config.speakRecordingDevice)
                        {
                            recordDevice = i;
                            break;
                        }
                    }
                    if (recordDevice < 0)
                    {
                        IEnumerable <string> devicesList = devices.Select(d => d.name);
                        Log(LogSeverity.Error, "Recording device \"" + Config.speakRecordingDevice + "\" not found.\nAvailable recording devices:\n * " + string.Join("\n * ", devicesList) + "\n");
                        return(false);
                    }
                }

                if (!Bass.BASS_RecordInit(recordDevice))
                {
                    Log(LogSeverity.Error, "Failed to init recording device: " + Bass.BASS_ErrorGetCode());
                    return(false);
                }
                recordProc = new RECORDPROC(recordDevice_audioReceived);
            }

            // init playback device
            if (Config.listenEnabled)
            {
                playbackDevice = -1;
                if (Config.listenPlaybackDevice != null)
                {
                    var devices = Bass.BASS_GetDeviceInfos();
                    for (int i = 0; i < devices.Length; i++)
                    {
                        if (devices[i].name == Config.listenPlaybackDevice)
                        {
                            playbackDevice = i;
                            break;
                        }
                    }
                    if (playbackDevice < 0)
                    {
                        IEnumerable <string> devicesList = devices.Select(d => d.name);
                        Log(LogSeverity.Error, "Playback device \"" + Config.listenPlaybackDevice + "\" not found.\nAvailable playback devices:\n * " + string.Join("\n * ", devicesList) + "\n");
                        return(false);
                    }
                }

                if (!Bass.BASS_Init(playbackDevice, SAMPLE_RATE, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero, null))
                {
                    Log(LogSeverity.Error, "Failed to init playback device: " + Bass.BASS_ErrorGetCode());
                    return(false);
                }
                playProc = new STREAMPROC(playbackDevice_audioRequested);
            }

            return(true);
        }