/// <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; } }
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)); }
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)); }
/// <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)); }
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); }
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); } } }
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); } }
/// <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); }
/// <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); } }
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)); } }
/// <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); } }
/// <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); }
public bool AddChannel(Channel channel) { return(BassMix.MixerAddChannel(Handle, channel.Handle, BassFlags.Default)); }
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)); }
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(); } }
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(); } }
/// <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; }