Пример #1
0
 internal override void DisconnectFile(clsMP3Bass mp3bass)
 {
     CheckOK(Bass.ChannelStop(mp3bass.StreamHandle));
     CheckOK(BassMix.MixerRemoveChannel(mp3bass.StreamHandle));
     CheckOK(Bass.StreamFree(mp3bass.StreamHandle));
     mp3bass.StreamHandle = 0;
 }
Пример #2
0
 internal override void DisconnectMidiDev(clsBassOutMidi bassoutmidi)
 {
     CheckOK(Bass.ChannelStop(bassoutmidi.MidiStream));
     CheckOK(BassMix.MixerRemoveChannel(bassoutmidi.MidiStream));
     CheckOK(Bass.StreamFree(bassoutmidi.MidiStream));
     bassoutmidi.MidiStream = 0;
 }
Пример #3
0
        private void removeChannelFromBassMix(IBassAudioChannel channel)
        {
            Debug.Assert(Handle != 0);
            Debug.Assert(channel.Handle != 0);

            channel.MixerChannelPaused = BassMix.ChannelHasFlag(channel.Handle, BassFlags.MixerChanPause);
            BassMix.MixerRemoveChannel(channel.Handle);
        }
Пример #4
0
        /// <summary>
        /// Removes a channel from the native BASS mix.
        /// </summary>
        private void removeChannelFromBassMix(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);

            channel.MixerChannelPaused = BassMix.ChannelHasFlag(channel.Handle, BassFlags.MixerChanPause);
            BassMix.MixerRemoveChannel(channel.Handle);
        }
Пример #5
0
        /// <summary>
        /// Remove an addd channel from this mixer.
        /// </summary>
        /// <param name="Label">Channel label.</param>
        public void RemoveChannel(string Label)
        {
            if (!Channels.ContainsKey(Label))
            {
                return;
            }

            foreach (IMixableComponent Component in Channels[Label])
            {
                BassMix.MixerRemoveChannel(Component.StreamHandler);
                Component.Parent = null;
            }

            Channels.Remove(Label);
        }
Пример #6
0
        void RemoveDevice(BassItem Device)
        {
            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;

                Bass.StreamFree(_devices[Device.Id].SilenceHandle);

                _devices[Device.Id].SilenceHandle = 0;
            }
        }
Пример #7
0
        private void RemoveDevice(BassItem device)
        {
            lock (_syncLock)
            {
                if (_devices[device.Id].RecordingHandle == 0)
                {
                    return;
                }

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

                BassMix.MixerRemoveChannel(handle);

                ManagedBass.Bass.StreamFree(handle);

                _devices[device.Id].RecordingHandle = 0;

                ManagedBass.Bass.StreamFree(_devices[device.Id].SilenceHandle);

                _devices[device.Id].SilenceHandle = 0;
            }
        }
Пример #8
0
        void RemoveDevice(IIsActive <BassItem> Device)
        {
            lock (_syncLock)
            {
                var id = Device.Item.Id;

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

                var handle = _devices[id].RecordingHandle;

                BassMix.MixerRemoveChannel(handle);

                Bass.StreamFree(handle);

                _devices[id].RecordingHandle = 0;

                Bass.StreamFree(_devices[id].SilenceHandle);

                _devices[id].SilenceHandle = 0;
            }
        }
Пример #9
0
 public bool RemoveChannel(Channel channel)
 {
     return(BassMix.MixerRemoveChannel(channel.Handle));
 }
Пример #10
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();
            }
        }
Пример #11
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();
            }
        }
Пример #12
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);
            }
        }
Пример #13
0
 /// <summary>
 /// Removes a Bass Channel from Wasapi Output Mixer.
 /// </summary>
 /// <returns>True on Success</returns>
 public bool RemoveOutputSource(int Channel) => BassMix.MixerRemoveChannel(Channel);