internal override void DisconnectFile(clsMP3Bass mp3bass) { CheckOK(Bass.ChannelStop(mp3bass.StreamHandle)); CheckOK(BassMix.MixerRemoveChannel(mp3bass.StreamHandle)); CheckOK(Bass.StreamFree(mp3bass.StreamHandle)); mp3bass.StreamHandle = 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; }
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); }
/// <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); }
/// <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); }
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; } }
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; } }
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; } }
public bool RemoveChannel(Channel channel) { return(BassMix.MixerRemoveChannel(channel.Handle)); }
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(); } }
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(); } }
/// <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); } }
/// <summary> /// Removes a Bass Channel from Wasapi Output Mixer. /// </summary> /// <returns>True on Success</returns> public bool RemoveOutputSource(int Channel) => BassMix.MixerRemoveChannel(Channel);