using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Text; using System.Threading; using System.Threading.Tasks; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v1.4", FrameworkDisplayName = "")] [assembly: AssemblyCompany("MathewSachin")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription(".Net wrapper for un4seen BASS audio library")] [assembly: AssemblyFileVersion("3.1.1.0")] [assembly: AssemblyInformationalVersion("3.1.1")] [assembly: AssemblyProduct("ManagedBass")] [assembly: AssemblyTitle("ManagedBass")] [assembly: AssemblyVersion("3.1.1.0")] namespace ManagedBass { public enum DSInterface { IDirectSound = 1, IDirectSound3DListener } public enum EAXEnvironment { LeaveCurrent = -1, Generic, PaddedCell, Room, Bathroom, Livingroom, Stoneroom, Auditorium, ConcertHall, Cave, Arena, Hangar, CarpetedHallway, Hallway, StoneCorridor, Alley, Forest, City, Mountains, Quarry, Plain, ParkingLot, SewerPipe, Underwater, Drugged, Dizzy, Psychotic, Count } public abstract class Effect : INotifyPropertyChanged, IDisposable where T : class, IEffectParameter, new() { private int _channel; private int _effectHandle; private int _hfsync; private GCHandle _gch; private int _priority; protected T Parameters { get; private set; } = new T(); public int Priority { get { return _priority; } set { if (IsActive && Bass.FXSetPriority(_effectHandle, value)) { _priority = value; } } } public bool IsActive { get { if (_channel != 0) { return _effectHandle != 0; } return false; } set { if (_channel != 0) { if (value && !IsActive) { _effectHandle = Bass.ChannelSetFX(_channel, Parameters.FXType, 1); } else if (!value && IsActive && Bass.ChannelRemoveFX(_channel, _effectHandle)) { _effectHandle = 0; } OnPropertyChanged("IsActive"); } } } public event PropertyChangedEventHandler PropertyChanged; public void ApplyOn(int Channel, int Priority = 0) { _channel = Channel; _priority = Priority; if (!_gch.IsAllocated) { _gch = GCHandle.Alloc(Parameters, GCHandleType.Pinned); } _hfsync = Bass.ChannelSetSync(Channel, SyncFlags.Free, 0L, delegate { Dispose(); }, (IntPtr)0); } public void Dispose() { Bass.ChannelRemoveSync(_channel, _hfsync); _channel = (_effectHandle = 0); if (_gch.IsAllocated) { _gch.Free(); } } public void Default() { _gch.Free(); Parameters = new T(); _gch = GCHandle.Alloc(Parameters, GCHandleType.Pinned); OnPreset(); } protected void OnPreset() { OnPropertyChanged(""); } protected virtual void OnPropertyChanged([CallerMemberName] string PropertyName = null) { this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(PropertyName)); } } public class GCPin : IDisposable { private GCHandle _gcHandle; public IntPtr Pointer => _gcHandle.AddrOfPinnedObject(); public GCPin(object Item) { _gcHandle = GCHandle.Alloc(Item, GCHandleType.Pinned); } public static int CreateStreamHelper(Func Function, object Memory) { GCHandle GCPin = GCHandle.Alloc(Memory, GCHandleType.Pinned); int num = Function(GCPin.AddrOfPinnedObject()); if (num == 0) { GCPin.Free(); } else { Bass.ChannelSetSync(num, SyncFlags.Free, 0L, delegate { GCPin.Free(); }, (IntPtr)0); } return num; } public void Dispose() { _gcHandle.Free(); } } public class BassException : Exception { public Errors ErrorCode { get; } public BassException() : this(Bass.LastError) { } public BassException(Errors ErrorCode) : base($"Error: {ErrorCode}") { this.ErrorCode = ErrorCode; } } public delegate void DownloadProcedure(IntPtr Buffer, int Length, IntPtr User); public delegate void DSPProcedure(int Handle, int Channel, IntPtr Buffer, int Length, IntPtr User); public delegate void FileCloseProcedure(IntPtr User); public delegate long FileLengthProcedure(IntPtr User); public delegate int FileReadProcedure(IntPtr Buffer, int Length, IntPtr User); public delegate bool FileSeekProcedure(long Offset, IntPtr User); public delegate bool RecordProcedure(int Handle, IntPtr Buffer, int Length, IntPtr User); public delegate int StreamProcedure(int Handle, IntPtr Buffer, int Length, IntPtr User); public delegate void SyncProcedure(int Handle, int Channel, int Data, IntPtr User); public enum Algorithm3D { Default, Off, Full, Light } [Flags] public enum BassFlags : uint { Default = 0u, Byte = 1u, Mono = 2u, Loop = 4u, Bass3D = 8u, SoftwareMixing = 0x10u, FX = 0x80u, Float = 0x100u, Prescan = 0x20000u, AutoFree = 0x40000u, RestrictDownloadRate = 0x80000u, StreamDownloadBlocks = 0x100000u, Decode = 0x200000u, StreamStatus = 0x800000u, AsyncFile = 0x40000000u, Unicode = 0x80000000u, FxBpmBackground = 1u, FXBpmMult2 = 2u, FxTempoAlgorithmLinear = 0x200u, FxTempoAlgorithmCubic = 0x400u, FxTempoAlgorithmShannon = 0x800u, FxFreeSource = 0x10000u, MidiNoHeader = 1u, Midi16Bit = 2u, MidiNoSystemReset = 0x800u, MidiDecayEnd = 0x1000u, MidiNoFx = 0x2000u, MidiDecaySeek = 0x4000u, MidiNoCrop = 0x8000u, MidiNoteOff1 = 0x10000u, MidiFontMemoryMap = 0x20000u, MidiFontXGDRUMS = 0x40000u, SincInterpolation = 0x800000u, MusicRamp = 0x200u, MusicSensitiveRamping = 0x400u, MusicSurround = 0x800u, MusicSurround2 = 0x1000u, MusicFT2Mod = 0x2000u, MusicFT2PAN = 0x2000u, MusicPT1Mod = 0x4000u, MusicPositionReset = 0x8000u, MusicNonInterpolated = 0x10000u, MusicStopBack = 0x80000u, MusicNoSample = 0x100000u, MusicPositionResetEx = 0x400000u, MuteMax = 0x20u, VAM = 0x40u, SampleOverrideLowestVolume = 0x10000u, SampleOverrideLongestPlaying = 0x20000u, SampleOverrideDistance = 0x30000u, SampleChannelNew = 1u, SampleChannelStream = 2u, CDSubChannel = 0x200u, CDSubchannelNoHW = 0x400u, CdC2Errors = 0x800u, MixerChanAbsolute = 0x1000u, SplitSlave = 0x1000u, SplitPosition = 0x2000u, MixerResume = 0x1000u, MixerPositionEx = 0x2000u, MixerChanBuffer = 0x2000u, [Obsolete("Renamed to MixerChanBuffer for clarity.")] MixerBuffer = 0x2000u, MixerChanLimit = 0x4000u, [Obsolete("Renamed to MixerChanLimit for clarity.")] MixerLimit = 0x4000u, MixerEnd = 0x10000u, MixerChanMatrix = 0x10000u, [Obsolete("Renamed to MixerChanMatrix for clarity.")] MixerMatrix = 0x10000u, MixerNonStop = 0x20000u, MixerChanPause = 0x20000u, [Obsolete("Renamed to MixerChanPause for clarity.")] MixerPause = 0x20000u, MixerChanDownMix = 0x400000u, [Obsolete("Renamed to MixerChanDownMix for clarity.")] MixerDownMix = 0x400000u, MixerChanNoRampin = 0x800000u, [Obsolete("Renamed to MixerChanNoRampin for clarity.")] MixerNoRampin = 0x800000u, RecordPause = 0x8000u, RecordEchoCancel = 0x2000u, RecordAGC = 0x4000u, SpeakerFront = 0x1000000u, SpeakerRear = 0x2000000u, SpeakerCenterLFE = 0x3000000u, SpeakerRearCenter = 0x4000000u, SpeakerPair1 = 0x1000000u, SpeakerPair2 = 0x2000000u, SpeakerPair3 = 0x3000000u, SpeakerPair4 = 0x4000000u, SpeakerPair5 = 0x5000000u, SpeakerPair6 = 0x6000000u, SpeakerPair7 = 0x7000000u, SpeakerPair8 = 0x8000000u, SpeakerPair9 = 0x9000000u, SpeakerPair10 = 0xA000000u, SpeakerPair11 = 0xB000000u, SpeakerPair12 = 0xC000000u, SpeakerPair13 = 0xD000000u, SpeakerPair14 = 0xE000000u, SpeakerPair15 = 0xF000000u, SpeakerLeft = 0x10000000u, SpeakerRight = 0x20000000u, SpeakerFrontLeft = 0x11000000u, SpeakerRearLeft = 0x12000000u, SpeakerCenter = 0x13000000u, SpeakerRearCenterLeft = 0x14000000u, SpeakerFrontRight = 0x21000000u, SpeakerRearRight = 0x22000000u, SpeakerLFE = 0x23000000u, SpeakerRearCenterRight = 0x24000000u, AacFrame960 = 0x1000u, AacStereo = 0x400000u, DSDOverPCM = 0x400u, DSDRaw = 0x200u, Ac3DownmixStereo = 0x200u, Ac3DownmixQuad = 0x400u, Ac3DownmixDolby = 0x600u, Ac3DRC = 0x800u, DShowNoAudioProcessing = 0x80000u, DShowStreamMix = 0x1000000u, DShowAutoDVD = 0x4000000u, DShowLoop = 0x8000000u, DShowVideoProcessing = 0x20000u, WVStereo = 0x400000u } [Flags] internal enum BASSInfoFlags { None = 0, ContinuousRate = 0x10, EmulatedDrivers = 0x20, Certified = 0x40, Mono = 0x100, Stereo = 0x200, Secondary8Bit = 0x400, Secondary16Bit = 0x800 } public enum ChannelAttribute { Frequency = 1, Volume = 2, Pan = 3, EaxMix = 4, NoBuffer = 5, CPUUsage = 7, SampleRateConversion = 8, NetworkResumeBufferLevel = 9, ScannedInfo = 10, NoRamp = 11, Bitrate = 12, Buffer = 13, Granule = 14, MusicAmplify = 256, MusicPanSeparation = 257, MusicPositionScaler = 258, MusicBPM = 259, MusicSpeed = 260, MusicVolumeGlobal = 261, MusicActiveChannelCount = 262, MusicVolumeChannel = 512, MusicVolumeInstrument = 768, Tempo = 65536, Pitch = 65537, TempoFrequency = 65538, TempoUseAAFilter = 65552, TempoAAFilterLength = 65553, TempoUseQuickAlgorithm = 65554, TempoSequenceMilliseconds = 65555, TempoSeekWindowMilliseconds = 65556, TempoOverlapMilliseconds = 65557, TempoPreventClick = 65558, ReverseDirection = 69632, MidiPPQN = 73728, MidiCPU = 73729, MidiChannels = 73730, MidiVoices = 73731, MidiVoicesActive = 73732, MidiState = 73733, MidiSRC = 73734, MidiKill = 73735, MidiTrackVolume = 73984, OpusOriginalFrequency = 77824, DSDGain = 81920, DSDRate = 81921, MixerLatency = 86016, SplitAsyncBuffer = 86032, SplitAsyncPeriod = 86033 } [Flags] public enum ChannelType { Unknown = 0, Sample = 1, Recording = 2, MO3 = 0x100, ZXTune = -820183040, Stream = 0x10000, OGG = 0x10002, MP1 = 0x10003, MP2 = 0x10004, MP3 = 0x10005, AIFF = 0x10006, CA = 0x10007, MF = 0x10008, CD = 0x10200, WMA = 0x10300, WMA_MP3 = 0x10301, WINAMP = 0x10400, WV = 0x10500, WV_H = 0x10501, WV_L = 0x10502, WV_LH = 0x10503, OFR = 0x10600, APE = 0x10700, Mixer = 0x10800, Split = 0x10801, FLAC = 0x10900, FLAC_OGG = 0x10901, MPC = 0x10A00, AAC = 0x10B00, MP4 = 0x10B01, SPX = 0x10C00, MIDI = 0x10D00, ALAC = 0x10E00, TTA = 0x10F00, AC3 = 0x11000, Video = 0x11100, OPUS = 0x11200, DSD = 0x11700, ADX = 0x1F000, AIX = 0x1F001, Tempo = 0x1F200, Reverse = 0x1F201, MOD = 0x20000, MTM = 0x20001, S3M = 0x20002, XM = 0x20003, IT = 0x20004, Wave = 0x40000, WavePCM = 0x50001, WaveFloat = 0x50003, Dummy = 0x18000, Device = 0x18001 } public enum Configuration { PlaybackBufferLength = 0, UpdatePeriod = 1, GlobalSampleVolume = 4, GlobalStreamVolume = 5, GlobalMusicVolume = 6, LogarithmicVolumeCurve = 7, LogarithmicPanCurve = 8, FloatDSP = 9, Algorithm3D = 10, NetTimeOut = 11, NetBufferLength = 12, PauseNoPlay = 13, NetPreBuffer = 15, NetAgent = 16, NetProxy = 17, NetPassive = 18, RecordingBufferLength = 19, NetPlaylist = 21, MusicVirtual = 22, FileVerificationBytes = 23, UpdateThreads = 24, DeviceBufferLength = 27, LoopbackRecording = 28, NoTimerResolution = 29, TruePlayPosition = 30, IOSMixAudio = 34, IOSSession = 34, SuppressMP3ErrorCorruptionSilence = 35, IncludeDefaultDevice = 36, NetReadTimeOut = 37, VistaSpeakerAssignment = 38, IOSSpeaker = 39, MFDisable = 40, HandleCount = 41, UnicodeDeviceInformation = 42, SRCQuality = 43, SampleSRCQuality = 44, AsyncFileBufferLength = 45, IOSNotify = 46, OggPreScan = 47, MFVideo = 48, Airplay = 49, DevNonStop = 50, IOSNoCategory = 51, NetVerificationBytes = 52, DevicePeriod = 53, Float = 54, AndroidSessionId = 62, AndroidAAudio = 67, AC3DynamicRangeCompression = 65537, WmaNetPreBuffer = 65793, WmaBassFileHandling = 65795, WmaNetSeek = 65796, WmaVideo = 65797, WmaAsync = 65807, CDFreeOld = 66048, CDRetry = 66049, CDAutoSpeed = 66050, CDSkipError = 66051, CDDBServer = 66052, EncodePriority = 66304, EncodeQueue = 66305, EncodeACMLoad = 66306, EncodeCastTimeout = 66320, EncodeCastProxy = 66321, MidiCompact = 66560, MidiVoices = 66561, MidiAutoFont = 66562, MidiDefaultFont = 66563, MidiInputPorts = 66564, MixerBufferLength = 67073, MixerPositionEx = 67074, SplitBufferLength = 67088, PlayAudioFromMp4 = 67328, AacSupportMp4 = 67329, DSDFrequency = 67584, WinampInputTimeout = 67584, DSDGain = 67585, ZXTuneMaxFileSize = -820182784 } [Flags] public enum DataFlags { Available = 0, FFTIndividual = 0x10, FFTNoWindow = 0x20, FFTRemoveDC = 0x40, FFTComplex = 0x80, Fixed = 0x20000000, Float = 0x40000000, FFT256 = int.MinValue, FFT512 = -2147483647, FFT1024 = -2147483646, FFT2048 = -2147483645, FFT4096 = -2147483644, FFT8192 = -2147483643, FFT16384 = -2147483642, FFT32768 = -2147483641 } [Flags] public enum DeviceInfoFlags { None = 0, Enabled = 1, Default = 2, Initialized = 4, Loopback = 8, TypeMask = -16777216 } [Flags] public enum DeviceInitFlags { Default = 0, Byte = 1, Mono = 2, Device3D = 4, Bits16 = 8, Latency = 0x100, CPSpeakers = 0x400, ForcedSpeakerAssignment = 0x800, NoSpeakerAssignment = 0x1000, DMix = 0x2000, Frequency = 0x4000, Stereo = 0x8000, Hog = 0x10000, AudioTrack = 0x20000, DirectSound = 0x40000 } public enum DeviceType { Network = 16777216, Speakers = 33554432, Line = 50331648, Headphones = 67108864, Microphone = 83886080, Headset = 100663296, Handset = 117440512, Digital = 134217728, SPDIF = 150994944, HDMI = 167772160, DisplayPort = 1073741824 } public enum DXPhase { Negative180, Negative90, Zero, Positive90, Positive180 } public enum DXWaveform { Triangle, Sine } public enum EffectType { DXChorus = 0, DXDistortion = 1, DXEcho = 2, DXFlanger = 3, DXCompressor = 4, DXGargle = 5, DX_I3DL2Reverb = 6, DXParamEQ = 7, DXReverb = 8, Rotate = 65536, Volume = 65539, PeakEQ = 65540, Mix = 65543, Damp = 65544, AutoWah = 65545, Phaser = 65547, Chorus = 65549, Distortion = 65552, Compressor = 65553, VolumeEnvelope = 65554, BQF = 65555, Echo = 65556, PitchShift = 65557, Freeverb = 65558 } public enum FileStreamPosition { Current = 0, Download = 1, End = 2, Start = 3, Connected = 4, Buffer = 5, Socket = 6, AsyncBuffer = 7, WmaBuffer = 1000, HlsSegment = 65536 } [Flags] public enum FXChannelFlags { All = -1, None = 0, Channel1 = 1, Channel2 = 2, Channel3 = 4, Channel4 = 8, Channel5 = 0x10, Channel6 = 0x20, Channel7 = 0x40, Channel8 = 0x80, Channel9 = 0x100, Channel10 = 0x200, Channel11 = 0x400, Channel12 = 0x800, Channel13 = 0x1000, Channel14 = 0x2000, Channel15 = 0x4000, Channel16 = 0x8000, Channel17 = 0x10000, Channel18 = 0x20000, Channel19 = 0x40000, Channel20 = 0x80000, Channel21 = 0x100000, Channel22 = 0x200000, Channel23 = 0x400000, Channel24 = 0x800000, Channel25 = 0x1000000, Channel26 = 0x2000000, Channel27 = 0x4000000, Channel28 = 0x8000000, Channel29 = 0x10000000, Channel30 = 0x20000000 } [Flags] public enum InputFlags { None = 0, Off = 0x10000, On = 0x20000 } [Flags] public enum InputTypeFlags { InputTypeMask = -16777216, Error = -1, Undefined = 0, Digital = 0x1000000, Line = 0x2000000, Microphone = 0x3000000, MIDISynthesizer = 0x4000000, AnalogCD = 0x5000000, Phone = 0x6000000, Speaker = 0x7000000, Wave = 0x8000000, Auxiliary = 0x9000000, Analog = 0xA000000 } [Flags] public enum LevelRetrievalFlags { All = 0, Mono = 1, Stereo = 2, RMS = 4, VolPan = 8 } public enum Mode3D { LeaveCurrent = -1, Normal, Relative, Off } public enum PlaybackState { Stopped, Playing, Stalled, Paused } [Flags] public enum PositionFlags { Bytes = 0, MusicOrders = 1, MIDITick = 2, OGG = 3, CDTrack = 4, ZXTuneSubCount = 0xF10000, ZXTuneSubLength = 0xF20000, MIDIDecaySeek = 0x4000, MixerReset = 0x10000, MusicPositionReset = 0x8000, MusicPositionResetEx = 0x400000, MixerNoRampIn = 0x800000, Inexact = 0x8000000, Relative = 0x4000000, Decode = 0x10000000, DecodeTo = 0x20000000, Scan = 0x40000000, HlsSegment = 0x10000 } [Flags] public enum RecordFormatFlags { Unknown = 0, WF1M08 = 1, WF1S08 = 2, WF1M16 = 4, WF1S16 = 8, WF2M08 = 0x10, WF2S08 = 0x20, WF2M16 = 0x40, WF2S16 = 0x80, WF4M08 = 0x100, WF4S08 = 0x200, WF4M16 = 0x400, WF4S16 = 0x800, WF48M08 = 0x1000, WF48S08 = 0x2000, WF48M16 = 0x4000, WF48S16 = 0x8000, WF96M08 = 0x10000, WF96S08 = 0x20000, WF96M16 = 0x40000, WF96S16 = 0x80000 } [Flags] internal enum RecordInfoFlags { None = 0, EmulatedDrivers = 0x20, Certified = 0x40 } public enum StreamProcedureType { End = int.MinValue, Push = -1, Dummy = 0, Device = -2 } public enum StreamSystem { NoBuffer, Buffer, BufferPush } [Flags] public enum SyncFlags { Onetime = int.MinValue, Mixtime = 0x40000000, Thread = 0x20000000, Position = 0, MusicInstrument = 1, End = 2, MusicFx = 3, MetadataReceived = 4, Slided = 5, Stalled = 6, Downloaded = 7, Free = 8, MusicPosition = 0xA, Seeking = 0xB, OggChange = 0xC, Stop = 0xE, WinampBitRate = 0x64, CDError = 0x3E8, CDSpeed = 0x3EA, MidiMarker = 0x10000, MidiCue = 0x10001, MidiLyric = 0x10002, MidiText = 0x10003, MidiEvent = 0x10004, MidiTick = 0x10005, MidiTimeSignature = 0x10006, MidiKeySignature = 0x10007, WmaChange = 0x10100, WmaMeta = 0x10101, MixerEnvelope = 0x10200, MixerEnvelopeNode = 0x10201, HlsSegement = 0x10300 } public enum TagType { ID3 = 0, ID3v2 = 1, OGG = 2, HTTP = 3, ICY = 4, META = 5, APE = 6, MP4 = 7, WMA = 8, OggEncoder = 9, Lyrics3v2 = 10, WmaMeta = 11, CoreAudioCodec = 11, WmaCodec = 12, FlacCue = 12, MF = 13, WaveFormat = 14, ZXTuneSuOgg = 15794176, RiffInfo = 256, RiffBext = 257, RiffCart = 258, RiffDISP = 259, ApeBinary = 4096, MusicName = 65536, MusicMessage = 65537, MusicOrders = 65538, MusicAuth = 65539, MusicInstrument = 65792, MusicSample = 66304, MidiTrack = 69632, FlacPicture = 73728, AdxLoop = 73728, DSDArtist = 77824, DSDTitle = 77825, DSDComment = 78080, HlsExtInf = 81920, HlsStreamInf = 81921, HlsDate = 81922 } [Flags] public enum VAMMode { Hardware = 1, Software = 2, TerminateTime = 4, TerminateDistance = 8, TerminatePriority = 0x10 } public enum WaveFormatTag : short { Extensible = -2, Unknown = 0, Pcm = 1, Adpcm = 2, IeeeFloat = 3, Vselp = 4, IbmCvsd = 5, ALaw = 6, MuLaw = 7, Dts = 8, Drm = 9, WmaVoice9 = 10, OkiAdpcm = 16, DviAdpcm = 17, ImaAdpcm = 17, MediaspaceAdpcm = 18, SierraAdpcm = 19, G723Adpcm = 20, DigiStd = 21, DigiFix = 22, DialogicOkiAdpcm = 23, MediaVisionAdpcm = 24, CUCodec = 25, YamahaAdpcm = 32, SonarC = 33, DspGroupTrueSpeech = 34, EchoSpeechCorporation1 = 35, AudioFileAf36 = 36, Aptx = 37, AudioFileAf10 = 38, Prosody1612 = 39, Lrc = 40, DolbyAc2 = 48, Gsm610 = 49, MsnAudio = 50, AntexAdpcme = 51, ControlResVqlpc = 52, DigiReal = 53, DigiAdpcm = 54, ControlResCr10 = 55, NMS_VBXADPCM = 56, CS_IMAADPCM = 57, ECHOSC3 = 58, ROCKWELL_ADPCM = 59, ROCKWELL_DIGITALK = 60, XEBEC = 61, G721_ADPCM = 64, G728_CELP = 65, MSG723 = 66, Mpeg = 80, RT24 = 82, PAC = 83, Mp3 = 85, LUCENT_G723 = 89, CIRRUS = 96, ESPCM = 97, VOXWARE = 98, CANOPUS_ATRAC = 99, G726_ADPCM = 100, G722_ADPCM = 101, DSAT_DISPLAY = 103, VOXWARE_BYTE_ALIGNED = 105, VOXWARE_AC8 = 112, VOXWARE_AC10 = 113, VOXWARE_AC16 = 114, VOXWARE_AC20 = 115, VOXWARE_RT24 = 116, VOXWARE_RT29 = 117, VOXWARE_RT29HW = 118, VOXWARE_VR12 = 119, VOXWARE_VR18 = 120, VOXWARE_TQ40 = 121, SOFTSOUND = 128, VOXWARE_TQ60 = 129, MSRT24 = 130, G729A = 131, MVI_MVI2 = 132, DF_G726 = 133, DF_GSM610 = 134, ISIAUDIO = 136, ONLIVE = 137, SBC24 = 145, DOLBY_AC3_SPDIF = 146, MEDIASONIC_G723 = 147, PROSODY_8KBPS = 148, ZYXEL_ADPCM = 151, PHILIPS_LPCBB = 152, PACKED = 153, MALDEN_PHONYTALK = 160, Gsm = 161, G729 = 162, G723 = 163, Acelp = 164, RawAac = 255, RHETOREX_ADPCM = 256, IRAT = 257, VIVO_G723 = 273, VIVO_SIREN = 274, DIGITAL_G723 = 291, SANYO_LD_ADPCM = 293, SIPROLAB_ACEPLNET = 304, SIPROLAB_ACELP4800 = 305, SIPROLAB_ACELP8V3 = 306, SIPROLAB_G729 = 307, SIPROLAB_G729A = 308, SIPROLAB_KELVIN = 309, G726ADPCM = 320, QUALCOMM_PUREVOICE = 336, QUALCOMM_HALFRATE = 337, TUBGSM = 341, MSAUDIO1 = 352, WMA = 353, WMAProfessional = 354, WMALosseless = 355, WMA_SPDIF = 356, UNISYS_NAP_ADPCM = 368, UNISYS_NAP_ULAW = 369, UNISYS_NAP_ALAW = 370, UNISYS_NAP_16K = 371, CREATIVE_ADPCM = 512, CREATIVE_FASTSPEECH8 = 514, CREATIVE_FASTSPEECH10 = 515, UHER_ADPCM = 528, QUARTERDECK = 544, ILINK_VC = 560, RAW_SPORT = 576, ESST_AC3 = 577, IPI_HSX = 592, IPI_RPELP = 593, CS2 = 608, SONY_SCX = 624, FM_TOWNS_SND = 768, BTV_DIGITAL = 1024, QDESIGN_MUSIC = 1104, VME_VMPCM = 1664, TPC = 1665, OLIGSM = 4096, OLIADPCM = 4097, OLICELP = 4098, OLISBC = 4099, OLIOPR = 4100, LH_CODEC = 4352, NORRIS = 5120, SOUNDSPACE_MUSICOMPRESS = 5376, MPEG_ADTS_AAC = 5632, MPEG_RAW_AAC = 5633, MPEG_LOAS = 5634, NOKIA_MPEG_ADTS_AAC = 5640, NOKIA_MPEG_RAW_AAC = 5641, VODAFONE_MPEG_ADTS_AAC = 5642, VODAFONE_MPEG_RAW_AAC = 5643, MPEG_HEAAC = 5648, DVM = 8192, Vorbis1 = 26447, Vorbis2 = 26448, Vorbis3 = 26449, Vorbis1P = 26479, Vorbis2P = 26480, Vorbis3P = 26481 } public static class Bass { private const string DllName = "bass"; private const int SlideLog = 16777216; public const int NoSoundDevice = 0; public const int DefaultDevice = -1; public static Algorithm3D Algorithm3D { get { return (Algorithm3D)GetConfig(Configuration.Algorithm3D); } set { Configure(Configuration.Algorithm3D, (int)value); } } public static string SupportedFormats => "*.mp3;*.mp2;*.mp1;*.ogg;*.wav;*.aif"; public static double CPUUsage => BASS_GetCPU(); public static Version Version => Extensions.GetVersion(BASS_GetVersion()); public static Errors LastError => BASS_ErrorGetCode(); public static bool Float => GetConfigBool(Configuration.Float); public static int PlaybackBufferLength { get { return GetConfig(Configuration.PlaybackBufferLength); } set { Configure(Configuration.PlaybackBufferLength, value); } } public static int UpdatePeriod { get { return GetConfig(Configuration.UpdatePeriod); } set { Configure(Configuration.UpdatePeriod, value); } } public static int GlobalSampleVolume { get { return GetConfig(Configuration.GlobalSampleVolume); } set { Configure(Configuration.GlobalSampleVolume, value); } } public static int GlobalStreamVolume { get { return GetConfig(Configuration.GlobalStreamVolume); } set { Configure(Configuration.GlobalStreamVolume, value); } } public static int GlobalMusicVolume { get { return GetConfig(Configuration.GlobalMusicVolume); } set { Configure(Configuration.GlobalMusicVolume, value); } } public static bool LogarithmicVolumeCurve { get { return GetConfigBool(Configuration.LogarithmicVolumeCurve); } set { Configure(Configuration.LogarithmicVolumeCurve, value); } } public static bool LogarithmicPanningCurve { get { return GetConfigBool(Configuration.LogarithmicPanCurve); } set { Configure(Configuration.LogarithmicPanCurve, value); } } public static bool FloatingPointDSP { get { return GetConfigBool(Configuration.FloatDSP); } set { Configure(Configuration.FloatDSP, value); } } public static int UpdateThreads { get { return GetConfig(Configuration.UpdateThreads); } set { Configure(Configuration.UpdateThreads, value); } } public static int AsyncFileBufferLength { get { return GetConfig(Configuration.AsyncFileBufferLength); } set { Configure(Configuration.AsyncFileBufferLength, value); } } public static int HandleCount => GetConfig(Configuration.HandleCount); public static int NetTimeOut { get { return GetConfig(Configuration.NetTimeOut); } set { Configure(Configuration.NetTimeOut, value); } } public static int NetReadTimeOut { get { return GetConfig(Configuration.NetReadTimeOut); } set { Configure(Configuration.NetReadTimeOut, value); } } public static int NetBufferLength { get { return GetConfig(Configuration.NetBufferLength); } set { Configure(Configuration.NetBufferLength, value); } } public static int PauseNoPlay { get { return GetConfig(Configuration.PauseNoPlay); } set { Configure(Configuration.PauseNoPlay, value); } } public static int NetPreBuffer { get { return GetConfig(Configuration.NetPreBuffer); } set { Configure(Configuration.NetPreBuffer, value); } } public static bool FTPPassive { get { return GetConfigBool(Configuration.NetPassive); } set { Configure(Configuration.NetPassive, value); } } public static int NetPlaylist { get { return GetConfig(Configuration.NetPlaylist); } set { Configure(Configuration.NetPlaylist, value); } } public static string NetAgent { get { return Marshal.PtrToStringAnsi(GetConfigPtr(Configuration.NetAgent)); } set { IntPtr intPtr = Marshal.StringToHGlobalAnsi(value); Configure(Configuration.NetAgent, intPtr); Marshal.FreeHGlobal(intPtr); } } public static string NetProxy { get { return Marshal.PtrToStringAnsi(GetConfigPtr(Configuration.NetProxy)); } set { IntPtr intPtr = Marshal.StringToHGlobalAnsi(value); Configure(Configuration.NetProxy, intPtr); Marshal.FreeHGlobal(intPtr); } } public static int MusicVirtial { get { return GetConfig(Configuration.MusicVirtual); } set { Configure(Configuration.MusicVirtual, value); } } public static int FileVerificationBytes { get { return GetConfig(Configuration.FileVerificationBytes); } set { Configure(Configuration.FileVerificationBytes, value); } } public static int NetVerificationBytes { get { return GetConfig(Configuration.NetVerificationBytes); } set { Configure(Configuration.NetVerificationBytes, value); } } public static int DeviceBufferLength { get { return GetConfig(Configuration.DeviceBufferLength); } set { Configure(Configuration.DeviceBufferLength, value); } } public static bool SuppressMP3ErrorCorruptionSilence { get { return GetConfigBool(Configuration.SuppressMP3ErrorCorruptionSilence); } set { Configure(Configuration.SuppressMP3ErrorCorruptionSilence, value); } } public static int SRCQuality { get { return GetConfig(Configuration.SRCQuality); } set { Configure(Configuration.SRCQuality, value); } } public static int SampleSRCQuality { get { return GetConfig(Configuration.SampleSRCQuality); } set { Configure(Configuration.SampleSRCQuality, value); } } public static bool OggPreScan { get { return GetConfigBool(Configuration.OggPreScan); } set { Configure(Configuration.OggPreScan, value); } } public static bool DeviceNonStop { get { return GetConfigBool(Configuration.DevNonStop); } set { Configure(Configuration.DevNonStop, value); } } public static int DeviceCount { get { int i; DeviceInfo Info; for (i = 0; GetDeviceInfo(i, out Info); i++) { } return i; } } public static double Volume { get { return BASS_GetVolume(); } set { if (!BASS_SetVolume((float)value)) { throw new BassException(); } } } public static int CurrentDevice { get { return BASS_GetDevice(); } set { if (!BASS_SetDevice(value)) { throw new BassException(); } } } public static BassInfo Info { get { if (!GetInfo(out var Info)) { throw new BassException(); } return Info; } } public static int CurrentRecordingDevice { get { return BASS_RecordGetDevice(); } set { if (!BASS_RecordSetDevice(value)) { throw new BassException(); } } } public static RecordInfo RecordingInfo { get { if (!RecordGetInfo(out var info)) { throw new BassException(); } return info; } } public static int RecordingBufferLength { get { return GetConfig(Configuration.RecordingBufferLength); } set { Configure(Configuration.RecordingBufferLength, value); } } public static int RecordingDeviceCount { get { int i; DeviceInfo Info; for (i = 0; RecordGetDeviceInfo(i, out Info); i++) { } return i; } } [DllImport("bass", EntryPoint = "BASS_Apply3D")] public static extern void Apply3D(); [DllImport("bass", EntryPoint = "BASS_Get3DFactors")] public static extern bool Get3DFactors(ref float Distance, ref float RollOff, ref float Doppler); [DllImport("bass", EntryPoint = "BASS_Set3DFactors")] public static extern bool Set3DFactors(float Distance, float RollOff, float Doppler); [DllImport("bass", EntryPoint = "BASS_Get3DPosition")] public static extern bool Get3DPosition(ref Vector3D Position, ref Vector3D Velocity, ref Vector3D Front, ref Vector3D Top); [DllImport("bass", EntryPoint = "BASS_Set3DPosition")] public static extern bool Set3DPosition(Vector3D Position, Vector3D Velocity, Vector3D Front, Vector3D Top); [DllImport("bass", EntryPoint = "BASS_ChannelGet3DAttributes")] public static extern bool ChannelGet3DAttributes(int Handle, ref Mode3D Mode, ref float Min, ref float Max, ref int iAngle, ref int oAngle, ref float OutVol); [DllImport("bass", EntryPoint = "BASS_ChannelSet3DAttributes")] public static extern bool ChannelSet3DAttributes(int Handle, Mode3D Mode, float Min, float Max, int iAngle, int oAngle, float OutVol); [DllImport("bass", EntryPoint = "BASS_ChannelGet3DPosition")] public static extern bool ChannelGet3DPosition(int Handle, ref Vector3D Position, ref Vector3D Orientation, ref Vector3D Velocity); [DllImport("bass", EntryPoint = "BASS_ChannelSet3DPosition")] public static extern bool ChannelSet3DPosition(int Handle, Vector3D Position, Vector3D Orientation, Vector3D Velocity); [DllImport("bass", EntryPoint = "BASS_Update")] public static extern bool Update(int Length); [DllImport("bass")] private static extern float BASS_GetCPU(); [DllImport("bass")] private static extern int BASS_GetVersion(); [DllImport("bass")] private static extern Errors BASS_ErrorGetCode(); [DllImport("bass", EntryPoint = "BASS_ChannelGetInfo")] public static extern bool ChannelGetInfo(int Handle, out ChannelInfo Info); public static ChannelInfo ChannelGetInfo(int Handle) { if (!ChannelGetInfo(Handle, out var Info)) { throw new BassException(); } return Info; } [DllImport("bass")] private static extern int BASS_ChannelSetDSP(int Handle, DSPProcedure Procedure, IntPtr User, int Priority); public static int ChannelSetDSP(int Handle, DSPProcedure Procedure, IntPtr User = default(IntPtr), int Priority = 0) { int num = BASS_ChannelSetDSP(Handle, Procedure, User, Priority); if (num != 0) { ChannelReferences.Add(Handle, num, Procedure); } return num; } [DllImport("bass")] private static extern bool BASS_ChannelRemoveDSP(int Handle, int DSP); public static bool ChannelRemoveDSP(int Handle, int DSP) { bool num = BASS_ChannelRemoveDSP(Handle, DSP); if (num) { ChannelReferences.Remove(Handle, DSP); } return num; } [DllImport("bass")] private static extern int BASS_ChannelSetSync(int Handle, SyncFlags Type, long Parameter, SyncProcedure Procedure, IntPtr User); public static int ChannelSetSync(int Handle, SyncFlags Type, long Parameter, SyncProcedure Procedure, IntPtr User = default(IntPtr)) { SyncProcedure syncProcedure = (Type.HasFlag(SyncFlags.Onetime) ? ((SyncProcedure)delegate(int I, int Channel, int Data, IntPtr Ptr) { Procedure(I, Channel, Data, Ptr); ChannelReferences.Remove(Channel, I); }) : Procedure); int num = BASS_ChannelSetSync(Handle, Type, Parameter, syncProcedure, User); if (num != 0) { ChannelReferences.Add(Handle, num, syncProcedure); } return num; } [DllImport("bass")] private static extern bool BASS_ChannelRemoveSync(int Handle, int Sync); public static bool ChannelRemoveSync(int Handle, int Sync) { bool num = BASS_ChannelRemoveSync(Handle, Sync); if (num) { ChannelReferences.Remove(Handle, Sync); } return num; } [DllImport("bass", EntryPoint = "BASS_ChannelPlay")] public static extern bool ChannelPlay(int Handle, bool Restart = false); [DllImport("bass", EntryPoint = "BASS_ChannelPause")] public static extern bool ChannelPause(int Handle); [DllImport("bass", EntryPoint = "BASS_ChannelStop")] public static extern bool ChannelStop(int Handle); [DllImport("bass", EntryPoint = "BASS_ChannelLock")] public static extern bool ChannelLock(int Handle, bool Lock = true); [DllImport("bass", EntryPoint = "BASS_ChannelIsActive")] public static extern PlaybackState ChannelIsActive(int Handle); [DllImport("bass", EntryPoint = "BASS_ChannelSetLink")] public static extern bool ChannelSetLink(int Handle, int Channel); [DllImport("bass", EntryPoint = "BASS_ChannelRemoveLink")] public static extern bool ChannelRemoveLink(int Handle, int Channel); [DllImport("bass", EntryPoint = "BASS_ChannelFlags")] public static extern BassFlags ChannelFlags(int Handle, BassFlags Flags, BassFlags Mask); public static bool ChannelHasFlag(int Handle, BassFlags Flag) { return ChannelFlags(Handle, BassFlags.Default, BassFlags.Default).HasFlag(Flag); } public static bool ChannelAddFlag(int Handle, BassFlags Flag) { return ChannelFlags(Handle, Flag, Flag).HasFlag(Flag); } public static bool ChannelRemoveFlag(int Handle, BassFlags Flag) { return !ChannelFlags(Handle, BassFlags.Default, Flag).HasFlag(Flag); } [DllImport("bass", EntryPoint = "BASS_ChannelGetAttribute")] public static extern bool ChannelGetAttribute(int Handle, ChannelAttribute Attribute, out float Value); public static double ChannelGetAttribute(int Handle, ChannelAttribute Attribute) { ChannelGetAttribute(Handle, Attribute, out var Value); return Value; } [DllImport("bass", EntryPoint = "BASS_ChannelGetAttributeEx")] public static extern int ChannelGetAttribute(int Handle, ChannelAttribute Attribute, IntPtr Value, int Size); [DllImport("bass", EntryPoint = "BASS_ChannelSetAttribute")] public static extern bool ChannelSetAttribute(int Handle, ChannelAttribute Attribute, float Value); public static bool ChannelSetAttribute(int Handle, ChannelAttribute Attribute, double Value) { return ChannelSetAttribute(Handle, Attribute, (float)Value); } [DllImport("bass", EntryPoint = "BASS_ChannelSetAttributeEx")] public static extern bool ChannelSetAttribute(int Handle, ChannelAttribute Attribute, IntPtr Value, int Size); [DllImport("bass", EntryPoint = "BASS_ChannelGetTags")] public static extern IntPtr ChannelGetTags(int Handle, TagType Tags); [DllImport("bass", EntryPoint = "BASS_ChannelGetLength")] public static extern long ChannelGetLength(int Handle, PositionFlags Mode = PositionFlags.Bytes); [DllImport("bass", EntryPoint = "BASS_ChannelBytes2Seconds")] public static extern double ChannelBytes2Seconds(int Handle, long Position); [DllImport("bass", EntryPoint = "BASS_ChannelSeconds2Bytes")] public static extern long ChannelSeconds2Bytes(int Handle, double Position); [DllImport("bass", EntryPoint = "BASS_ChannelGetPosition")] public static extern long ChannelGetPosition(int Handle, PositionFlags Mode = PositionFlags.Bytes); [DllImport("bass", EntryPoint = "BASS_ChannelSetPosition")] public static extern bool ChannelSetPosition(int Handle, long Position, PositionFlags Mode = PositionFlags.Bytes); [DllImport("bass", EntryPoint = "BASS_ChannelIsSliding")] public static extern bool ChannelIsSliding(int Handle, ChannelAttribute Attribute); [DllImport("bass")] private static extern bool BASS_ChannelSlideAttribute(int Handle, int Attribute, float Value, int Time); public static bool ChannelSlideAttribute(int Handle, ChannelAttribute Attribute, float Value, int Time, bool Logarithmic = false) { int num = (int)Attribute; if (Logarithmic) { num |= 0x1000000; } return BASS_ChannelSlideAttribute(Handle, num, Value, Time); } [DllImport("bass", EntryPoint = "BASS_ChannelGetLevel")] public static extern int ChannelGetLevel(int Handle); public static int ChannelGetLevelLeft(int Handle) { int num = ChannelGetLevel(Handle); if (num == -1) { return -1; } return num.LoWord(); } public static int ChannelGetLevelRight(int Handle) { int num = ChannelGetLevel(Handle); if (num == -1) { return -1; } return num.HiWord(); } [DllImport("bass", EntryPoint = "BASS_ChannelGetLevelEx")] public static extern bool ChannelGetLevel(int Handle, [In][Out] float[] Levels, float Length, LevelRetrievalFlags Flags); public static float[] ChannelGetLevel(int Handle, float Length, LevelRetrievalFlags Flags) { int num = ChannelGetInfo(Handle).Channels; if (Flags.HasFlag(LevelRetrievalFlags.Mono)) { num = 1; } else if (Flags.HasFlag(LevelRetrievalFlags.Stereo)) { num = 2; } float[] array = new float[num]; if (!ChannelGetLevel(Handle, array, Length, Flags)) { return null; } return array; } [DllImport("bass", EntryPoint = "BASS_ChannelGetData")] public static extern int ChannelGetData(int Handle, IntPtr Buffer, int Length); [DllImport("bass", EntryPoint = "BASS_ChannelGetData")] public static extern int ChannelGetData(int Handle, [In][Out] byte[] Buffer, int Length); [DllImport("bass", EntryPoint = "BASS_ChannelGetData")] public static extern int ChannelGetData(int Handle, [In][Out] short[] Buffer, int Length); [DllImport("bass", EntryPoint = "BASS_ChannelGetData")] public static extern int ChannelGetData(int Handle, [In][Out] int[] Buffer, int Length); [DllImport("bass", EntryPoint = "BASS_ChannelGetData")] public static extern int ChannelGetData(int Handle, [In][Out] float[] Buffer, int Length); [DllImport("bass", EntryPoint = "BASS_ChannelUpdate")] public static extern bool ChannelUpdate(int Handle, int Length); [DllImport("bass", EntryPoint = "BASS_SetConfig")] public static extern bool Configure(Configuration Option, bool NewValue); [DllImport("bass", EntryPoint = "BASS_SetConfig")] public static extern bool Configure(Configuration Option, int NewValue); [DllImport("bass", EntryPoint = "BASS_SetConfigPtr")] public static extern bool Configure(Configuration Option, IntPtr NewValue); [DllImport("bass", EntryPoint = "BASS_GetConfig")] public static extern int GetConfig(Configuration Option); [DllImport("bass", EntryPoint = "BASS_GetConfigPtr")] public static extern IntPtr GetConfigPtr(Configuration Option); public static bool GetConfigBool(Configuration Option) { int config = GetConfig(Option); if (config != -1) { return config != 0; } return false; } [DllImport("bass", CharSet = CharSet.Unicode)] private static extern int BASS_StreamCreateFile(bool mem, string file, long offset, long length, BassFlags flags); [DllImport("bass")] private static extern int BASS_StreamCreateFile(bool mem, IntPtr file, long offset, long length, BassFlags flags); public static int CreateStream(string File, long Offset = 0L, long Length = 0L, BassFlags Flags = BassFlags.Default) { return BASS_StreamCreateFile(mem: false, File, Offset, Length, Flags | BassFlags.Unicode); } public static int CreateStream(IntPtr Memory, long Offset, long Length, BassFlags Flags = BassFlags.Default) { return BASS_StreamCreateFile(mem: true, new IntPtr(Memory.ToInt64() + Offset), 0L, Length, Flags); } public static int CreateStream(byte[] Memory, long Offset, long Length, BassFlags Flags) { return GCPin.CreateStreamHelper((IntPtr Pointer) => CreateStream(Pointer, Offset, Length, Flags), Memory); } [DllImport("bass")] private static extern int BASS_StreamCreateFileUser(StreamSystem system, BassFlags flags, [In][Out] FileProcedures procs, IntPtr user); public static int CreateStream(StreamSystem System, BassFlags Flags, FileProcedures Procedures, IntPtr User = default(IntPtr)) { int num = BASS_StreamCreateFileUser(System, Flags, Procedures, User); if (num != 0) { ChannelReferences.Add(num, 0, Procedures); } return num; } [DllImport("bass", CharSet = CharSet.Unicode)] private static extern int BASS_StreamCreateURL(string Url, int Offset, BassFlags Flags, DownloadProcedure Procedure, IntPtr User); public static int CreateStream(string Url, int Offset, BassFlags Flags, DownloadProcedure Procedure, IntPtr User = default(IntPtr)) { int num = BASS_StreamCreateURL(Url, Offset, Flags | BassFlags.Unicode, Procedure, User); if (num != 0) { ChannelReferences.Add(num, 0, Procedure); } return num; } [DllImport("bass", EntryPoint = "BASS_Init")] public static extern bool Init(int Device = -1, int Frequency = 44100, DeviceInitFlags Flags = DeviceInitFlags.Default, IntPtr Win = default(IntPtr), IntPtr ClsID = default(IntPtr)); [DllImport("bass", EntryPoint = "BASS_Start")] public static extern bool Start(); [DllImport("bass", EntryPoint = "BASS_Pause")] public static extern bool Pause(); [DllImport("bass", EntryPoint = "BASS_Stop")] public static extern bool Stop(); [DllImport("bass", EntryPoint = "BASS_Free")] public static extern bool Free(); [DllImport("bass", EntryPoint = "BASS_ChannelGetDevice")] public static extern int ChannelGetDevice(int Handle); [DllImport("bass", EntryPoint = "BASS_ChannelSetDevice")] public static extern bool ChannelSetDevice(int Handle, int Device); [DllImport("bass")] private static extern float BASS_GetVolume(); [DllImport("bass")] private static extern bool BASS_SetVolume(float volume); [DllImport("bass")] private static extern int BASS_GetDevice(); [DllImport("bass")] private static extern bool BASS_SetDevice(int Device); [DllImport("bass", EntryPoint = "BASS_GetDeviceInfo")] public static extern bool GetDeviceInfo(int Device, out DeviceInfo Info); public static DeviceInfo GetDeviceInfo(int Device) { if (!GetDeviceInfo(Device, out var Info)) { throw new BassException(); } return Info; } [DllImport("bass", EntryPoint = "BASS_GetInfo")] public static extern bool GetInfo(out BassInfo Info); [DllImport("bass", EntryPoint = "BASS_FXSetParameters")] public static extern bool FXSetParameters(int Handle, IntPtr Parameters); public static bool FXSetParameters(int Handle, IEffectParameter Parameters) { using GCPin gCPin = new GCPin(Parameters); return FXSetParameters(Handle, gCPin.Pointer); } [DllImport("bass", EntryPoint = "BASS_FXGetParameters")] public static extern bool FXGetParameters(int Handle, IntPtr Parameters); public static bool FXGetParameters(int Handle, IEffectParameter Parameters) { using GCPin gCPin = new GCPin(Parameters); return FXGetParameters(Handle, gCPin.Pointer); } [DllImport("bass", EntryPoint = "BASS_FXReset")] public static extern bool FXReset(int Handle); [DllImport("bass", EntryPoint = "BASS_ChannelSetFX")] public static extern int ChannelSetFX(int Handle, EffectType Type, int Priority); [DllImport("bass", EntryPoint = "BASS_ChannelRemoveFX")] public static extern bool ChannelRemoveFX(int Handle, int FX); [DllImport("bass", EntryPoint = "BASS_FXSetPriority")] public static extern bool FXSetPriority(int Handle, int Priority); [DllImport("bass", EntryPoint = "BASS_MusicFree")] public static extern bool MusicFree(int Handle); [DllImport("bass", CharSet = CharSet.Unicode)] private static extern int BASS_MusicLoad(bool mem, string file, long offset, int Length, BassFlags flags, int freq); [DllImport("bass")] private static extern int BASS_MusicLoad(bool mem, IntPtr file, long offset, int Length, BassFlags flags, int freq); public static int MusicLoad(string File, long Offset = 0L, int Length = 0, BassFlags Flags = BassFlags.Default, int Frequency = 0) { return BASS_MusicLoad(mem: false, File, Offset, Length, Flags | BassFlags.Unicode, Frequency); } public static int MusicLoad(IntPtr Memory, long Offset, int Length, BassFlags Flags = BassFlags.Default, int Frequency = 0) { return BASS_MusicLoad(mem: true, new IntPtr(Memory.ToInt64() + Offset), 0L, Length, Flags, Frequency); } public static int MusicLoad(byte[] Memory, long Offset, int Length, BassFlags Flags = BassFlags.Default, int Frequency = 0) { return GCPin.CreateStreamHelper((IntPtr Pointer) => MusicLoad(Pointer, Offset, Length, Flags), Memory); } [DllImport("bass")] private static extern IntPtr BASS_PluginGetInfo(int Handle); public static PluginInfo PluginGetInfo(int Handle) { return Marshal.PtrToStructure(BASS_PluginGetInfo(Handle)); } [DllImport("bass", CharSet = CharSet.Unicode)] private static extern int BASS_PluginLoad(string FileName, BassFlags Flags = BassFlags.Unicode); public static int PluginLoad(string FilePath) { if (Path.HasExtension(FilePath)) { return BASS_PluginLoad(FilePath); } string directoryName = Path.GetDirectoryName(FilePath); string fileName = Path.GetFileName(FilePath); string[] array = new string[3] { Path.Combine(directoryName, fileName + ".dll"), Path.Combine(directoryName, "lib" + fileName + ".so"), Path.Combine(directoryName, "lib" + fileName + ".dylib") }; foreach (string text in array) { if (File.Exists(text)) { int num = BASS_PluginLoad(text); if (num != 0 || LastError == Errors.Already) { return num; } } } return BASS_PluginLoad(FilePath); } [DllImport("bass", EntryPoint = "BASS_PluginFree")] public static extern bool PluginFree(int Handle); [DllImport("bass", EntryPoint = "BASS_RecordInit")] public static extern bool RecordInit(int Device = -1); [DllImport("bass", EntryPoint = "BASS_RecordFree")] public static extern bool RecordFree(); [DllImport("bass")] private static extern int BASS_RecordStart(int freq, int chans, BassFlags flags, RecordProcedure proc, IntPtr User); public static int RecordStart(int Frequency, int Channels, BassFlags Flags, RecordProcedure Procedure, IntPtr User = default(IntPtr)) { int num = BASS_RecordStart(Frequency, Channels, Flags, Procedure, User); if (num != 0) { ChannelReferences.Add(num, 0, Procedure); } return num; } public static int RecordStart(int Frequency, int Channels, BassFlags Flags, int Period, RecordProcedure Procedure, IntPtr User = default(IntPtr)) { return RecordStart(Frequency, Channels, (BassFlags)BitHelper.MakeLong((short)Flags, (short)Period), Procedure, User); } [DllImport("bass")] private static extern int BASS_RecordGetDevice(); [DllImport("bass")] private static extern bool BASS_RecordSetDevice(int Device); [DllImport("bass", EntryPoint = "BASS_RecordGetDeviceInfo")] public static extern bool RecordGetDeviceInfo(int Device, out DeviceInfo Info); public static DeviceInfo RecordGetDeviceInfo(int Device) { if (!RecordGetDeviceInfo(Device, out var Info)) { throw new BassException(); } return Info; } [DllImport("bass", EntryPoint = "BASS_RecordGetInfo")] public static extern bool RecordGetInfo(out RecordInfo info); [DllImport("bass", EntryPoint = "BASS_RecordGetInput")] public static extern int RecordGetInput(int Input, out float Volume); [DllImport("bass")] private static extern int BASS_RecordGetInput(int Input, IntPtr Volume); public static int RecordGetInput(int Input) { return BASS_RecordGetInput(Input, IntPtr.Zero); } [DllImport("bass")] private static extern IntPtr BASS_RecordGetInputName(int input); public static string RecordGetInputName(int Input) { IntPtr intPtr = BASS_RecordGetInputName(Input); if (intPtr == IntPtr.Zero) { return null; } return GetConfig(Configuration.UnicodeDeviceInformation) switch { -1 => Extensions.PtrToStringUtf8(intPtr), 0 => Marshal.PtrToStringAnsi(intPtr), _ => Extensions.PtrToStringUtf8(intPtr), }; } [DllImport("bass", EntryPoint = "BASS_RecordSetInput")] public static extern bool RecordSetInput(int Input, InputFlags Setting, float Volume); public static int SampleGetChannel(int Sample, bool OnlyNew = false) { return SampleGetChannel(Sample, OnlyNew ? BassFlags.Byte : BassFlags.Default); } [DllImport("bass", EntryPoint = "BASS_SampleGetChannel")] public static extern int SampleGetChannel(int Sample, BassFlags Flags); [DllImport("bass", EntryPoint = "BASS_SampleFree")] public static extern bool SampleFree(int Handle); [DllImport("bass", EntryPoint = "BASS_SampleSetData")] public static extern bool SampleSetData(int Handle, IntPtr Buffer); [DllImport("bass", EntryPoint = "BASS_SampleSetData")] public static extern bool SampleSetData(int Handle, byte[] Buffer); [DllImport("bass", EntryPoint = "BASS_SampleSetData")] public static extern bool SampleSetData(int Handle, int[] Buffer); [DllImport("bass", EntryPoint = "BASS_SampleSetData")] public static extern bool SampleSetData(int Handle, short[] Buffer); [DllImport("bass", EntryPoint = "BASS_SampleSetData")] public static extern bool SampleSetData(int Handle, float[] Buffer); [DllImport("bass", EntryPoint = "BASS_SampleCreate")] public static extern int CreateSample(int Length, int Frequency, int Channels, int Max, BassFlags Flags); [DllImport("bass", EntryPoint = "BASS_SampleGetData")] public static extern bool SampleGetData(int Handle, IntPtr Buffer); [DllImport("bass", EntryPoint = "BASS_SampleGetData")] public static extern bool SampleGetData(int Handle, [In][Out] byte[] Buffer); [DllImport("bass", EntryPoint = "BASS_SampleGetData")] public static extern bool SampleGetData(int Handle, [In][Out] short[] Buffer); [DllImport("bass", EntryPoint = "BASS_SampleGetData")] public static extern bool SampleGetData(int Handle, [In][Out] int[] Buffer); [DllImport("bass", EntryPoint = "BASS_SampleGetData")] public static extern bool SampleGetData(int Handle, [In][Out] float[] Buffer); [DllImport("bass", EntryPoint = "BASS_SampleGetInfo")] public static extern bool SampleGetInfo(int Handle, [In][Out] SampleInfo Info); public static SampleInfo SampleGetInfo(int Handle) { SampleInfo sampleInfo = new SampleInfo(); if (!SampleGetInfo(Handle, sampleInfo)) { throw new BassException(); } return sampleInfo; } [DllImport("bass", EntryPoint = "BASS_SampleSetInfo")] public static extern bool SampleSetInfo(int Handle, SampleInfo Info); [DllImport("bass")] private static extern int BASS_SampleGetChannels(int handle, [In][Out] int[] channels); public static int[] SampleGetChannels(int Handle) { int num = BASS_SampleGetChannels(Handle, null); if (num < 0) { return null; } int[] array = new int[num]; num = BASS_SampleGetChannels(Handle, array); if (num >= 0) { return array; } return null; } [DllImport("bass", EntryPoint = "BASS_SampleStop")] public static extern bool SampleStop(int Handle); [DllImport("bass", CharSet = CharSet.Unicode)] private static extern int BASS_SampleLoad(bool mem, string file, long offset, int Length, int max, BassFlags flags); [DllImport("bass")] private static extern int BASS_SampleLoad(bool mem, IntPtr file, long offset, int Length, int max, BassFlags flags); public static int SampleLoad(string File, long Offset, int Length, int MaxNoOfPlaybacks, BassFlags Flags) { return BASS_SampleLoad(mem: false, File, Offset, Length, MaxNoOfPlaybacks, Flags | BassFlags.Unicode); } public static int SampleLoad(IntPtr Memory, long Offset, int Length, int MaxNoOfPlaybacks, BassFlags Flags) { return BASS_SampleLoad(mem: true, new IntPtr(Memory.ToInt64() + Offset), 0L, Length, MaxNoOfPlaybacks, Flags); } public static int SampleLoad(byte[] Memory, long Offset, int Length, int MaxNoOfPlaybacks, BassFlags Flags) { return GCPin.CreateStreamHelper((IntPtr Pointer) => SampleLoad(Pointer, Offset, Length, MaxNoOfPlaybacks, Flags), Memory); } [DllImport("bass", EntryPoint = "BASS_StreamGetFilePosition")] public static extern long StreamGetFilePosition(int Handle, FileStreamPosition Mode = FileStreamPosition.Current); [DllImport("bass")] private static extern int BASS_StreamCreate(int Frequency, int Channels, BassFlags Flags, StreamProcedure Procedure, IntPtr User); public static int CreateStream(int Frequency, int Channels, BassFlags Flags, StreamProcedure Procedure, IntPtr User = default(IntPtr)) { int num = BASS_StreamCreate(Frequency, Channels, Flags, Procedure, User); if (num != 0) { ChannelReferences.Add(num, 0, Procedure); } return num; } [DllImport("bass")] private static extern int BASS_StreamCreate(int Frequency, int Channels, BassFlags Flags, IntPtr ProcedureType, IntPtr User = default(IntPtr)); public static int CreateStream(int Frequency, int Channels, BassFlags Flags, StreamProcedureType ProcedureType) { return BASS_StreamCreate(Frequency, Channels, Flags, new IntPtr((int)ProcedureType), (IntPtr)0); } [DllImport("bass", EntryPoint = "BASS_StreamPutData")] public static extern int StreamPutData(int Handle, IntPtr Buffer, int Length); [DllImport("bass", EntryPoint = "BASS_StreamPutData")] public static extern int StreamPutData(int Handle, byte[] Buffer, int Length); [DllImport("bass", EntryPoint = "BASS_StreamPutData")] public static extern int StreamPutData(int Handle, short[] Buffer, int Length); [DllImport("bass", EntryPoint = "BASS_StreamPutData")] public static extern int StreamPutData(int Handle, int[] Buffer, int Length); [DllImport("bass", EntryPoint = "BASS_StreamPutData")] public static extern int StreamPutData(int Handle, float[] Buffer, int Length); [DllImport("bass", EntryPoint = "BASS_StreamPutFileData")] public static extern int StreamPutFileData(int Handle, IntPtr Buffer, int Length); [DllImport("bass", EntryPoint = "BASS_StreamPutFileData")] public static extern int StreamPutFileData(int Handle, byte[] Buffer, int Length); [DllImport("bass", EntryPoint = "BASS_StreamPutFileData")] public static extern int StreamPutFileData(int Handle, short[] Buffer, int Length); [DllImport("bass", EntryPoint = "BASS_StreamPutFileData")] public static extern int StreamPutFileData(int Handle, int[] Buffer, int Length); [DllImport("bass", EntryPoint = "BASS_StreamPutFileData")] public static extern int StreamPutFileData(int Handle, float[] Buffer, int Length); [DllImport("bass", EntryPoint = "BASS_StreamFree")] public static extern bool StreamFree(int Handle); } public struct BassInfo { private BASSInfoFlags flags; private int hwsize; private int hwfree; private int freesam; private int free3d; private int minrate; private int maxrate; private bool eax; private int minbuf; private int dsver; private int latency; private DeviceInitFlags initFlags; private int speakers; private int freq; public int TotalHardwareMemory => hwsize; public int FreeHardwareMemory => hwsize; public int FreeSampleSlots => freesam; public int Free3DSampleSlots => free3d; public int MinSampleRate => minrate; public int MaxSampleRate => maxrate; public bool EAXEnabled => eax; public int MinBufferLength => minbuf; public int DSVersion => dsver; public int Latency => latency; public DeviceInitFlags InitFlags => initFlags; public int SpeakerCount => speakers; public int SampleRate => freq; public bool IsCertified => flags.HasFlag(BASSInfoFlags.Certified); public bool Supports16BitSamples => flags.HasFlag(BASSInfoFlags.Secondary16Bit); public bool Supports8BitSamples => flags.HasFlag(BASSInfoFlags.Secondary8Bit); public bool SupportsContinuousRate => flags.HasFlag(BASSInfoFlags.ContinuousRate); public bool SupportsDirectSound => !flags.HasFlag(BASSInfoFlags.EmulatedDrivers); public bool SupportsMonoSamples => flags.HasFlag(BASSInfoFlags.Mono); public bool SupportsStereoSamples => flags.HasFlag(BASSInfoFlags.Stereo); } public struct ChannelInfo { private int freq; private int chans; private BassFlags flags; private ChannelType ctype; private int origres; private int plugin; private int sample; private IntPtr filename; public int Frequency => freq; public int Channels => chans; public BassFlags Flags => flags; public ChannelType ChannelType => ctype; public int Plugin => plugin; public int Sample => sample; public Resolution Resolution { get { if (flags.HasFlag(BassFlags.Byte)) { return Resolution.Byte; } if (!flags.HasFlag(BassFlags.Float)) { return Resolution.Short; } return Resolution.Float; } } public int OriginalResolution => origres; public string FileName { get { if (!(filename == IntPtr.Zero)) { return Marshal.PtrToStringAnsi(filename); } return null; } } public bool IsDecodingChannel => flags.HasFlag(BassFlags.Decode); } public struct DeviceInfo { private IntPtr name; private IntPtr driver; private DeviceInfoFlags flags; public string Name => PtrToString(name); public string Driver => PtrToString(driver); public bool IsDefault => flags.HasFlag(DeviceInfoFlags.Default); public bool IsEnabled => flags.HasFlag(DeviceInfoFlags.Enabled); public bool IsInitialized => flags.HasFlag(DeviceInfoFlags.Initialized); public bool IsLoopback => flags.HasFlag(DeviceInfoFlags.Loopback); public DeviceType Type => (DeviceType)(flags & DeviceInfoFlags.TypeMask); private static string PtrToString(IntPtr ptr) { if (ptr == IntPtr.Zero) { return null; } return Bass.GetConfig(Configuration.UnicodeDeviceInformation) switch { -1 => Extensions.PtrToStringUtf8(ptr), 0 => Marshal.PtrToStringAnsi(ptr), _ => Extensions.PtrToStringUtf8(ptr), }; } } [StructLayout(LayoutKind.Sequential)] public class FileProcedures { public FileCloseProcedure Close; public FileLengthProcedure Length; public FileReadProcedure Read; public FileSeekProcedure Seek; } public struct PluginFormat { private ChannelType ctype; private IntPtr name; private IntPtr exts; public ChannelType ChannelType => ctype; public string Name { get { if (!(name == IntPtr.Zero)) { return Marshal.PtrToStringAnsi(name); } return null; } } public string FileExtensions { get { if (!(exts == IntPtr.Zero)) { return Marshal.PtrToStringAnsi(exts); } return null; } } } public struct PluginInfo { private int version; private int formatc; private IntPtr formats; public Version Version => Extensions.GetVersion(version); public PluginFormat[] Formats { get { PluginFormat[] array = new PluginFormat[formatc]; int num = Marshal.SizeOf(); int num2 = 0; while (num2 < formatc) { array[num2] = Marshal.PtrToStructure(formats); num2++; formats += num; } return array; } } } public struct RecordInfo { private RecordInfoFlags flags; private int formats; private int inputs; private bool singlein; private int freq; public RecordFormatFlags SupportedFormats => (RecordFormatFlags)(formats & 0xFFFFFF); public int Inputs => inputs; public bool SingleInput => singlein; public int Frequency => freq; public int Channels => formats >> 24; public bool IsCertified => flags.HasFlag(RecordInfoFlags.Certified); public bool SupportsDirectSound => flags.HasFlag(RecordInfoFlags.EmulatedDrivers); } [StructLayout(LayoutKind.Sequential)] public class SampleInfo { public int Frequency = 44100; public float Volume = 1f; public float Pan; public BassFlags Flags; public int Length; public int Max = 1; public int OriginalResolution; public int Channels = 2; public int MinGap; public Mode3D Mode3D; public float MinDistance; public float MaxDistance; public int InsideAngle; public int OutsideAngle; public float OutsideVolume = 1f; public VAMMode VAM = VAMMode.Hardware; public int Priority; } [StructLayout(LayoutKind.Sequential)] public class Vector3D { public float X; public float Y; public float Z; public Vector3D() { } public Vector3D(float X, float Y, float Z) { this.X = X; this.Y = Y; this.Z = Z; } public override string ToString() { return $"({X}, {Y}, {Z})"; } } public static class BitHelper { public static long HiDword(this long DWord) { return DWord >>> 32; } public static long LoDword(this long DWord) { return DWord & 0xFFFFFFFFu; } public static int HiWord(this int DWord) { return DWord >>> 16; } public static int LoWord(this int DWord) { return DWord & 0xFFFF; } public static byte HiByte(this short Word) { return (byte)(Word >> 8); } public static byte LoByte(this short Word) { return (byte)((uint)Word & 0xFFu); } public static short MakeWord(byte Low, byte High) { return (short)(Low | (ushort)(High << 8)); } public static int MakeLong(short Low, short High) { return (ushort)Low | (High << 16); } } public enum Errors { Unknown = -1, OK = 0, Memory = 1, FileOpen = 2, Driver = 3, BufferLost = 4, Handle = 5, SampleFormat = 6, Position = 7, Init = 8, Start = 9, [Obsolete("Use SSL instead.")] SLL = 10, SSL = 10, NoCD = 12, CDTrack = 13, Already = 14, NotPaused = 16, NotAudioTrack = 17, NoChannel = 18, Type = 19, Parameter = 20, No3D = 21, NoEAX = 22, Device = 23, NotPlaying = 24, SampleRate = 25, NotFile = 27, NoHW = 29, Empty = 31, NoInternet = 32, Create = 33, NoFX = 34, Playing = 35, NotAvailable = 37, Decode = 38, DirectX = 39, Timeout = 40, FileFormat = 41, Speaker = 42, Version = 43, Codec = 44, Ended = 45, Busy = 46, Unstreamable = 47, WmaLicense = 1000, WM9 = 1001, WmaAccesDenied = 1002, WmaCodec = 1003, WmaIndividual = 1004, Wasapi = 5000, AcmCancel = 2000, CastDenied = 2100, Mp4NoStream = 6000 } public static class Extensions { private static bool? _floatable; public static bool SupportsFloatingPoint { get { if (_floatable.HasValue) { return _floatable.Value; } int num = Bass.CreateStream(44100, 1, BassFlags.Float, StreamProcedureType.Dummy); _floatable = num != 0; if (_floatable.Value) { Bass.StreamFree(num); } return _floatable.Value; } } public static StreamProcedure SilenceStreamProcedure { get; } = delegate(int Handle, IntPtr Buffer, int Length, IntPtr User) { for (int i = 0; i < Length; i++) { Marshal.WriteByte(Buffer, i, 0); } return Length; }; public static T Clip(this T Item, T MinValue, T MaxValue) where T : IComparable { if (Item.CompareTo(MaxValue) > 0) { return MaxValue; } if (Item.CompareTo(MinValue) >= 0) { return Item; } return MinValue; } public static BassFlags ToBassFlag(this Resolution Resolution) { return Resolution switch { Resolution.Byte => BassFlags.Byte, Resolution.Float => BassFlags.Float, _ => BassFlags.Default, }; } public static BassFlags SpeakerN(int N) { return (BassFlags)(N << 24); } public static Version GetVersion(int Num) { return new Version((Num >> 24) & 0xFF, (Num >> 16) & 0xFF, (Num >> 8) & 0xFF, Num & 0xFF); } public static string ChannelCountToString(int Channels) { switch (Channels) { case 1: return "Mono"; case 2: return "Stereo"; case 3: return "2.1"; case 4: return "Quad"; case 5: return "4.1"; case 6: return "5.1"; case 7: return "6.1"; default: if (Channels < 1) { throw new ArgumentException("Channels must be greater than Zero."); } return Channels + " Channels"; } } public static string[] ExtractMultiStringAnsi(IntPtr Ptr) { List list = new List(); while (true) { string text = ((Ptr == IntPtr.Zero) ? null : Marshal.PtrToStringAnsi(Ptr)); if (string.IsNullOrEmpty(text)) { break; } list.Add(text); Ptr += text.Length + 1; } return list.ToArray(); } public static string[] ExtractMultiStringUtf8(IntPtr Ptr) { List list = new List(); while (true) { int Size; string text = PtrToStringUtf8(Ptr, out Size); if (string.IsNullOrEmpty(text)) { break; } list.Add(text); Ptr += Size + 1; } return list.ToArray(); } private unsafe static string PtrToStringUtf8(IntPtr Ptr, out int Size) { Size = 0; byte* ptr = (byte*)Ptr.ToPointer(); if (Ptr == IntPtr.Zero || *ptr == 0) { return null; } while (ptr[Size] != 0) { Size++; } byte[] array = new byte[Size]; Marshal.Copy(Ptr, array, 0, Size); return Encoding.UTF8.GetString(array, 0, array.Length); } public static string PtrToStringUtf8(IntPtr Ptr) { int Size; return PtrToStringUtf8(Ptr, out Size); } public static FileProcedures StreamFileProcedures(Stream InputStream) { return new StreamFileProcedures(InputStream); } public static void ApplyOn(this Effect Effect, MediaPlayer Player, int Priority = 0) where T : class, IEffectParameter, new() { Effect.ApplyOn(Player.Handle, Priority); Player.MediaLoaded += delegate(int NewHandle) { Effect.Dispose(); Effect.ApplyOn(NewHandle, Priority); }; } } public interface IEffectParameter { EffectType FXType { get; } } public class MediaPlayer : INotifyPropertyChanged, IDisposable { private readonly SynchronizationContext _syncContext; private int _handle; private bool _restartOnNextPlayback; private double _freq = 44100.0; private double _pan; private int _dev = -1; private double _vol = 0.5; private bool _loop; private string _title = ""; private string _artist = ""; private string _album = ""; protected internal int Handle { get { return _handle; } private set { if (!Bass.ChannelGetInfo(value, out var _)) { throw new ArgumentException("Invalid Channel Handle: " + value); } _handle = value; Bass.ChannelSetSync(Handle, SyncFlags.Free, 0L, GetSyncProcedure(delegate { this.Disposed?.Invoke(this, EventArgs.Empty); }), (IntPtr)0); Bass.ChannelSetSync(Handle, SyncFlags.Stop, 0L, GetSyncProcedure(delegate { this.MediaFailed?.Invoke(this, EventArgs.Empty); }), (IntPtr)0); Bass.ChannelSetSync(Handle, SyncFlags.End, 0L, GetSyncProcedure(delegate { try { if (!Bass.ChannelHasFlag(Handle, BassFlags.Loop)) { this.MediaEnded?.Invoke(this, EventArgs.Empty); } } finally { OnStateChanged(); } }), (IntPtr)0); } } public double Frequency { get { return _freq; } set { if (Bass.ChannelSetAttribute(Handle, ChannelAttribute.Frequency, value)) { _freq = value; OnPropertyChanged("Frequency"); } } } public double Balance { get { return _pan; } set { if (Bass.ChannelSetAttribute(Handle, ChannelAttribute.Pan, value)) { _pan = value; OnPropertyChanged("Balance"); } } } public int Device { get { return _dev = ((_dev == -1) ? Bass.ChannelGetDevice(Handle) : _dev); } set { if ((Bass.GetDeviceInfo(value).IsInitialized || Bass.Init(value, 44100, DeviceInitFlags.Default, (IntPtr)0, (IntPtr)0)) && Bass.ChannelSetDevice(Handle, value)) { _dev = value; OnPropertyChanged("Device"); } } } public double Volume { get { return _vol; } set { if (Bass.ChannelSetAttribute(Handle, ChannelAttribute.Volume, value)) { _vol = value; OnPropertyChanged("Volume"); } } } public bool Loop { get { return _loop; } set { if (!(value ? (!Bass.ChannelAddFlag(Handle, BassFlags.Loop)) : (!Bass.ChannelRemoveFlag(Handle, BassFlags.Loop)))) { _loop = value; OnPropertyChanged("Loop"); } } } public string Title { get { return _title; } private set { _title = value; OnPropertyChanged("Title"); } } public string Artist { get { return _artist; } private set { _artist = value; OnPropertyChanged("Artist"); } } public string Album { get { return _album; } private set { _album = value; OnPropertyChanged("Album"); } } public PlaybackState State { get { if (Handle != 0) { return Bass.ChannelIsActive(Handle); } return PlaybackState.Stopped; } } public TimeSpan Duration => TimeSpan.FromSeconds(Bass.ChannelBytes2Seconds(Handle, Bass.ChannelGetLength(Handle))); public TimeSpan Position { get { return TimeSpan.FromSeconds(Bass.ChannelBytes2Seconds(Handle, Bass.ChannelGetPosition(Handle))); } set { Bass.ChannelSetPosition(Handle, Bass.ChannelSeconds2Bytes(Handle, value.TotalSeconds)); } } public event EventHandler Disposed; public event EventHandler MediaEnded; public event EventHandler MediaFailed; public event Action MediaLoaded; public event PropertyChangedEventHandler PropertyChanged; private SyncProcedure GetSyncProcedure(Action Handler) { return delegate { if (Handler != null) { if (_syncContext == null) { Handler(); } else { _syncContext.Post(delegate { Handler(); }, null); } } }; } static MediaPlayer() { int currentDevice = Bass.CurrentDevice; if (currentDevice == -1 || !Bass.GetDeviceInfo(Bass.CurrentDevice).IsInitialized) { Bass.Init(currentDevice, 44100, DeviceInitFlags.Default, (IntPtr)0, (IntPtr)0); } } public MediaPlayer() { _syncContext = SynchronizationContext.Current; } protected virtual int OnLoad(string FileName) { return Bass.CreateStream(FileName, 0L, 0L); } public bool Play() { try { bool num = Bass.ChannelPlay(Handle, _restartOnNextPlayback); if (num) { _restartOnNextPlayback = false; } return num; } finally { OnStateChanged(); } } public bool Pause() { try { return Bass.ChannelPause(Handle); } finally { OnStateChanged(); } } public bool Stop() { try { _restartOnNextPlayback = true; return Bass.ChannelStop(Handle); } finally { OnStateChanged(); } } public async Task LoadAsync(string FileName) { try { if (Handle != 0) { Bass.StreamFree(Handle); } } catch { } if (_dev != -1) { Bass.CurrentDevice = _dev; } int currentDevice = Bass.CurrentDevice; if (currentDevice == -1 || !Bass.GetDeviceInfo(Bass.CurrentDevice).IsInitialized) { Bass.Init(currentDevice, 44100, DeviceInitFlags.Default, (IntPtr)0, (IntPtr)0); } int num = await Task.Run(() => OnLoad(FileName)); if (num == 0) { return false; } Handle = num; TagReader tagReader = TagReader.Read(Handle); Title = ((!string.IsNullOrWhiteSpace(tagReader.Title)) ? tagReader.Title : Path.GetFileNameWithoutExtension(FileName)); Artist = tagReader.Artist; Album = tagReader.Album; InitProperties(); this.MediaLoaded?.Invoke(num); OnPropertyChanged(""); return true; } public virtual void Dispose() { try { if (Bass.StreamFree(Handle)) { _handle = 0; } } finally { OnStateChanged(); } } protected virtual void InitProperties() { Frequency = _freq; Balance = _pan; Volume = _vol; Loop = _loop; } private void OnStateChanged() { OnPropertyChanged("State"); } protected virtual void OnPropertyChanged([CallerMemberName] string PropertyName = null) { Action f = delegate { this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(PropertyName)); }; if (_syncContext == null) { f(); return; } _syncContext.Post(delegate { f(); }, null); } } public static class ChannelReferences { private static readonly ConcurrentDictionary, object> Procedures = new ConcurrentDictionary, object>(); private static readonly SyncProcedure Freeproc = Callback; public static void Add(int Handle, int SpecificHandle, object proc) { if (proc != null && !proc.Equals(Freeproc)) { Tuple key = Tuple.Create(Handle, SpecificHandle); bool num = Procedures.ContainsKey(key); if (Freeproc != null && Procedures.All((KeyValuePair, object> pair) => pair.Key.Item1 != Handle)) { Bass.ChannelSetSync(Handle, SyncFlags.Free, 0L, Freeproc, (IntPtr)0); } if (num) { Procedures[key] = proc; } else { Procedures.TryAdd(key, proc); } } } public static void Remove(int Handle, int SpecialHandle) { Tuple key = Tuple.Create(Handle, SpecialHandle); Procedures.TryRemove(key, out var _); } private static void Callback(int Handle, int Channel, int Data, IntPtr User) { Tuple[] array = (from Pair in Procedures where Pair.Key.Item1 == Channel select Pair.Key).ToArray(); foreach (Tuple key in array) { Procedures.TryRemove(key, out var _); } } } public enum Resolution { Short, Byte, Float } internal class StreamFileProcedures : FileProcedures { private readonly Stream _stream; private byte[] b; public StreamFileProcedures(Stream InputStream) { _stream = InputStream; if (!_stream.CanRead) { throw new ArgumentException("Provide a readable stream", "InputStream"); } Close = delegate { _stream.Dispose(); }; Length = (IntPtr M) => _stream.Length; Read = ReadProc; Seek = SeekProc; } private int ReadProc(IntPtr Buffer, int Length, IntPtr User) { try { if (b == null || b.Length < Length) { b = new byte[Length]; } int num = _stream.Read(b, 0, Length); Marshal.Copy(b, 0, Buffer, num); return num; } catch { return 0; } } private bool SeekProc(long Offset, IntPtr User) { if (!_stream.CanSeek) { return false; } try { _stream.Seek(Offset, SeekOrigin.Current); return true; } catch { return false; } } } public class ID3v2Tag { private enum TextEncodings { Ascii, Utf16, Utf16Be, Utf8 } private IntPtr _ptr; private readonly Version _versionInfo; public Dictionary TextFrames { get; } = new Dictionary(); public List PictureFrames { get; } = new List(); public ID3v2Tag(IntPtr Pointer) { _ptr = Pointer; if (ReadText(3, TextEncodings.Ascii) != "ID3") { throw new DataMisalignedException("ID3v2 info not found"); } _versionInfo = new Version(2, ReadByte(), ReadByte()); _ptr += 1; ReadAllFrames(ReadSize()); } public ID3v2Tag(int Channel) : this(Bass.ChannelGetTags(Channel, TagType.ID3v2)) { } private void ReadAllFrames(int Length) { int num = ((_versionInfo.Minor == 2) ? 3 : 4); while (Length > 10) { if (ReadByte() == 0) { Length--; continue; } _ptr -= 1; string frameID = ReadText(num, TextEncodings.Ascii); int val = Convert.ToInt32(ReadUInt(num)); if (num == 4) { ReadUInt(2); } val = Math.Min(val, Length - 10); if (!AddFrame(frameID, val)) { _ptr += val; } Length -= val + 10; } } private bool AddFrame(string FrameID, int Length) { if (FrameID == null || !IsValidFrameID(FrameID)) { return false; } if (FrameID[0] == 'T' || FrameID[0] == 'W') { TextEncodings textEncodings; if (FrameID[0] == 'W') { textEncodings = TextEncodings.Ascii; } else { textEncodings = (TextEncodings)ReadByte(); Length--; if (!Enum.IsDefined(typeof(TextEncodings), textEncodings)) { return false; } } string value = ReadText(Length, textEncodings); AddTextFrame(FrameID, value); return true; } switch (FrameID) { case "POPM": { ReadText(Length, TextEncodings.Ascii, ref Length, DetectEncoding: true); string value2 = ReadByte().ToString(); if (--Length > 8) { return false; } _ptr += Length; AddTextFrame("POPM", value2); return true; } case "COM": case "COMM": { TextEncodings textEncodings3 = (TextEncodings)ReadByte(); Length--; if (!Enum.IsDefined(typeof(TextEncodings), textEncodings3)) { return false; } _ptr += 3; Length -= 3; ReadText(Length, textEncodings3, ref Length, DetectEncoding: true); AddTextFrame("COMM", ReadText(Length, textEncodings3)); return true; } case "APIC": { TextEncodings textEncodings2 = (TextEncodings)ReadByte(); Length--; if (!Enum.IsDefined(typeof(TextEncodings), textEncodings2)) { return false; } string mimeType = ReadText(Length, TextEncodings.Ascii, ref Length, DetectEncoding: true); PictureTypes pictureType = (PictureTypes)ReadByte(); Length--; ReadText(Length, textEncodings2, ref Length, DetectEncoding: true); byte[] array = new byte[Length]; Read(array, 0, Length); PictureFrames.Add(new PictureTag { Data = array, MimeType = mimeType, PictureType = pictureType }); return true; } default: return false; } } private static bool IsValidFrameID(string FrameID) { if (FrameID == null || (FrameID.Length != 3 && FrameID.Length != 4)) { return false; } return FrameID.Cast().All((char ch) => char.IsUpper(ch) || char.IsDigit(ch)); } private void AddTextFrame(string Key, string Value) { if (TextFrames.ContainsKey(Key)) { Dictionary textFrames = TextFrames; textFrames[Key] = textFrames[Key] + ";" + Value; } else { TextFrames.Add(Key, Value); } } private string ReadText(int MaxLength, TextEncodings TEncoding) { int ReadedLength = 0; return ReadText(MaxLength, TEncoding, ref ReadedLength, DetectEncoding: false); } private string ReadText(int MaxLength, TextEncodings TEncoding, ref int ReadedLength, bool DetectEncoding) { if (MaxLength <= 0) { return ""; } int num = 0; using MemoryStream memoryStream = new MemoryStream(); if (DetectEncoding && MaxLength >= 3) { byte[] array = new byte[3]; Read(array, 0, array.Length); if (array[0] == byte.MaxValue && array[1] == 254) { TEncoding = TextEncodings.Utf16; _ptr -= 1; num++; MaxLength -= 2; } else if (array[0] == 254 && array[1] == byte.MaxValue) { TEncoding = TextEncodings.Utf16Be; _ptr -= 1; num++; MaxLength -= 2; } else if (array[0] == 239 && array[1] == 187 && array[2] == 191) { TEncoding = TextEncodings.Utf8; MaxLength -= 3; } _ptr -= 3; num += 3; } bool flag = TEncoding == TextEncodings.Utf16 || TEncoding == TextEncodings.Utf16Be; while (MaxLength > 0) { byte b = ReadByte(); if (b != 0) { memoryStream.WriteByte(b); } else { if (!flag) { break; } byte b2 = ReadByte(); if (b2 == 0) { break; } memoryStream.WriteByte(b); memoryStream.WriteByte(b2); MaxLength--; } MaxLength--; } if (MaxLength < 0) { _ptr += MaxLength; } ReadedLength -= num; return GetEncoding(TEncoding).GetString(memoryStream.ToArray(), 0, (int)memoryStream.Length); } private byte ReadByte() { byte[] array = new byte[1]; Read(array, 0, 1); return array[0]; } private uint ReadUInt(int Length) { if (Length > 4 || Length < 1) { throw new ArgumentOutOfRangeException("Length", "ReadUInt method can read 1-4 byte(s)"); } byte[] array = new byte[Length]; byte[] array2 = new byte[4]; Read(array, 0, Length); array.CopyTo(array2, 4 - array.Length); Array.Reverse((Array)array2); return BitConverter.ToUInt32(array2, 0); } private int ReadSize() { return ReadByte() * 2097152 + ReadByte() * 16384 + ReadByte() * 128 + ReadByte(); } private static Encoding GetEncoding(TextEncodings TEncoding) { return TEncoding switch { TextEncodings.Utf16 => Encoding.Unicode, TextEncodings.Utf16Be => Encoding.GetEncoding("UTF-16BE"), _ => Encoding.UTF8, }; } private void Read(byte[] Buffer, int Offset, int Count) { Marshal.Copy(_ptr, Buffer, Offset, Count); _ptr += Count; } } public class PictureTag { public string MimeType; public PictureTypes PictureType; public byte[] Data; } public enum PictureTypes { Other, FileIcon, OtherFileIcon, FrontCover, BackCover, LeafletPage, Media, Soloist, Artist, Conductor, Band, Composer, Lyricist, RecordingLocation, DuringRecording, DuringPerformance, Movie, ABrightColouredFish, Illustration, BandLogo, PublisherLogo } internal static class LookupTables { public static readonly TagProperties> Ape = new TagProperties> { Title = new string[1] { "title" }, Artist = new string[1] { "artist" }, Album = new string[1] { "album" }, AlbumArtist = new string[1] { "album artist" }, Track = new string[1] { "track" }, Year = new string[1] { "year" }, Genre = new string[1] { "genre" }, Copyright = new string[1] { "copyright" }, Encoder = new string[1] { "encodedby" }, Publisher = new string[1] { "label" }, Composer = new string[1] { "composer" }, Conductor = new string[1] { "conductor" }, Lyricist = new string[1] { "lyricist" }, Remixer = new string[1] { "remixer" }, Producer = new string[1] { "producer" }, Comment = new string[1] { "comment" }, Grouping = new string[1] { "grouping" }, Mood = new string[1] { "mood" }, Rating = new string[1] { "rating" }, ISRC = new string[1] { "isrc" }, BPM = new string[1] { "bpm" } }; public static readonly TagProperties> Ogg = new TagProperties> { Title = new string[1] { "title" }, Artist = new string[1] { "artist" }, Album = new string[1] { "album" }, AlbumArtist = new string[1] { "albumartist" }, Track = new string[1] { "tracknumber" }, Year = new string[1] { "date" }, Genre = new string[1] { "genre" }, Copyright = new string[1] { "copyright" }, Encoder = new string[1] { "encodedby" }, Publisher = new string[1] { "label" }, Composer = new string[1] { "composer" }, Conductor = new string[1] { "conductor" }, Lyricist = new string[1] { "lyricist" }, Remixer = new string[1] { "remixer" }, Producer = new string[1] { "producer" }, Comment = new string[1] { "comment" }, Grouping = new string[1] { "grouping" }, Mood = new string[1] { "mood" }, Rating = new string[1] { "rating" }, ISRC = new string[1] { "isrc" }, BPM = new string[1] { "bpm" } }; public static readonly TagProperties> RiffInfo = new TagProperties> { Title = new string[1] { "inam" }, Artist = new string[1] { "iart" }, Album = new string[1] { "iprd" }, AlbumArtist = new string[1] { "isbj" }, Track = new string[2] { "itrk", "iprt" }, Year = new string[1] { "icrd" }, Genre = new string[1] { "ignr" }, Copyright = new string[1] { "icop" }, Encoder = new string[1] { "isft" }, Publisher = new string[1] { "icms" }, Composer = new string[1] { "ieng" }, Conductor = new string[1] { "itch" }, Lyricist = new string[1] { "iwri" }, Remixer = new string[1] { "iedt" }, Producer = new string[1] { "ipro" }, Comment = new string[1] { "icmt" }, Grouping = new string[1] { "isrf" }, Mood = new string[1] { "ikey" }, Rating = new string[1] { "ishp" }, ISRC = new string[1] { "isrc" }, BPM = new string[1] { "ibpm" } }; public static readonly TagProperties> Mp4 = new TagProperties> { Title = new string[1] { "©nam" }, Artist = new string[1] { "©art" }, Album = new string[1] { "©alb" }, AlbumArtist = new string[1] { "aart" }, Track = new string[1] { "trkn" }, Year = new string[1] { "©day" }, Genre = new string[1] { "©gen" }, Copyright = new string[1] { "cprt" }, Encoder = new string[1] { "©too" }, Composer = new string[1] { "©wrt" }, Comment = new string[1] { "©cmt" }, Grouping = new string[1] { "©grp" }, Rating = new string[1] { "rtng" } }; public static readonly TagProperties> Id3v2 = new TagProperties> { Title = new string[2] { "TIT2", "TT2" }, Artist = new string[2] { "TPE1", "TP1" }, Album = new string[2] { "TALB", "TAL" }, AlbumArtist = new string[2] { "TPE2", "TP2" }, Subtitle = new string[2] { "TIT3", "TT3" }, Track = new string[2] { "TRK", "TRCK" }, Year = new string[2] { "TYER", "TYE" }, Genre = new string[2] { "TCON", "TCO" }, Copyright = new string[2] { "TCOP", "TCR" }, Encoder = new string[2] { "TENC", "TEN" }, Publisher = new string[2] { "TPUB", "TPB" }, Composer = new string[2] { "TCOM", "TCM" }, Conductor = new string[2] { "TPE3", "TP3" }, Lyricist = new string[2] { "TEXT", "TXT" }, Remixer = new string[2] { "TPE4", "TP4" }, Producer = new string[1] { "TIPL" }, Comment = new string[2] { "COMM", "COM" }, Grouping = new string[2] { "TIT1", "TT1" }, Mood = new string[1] { "TMOO" }, Rating = new string[1] { "POPM" }, ISRC = new string[1] { "TSCR" }, BPM = new string[2] { "TBPM", "TBP" } }; } public class TagProperties { public T Title { get; set; } public T Artist { get; set; } public T Album { get; set; } public T AlbumArtist { get; set; } public T Subtitle { get; set; } public T BPM { get; set; } public T Composer { get; set; } public T Copyright { get; set; } public T Genre { get; set; } public T Grouping { get; set; } public T Publisher { get; set; } public T Encoder { get; set; } public T Lyricist { get; set; } public T Year { get; set; } public T Conductor { get; set; } public T Track { get; set; } public T Producer { get; set; } public T Comment { get; set; } public T Mood { get; set; } public T Rating { get; set; } public T ISRC { get; set; } public T Remixer { get; set; } } public sealed class TagReader : TagProperties { public Dictionary Other { get; } = new Dictionary(); public List Pictures { get; } = new List(); public string Lyrics { get; set; } public static TagReader Read(string FileName) { Bass.Init(-1, 44100, DeviceInitFlags.Default, (IntPtr)0, (IntPtr)0); int num = Bass.CreateStream(FileName, 0L, 0L, BassFlags.Prescan); TagReader tagReader = null; if (num != 0) { tagReader = Read(num); Bass.StreamFree(num); } else { num = Bass.MusicLoad(FileName, 0L, 0, BassFlags.Prescan); if (num != 0) { tagReader = Read(num); Bass.MusicFree(num); } } if (!string.IsNullOrWhiteSpace(tagReader?.Title)) { tagReader.Title = Path.GetFileNameWithoutExtension(FileName); } return tagReader; } public static TagReader Read(int Channel) { TagReader tagReader = new TagReader(); switch (Bass.ChannelGetInfo(Channel).ChannelType) { case ChannelType.MP1: case ChannelType.MP2: case ChannelType.MP3: if (!tagReader.ReadID3v2(Channel) && !tagReader.ReadID3v1(Channel) && !tagReader.ReadApe(Channel) && !tagReader.ReadBWF(Channel)) { } break; case ChannelType.OGG: if (!tagReader.ReadOgg(Channel) && !tagReader.ReadApe(Channel)) { } break; case ChannelType.AAC: case ChannelType.MP4: if (!tagReader.ReadMp4(Channel) && !tagReader.ReadID3v2(Channel) && !tagReader.ReadApe(Channel) && !tagReader.ReadOgg(Channel)) { } break; case ChannelType.Wave: case ChannelType.WavePCM: case ChannelType.WaveFloat: if (!tagReader.ReadRiffInfo(Channel) && !tagReader.ReadBWF(Channel) && !tagReader.ReadID3v2(Channel)) { } break; case ChannelType.DSD: tagReader.Title = Marshal.PtrToStringAnsi(Bass.ChannelGetTags(Channel, TagType.DSDTitle)); tagReader.Artist = Marshal.PtrToStringAnsi(Bass.ChannelGetTags(Channel, TagType.DSDArtist)); break; case ChannelType.MOD: tagReader.Title = Marshal.PtrToStringAnsi(Bass.ChannelGetTags(Channel, TagType.MusicName)); tagReader.Artist = Marshal.PtrToStringAnsi(Bass.ChannelGetTags(Channel, TagType.MusicAuth)); tagReader.Comment = Marshal.PtrToStringAnsi(Bass.ChannelGetTags(Channel, TagType.MusicMessage)); break; default: if (!tagReader.ReadApe(Channel) && !tagReader.ReadOgg(Channel) && !tagReader.ReadID3v2(Channel)) { tagReader.ReadID3v1(Channel); } break; } if (string.IsNullOrWhiteSpace(tagReader.Lyrics)) { IntPtr intPtr = Bass.ChannelGetTags(Channel, TagType.Lyrics3v2); if (intPtr != IntPtr.Zero) { tagReader.Lyrics = Marshal.PtrToStringAnsi(intPtr); } } return tagReader; } private IEnumerable> ReadUsingLookupTable(IEnumerable Tags, TagProperties> LookupTable, char Separator) { foreach (string Tag in Tags) { string[] array = Tag.Split(new char[1] { Separator }); string key = array[0].ToLower(); string value = array[1]; if (!SetTagUsingLookupTable(key, value, LookupTable)) { yield return new KeyValuePair(array[0], value); } } } private bool SetTagUsingLookupTable(string Key, string Value, TagProperties> LookupTable) { if (LookupTable.Title != null && LookupTable.Title.Contains(Key)) { base.Title = Value; } else if (LookupTable.Artist != null && LookupTable.Artist.Contains(Key)) { base.Artist = Value; } else if (LookupTable.Album != null && LookupTable.Album.Contains(Key)) { base.Album = Value; } else if (LookupTable.AlbumArtist != null && LookupTable.AlbumArtist.Contains(Key)) { base.AlbumArtist = Value; } else if (LookupTable.Subtitle != null && LookupTable.Subtitle.Contains(Key)) { base.Subtitle = Value; } else if (LookupTable.BPM != null && LookupTable.BPM.Contains(Key)) { base.BPM = Value; } else if (LookupTable.Composer != null && LookupTable.Composer.Contains(Key)) { base.Composer = Value; } else if (LookupTable.Copyright != null && LookupTable.Copyright.Contains(Key)) { base.Copyright = Value; } else if (LookupTable.Genre != null && LookupTable.Genre.Contains(Key)) { base.Genre = Value; } else if (LookupTable.Grouping != null && LookupTable.Grouping.Contains(Key)) { base.Grouping = Value; } else if (LookupTable.Publisher != null && LookupTable.Publisher.Contains(Key)) { base.Publisher = Value; } else if (LookupTable.Encoder != null && LookupTable.Encoder.Contains(Key)) { base.Encoder = Value; } else if (LookupTable.Lyricist != null && LookupTable.Lyricist.Contains(Key)) { base.Lyricist = Value; } else if (LookupTable.Year != null && LookupTable.Year.Contains(Key)) { base.Year = Value; } else if (LookupTable.Conductor != null && LookupTable.Conductor.Contains(Key)) { base.Conductor = Value; } else if (LookupTable.Track != null && LookupTable.Track.Contains(Key)) { base.Track = Value; } else if (LookupTable.Producer != null && LookupTable.Producer.Contains(Key)) { base.Producer = Value; } else if (LookupTable.Comment != null && LookupTable.Comment.Contains(Key)) { base.Comment = Value; } else if (LookupTable.Mood != null && LookupTable.Mood.Contains(Key)) { base.Mood = Value; } else if (LookupTable.Rating != null && LookupTable.Rating.Contains(Key)) { base.Rating = Value; } else if (LookupTable.ISRC != null && LookupTable.ISRC.Contains(Key)) { base.ISRC = Value; } else { if (LookupTable.Remixer == null || !LookupTable.Remixer.Contains(Key)) { return false; } base.Remixer = Value; } return true; } public bool ReadApe(int Channel) { IntPtr intPtr = Bass.ChannelGetTags(Channel, TagType.APE); if (intPtr == IntPtr.Zero) { return false; } foreach (KeyValuePair item in ReadUsingLookupTable(Extensions.ExtractMultiStringUtf8(intPtr), LookupTables.Ape, '=')) { Other.Add(item.Key, item.Value); } return true; } public bool ReadOgg(int Channel) { IntPtr intPtr = Bass.ChannelGetTags(Channel, TagType.OGG); if (intPtr == IntPtr.Zero) { return false; } foreach (KeyValuePair item in ReadUsingLookupTable(Extensions.ExtractMultiStringUtf8(intPtr), LookupTables.Ogg, '=')) { Other.Add(item.Key, item.Value); } if (string.IsNullOrWhiteSpace(base.Encoder)) { IntPtr intPtr2 = Bass.ChannelGetTags(Channel, TagType.OggEncoder); if (intPtr2 != IntPtr.Zero) { base.Encoder = Extensions.PtrToStringUtf8(intPtr2); } } return true; } public bool ReadRiffInfo(int Channel) { IntPtr intPtr = Bass.ChannelGetTags(Channel, TagType.RiffInfo); if (intPtr == IntPtr.Zero) { return false; } foreach (KeyValuePair item in ReadUsingLookupTable(Extensions.ExtractMultiStringAnsi(intPtr), LookupTables.RiffInfo, '=')) { Other.Add(item.Key, item.Value); } return true; } public bool ReadMp4(int Channel) { IntPtr intPtr = Bass.ChannelGetTags(Channel, TagType.MP4); if (intPtr == IntPtr.Zero) { return false; } foreach (KeyValuePair item in ReadUsingLookupTable(Extensions.ExtractMultiStringUtf8(intPtr), LookupTables.Mp4, '=')) { Other.Add(item.Key, item.Value); } return true; } public bool ReadID3v1(int Channel) { IntPtr intPtr = Bass.ChannelGetTags(Channel, TagType.ID3); if (intPtr == IntPtr.Zero) { return false; } ID3v1Tag iD3v1Tag = Marshal.PtrToStructure(intPtr); base.Title = iD3v1Tag.Title; base.Artist = iD3v1Tag.Artist; base.Album = iD3v1Tag.Album; base.Year = iD3v1Tag.Year; base.Genre = iD3v1Tag.Genre; base.Track = iD3v1Tag.TrackNo.ToString(); base.Comment = iD3v1Tag.Comment; return true; } public bool ReadID3v2(int Channel) { IntPtr intPtr = Bass.ChannelGetTags(Channel, TagType.ID3v2); if (intPtr == IntPtr.Zero) { return false; } ID3v2Tag iD3v2Tag = new ID3v2Tag(intPtr); foreach (KeyValuePair textFrame in iD3v2Tag.TextFrames) { if (!SetTagUsingLookupTable(textFrame.Key, textFrame.Value, LookupTables.Id3v2)) { Other.Add(textFrame.Key, textFrame.Value); } } Pictures.AddRange(iD3v2Tag.PictureFrames); return true; } public bool ReadBWF(int Channel) { IntPtr intPtr = Bass.ChannelGetTags(Channel, TagType.RiffBext); if (intPtr == IntPtr.Zero) { return false; } BextTag bextTag = Marshal.PtrToStructure(intPtr); base.Title = bextTag.Description; base.Artist = bextTag.Originator; base.Encoder = bextTag.OriginatorReference; base.Year = bextTag.OriginationDate.Split(new char[1] { '-' })[0]; return true; } } [StructLayout(LayoutKind.Sequential)] public class BextTag { [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] public string Description; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] public string Originator; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] public string OriginatorReference; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)] public string OriginationDate; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)] public string OriginationTime; public long TimeReference; public short Version; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)] public byte[] UMID; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 190)] private byte[] reserved; private IntPtr codinghistory; public DateTime OriginationDateTime { get { int year = int.Parse(OriginationDate.Substring(0, 4)); int month = int.Parse(OriginationDate.Substring(5, 2)); int day = int.Parse(OriginationDate.Substring(8, 2)); int hour = int.Parse(OriginationTime.Substring(0, 2)); int minute = int.Parse(OriginationTime.Substring(3, 2)); int second = int.Parse(OriginationTime.Substring(6, 2)); return new DateTime(year, month, day, hour, minute, second); } } public string CodingHistory { get { if (!(codinghistory == IntPtr.Zero)) { return Marshal.PtrToStringAnsi(codinghistory); } return null; } } public static BextTag Read(int Channel) { return Marshal.PtrToStructure(Bass.ChannelGetTags(Channel, TagType.RiffBext)); } } [StructLayout(LayoutKind.Sequential)] public class CACodecTag { public int ftype; public int atype; private IntPtr name; public string Name { get { if (!(name == IntPtr.Zero)) { return Marshal.PtrToStringAnsi(name); } return null; } } public static CACodecTag Read(int Channel) { return Marshal.PtrToStructure(Bass.ChannelGetTags(Channel, TagType.WmaMeta)); } } [StructLayout(LayoutKind.Sequential)] public class CartTimer { public int Usage; public int Value; } [StructLayout(LayoutKind.Sequential)] public class CartTag { [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)] public string Version; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)] public string Title; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)] public string Artist; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)] public string CutID; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)] public string ClientID; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)] public string Category; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)] public string Classification; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)] public string OutCue; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)] private string startDate; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)] private string startTime; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)] private string endDate; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)] private string endTime; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)] public string ProducerAppID; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)] public string ProducerAppVersion; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)] public string UserDef; public int dwLevelReference; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public CartTimer[] PostTimer; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 276)] private char[] Reserved; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)] public string URL; private IntPtr tagText; public string TagText { get { if (!(tagText == IntPtr.Zero)) { return Marshal.PtrToStringAnsi(tagText); } return null; } } public DateTime StartTime { get { string[] array = startDate.Split(new char[1] { '-' }); string[] array2 = startTime.Split(new char[1] { ':' }); return new DateTime(int.Parse(array[0]), int.Parse(array[1]), int.Parse(array[2]), int.Parse(array2[0]), int.Parse(array2[1]), int.Parse(array2[2])); } } public DateTime EndTime { get { string[] array = endDate.Split(new char[1] { '-' }); string[] array2 = endTime.Split(new char[1] { ':' }); return new DateTime(int.Parse(array[0]), int.Parse(array[1]), int.Parse(array[2]), int.Parse(array2[0]), int.Parse(array2[1]), int.Parse(array2[2])); } } public static CartTag Read(int Channel) { return Marshal.PtrToStructure(Bass.ChannelGetTags(Channel, TagType.RiffCart)); } } [StructLayout(LayoutKind.Sequential)] public class ID3v1Tag { [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] private char[] id; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 30)] public string Title; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 30)] public string Artist; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 30)] public string Album; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)] public string Year; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 30)] private char[] comment; public byte genre = 147; public static string[] Genres = new string[148] { "Blues", "Classic Rock", "Country", "Dance", "Disco", "Funk", "Grunge", "Hip-Hop", "Jazz", "Metal", "New Age", "Oldies", "Other", "Pop", "R&B", "Rap", "Reggae", "Rock", "Techno", "Industrial", "Alternative", "Ska", "Death Metal", "Pranks", "Soundtrack", "Euro-Techno", "Ambient", "Trip-Hop", "Vocal", "Jazz+Funk", "Fusion", "Trance", "Classical", "Instrumental", "Acid", "House", "Game", "Sound Clip", "Gospel", "Noise", "Alternative Rock", "Bass", "Soul", "Punk", "Space", "Meditative", "Instrumental Pop", "Instrumental Rock", "Ethnic", "Gothic", "Darkwave", "Techno-Industrial", "Electronic", "Pop-Folk", "Eurodance", "Dream", "Southern Rock", "Comedy", "Cult", "Gangsta", "Top Christian Rap", "Pop/Funk", "Jungle", "Native US", "Cabaret", "New Wave", "Psychadelic", "Rave", "Showtunes", "Trailer", "Lo-Fi", "Tribal", "Acid Punk", "Acid Jazz", "Polka", "Retro", "Musical", "Rock & Roll", "Hard Rock", "Folk", "Folk-Rock", "National Folk", "Swing", "Fast Fusion", "Bebob", "Latin", "Revival", "Celtic", "Bluegrass", "Avantgarde", "Gothic Rock", "Progressive Rock", "Psychedelic Rock", "Symphonic Rock", "Slow Rock", "Big Band", "Chorus", "Easy Listening", "Acoustic", "Humour", "Speech", "Chanson", "Opera", "Chamber Music", "Sonata", "Symphony", "Booty Bass", "Primus", "Porn Groove", "Satire", "Slow Jam", "Club", "Tango", "Samba", "Folklore", "Ballad", "Power Ballad", "Rhythmic Soul", "Freestyle", "Duet", "Punk Rock", "Drum Solo", "Acapella", "Euro-House", "Dance Hall", "Goa", "Drum & Bass", "Club - House", "Hardcore", "Terror", "Indie", "BritPop", "Negerpunk", "Polsk Punk", "Beat", "Christian Gangsta Rap", "Heavy Metal", "Black Metal", "Crossover", "Contemporary Christian", "Christian Rock", "Merengue", "Salsa", "Thrash Metal", "Anime", "JPop", "Synthpop", "Unknown" }; public string Comment { get { if (comment != null) { return new string(comment).Replace("\0", "").Trim(); } return ""; } } public string Genre => Genres[(genre > 147) ? 147 : genre]; public int TrackNo { get { if (comment[28] != 0) { return -1; } return comment[29]; } } public static ID3v1Tag Read(int Channel) { return Marshal.PtrToStructure(Bass.ChannelGetTags(Channel, TagType.ID3)); } } public class WaveFileWriter : IDisposable { private Stream _ofstream; private BinaryWriter _writer; private readonly long _dataSizePos; private readonly long _factSampleCountPos; private readonly object _locker = new object(); private readonly WaveFormat _waveFormat; public long Length { get; set; } public WaveFileWriter(Stream outStream, WaveFormat format) { _ofstream = outStream; _writer = new BinaryWriter(outStream, Encoding.UTF8); _writer.Write(Encoding.UTF8.GetBytes("RIFF")); _writer.Write(0); _writer.Write(Encoding.UTF8.GetBytes("WAVEfmt ")); _waveFormat = format; _writer.Write(18 + format.ExtraSize); format.Serialize(_writer); if (format.Encoding != WaveFormatTag.Pcm) { _writer.Write(Encoding.UTF8.GetBytes("fact")); _writer.Write(4); _factSampleCountPos = outStream.Position; _writer.Write(0); } _writer.Write(Encoding.UTF8.GetBytes("data")); _dataSizePos = outStream.Position; _writer.Write(0); Length = 0L; } public bool Write(byte[] Data, int Length) { try { lock (_locker) { _writer.Write(Data, 0, Length); } this.Length += Length; return true; } catch { return false; } } public bool Write(short[] Data, int Length) { try { int num = Length / 2; lock (_locker) { for (int i = 0; i < num; i++) { _writer.Write(Data[i]); } } this.Length += Length; return true; } catch { return false; } } public bool Write(float[] Data, int Length) { try { int num = Length / 4; lock (_locker) { for (int i = 0; i < num; i++) { _writer.Write(Data[i]); } } this.Length += Length; return true; } catch { return false; } } public void Dispose() { GC.SuppressFinalize(this); Dispose(Disposing: true); } private void Dispose(bool Disposing) { if (!Disposing || _writer == null) { return; } try { lock (_locker) { _writer.Flush(); _writer.Seek(4, SeekOrigin.Begin); _writer.Write((int)(_ofstream.Length - 8)); if (_waveFormat.Encoding != WaveFormatTag.Pcm) { _writer.Seek((int)_factSampleCountPos, SeekOrigin.Begin); _writer.Write((int)(Length * 8 / _waveFormat.BitsPerSample)); } _writer.Seek((int)_dataSizePos, SeekOrigin.Begin); _writer.Write((int)Length); } } finally { lock (_locker) { _writer.Dispose(); _writer = null; } _ofstream.Dispose(); _ofstream = null; } } ~WaveFileWriter() { Dispose(Disposing: false); } } public class WaveFormat { public WaveFormatTag Encoding { get; set; } public int Channels { get; set; } public int SampleRate { get; set; } public int AverageBytesPerSecond { get; set; } public int BlockAlign { get; set; } public int BitsPerSample { get; set; } public int ExtraSize { get; set; } public WaveFormat() : this(44100, 16, 2) { } public WaveFormat(int SampleRate, int Channels) : this(SampleRate, 16, Channels) { } public WaveFormat(int SampleRate, int BitsPerSample, int Channels) { if (Channels < 1) { throw new ArgumentOutOfRangeException("Channels", "Channels must be 1 or greater"); } Encoding = WaveFormatTag.Pcm; this.Channels = Channels; this.SampleRate = SampleRate; this.BitsPerSample = BitsPerSample; ExtraSize = 0; BlockAlign = Channels * (BitsPerSample / 8); AverageBytesPerSecond = SampleRate * BlockAlign; } public static WaveFormat CreateIeeeFloat(int SampleRate, int Channels) { return new WaveFormat(SampleRate, 32, Channels) { Encoding = WaveFormatTag.IeeeFloat }; } internal static WaveFormat FromParams(int Frequency, int Channels, Resolution Resolution) { return Resolution switch { Resolution.Byte => new WaveFormat(Frequency, 8, Channels), Resolution.Float => CreateIeeeFloat(Frequency, Channels), _ => new WaveFormat(Frequency, Channels), }; } public static WaveFormat FromChannel(int Channel) { ChannelInfo channelInfo = Bass.ChannelGetInfo(Channel); return FromParams(channelInfo.Frequency, channelInfo.Channels, channelInfo.Resolution); } public virtual void Serialize(BinaryWriter Writer) { Writer.Write((short)Encoding); Writer.Write((short)Channels); Writer.Write(SampleRate); Writer.Write(AverageBytesPerSecond); Writer.Write((short)BlockAlign); Writer.Write((short)BitsPerSample); Writer.Write((short)ExtraSize); } } } namespace ManagedBass.DirectX8 { public sealed class DXChorusEffect : Effect { public DXWaveform Waveform { get { return base.Parameters.lWaveform; } set { base.Parameters.lWaveform = value; OnPropertyChanged("Waveform"); } } public double WetDryMix { get { return base.Parameters.fWetDryMix; } set { base.Parameters.fWetDryMix = (float)value; OnPropertyChanged("WetDryMix"); } } public double Depth { get { return base.Parameters.fDepth; } set { base.Parameters.fDepth = (float)value; OnPropertyChanged("Depth"); } } public double Feedback { get { return base.Parameters.fFeedback; } set { base.Parameters.fFeedback = (float)value; OnPropertyChanged("Feedback"); } } public double Frequency { get { return base.Parameters.fFrequency; } set { base.Parameters.fFrequency = (float)value; OnPropertyChanged("Frequency"); } } public double Delay { get { return base.Parameters.fDelay; } set { base.Parameters.fDelay = (float)value; OnPropertyChanged("Delay"); } } public DXPhase Phase { get { return base.Parameters.lPhase; } set { base.Parameters.lPhase = value; OnPropertyChanged("Phase"); } } } public sealed class DXCompressorEffect : Effect { public double Gain { get { return base.Parameters.fGain; } set { base.Parameters.fGain = (float)value; OnPropertyChanged("Gain"); } } public double Attack { get { return base.Parameters.fAttack; } set { base.Parameters.fAttack = (float)value; OnPropertyChanged("Attack"); } } public double Release { get { return base.Parameters.fRelease; } set { base.Parameters.fRelease = (float)value; OnPropertyChanged("Release"); } } public double Threshold { get { return base.Parameters.fThreshold; } set { base.Parameters.fThreshold = (float)value; OnPropertyChanged("Threshold"); } } public double Ratio { get { return base.Parameters.fRatio; } set { base.Parameters.fRatio = (float)value; OnPropertyChanged("Ratio"); } } public double Predelay { get { return base.Parameters.fPredelay; } set { base.Parameters.fPredelay = (float)value; OnPropertyChanged("Predelay"); } } } public sealed class DXDistortionEffect : Effect { public double Gain { get { return base.Parameters.fGain; } set { base.Parameters.fGain = (float)value; OnPropertyChanged("Gain"); } } public double Edge { get { return base.Parameters.fEdge; } set { base.Parameters.fEdge = (float)value; OnPropertyChanged("Edge"); } } public double PostEQCenterFrequency { get { return base.Parameters.fPostEQCenterFrequency; } set { base.Parameters.fPostEQCenterFrequency = (float)value; OnPropertyChanged("PostEQCenterFrequency"); } } public double PostEQBandwidth { get { return base.Parameters.fPostEQBandwidth; } set { base.Parameters.fPostEQBandwidth = (float)value; OnPropertyChanged("PostEQBandwidth"); } } public double PreLowpassCutoff { get { return base.Parameters.fPreLowpassCutoff; } set { base.Parameters.fPreLowpassCutoff = (float)value; OnPropertyChanged("PreLowpassCutoff"); } } } public sealed class DXEchoEffect : Effect { public double WetDryMix { get { return base.Parameters.fWetDryMix; } set { base.Parameters.fWetDryMix = (float)value; OnPropertyChanged("WetDryMix"); } } public double Feedback { get { return base.Parameters.fFeedback; } set { base.Parameters.fFeedback = (float)value; OnPropertyChanged("Feedback"); } } public double LeftDelay { get { return base.Parameters.fLeftDelay; } set { base.Parameters.fLeftDelay = (float)value; OnPropertyChanged("LeftDelay"); } } public double RightDelay { get { return base.Parameters.fRightDelay; } set { base.Parameters.fRightDelay = (float)value; OnPropertyChanged("RightDelay"); } } public bool PanDelay { get { return base.Parameters.lPanDelay; } set { base.Parameters.lPanDelay = value; OnPropertyChanged("PanDelay"); } } } public sealed class DXFlangerEffect : Effect { public double WetDryMix { get { return base.Parameters.fWetDryMix; } set { base.Parameters.fWetDryMix = (float)value; OnPropertyChanged("WetDryMix"); } } public double Depth { get { return base.Parameters.fDepth; } set { base.Parameters.fDepth = (float)value; OnPropertyChanged("Depth"); } } public double Feedback { get { return base.Parameters.fFeedback; } set { base.Parameters.fFeedback = (float)value; OnPropertyChanged("Feedback"); } } public double Frequency { get { return base.Parameters.fFrequency; } set { base.Parameters.fFrequency = (float)value; OnPropertyChanged("Frequency"); } } public DXWaveform Waveform { get { return base.Parameters.lWaveform; } set { base.Parameters.lWaveform = value; OnPropertyChanged("Waveform"); } } public double Delay { get { return base.Parameters.fDelay; } set { base.Parameters.fDelay = (float)value; OnPropertyChanged("Delay"); } } public DXPhase Phase { get { return base.Parameters.lPhase; } set { base.Parameters.lPhase = value; OnPropertyChanged("Phase"); } } } public sealed class DXGargleEffect : Effect { public int Rate { get { return base.Parameters.dwRateHz; } set { base.Parameters.dwRateHz = value; OnPropertyChanged("Rate"); } } public DXWaveform WaveShape { get { return base.Parameters.dwWaveShape; } set { base.Parameters.dwWaveShape = value; OnPropertyChanged("WaveShape"); } } } public sealed class DXParamEQ : IDisposable { private readonly DXParamEQParameters _parameters; private GCHandle _gch; private readonly int _channel; private readonly List _handles = new List(); public DXParamEQ(int Channel, double Bandwidth = 18.0) { _channel = Channel; _parameters = new DXParamEQParameters { fBandwidth = (float)Bandwidth }; _gch = GCHandle.Alloc(_parameters, GCHandleType.Pinned); } public int AddBand(double CenterFrequency = 100.0) { _parameters.fCenter = (float)CenterFrequency; _parameters.fGain = 0f; int num = Bass.ChannelSetFX(_channel, EffectType.DXParamEQ, 0); Bass.FXSetParameters(num, _gch.AddrOfPinnedObject()); _handles.Add(num); return _handles.Count - 1; } public void UpdateBand(int Band, double Gain) { Bass.FXGetParameters(_handles[Band], _gch.AddrOfPinnedObject()); _parameters.fGain = (float)Gain; Bass.FXSetParameters(_handles[Band], _gch.AddrOfPinnedObject()); } public void Dispose() { _gch.Free(); foreach (int handle in _handles) { Bass.ChannelRemoveFX(_channel, handle); } } } [Obsolete("Use DXParamEQ instead.")] public sealed class DXParamEQEffect : Effect { public double Center { get { return base.Parameters.fCenter; } set { base.Parameters.fCenter = (float)value; OnPropertyChanged("Center"); } } public double Bandwidth { get { return base.Parameters.fBandwidth; } set { base.Parameters.fBandwidth = (float)value; OnPropertyChanged("Bandwidth"); } } public double Gain { get { return base.Parameters.fGain; } set { base.Parameters.fGain = (float)value; OnPropertyChanged("Gain"); } } } public sealed class DXReverbEffect : Effect { public double InGain { get { return base.Parameters.fInGain; } set { base.Parameters.fInGain = (float)value; OnPropertyChanged("InGain"); } } public double ReverbMix { get { return base.Parameters.fReverbMix; } set { base.Parameters.fReverbMix = (float)value; OnPropertyChanged("ReverbMix"); } } public double ReverbTime { get { return base.Parameters.fReverbTime; } set { base.Parameters.fReverbTime = (float)value; OnPropertyChanged("ReverbTime"); } } public double HighFreqRTRatio { get { return base.Parameters.fHighFreqRTRatio; } set { base.Parameters.fHighFreqRTRatio = (float)value; OnPropertyChanged("HighFreqRTRatio"); } } } public sealed class DX_ID3DL2ReverbEffect : Effect { public int Room { get { return base.Parameters.lRoom; } set { base.Parameters.lRoom = value; OnPropertyChanged("Room"); } } public int RoomHF { get { return base.Parameters.lRoomHF; } set { base.Parameters.lRoomHF = value; OnPropertyChanged("RoomHF"); } } public double RoomRolloffFactor { get { return base.Parameters.flRoomRolloffFactor; } set { base.Parameters.flRoomRolloffFactor = (float)value; OnPropertyChanged("RoomRolloffFactor"); } } public double DecayTime { get { return base.Parameters.flDecayTime; } set { base.Parameters.flDecayTime = (float)value; OnPropertyChanged("DecayTime"); } } public double DecayHFRatio { get { return base.Parameters.flDecayHFRatio; } set { base.Parameters.flDecayHFRatio = (float)value; OnPropertyChanged("DecayHFRatio"); } } public int Reflections { get { return base.Parameters.lReflections; } set { base.Parameters.lReflections = value; OnPropertyChanged("Reflections"); } } public double ReflectionsDelay { get { return base.Parameters.flReflectionsDelay; } set { base.Parameters.flReflectionsDelay = (float)value; OnPropertyChanged("ReflectionsDelay"); } } public int Reverb { get { return base.Parameters.lReverb; } set { base.Parameters.lReverb = value; OnPropertyChanged("Reverb"); } } public double ReverbDelay { get { return base.Parameters.flReverbDelay; } set { base.Parameters.flReverbDelay = (float)value; OnPropertyChanged("ReverbDelay"); } } public double Diffusion { get { return base.Parameters.flDiffusion; } set { base.Parameters.flDiffusion = (float)value; OnPropertyChanged("Diffusion"); } } public double Density { get { return base.Parameters.flDensity; } set { base.Parameters.flDensity = (float)value; OnPropertyChanged("Density"); } } public double HFReference { get { return base.Parameters.flHFReference; } set { base.Parameters.flHFReference = (float)value; OnPropertyChanged("HFReference"); } } } [StructLayout(LayoutKind.Sequential)] public class DXCompressorParameters : IEffectParameter { public float fGain; public float fAttack = 10f; public float fRelease = 200f; public float fThreshold = -20f; public float fRatio = 3f; public float fPredelay = 4f; public EffectType FXType => EffectType.DXCompressor; } [StructLayout(LayoutKind.Sequential)] public class DXGargleParameters : IEffectParameter { public int dwRateHz = 500; public DXWaveform dwWaveShape = DXWaveform.Sine; public EffectType FXType => EffectType.DXGargle; } [StructLayout(LayoutKind.Sequential)] public class DX_ID3DL2ReverbParameters : IEffectParameter { public int lRoom = -1000; public int lRoomHF; public float flRoomRolloffFactor; public float flDecayTime = 1.49f; public float flDecayHFRatio = 0.83f; public int lReflections = -2602; public float flReflectionsDelay = 0.007f; public int lReverb = 200; public float flReverbDelay = 0.011f; public float flDiffusion = 100f; public float flDensity = 100f; public float flHFReference = 5000f; public EffectType FXType => EffectType.DX_I3DL2Reverb; } [StructLayout(LayoutKind.Sequential)] public class DXChorusParameters : IEffectParameter { public float fWetDryMix = 50f; public float fDepth = 25f; public float fFeedback; public float fFrequency; public DXWaveform lWaveform = DXWaveform.Sine; public float fDelay; public DXPhase lPhase = DXPhase.Zero; public EffectType FXType => EffectType.DXChorus; } [StructLayout(LayoutKind.Sequential)] public class DXDistortionParameters : IEffectParameter { public float fGain; public float fEdge; public float fPostEQCenterFrequency; public float fPostEQBandwidth; public float fPreLowpassCutoff; public EffectType FXType => EffectType.DXDistortion; } [StructLayout(LayoutKind.Sequential)] public class DXEchoParameters : IEffectParameter { public float fWetDryMix; public float fFeedback; public float fLeftDelay; public float fRightDelay; public bool lPanDelay; public EffectType FXType => EffectType.DXEcho; } [StructLayout(LayoutKind.Sequential)] public class DXFlangerParameters : IEffectParameter { public float fWetDryMix; public float fDepth; public float fFeedback; public float fFrequency; public DXWaveform lWaveform = DXWaveform.Sine; public float fDelay; public DXPhase lPhase; public EffectType FXType => EffectType.DXFlanger; } [StructLayout(LayoutKind.Sequential)] public class DXParamEQParameters : IEffectParameter { public float fCenter; public float fBandwidth; public float fGain; public EffectType FXType => EffectType.DXParamEQ; } [StructLayout(LayoutKind.Sequential)] public class DXReverbParameters : IEffectParameter { public float fInGain; public float fReverbMix; public float fReverbTime; public float fHighFreqRTRatio; public EffectType FXType => EffectType.DXReverb; } }