Пример #1
0
        /// <summary>
        /// Start Recording.
        /// </summary>
        public void Start()
        {
            lock (_syncLock)
            {
                foreach (var loop in _loopback.Values.Where(M => M.RecordingHandle != 0))
                {
                    Bass.ChannelPlay(loop.SilenceStreamHandle);
                    Bass.ChannelPlay(loop.RecordingHandle);
                }

                foreach (var rec in _recording.Values.Where(M => M.RecordingHandle != 0))
                {
                    Bass.ChannelPlay(rec.RecordingHandle);
                }

                Bass.ChannelPlay(_mixer);

                if (!_fillerAdded)
                {
                    // Add Filler only after mixer has started
                    BassMix.MixerAddChannel(_mixer, _filler, BassFlags.Default);

                    _fillerAdded = true;
                }

                _running = true;
            }
        }
Пример #2
0
 internal override void ConnectFile(clsMP3Bass mp3bass)
 {
     mp3bass.StreamHandle = CheckHandleHard(Bass.CreateStream(
                                                mp3bass.FilePath, 0, 0, BassFlags.Decode | BassFlags.Prescan));
     CheckOKHard(BassMix.MixerAddChannel(
                     MixerStream, mp3bass.StreamHandle, BassFlags.Default));
     CheckOKHard(Bass.ChannelStop(mp3bass.StreamHandle));
 }
Пример #3
0
 internal override void ConnectMidiDev(clsBassOutMidi bassoutmidi)
 {
     bassoutmidi.MidiStream = CheckHandleHard(BassMidi.CreateStream(
                                                  bassoutmidi.NumMidiChans, BassFlags.Decode | BassFlags.Float, 1));
     bassoutmidi.InitStream();
     CheckOKHard(BassMix.MixerAddChannel(
                     MixerStream, bassoutmidi.MidiStream, BassFlags.Default));
 }
Пример #4
0
        /// <summary>
        /// Adds a Bass Channel to Wasapi Output Mixer.
        /// </summary>
        /// <returns>True on Success</returns>
        public bool AddOutputSource(int Channel)
        {
            ChannelInfo info;

            if (!Bass.ChannelGetInfo(Channel, out info) ||
                (!info.IsDecodingChannel && info.ChannelType != ChannelType.Recording))
            {
                return(false);
            }

            return(BassMix.MixerAddChannel(_mixerStream, Channel, BassFlags.Default));
        }
Пример #5
0
 public override void Connect(IBassStreamComponent previous)
 {
     Logger.Write(this, LogLevel.Debug, "Creating BASS MIX stream with rate {0} and {1} channels.", this.Rate, this.Channels);
     this.ChannelHandle = BassMix.CreateMixerStream(this.Rate, this.Channels, this.Flags);
     if (this.ChannelHandle == 0)
     {
         BassUtils.Throw();
     }
     Logger.Write(this, LogLevel.Debug, "Adding stream to the mixer: {0}", previous.ChannelHandle);
     BassUtils.OK(BassMix.MixerAddChannel(this.ChannelHandle, previous.ChannelHandle, BassFlags.Default | BassFlags.MixerBuffer));
     this.MixerChannelHandles.Add(previous.ChannelHandle);
 }
Пример #6
0
        void AddDevice(IIsActive <BassItem> Device)
        {
            lock (_syncLock)
            {
                var id = Device.Item.Id;

                if (_devices[id].RecordingHandle != 0)
                {
                    return;
                }

                Bass.RecordInit(id);

                var devInfo = Bass.RecordGetDeviceInfo(id);

                if (devInfo.IsLoopback)
                {
                    var playbackDevice = FindPlaybackDevice(devInfo);

                    if (playbackDevice != -1)
                    {
                        Bass.Init(playbackDevice);
                        Bass.CurrentDevice = playbackDevice;

                        var silence = Bass.CreateStream(44100, 2, BassFlags.Default, Extensions.SilenceStreamProcedure);

                        Bass.ChannelSetAttribute(silence, ChannelAttribute.Volume, 0);

                        _devices[id].SilenceHandle = silence;
                    }
                }

                Bass.CurrentRecordingDevice = id;

                var info = Bass.RecordingInfo;

                var handle = Bass.RecordStart(info.Frequency, info.Channels, BassFlags.RecordPause, null);

                _devices[id].RecordingHandle = handle;

                BassMix.MixerAddChannel(_mixer, handle, BassFlags.MixerDownMix | BassFlags.MixerLimit);

                if (_running)
                {
                    Bass.ChannelPlay(handle);
                }
            }
        }
Пример #7
0
        public void AddChannelToBassMix(IBassAudioChannel channel)
        {
            Debug.Assert(Handle != 0);
            Debug.Assert(channel.Handle != 0);

            BassFlags flags = BassFlags.MixerChanBuffer | BassFlags.MixerChanNoRampin;

            if (channel.MixerChannelPaused)
            {
                flags |= BassFlags.MixerChanPause;
            }

            if (BassMix.MixerAddChannel(Handle, channel.Handle, flags))
            {
                activeChannels.Add(channel);
            }
        }
Пример #8
0
        /// <summary>
        /// Creates a new instance of <see cref="MixedAudioProvider"/>.
        /// </summary>
        /// <param name="RecordingDevice">Index of Recording Device. null = No Microphone Recording.</param>
        /// <param name="LoopbackDevice">Index of Loopback Device. null = No Loopback Recording.</param>
        /// <exception cref="InvalidOperationException">Can't Record when both <paramref name="LoopbackDevice"/> and <paramref name="RecordingDevice"/> are null.</exception>
        public MixedAudioProvider(int?RecordingDevice, int?LoopbackDevice)
        {
            if (RecordingDevice == null && LoopbackDevice == null)
            {
                throw new InvalidOperationException("Nothing to Record.");
            }

            _mixer = BassMix.CreateMixerStream(44100, 2, BassFlags.Default);

            if (RecordingDevice != null)
            {
                Bass.RecordInit(RecordingDevice.Value);
                Bass.CurrentRecordingDevice = RecordingDevice.Value;

                var info = Bass.RecordingInfo;

                _recording = Bass.RecordStart(info.Frequency, info.Channels, BassFlags.Float | BassFlags.RecordPause, null);

                BassMix.MixerAddChannel(_mixer, _recording, BassFlags.MixerDownMix);
            }

            if (LoopbackDevice != null)
            {
                var playbackDevice = FindPlaybackDevice(LoopbackDevice.Value);

                Bass.Init(playbackDevice);
                Bass.CurrentDevice = playbackDevice;

                _silence = Bass.CreateStream(44100, 2, BassFlags.Float, ManagedBass.Extensions.SilenceStreamProcedure);

                Bass.RecordInit(LoopbackDevice.Value);
                Bass.CurrentRecordingDevice = LoopbackDevice.Value;

                var info = Bass.RecordingInfo;

                _loopback = Bass.RecordStart(info.Frequency, info.Channels, BassFlags.Float | BassFlags.RecordPause, null);

                BassMix.MixerAddChannel(_mixer, _loopback, BassFlags.MixerDownMix);
            }

            // mute the mixer
            Bass.ChannelSetAttribute(_mixer, ChannelAttribute.Volume, 0);

            Bass.ChannelSetDSP(_mixer, Procedure);
        }
Пример #9
0
        /// <summary>
        /// Adds a channel to the native BASS mix.
        /// </summary>
        public void AddChannelToBassMix(IBassAudioChannel channel)
        {
            // TODO: This fails and throws unobserved exceptions in github CI runs on macOS.
            // Needs further investigation at some point as something is definitely not right.
            // Debug.Assert(Handle != 0);
            // Debug.Assert(channel.Handle != 0);

            BassFlags flags = BassFlags.MixerChanBuffer | BassFlags.MixerChanNoRampin;

            if (channel.MixerChannelPaused)
            {
                flags |= BassFlags.MixerChanPause;
            }

            if (BassMix.MixerAddChannel(Handle, channel.Handle, flags))
            {
                activeChannels.Add(channel);
            }
        }
Пример #10
0
 public override void Connect(IBassStreamComponent previous)
 {
     this.ConfigureWASAPI(previous);
     if (this.ShouldCreateMixer(previous))
     {
         Logger.Write(this, LogLevel.Debug, "Creating BASS MIX stream with rate {0} and {1} channels.", this.Rate, this.Channels);
         this.ChannelHandle = BassMix.CreateMixerStream(this.Rate, this.Channels, this.Flags);
         if (this.ChannelHandle == 0)
         {
             BassUtils.Throw();
         }
         Logger.Write(this, LogLevel.Debug, "Adding stream to the mixer: {0}", previous.ChannelHandle);
         BassUtils.OK(BassMix.MixerAddChannel(this.ChannelHandle, previous.ChannelHandle, BassFlags.Default | BassFlags.MixerBuffer));
         BassUtils.OK(BassWasapiHandler.StreamSet(this.ChannelHandle));
         this.MixerChannelHandles.Add(previous.ChannelHandle);
     }
     else
     {
         Logger.Write(this, LogLevel.Debug, "The stream properties match the device, playing directly.");
         BassUtils.OK(BassWasapiHandler.StreamSet(previous.ChannelHandle));
     }
 }
Пример #11
0
        /// <summary>
        /// 切鸡鸡
        /// </summary>
        /// <param name="dir_path"></param>
        /// <param name="specific_bms_file_name">可选,钦定文件夹下某个bms谱面文件,如果不钦定就随机选取一个</param>
        /// <param name="start_time">起始时间,单位毫秒或者百分比,默认最初</param>
        /// <param name="end_time">终止时间,单位毫秒或者百分比,默认谱面末尾</param>
        /// <param name="encoder_command_line">编码命令</param>
        /// <param name="save_file_name">保存的文件名</param>
        public static bool GeneratePreviewAudio(
            string dir_path,
            string specific_bms_file_name = null,
            string start_time             = null,
            string end_time             = null,
            string encoder_command_line = "",
            string save_file_name       = "preview_auto_generator.ogg",
            int fade_out     = 0,
            int fade_in      = 0,
            bool check_vaild = false,
            bool fast_clip   = false,
            bool no_skip     = false)
        {
            var created_audio_handles = new HashSet <int>();
            var sync_record           = new HashSet <int>();
            int mixer = 0;

            try
            {
                save_file_name = string.IsNullOrWhiteSpace(save_file_name) ? "preview_auto_generator.ogg" : save_file_name;

                if (!Directory.Exists(dir_path))
                {
                    throw new Exception($"Directory {dir_path} not found.");
                }

                var bms_file_path = string.IsNullOrWhiteSpace(specific_bms_file_name) ? Directory.EnumerateFiles(dir_path, "*.bm*", SearchOption.TopDirectoryOnly).Where(x => support_bms_format.Any(y => x.EndsWith(y, StringComparison.InvariantCultureIgnoreCase))).FirstOrDefault() : Path.Combine(dir_path, specific_bms_file_name);

                if (!File.Exists(bms_file_path))
                {
                    throw new Exception($"BMS file {bms_file_path} not found.");
                }

                Console.WriteLine($"BMS file path:{bms_file_path}");

                var content = File.ReadAllText(bms_file_path);

                if (((check_vaild && CheckBeforeFileVaild(dir_path, save_file_name)) || CheckSkipable(dir_path, content)) && !no_skip)
                {
                    Console.WriteLine("This bms contains preview audio file, skiped.");
                    return(true);
                }

                var chart = bms_file_path.EndsWith(".bmson", StringComparison.InvariantCultureIgnoreCase) ? new BmsonChart(content) as Chart : new BMSChart(content);
                chart.Parse(ParseType.Header);
                chart.Parse(ParseType.Resources);
                chart.Parse(ParseType.Content);


                var audio_map = chart.IterateResourceData(ResourceType.wav)
                                .Select(x => (x.resourceId, Directory.EnumerateFiles(dir_path, $"{Path.GetFileNameWithoutExtension(x.dataPath)}.*").FirstOrDefault()))
                                .Select(x => (x.resourceId, LoadAudio(x.Item2)))
                                .ToDictionary(x => x.resourceId, x => x.Item2);

                var bms_evemts = chart.Events
                                 .Where(e => e.type ==
                                        BMSEventType.WAV ||
                                        e.type == BMSEventType.Note ||
                                        e.type == BMSEventType.LongNoteEnd ||
                                        e.type == BMSEventType.LongNoteStart)
                                 .OrderBy(x => x.time)
                                 .Where(x => audio_map.ContainsKey(x.data2))//filter
                                 .ToArray();

                //init mixer
                mixer = BassMix.CreateMixerStream(44100, 2, BassFlags.Decode | BassFlags.MixerNonStop);

                //build triggers
                var mixer_events = new List <MixEventBase>(bms_evemts.Select(x => new AudioMixEvent()
                {
                    Time        = x.time,
                    Duration    = TimeSpan.FromSeconds(Bass.ChannelBytes2Seconds(audio_map[x.data2], Bass.ChannelGetLength(audio_map[x.data2]))),
                    PlayOffset  = TimeSpan.Zero,
                    AudioHandle = audio_map[x.data2]
                }));

                #region Calculate and Adjust StartTime/EndTime

                var full_audio_duration = mixer_events.OfType <AudioMixEvent>().Max(x => x.Duration + x.Time).Add(TimeSpan.FromSeconds(1));
                var actual_end_time     = string.IsNullOrWhiteSpace(end_time) ? full_audio_duration : (end_time.EndsWith("%") ? TimeSpan.FromMilliseconds(float.Parse(end_time.TrimEnd('%')) / 100.0f * full_audio_duration.TotalMilliseconds) : TimeSpan.FromMilliseconds(int.Parse(end_time)));
                var actual_start_time   = string.IsNullOrWhiteSpace(start_time) ? TimeSpan.Zero : (start_time.EndsWith("%") ? TimeSpan.FromMilliseconds(float.Parse(start_time.TrimEnd('%')) / 100.0f * full_audio_duration.TotalMilliseconds) : TimeSpan.FromMilliseconds(int.Parse(start_time)));

                actual_start_time = actual_start_time < TimeSpan.Zero ? TimeSpan.Zero : actual_start_time;
                actual_start_time = actual_start_time > full_audio_duration ? full_audio_duration : actual_start_time;

                actual_end_time = actual_end_time < TimeSpan.Zero ? TimeSpan.Zero : actual_end_time;
                actual_end_time = actual_end_time > full_audio_duration ? full_audio_duration : actual_end_time;

                if (actual_end_time < actual_start_time)
                {
                    var t = actual_end_time;
                    actual_end_time   = actual_start_time;
                    actual_start_time = t;
                }

                Console.WriteLine($"Actual clip({(int)full_audio_duration.TotalMilliseconds}ms):{(int)actual_start_time.TotalMilliseconds}ms ~ {(int)actual_end_time.TotalMilliseconds}ms");

                #endregion

                if (fast_clip)
                {
                    FastClipEvent(mixer_events, ref actual_start_time, ref actual_end_time);
                }

                //add special events to control encorder and mixer
                mixer_events.Add(new StopMixEvent {
                    Time = actual_end_time
                });
                mixer_events.Add(new StartMixEvent()
                {
                    Time = actual_start_time
                });

                //save encoder handle
                int encoder = 0;

                #region apply fade in/out

                var effect = new VolumeParameters();
                var fx     = Bass.ChannelSetFX(mixer, effect.FXType, 0);

                if (fade_in != 0)
                {
                    var fade_in_evt = new FadeMixEvent(false, fade_in)
                    {
                        Time = actual_start_time
                    };

                    mixer_events.Add(fade_in_evt);
                }

                if (fade_out != 0)
                {
                    var fade_out_evt = new FadeMixEvent(true, fade_out)
                    {
                        Time = actual_end_time.Subtract(TimeSpan.FromMilliseconds(fade_out))
                    };

                    mixer_events.Add(fade_out_evt);
                }

                #endregion

                foreach (var evt in mixer_events)
                {
                    var trigger_position = Bass.ChannelSeconds2Bytes(mixer, evt.Time.TotalSeconds);

                    sync_record.Add(Bass.ChannelSetSync(mixer, SyncFlags.Position | SyncFlags.Mixtime, trigger_position, (nn, mm, ss, ll) =>
                    {
                        if (evt is StopMixEvent && encoder != 0)
                        {
                            Bass.ChannelStop(mixer);
                            BassEnc.EncodeStop(encoder);
                            encoder = 0;
                        }
                        else if (evt is StartMixEvent && encoder == 0)
                        {
                            var output_path = Path.Combine(dir_path, save_file_name);
                            Console.WriteLine($"Encoding output file path:{output_path}");
                            encoder = BassEnc_Ogg.Start(mixer, encoder_command_line, EncodeFlags.AutoFree, output_path);
                        }
                        else if (evt is AudioMixEvent audio)
                        {
                            var handle = audio.AudioHandle;
                            BassMix.MixerRemoveChannel(handle);
                            Bass.ChannelSetPosition(handle, Bass.ChannelSeconds2Bytes(handle, audio.PlayOffset.TotalSeconds));
                            BassMix.MixerAddChannel(mixer, handle, BassFlags.Default);
                        }
                        else if (evt is FadeMixEvent fade)
                        {
                            effect.fTime = fade.Duration / 1000.0f;

                            if (fade.FadeOut)
                            {
                                effect.fCurrent = 1;
                                effect.fTarget  = 0;
                            }
                            else
                            {
                                effect.fCurrent = 0;
                                effect.fTarget  = 1;
                            }

                            Bass.FXSetParameters(fx, effect);
                        }
                    }));
                }

                WaitChannelDataProcessed(mixer);

                Console.WriteLine("Success!");
                return(true);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Failed.\n{ex.Message}\n{ex.StackTrace}");
                return(false);
            }
            finally
            {
                #region Clean Resource

                foreach (var record in sync_record)
                {
                    Bass.ChannelRemoveSync(mixer, record);
                }

                foreach (var handle in created_audio_handles)
                {
                    Bass.StreamFree(handle);
                }

                if (mixer != 0)
                {
                    Bass.StreamFree(mixer);
                }

                #endregion
            }

            int LoadAudio(string item2)
            {
                var handle = Bass.CreateStream(item2, 0, 0, BassFlags.Decode | BassFlags.Float);

                created_audio_handles.Add(handle);

                return(handle);
            }
        }
Пример #12
0
        /// <inheritdoc />
        public void Load(string fileName)
        {
            _networkstream = ExtensionProvider.IsNetworkStream(fileName);

            Log.Info("Loading file: {0}", fileName);

            if (_decodeChannel != 0 || _mixerChannel != 0)
            {
                Stop();
            }

            try { Bass.StreamFree(_decodeChannel); }
            catch (Exception ex) { Debug.WriteLine(ex); }

            if (string.IsNullOrEmpty(fileName))
            {
                Log.Error("Filename was null or empty. Aborted load");
                return;
            }

            var sourceflags = BassFlags.Decode | BassFlags.Loop | BassFlags.Float | BassFlags.Prescan;
            var mixerflags  = BassFlags.MixerDownMix | BassFlags.MixerPositionEx | BassFlags.AutoFree;

            if (_networkstream)
            {
                int r;
                lock (Lock)
                {
                    // make sure only 1 thread at a time can do the following
                    // increment the request counter for this request
                    r = ++_req;
                }
                var netFlags = BassFlags.StreamDownloadBlocks | sourceflags;
                Bass.NetProxy  = ""; //os default proxy
                _decodeChannel = Bass.CreateStream(fileName, 0, netFlags, _streamDloadProc, new IntPtr(r));
                lock (Lock)
                {
                    if (r != _req)
                    {
                        if (_decodeChannel != 0)
                        {
                            Bass.StreamFree(_decodeChannel);
                        }
                        return;
                    }
                }
                _netadress = fileName;
            }
            else
            {
                if (ExtensionProvider.IsCdStream(fileName))
                {
                    var cd = new CDTrackInfo(fileName);
                    _decodeChannel = BassCd.CreateStream(cd.Drive, cd.Track, sourceflags);
                    Log.Info("Geting track metadata...");
                    UpdateCDTags(cd.Drive, cd.Track);
                }
                else
                {
                    _decodeChannel = Bass.CreateStream(fileName, 0, 0, sourceflags);
                    Log.Info("Geting track metadata...");
                    UpdateFileTags(fileName);
                }
            }

            if (_decodeChannel == 0)
            {
                Log.Error("Decode chanel creation failed: {0}", Bass.LastError);
                return;
            }

            var channelInfo = Bass.ChannelGetInfo(_decodeChannel);

            _mixerChannel = BassMix.CreateMixerStream(channelInfo.Frequency, channelInfo.Channels, mixerflags);
            if (_mixerChannel == 0)
            {
                Log.Error("Mixer chanel creation failed: {0}", Bass.LastError);
                return;
            }
            if (!BassMix.MixerAddChannel(_mixerChannel, _decodeChannel, BassFlags.MixerDownMix))
            {
                Log.Error("Failed to route decoded stream to mixer: {0}", Bass.LastError);
                return;
            }

            if (!_networkstream)
            {
                Log.Info("Getting track length...");
                var len = Bass.ChannelGetLength(_decodeChannel, PositionFlags.Bytes);
                _length = Bass.ChannelBytes2Seconds(_decodeChannel, len);
                NotifyChanged(nameof(Length));

                Log.Info("Getting Chapters...");
                Chapters.Clear();
                Chapters.AddRange(ChapterFactory.GetChapters(fileName, _length));
            }

            Volume = _LastVolume;
            Bass.ChannelSetAttribute(_mixerChannel, ChannelAttribute.Volume, Volume);
            Log.Info("Loaded file {0}", fileName);
        }
Пример #13
0
 public bool AddChannel(Channel channel)
 {
     return(BassMix.MixerAddChannel(Handle, channel.Handle, BassFlags.Default));
 }
Пример #14
0
        public void Load(string url)
        {
            CurrentMediaKind = MediaKind.None;

            FreeHandles();

            if (FormatHelpers.IsMidi(url) && File.Exists(_configuration.SoundFontPath))
            {
                BassMidi.DefaultFont = _configuration.SoundFontPath;
            }

            const BassFlags sourceflags = BassFlags.Decode | BassFlags.Loop | BassFlags.Float | BassFlags.Prescan;
            const BassFlags mixerflags  = BassFlags.MixerDownMix | BassFlags.MixerPositionEx | BassFlags.AutoFree;

            if (FormatHelpers.IsNetwork(url))
            {
                _sourceHandle    = Bass.CreateStream(url, 0, sourceflags, _callback, IntPtr.Zero);
                CurrentMediaKind = MediaKind.Network;
            }
            else if (FormatHelpers.IsCd(url))
            {
                (int drive, int track)cdInfo = FormatHelpers.ProcessCdUrl(url);
                _sourceHandle    = BassCd.CreateStream(cdInfo.drive, cdInfo.track, sourceflags);
                CurrentMediaKind = MediaKind.CDStream;
            }
            else if (FormatHelpers.IsTracker(url))
            {
                _sourceHandle    = Bass.MusicLoad(url, 0, 0, sourceflags);
                CurrentMediaKind = MediaKind.Tracker;
                MetaInfo         = TrackMetaInfoFactory.CreateTrackerInfo(url, _sourceHandle);
            }
            else
            {
                _sourceHandle    = Bass.CreateStream(url, 0, 0, sourceflags);
                CurrentMediaKind = MediaKind.File;
                MetaInfo         = TrackMetaInfoFactory.CreateFileInfo(url);
            }

            if (_sourceHandle == 0)
            {
                ExceptionFactory.Create(Bass.LastError, "File Load failed");
            }

            _sourceInfo  = Bass.ChannelGetInfo(_sourceHandle);
            _mixerHandle = BassMix.CreateMixerStream(_sourceInfo.Frequency, _sourceInfo.Channels, mixerflags);

            if (_mixerHandle == 0)
            {
                ExceptionFactory.Create(Bass.LastError, "Mixer failed");
            }

            if (!BassMix.MixerAddChannel(_mixerHandle, _sourceHandle, BassFlags.MixerDownMix))
            {
                ExceptionFactory.Create(Bass.LastError, "Channel mixing failed");
            }

            Bass.ChannelSetAttribute(_mixerHandle, ChannelAttribute.Volume, _lastvol);
            InitEq(ref _mixerHandle);
            Bass.ChannelPlay(_mixerHandle, false);
            IsPlaying = true;
            NotifyPropertyChanged(nameof(MetaInfo));
        }
Пример #15
0
        void InitLoopbackDevice(BassItem LoopbackDevice)
        {
            var playbackDevice = FindPlaybackDevice(LoopbackDevice.Id);

            _loopback.Add(LoopbackDevice.Id, new LoopbackItem
            {
                DeviceId         = LoopbackDevice.Id,
                PlaybackDeviceId = playbackDevice
            });

            void AddDevice()
            {
                lock (_syncLock)
                {
                    if (_loopback[LoopbackDevice.Id].RecordingHandle != 0)
                    {
                        return;
                    }

                    Bass.Init(playbackDevice);
                    Bass.CurrentDevice = playbackDevice;

                    var silence = Bass.CreateStream(44100, 2, BassFlags.Float, ManagedBass.Extensions.SilenceStreamProcedure);

                    _loopback[LoopbackDevice.Id].SilenceStreamHandle = silence;

                    Bass.RecordInit(LoopbackDevice.Id);
                    Bass.CurrentRecordingDevice = LoopbackDevice.Id;

                    var info = Bass.RecordingInfo;

                    var handle = Bass.RecordStart(info.Frequency, info.Channels, BassFlags.Float | BassFlags.RecordPause, null);

                    _loopback[LoopbackDevice.Id].RecordingHandle = handle;

                    BassMix.MixerAddChannel(_mixer, handle, BassFlags.MixerDownMix);

                    if (_running)
                    {
                        Bass.ChannelPlay(silence);
                        Bass.ChannelPlay(handle);
                    }
                }
            }

            void RemoveDevice()
            {
                lock (_syncLock)
                {
                    if (_loopback[LoopbackDevice.Id].RecordingHandle == 0)
                    {
                        return;
                    }

                    var item = _loopback[LoopbackDevice.Id];

                    BassMix.MixerRemoveChannel(item.RecordingHandle);

                    Bass.StreamFree(item.RecordingHandle);

                    Bass.StreamFree(item.SilenceStreamHandle);

                    _loopback[LoopbackDevice.Id].RecordingHandle     = 0;
                    _loopback[LoopbackDevice.Id].SilenceStreamHandle = 0;
                }
            }

            LoopbackDevice.PropertyChanged += (S, E) =>
            {
                if (E.PropertyName == nameof(LoopbackDevice.Active))
                {
                    if (LoopbackDevice.Active)
                    {
                        AddDevice();
                    }
                    else
                    {
                        RemoveDevice();
                    }
                }
            };

            if (LoopbackDevice.Active)
            {
                AddDevice();
            }
        }
Пример #16
0
        void InitDevice(BassItem Device)
        {
            _devices.Add(Device.Id, new RecordingItem
            {
                DeviceId = Device.Id
            });

            void AddDevice()
            {
                lock (_syncLock)
                {
                    if (_devices[Device.Id].RecordingHandle != 0)
                    {
                        return;
                    }

                    Bass.RecordInit(Device.Id);
                    Bass.CurrentRecordingDevice = Device.Id;

                    var info = Bass.RecordingInfo;

                    var handle = Bass.RecordStart(info.Frequency, info.Channels, BassFlags.Float | BassFlags.RecordPause, null);

                    _devices[Device.Id].RecordingHandle = handle;

                    BassMix.MixerAddChannel(_mixer, handle, BassFlags.MixerDownMix);

                    if (_running)
                    {
                        Bass.ChannelPlay(handle);
                    }
                }
            }

            void RemoveDevice()
            {
                lock (_syncLock)
                {
                    if (_devices[Device.Id].RecordingHandle == 0)
                    {
                        return;
                    }

                    var handle = _devices[Device.Id].RecordingHandle;

                    BassMix.MixerRemoveChannel(handle);

                    Bass.StreamFree(handle);

                    _devices[Device.Id].RecordingHandle = 0;
                }
            }

            Device.PropertyChanged += (S, E) =>
            {
                if (E.PropertyName == nameof(Device.Active))
                {
                    if (Device.Active)
                    {
                        AddDevice();
                    }
                    else
                    {
                        RemoveDevice();
                    }
                }
            };

            if (Device.Active)
            {
                AddDevice();
            }
        }
Пример #17
0
        /// <summary>
        /// Load a file for playback
        /// </summary>
        /// <param name="file">File to load</param>
        public void Load(string file)
        {
            _isstream = false;
            if (Helpers.IsMidi(file))
            {
                if (!File.Exists(Properties.Settings.Default.SoundfontPath))
                {
                    Error(Resources.Engine_ErrorSoundfont);
                    return;
                }
                BassMidi.DefaultFont = Properties.Settings.Default.SoundfontPath;
            }
            if (_source != 0)
            {
                Bass.StreamFree(_source);
                _source   = 0;
                IsPlaying = false;
            }
            if (_mixer != 0)
            {
                Bass.StreamFree(_mixer);
                _mixer    = 0;
                IsPlaying = false;
            }
            var sourceflags = BassFlags.Decode | BassFlags.Loop | BassFlags.Float | BassFlags.Prescan;
            var mixerflags  = BassFlags.MixerDownMix | BassFlags.MixerPositionEx | BassFlags.AutoFree;

            if (file.StartsWith("http://") || file.StartsWith("https://"))
            {
                _source   = Bass.CreateStream(file, 0, sourceflags, _callback, IntPtr.Zero);
                _isstream = true;
                App.RecentUrls.Add(file);
            }
            else if (file.StartsWith("cd://"))
            {
                string[] info = file.Replace("cd://", "").Split('/');
                _source = BassCd.CreateStream(Convert.ToInt32(info[0]), Convert.ToInt32(info[1]), sourceflags);
            }
            else if (Helpers.IsTracker(file))
            {
                _source = Bass.MusicLoad(file, 0, 0, sourceflags);
            }
            else
            {
                _source = Bass.CreateStream(file, 0, 0, sourceflags);
            }
            if (_source == 0)
            {
                Error("Load failed");
                IsPlaying = false;
                _isstream = false;
                return;
            }
            var ch = Bass.ChannelGetInfo(_source);

            _mixer = BassMix.CreateMixerStream(ch.Frequency, ch.Channels, mixerflags);
            if (_mixer == 0)
            {
                Error(Resources.Engine_ErrorMixer);
                IsPlaying = false;
                return;
            }
            if (!BassMix.MixerAddChannel(_mixer, _source, BassFlags.MixerDownMix))
            {
                Error(Resources.Engine_ErrorMixerChannel);
                IsPlaying = false;
                return;
            }
            Bass.ChannelSetAttribute(_mixer, ChannelAttribute.Volume, _lastvol);
            Bass.ChannelPlay(_mixer, false);
            _paused   = false;
            IsPlaying = true;
        }